<commit_before>#include <rpcndr.h>
#include <iostream>
#include <fstream>
#include <map>
#include "Graph.h"

using namespace std;

struct Node {
    string vert;
    int weight;
    Node *next;
};
struct List {
    struct Node *head;
};

class Graph {
    int vertices;
    struct List *vertexArray;
    int count = 0;
    map<string, int> vertList;

public:

    Graph(int vertices) {
        this->vertices = vertices;
        vertexArray = new List[vertices];
        for (int i = 0; i < vertices; i++) {
            vertexArray[i].head = NULL;
        }
    }

    Node *nextNode(string vert) {
        Node *newNode = new Node;
        newNode->vert = vert;
        newNode->weight=NULL;
        newNode->next = NULL;
        return newNode;
    }

    void addVertex(string vert) {
        vertList[vert] = count;
        count++;
    }

    void addEdge(string head, string vert, int weight) {
        Node *newNode = nextNode(vert);
        newNode->weight = weight;
        newNode->next = vertexArray[vertList.at(head)].head;
        vertexArray[vertList.at(head)].head = newNode;
    }

    boolean readGraph(char arg[]) {
        ifstream inputFile((const char *) arg[0]);
        if (!inputFile.is_open()) {
            cout << "Error opening file " << arg[1] << endl;
        } else {
            string str;
            getline(inputFile, str);
            vertices = stoi(str);
            while (!inputFile.eof()) {
                getline(inputFile, str);
                if (strtol(str)){
                    cout<<"test";
                }
                addVertex(str);
            }
        }
    }

    void TopologicalSort() {}

    void ShortestPath() {}

    void MinimumSpanningTree() {}
};

int main(char *arg[]) {
    Graph *graph = new Graph(5);

    graph->readGraph(arg[0]);

//    graph->addVertex("a");
//    graph->addVertex("b");
//    graph->addVertex("c");
//    graph->addVertex("d");
//    graph->addVertex("e");
//
//    graph->addEdge("a", "b", 1);
//    graph->addEdge("a", "d", 3);
//    graph->addEdge("b", "c", 4);
//    graph->addEdge("d", "e", 6);
//    graph->addEdge("a", "c", 2);
//    graph->addEdge("b", "d", 3);

    return 0;
}
<commit_msg>Logic for ReadGraph<commit_after>#include <iostream>
#include <fstream>
#include <map>
#include <sstream>
#include "Graph.h"

using namespace std;

struct Node {
    string vert;
    int weight;
    Node *next;
};
struct List {
    struct Node *head;
};

class Graph {
    int vertices;
    int edges;
    struct List *vertexArray;
    int count = 0;
    map<string, int> vertList;

public:

    Graph(int vertices) {
        this->vertices = vertices;
        vertexArray = new List[vertices];
        for (int i = 0; i < vertices; i++) {
            vertexArray[i].head = NULL;
        }
    }

    Node *nextNode(string vert) {
        Node *newNode = new Node;
        newNode->vert = vert;
        newNode->weight=NULL;
        newNode->next = NULL;
        return newNode;
    }

    void addVertex(string vert) {
        vertList[vert] = count;
        count++;
    }

    void addEdge(string head, string vert, int weight) {
        Node *newNode = nextNode(vert);
        newNode->weight = weight;
        newNode->next = vertexArray[vertList.at(head)].head;
        vertexArray[vertList.at(head)].head = newNode;
    }

    bool readGraph(char arg[]) {
        ifstream inputFile((const char *) arg[0]);
        if (!inputFile.is_open()) {
            cout << "Error opening file " << endl;
        } else {
            string str;
            string str2;
            string str3;
            getline(inputFile, str);
            vertices = stoi(str);
            while (!inputFile.eof()) {
                getline(inputFile, str);
                if (stoi(str)){
                    edges = stoi(str);
                    break;
                }else{
                    addVertex(str);
                }
            }
            while (!inputFile.eof()) {
                getline(inputFile, str);
                stringstream line(str);
                line >> str >> str2 >> str3;
                    addEdge(str,str2,stoi(str3));
            }
        }
    }

    void TopologicalSort() {}

    void ShortestPath() {}

    void MinimumSpanningTree() {}
};

int main(char *arg[]) {
    Graph *graph = new Graph(5);

    graph->readGraph(arg[0]);

//    graph->addVertex("a");
//    graph->addVertex("b");
//    graph->addVertex("c");
//    graph->addVertex("d");
//    graph->addVertex("e");
//
//    graph->addEdge("a", "b", 1);
//    graph->addEdge("a", "d", 3);
//    graph->addEdge("b", "c", 4);
//    graph->addEdge("d", "e", 6);
//    graph->addEdge("a", "c", 2);
//    graph->addEdge("b", "d", 3);

    return 0;
}
<|endoftext|>


<commit_before>#ifndef RDB_PROTOCOL_DATUM_HPP_
#define RDB_PROTOCOL_DATUM_HPP_
#include <map>
#include <string>
#include <utility>
#include <vector>

#include "utils.hpp"
#include <boost/shared_ptr.hpp>

#include "containers/archive/archive.hpp"
#include "containers/ptr_bag.hpp"
#include "http/json.hpp"
#include "rdb_protocol/err.hpp"

class Datum;

namespace ql {
class datum_stream_t;
class env_t;
class val_t;

// These let us write e.g. `foo(NOTHROW) instead of `foo(false/*nothrow*/)`.
// They should be passed to functions that have multiple behaviors (like `el` or
// `add` below).

// NOTHROW: Return NULL
// THROW: Throw an error
enum throw_bool_t { NOTHROW = 0, THROW = 1};

// NOCLOBBER: Don't overwrite existing values.
// CLOBBER: Overwrite existing values.
enum clobber_bool_t { NOCLOBBER = 0, CLOBBER = 1};

// A `datum_t` is basically a JSON value, although we may extend it later.
// TODO: When we optimize for memory, this needs to stop inheriting from `rcheckable_t`
class datum_t : public ptr_baggable_t, public rcheckable_t {
public:
    // This ordering is important, because we use it to sort objects of
    // disparate type.  It should be alphabetical.
    enum type_t { R_ARRAY = 1, R_BOOL = 2, R_NULL = 3,
                  R_NUM = 4, R_OBJECT = 5, R_STR = 6 };
    explicit datum_t(type_t _type);

    // These allow you to construct a datum from the type of value it
    // represents.  Note that the `bool` constructor is special to avoid nasty
    // pointer conversion bugs, and an undefined `bool` constructor is declared
    // to catch cases where people try to write `datum_t(true)` (which would
    // otherwise be converted to an `int`).
    explicit datum_t(bool _bool); // undefined, catches implicit conversion errors
    // Need to explicitly ask to construct a bool.
    datum_t(type_t _type, bool _bool);
    explicit datum_t(double _num);
    explicit datum_t(const std::string &_str);
    explicit datum_t(const char *cstr);
    explicit datum_t(const std::vector<const datum_t *> &_array);
    explicit datum_t(const std::map<const std::string, const datum_t *> &_object);

    // These construct a datum from an equivalent representation.
    explicit datum_t(const Datum *d); // Undefined, need to pass `env` below.
    datum_t(const Datum *d, env_t *env);
    explicit datum_t(cJSON *json);
    datum_t(cJSON *json, env_t *env);
    explicit datum_t(const boost::shared_ptr<scoped_cJSON_t> &json);
    datum_t(const boost::shared_ptr<scoped_cJSON_t> &json, env_t *env);

    void write_to_protobuf(Datum *out) const;

    type_t get_type() const;
    const char *get_type_name() const;
    std::string print() const;
    std::string print_primary() const;
    void check_type(type_t desired) const;

    bool as_bool() const;
    double as_num() const;
    int64_t as_int() const;
    const std::string &as_str() const;

    // Use of `size` and `el` is preferred to `as_array` when possible.
    const std::vector<const datum_t *> &as_array() const;
    void add(const datum_t *val); // add to an array
    size_t size() const;
    // Access an element of an array.
    const datum_t *el(size_t index, throw_bool_t throw_bool = THROW) const;

    // Use of `el` is preferred to `as_object` when possible.
    const std::map<const std::string, const datum_t *> &as_object() const;
    // Returns true if `key` was already in object.
    MUST_USE bool add(const std::string &key, const datum_t *val,
                      clobber_bool_t clobber_bool = NOCLOBBER); // add to an object
    // Returns true if key was in object.
    MUST_USE bool del(const std::string &key);
    // Access an element of an object.
    const datum_t *el(const std::string &key, throw_bool_t throw_bool = THROW) const;
    const datum_t *merge(const datum_t *rhs) const;
    typedef const datum_t *(*merge_res_f)(env_t *env, const std::string &key,
                                          const datum_t *l, const datum_t *r,
                                          const rcheckable_t *caller);
    const datum_t *merge(env_t *env, const datum_t *rhs, merge_res_f f) const;

    cJSON *as_raw_json() const;
    boost::shared_ptr<scoped_cJSON_t> as_json() const;
    datum_stream_t *as_datum_stream(env_t *env, const pb_rcheckable_t *bt_src) const;

    // These behave as expected and defined in RQL.  Theoretically, two data of
    // the same type should compare the same way their printed representations
    // would compare lexicographcally, while dispareate types are compared
    // alphabetically by type name.
    int cmp(const datum_t &rhs) const;
    bool operator==(const datum_t &rhs) const;
    bool operator!=(const datum_t &rhs) const;

    bool operator<(const datum_t &rhs) const;
    bool operator<=(const datum_t &rhs) const;
    bool operator>(const datum_t &rhs) const;
    bool operator>=(const datum_t &rhs) const;

    // Iterate through an object or array with a callback.  (The callback
    // returns whether or not to continue iterating.)  Used for e.g. garbage
    // collection.
    void iter(bool (*callback)(const datum_t *, env_t *), env_t *env) const;

    virtual void runtime_check(const char *test, const char *file, int line,
                               bool pred, std::string msg) const {
        ql::runtime_check(test, file, line, pred, msg);
    }
private:
    void init_json(cJSON *json, env_t *env);

    // TODO: fix later.  Listing everything is more debugging-friendly than a
    // boost::variant, but less efficient.
    type_t type;
    bool r_bool;
    double r_num;
    std::string r_str;
    std::vector<const datum_t *> r_array;
    std::map<const std::string, const datum_t *> r_object;
};

RDB_DECLARE_SERIALIZABLE(Datum);
// A `wire_datum_t` is necessary to serialize data over the wire.  See README.md
// for more info.
class wire_datum_t {
public:
    wire_datum_t() : ptr(0), state(INVALID) { }
    explicit wire_datum_t(const datum_t *_ptr) : ptr(_ptr), state(COMPILED) { }
    const datum_t *get() const;
    const datum_t *reset(const datum_t *ptr2);
    const datum_t *compile(env_t *env);

    void finalize();
private:
    const datum_t *ptr;
    Datum ptr_pb;

public:
    friend class write_message_t;
    void rdb_serialize(write_message_t &msg /* NOLINT */) const {
        r_sanity_check(state == READY_TO_WRITE);
        msg << ptr_pb;
    }
    friend class archive_deserializer_t;
    archive_result_t rdb_deserialize(read_stream_t *s) {
        archive_result_t res = deserialize(s, &ptr_pb);
        if (res) return res;
        state = JUST_READ;
        return ARCHIVE_SUCCESS;
    }

private:
    enum { INVALID, JUST_READ, COMPILED, READY_TO_WRITE } state;
};

// This is like a `wire_datum_t` but for gmr.  We need it because gmr allows
// non-strings as keys, while the data model we pinched from JSON doesn't.  See
// README.md for more info.
class wire_datum_map_t {
public:
    wire_datum_map_t() : state(COMPILED) { }
    bool has(const datum_t *key);
    const datum_t *get(const datum_t *key);
    void set(const datum_t *key, const datum_t *val);

    void compile(env_t *env);
    void finalize();

    const datum_t *to_arr(env_t *env) const;
private:
    struct datum_value_compare_t {
        bool operator()(const datum_t *a, const datum_t *b) const {
            return *a < *b;
        }
    };
    typedef std::map<const datum_t *, const datum_t *, datum_value_compare_t> map_t;
    map_t map;
    std::vector<std::pair<Datum, Datum> > map_pb;

public:
    friend class write_message_t;
    void rdb_serialize(write_message_t &msg /* NOLINT */) const {
        r_sanity_check(state == READY_TO_WRITE);
        msg << map_pb;
    }
    friend class archive_deserializer_t;
    archive_result_t rdb_deserialize(read_stream_t *s) {
        archive_result_t res = deserialize(s, &map_pb);
        if (res) return res;
        state = JUST_READ;
        return ARCHIVE_SUCCESS;
    }

private:
    enum { JUST_READ, COMPILED, READY_TO_WRITE } state;
};

} // namespace ql
#endif // RDB_PROTOCOL_DATUM_HPP_
<commit_msg>Made datum_t(int), datum_t(bool), datum_t(float) constructors deleted.<commit_after>#ifndef RDB_PROTOCOL_DATUM_HPP_
#define RDB_PROTOCOL_DATUM_HPP_
#include <map>
#include <string>
#include <utility>
#include <vector>

#include "utils.hpp"
#include <boost/shared_ptr.hpp>

#include "containers/archive/archive.hpp"
#include "containers/ptr_bag.hpp"
#include "http/json.hpp"
#include "rdb_protocol/err.hpp"

class Datum;

namespace ql {
class datum_stream_t;
class env_t;
class val_t;

// These let us write e.g. `foo(NOTHROW) instead of `foo(false/*nothrow*/)`.
// They should be passed to functions that have multiple behaviors (like `el` or
// `add` below).

// NOTHROW: Return NULL
// THROW: Throw an error
enum throw_bool_t { NOTHROW = 0, THROW = 1};

// NOCLOBBER: Don't overwrite existing values.
// CLOBBER: Overwrite existing values.
enum clobber_bool_t { NOCLOBBER = 0, CLOBBER = 1};

// A `datum_t` is basically a JSON value, although we may extend it later.
// TODO: When we optimize for memory, this needs to stop inheriting from `rcheckable_t`
class datum_t : public ptr_baggable_t, public rcheckable_t {
public:
    // This ordering is important, because we use it to sort objects of
    // disparate type.  It should be alphabetical.
    enum type_t { R_ARRAY = 1, R_BOOL = 2, R_NULL = 3,
                  R_NUM = 4, R_OBJECT = 5, R_STR = 6 };
    explicit datum_t(type_t _type);

    // These allow you to construct a datum from the type of value it
    // represents.  We have some gotchya-constructors to scare away implicit
    // conversions.
    explicit datum_t(bool) = delete;
    explicit datum_t(int) = delete;
    explicit datum_t(float) = delete;
    // Need to explicitly ask to construct a bool.
    datum_t(type_t _type, bool _bool);
    explicit datum_t(double _num);
    explicit datum_t(const std::string &_str);
    explicit datum_t(const char *cstr);
    explicit datum_t(const std::vector<const datum_t *> &_array);
    explicit datum_t(const std::map<const std::string, const datum_t *> &_object);

    // These construct a datum from an equivalent representation.
    explicit datum_t(const Datum *d); // Undefined, need to pass `env` below.
    datum_t(const Datum *d, env_t *env);
    explicit datum_t(cJSON *json);
    datum_t(cJSON *json, env_t *env);
    explicit datum_t(const boost::shared_ptr<scoped_cJSON_t> &json);
    datum_t(const boost::shared_ptr<scoped_cJSON_t> &json, env_t *env);

    void write_to_protobuf(Datum *out) const;

    type_t get_type() const;
    const char *get_type_name() const;
    std::string print() const;
    std::string print_primary() const;
    void check_type(type_t desired) const;

    bool as_bool() const;
    double as_num() const;
    int64_t as_int() const;
    const std::string &as_str() const;

    // Use of `size` and `el` is preferred to `as_array` when possible.
    const std::vector<const datum_t *> &as_array() const;
    void add(const datum_t *val); // add to an array
    size_t size() const;
    // Access an element of an array.
    const datum_t *el(size_t index, throw_bool_t throw_bool = THROW) const;

    // Use of `el` is preferred to `as_object` when possible.
    const std::map<const std::string, const datum_t *> &as_object() const;
    // Returns true if `key` was already in object.
    MUST_USE bool add(const std::string &key, const datum_t *val,
                      clobber_bool_t clobber_bool = NOCLOBBER); // add to an object
    // Returns true if key was in object.
    MUST_USE bool del(const std::string &key);
    // Access an element of an object.
    const datum_t *el(const std::string &key, throw_bool_t throw_bool = THROW) const;
    const datum_t *merge(const datum_t *rhs) const;
    typedef const datum_t *(*merge_res_f)(env_t *env, const std::string &key,
                                          const datum_t *l, const datum_t *r,
                                          const rcheckable_t *caller);
    const datum_t *merge(env_t *env, const datum_t *rhs, merge_res_f f) const;

    cJSON *as_raw_json() const;
    boost::shared_ptr<scoped_cJSON_t> as_json() const;
    datum_stream_t *as_datum_stream(env_t *env, const pb_rcheckable_t *bt_src) const;

    // These behave as expected and defined in RQL.  Theoretically, two data of
    // the same type should compare the same way their printed representations
    // would compare lexicographcally, while dispareate types are compared
    // alphabetically by type name.
    int cmp(const datum_t &rhs) const;
    bool operator==(const datum_t &rhs) const;
    bool operator!=(const datum_t &rhs) const;

    bool operator<(const datum_t &rhs) const;
    bool operator<=(const datum_t &rhs) const;
    bool operator>(const datum_t &rhs) const;
    bool operator>=(const datum_t &rhs) const;

    // Iterate through an object or array with a callback.  (The callback
    // returns whether or not to continue iterating.)  Used for e.g. garbage
    // collection.
    void iter(bool (*callback)(const datum_t *, env_t *), env_t *env) const;

    virtual void runtime_check(const char *test, const char *file, int line,
                               bool pred, std::string msg) const {
        ql::runtime_check(test, file, line, pred, msg);
    }
private:
    void init_json(cJSON *json, env_t *env);

    // TODO: fix later.  Listing everything is more debugging-friendly than a
    // boost::variant, but less efficient.
    type_t type;
    bool r_bool;
    double r_num;
    std::string r_str;
    std::vector<const datum_t *> r_array;
    std::map<const std::string, const datum_t *> r_object;
};

RDB_DECLARE_SERIALIZABLE(Datum);
// A `wire_datum_t` is necessary to serialize data over the wire.  See README.md
// for more info.
class wire_datum_t {
public:
    wire_datum_t() : ptr(0), state(INVALID) { }
    explicit wire_datum_t(const datum_t *_ptr) : ptr(_ptr), state(COMPILED) { }
    const datum_t *get() const;
    const datum_t *reset(const datum_t *ptr2);
    const datum_t *compile(env_t *env);

    void finalize();
private:
    const datum_t *ptr;
    Datum ptr_pb;

public:
    friend class write_message_t;
    void rdb_serialize(write_message_t &msg /* NOLINT */) const {
        r_sanity_check(state == READY_TO_WRITE);
        msg << ptr_pb;
    }
    friend class archive_deserializer_t;
    archive_result_t rdb_deserialize(read_stream_t *s) {
        archive_result_t res = deserialize(s, &ptr_pb);
        if (res) return res;
        state = JUST_READ;
        return ARCHIVE_SUCCESS;
    }

private:
    enum { INVALID, JUST_READ, COMPILED, READY_TO_WRITE } state;
};

// This is like a `wire_datum_t` but for gmr.  We need it because gmr allows
// non-strings as keys, while the data model we pinched from JSON doesn't.  See
// README.md for more info.
class wire_datum_map_t {
public:
    wire_datum_map_t() : state(COMPILED) { }
    bool has(const datum_t *key);
    const datum_t *get(const datum_t *key);
    void set(const datum_t *key, const datum_t *val);

    void compile(env_t *env);
    void finalize();

    const datum_t *to_arr(env_t *env) const;
private:
    struct datum_value_compare_t {
        bool operator()(const datum_t *a, const datum_t *b) const {
            return *a < *b;
        }
    };
    typedef std::map<const datum_t *, const datum_t *, datum_value_compare_t> map_t;
    map_t map;
    std::vector<std::pair<Datum, Datum> > map_pb;

public:
    friend class write_message_t;
    void rdb_serialize(write_message_t &msg /* NOLINT */) const {
        r_sanity_check(state == READY_TO_WRITE);
        msg << map_pb;
    }
    friend class archive_deserializer_t;
    archive_result_t rdb_deserialize(read_stream_t *s) {
        archive_result_t res = deserialize(s, &map_pb);
        if (res) return res;
        state = JUST_READ;
        return ARCHIVE_SUCCESS;
    }

private:
    enum { JUST_READ, COMPILED, READY_TO_WRITE } state;
};

} // namespace ql
#endif // RDB_PROTOCOL_DATUM_HPP_
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/client/local_client.h"

#include <utility>

#include "absl/memory/memory.h"
#include "llvm/ADT/Triple.h"
#include "tensorflow/compiler/xla/client/xla_computation.h"
#include "tensorflow/compiler/xla/service/backend.h"
#include "tensorflow/compiler/xla/service/service_executable_run_options.h"
#include "tensorflow/compiler/xla/service/source_map_util.h"
#include "tensorflow/compiler/xla/service/stream_pool.h"
#include "tensorflow/compiler/xla/status_macros.h"

using xla::source_map_util::InvalidParameterArgument;

namespace xla {

namespace {
StatusOr<StreamPool::Ptr> BorrowStreamForDevice(int device_ordinal,
                                                Backend* backend) {
  if (device_ordinal < 0) {
    device_ordinal = backend->default_device_ordinal();
  }
  return backend->BorrowStream(device_ordinal);
}
}  // namespace

LocalExecutable::LocalExecutable(std::unique_ptr<Executable> executable,
                                 Backend* backend,
                                 ExecutableBuildOptions build_options)
    : executable_(std::move(executable)),
      backend_(backend),
      build_options_(std::move(build_options)) {
  CHECK_GE(build_options_.device_ordinal(), 0)
      << "Must have a valid device ordinal that the executable was built for.";
}

Status LocalExecutable::ValidateExecutionOptions(
    const absl::Span<const ShapedBuffer* const> arguments,
    const ExecutableRunOptions& run_options, const Backend& backend) {
  const ComputationLayout& computation_layout =
      executable_->module_config().entry_computation_layout();

  // Check argument number, shapes, and layouts.
  if (arguments.size() != computation_layout.parameter_count()) {
    return InvalidArgument(
        "invalid number of arguments for computation: expected %d, got %u",
        computation_layout.parameter_count(), arguments.size());
  }
  for (int i = 0; i < arguments.size(); ++i) {
    if (!computation_layout.parameter_layout(i).MatchesLayoutInShape(
            arguments[i]->on_host_shape())) {
      return InvalidParameterArgument(
          executable_.get(), i,
          "Argument does not match host shape or layout of computation "
          "parameter "
          "%d: want %s, got %s",
          i,
          ShapeUtil::HumanString(
              computation_layout.parameter_layout(i).shape()),
          ShapeUtil::HumanString(arguments[i]->on_host_shape()));
    }
  }

  if (run_options.stream() != nullptr) {
    if (!run_options.stream()->ok()) {
      return InvalidArgument("stream is uninitialized or in an error state");
    }

    // Check stream matches service platform.
    const se::Platform* stream_platform =
        run_options.stream()->parent()->platform();
    if (stream_platform != backend_->platform()) {
      return InvalidArgument(
          "stream is for platform %s, but service targets platform %s",
          stream_platform->Name(), backend_->platform()->Name());
    }

    // Cannot specify device_ordinal with a stream. The stream determines these
    // values.
    if (run_options.device_ordinal() != -1) {
      return InvalidArgument(
          "cannot set both device ordinal and stream options in "
          "ExecutableRunOptions; the stream determines the device ordinal");
    }
  }

  // Verify that the device the executable was built for is equivalent
  // to the device it will run on.
  int run_device_ordinal = run_options.device_ordinal();
  if (run_device_ordinal == -1) {
    run_device_ordinal = run_options.stream() != nullptr
                             ? run_options.stream()->parent()->device_ordinal()
                             : backend_->default_device_ordinal();
  }
  TF_ASSIGN_OR_RETURN(bool devices_equivalent,
                      backend_->devices_equivalent(
                          run_device_ordinal, build_options_.device_ordinal()));
  if (!devices_equivalent) {
    TF_ASSIGN_OR_RETURN(se::StreamExecutor * run_executor,
                        backend_->stream_executor(run_device_ordinal));
    TF_ASSIGN_OR_RETURN(se::StreamExecutor * build_executor,
                        backend_->stream_executor(build_device_ordinal()));
    return InvalidArgument(
        "executable is built for device %s of type \"%s\"; cannot run it on "
        "device %s of type \"%s\"",
        backend_->device_name(build_device_ordinal()),
        build_executor->GetDeviceDescription().name(),
        backend_->device_name(run_device_ordinal),
        run_executor->GetDeviceDescription().name());
  }

  if (!run_options.allocator()) {
    return InvalidArgument("an allocator must be provided to ExecuteLocally");
  }

  if (run_options.allocator()->platform() != backend.platform()) {
    return InvalidArgument(
        "allocator platform (%s) does not match service platform (%s)",
        run_options.allocator()->platform()->Name(),
        backend.platform()->Name());
  }

  return Status::OK();
}

StatusOr<ScopedShapedBuffer> LocalExecutable::Run(
    const absl::Span<const ShapedBuffer* const> arguments,
    ExecutableRunOptions run_options) {
  TF_RETURN_IF_ERROR(
      ValidateExecutionOptions(arguments, run_options, *backend_));

  StreamPool::Ptr stream;
  if (run_options.stream() == nullptr) {
    // NB!  The lifetime of `stream` needs to match the lifetime of
    // `actual_options` (otherwise we will end up using a returned stream in
    // ExecuteOnStreamWrapper), which is why it isn't declared in the inner "if"
    // scope.
    TF_ASSIGN_OR_RETURN(
        stream, BorrowStreamForDevice(run_options.device_ordinal(), backend_));
    run_options.set_stream(stream.get());
  }
  if (run_options.allocator() == nullptr) {
    run_options.set_allocator(backend_->memory_allocator());
  }

  // For local client execution on CPU backends:
  // *) The thread pool used for eigen CPU ops is from
  //    ExecutableRunOptions.eigen_intra_op_thread_pool.
  // *) The thread pool used for XLA CPU ops is from
  //    backend_->eigen_intra_op_thread_pool().
  ServiceExecutableRunOptions service_options(
      run_options, backend_->StreamBorrower(),
      backend_->eigen_intra_op_thread_pool());

  if (executable_->dumping_snapshot()) {
    return ExecuteAndDump(&service_options, arguments);
  }
  return executable_->ExecuteOnStreamWrapper(
      &service_options, run_options.execution_profile(), arguments);
}

StatusOr<ScopedShapedBuffer> LocalExecutable::ExecuteAndDump(
    const ServiceExecutableRunOptions* run_options,
    const absl::Span<const ShapedBuffer* const> arguments) {
  executable_->hlo_snapshot()->set_execution_platform(
      backend_->platform()->Name());
  TF_RETURN_IF_ERROR(RecordArguments(arguments, executable_->hlo_snapshot()));
  TF_ASSIGN_OR_RETURN(
      ScopedShapedBuffer result,
      executable_->ExecuteOnStream(run_options, arguments,
                                   /*hlo_execution_profile=*/nullptr));
  TF_RETURN_IF_ERROR(RecordResult(&result, executable_->hlo_snapshot()));
  TF_RETURN_IF_ERROR(executable_->DumpHloSnapshot());
  return std::move(result);
}

Status LocalExecutable::RecordArguments(
    const absl::Span<const ShapedBuffer* const> arguments,
    HloSnapshot* hlo_snapshot) {
  hlo_snapshot->clear_arguments();
  for (const ShapedBuffer* argument : arguments) {
    TF_ASSIGN_OR_RETURN(Literal literal, LiteralFromShapedBuffer(*argument));
    *hlo_snapshot->add_arguments() = literal.ToProto();
  }
  return Status::OK();
}

Status LocalExecutable::RecordResult(const ShapedBuffer* result,
                                     HloSnapshot* hlo_snapshot) {
  hlo_snapshot->clear_result();
  TF_ASSIGN_OR_RETURN(Literal literal, LiteralFromShapedBuffer(*result));
  *hlo_snapshot->mutable_result() = literal.ToProto();
  return Status::OK();
}

StatusOr<Literal> LocalExecutable::LiteralFromShapedBuffer(
    const ShapedBuffer& shaped_buffer) {
  TF_ASSIGN_OR_RETURN(auto stream,
                      backend_->BorrowStream(shaped_buffer.device_ordinal()));
  return backend_->transfer_manager()->TransferLiteralFromDevice(stream.get(),
                                                                 shaped_buffer);
}

se::Platform* LocalClient::platform() const {
  return local_service_->backend().platform();
}

int LocalClient::device_count() const {
  return local_service_->backend().device_count();
}

bool LocalClient::device_ordinal_supported(int device_ordinal) const {
  return local_service_->backend().device_ordinal_supported(device_ordinal);
}

int LocalClient::default_device_ordinal() const {
  return local_service_->backend().default_device_ordinal();
}

const Backend& LocalClient::backend() const {
  return local_service_->backend();
}

Backend* LocalClient::mutable_backend() {
  return local_service_->mutable_backend();
}

StatusOr<std::unique_ptr<LocalExecutable>> LocalClient::Compile(
    const XlaComputation& computation,
    const absl::Span<const Shape* const> argument_layouts,
    const ExecutableBuildOptions& options) {
  ExecutableBuildOptions updated_options = options;
  if (options.device_ordinal() == -1) {
    updated_options.set_device_ordinal(default_device_ordinal());
    VLOG(3) << "Set device ordinal to default value of: "
            << updated_options.device_ordinal();
  }
  TF_ASSIGN_OR_RETURN(std::unique_ptr<Executable> executable,
                      local_service_->CompileExecutable(
                          computation, argument_layouts, updated_options));
  return absl::WrapUnique(new LocalExecutable(std::move(executable),
                                              local_service_->mutable_backend(),
                                              updated_options));
}

StatusOr<ScopedShapedBuffer> LocalClient::LiteralToShapedBuffer(
    const Literal& literal, int device_ordinal,
    DeviceMemoryAllocator* allocator) {
  if (allocator == nullptr) {
    allocator = backend().memory_allocator();
  }
  TF_ASSIGN_OR_RETURN(auto scoped_buffer,
                      backend().transfer_manager()->AllocateScopedShapedBuffer(
                          literal.shape(), allocator, device_ordinal));
  TF_ASSIGN_OR_RETURN(auto stream,
                      mutable_backend()->BorrowStream(device_ordinal));
  TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralToDevice(
      stream.get(), literal, scoped_buffer));
  return std::move(scoped_buffer);
}

StatusOr<Literal> LocalClient::ShapedBufferToLiteral(
    const ShapedBuffer& shaped_buffer) {
  TF_ASSIGN_OR_RETURN(auto stream, mutable_backend()->BorrowStream(
                                       shaped_buffer.device_ordinal()));
  return backend().transfer_manager()->TransferLiteralFromDevice(stream.get(),
                                                                 shaped_buffer);
}

StatusOr<const ShapedBuffer*> LocalClient::GlobalDataToShapedBuffer(
    const GlobalDataHandle& data, int replica_number) {
  return local_service_->GlobalDataToShapedBuffer(data, replica_number);
}

Status LocalClient::TransferToInfeedLocal(const Literal& literal,
                                          int device_ordinal) {
  TF_ASSIGN_OR_RETURN(se::StreamExecutor * executor,
                      backend().stream_executor(device_ordinal));
  return backend().transfer_manager()->TransferLiteralToInfeed(executor,
                                                               literal);
}

StatusOr<Literal> LocalClient::TransferFromOutfeedLocal(const Shape& shape,
                                                        int device_ordinal) {
  TF_ASSIGN_OR_RETURN(se::StreamExecutor * executor,
                      backend().stream_executor(device_ordinal));
  auto literal = Literal::CreateFromShape(shape);
  TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralFromOutfeed(
      executor, shape, &literal));
  return std::move(literal);
}

StatusOr<int> LocalClient::ReplicaNumberToDeviceOrdinal(int replica_number) {
  return local_service_->ReplicaNumberToDeviceOrdinal(replica_number);
}

StatusOr<TransferToServerResponse> LocalClient::TransferToLocalServer(
    const ::xla::BorrowingLiteral& literal, int device_oridinal) {
  const ::xla::Shape& shape = literal.shape();

  TF_ASSIGN_OR_RETURN(
      ::xla::ScopedShapedBuffer shaped_buffer,
      backend().transfer_manager()->AllocateScopedShapedBuffer(
          shape, backend().memory_allocator(), device_oridinal));
  TF_ASSIGN_OR_RETURN(auto stream,
                      mutable_backend()->BorrowStream(device_oridinal));
  TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralToDevice(
      stream.get(), literal, shaped_buffer));
  std::vector<::xla::ScopedShapedBuffer> replicated_buffer;
  replicated_buffer.emplace_back(std::move(shaped_buffer));
  ::xla::TransferToServerResponse result;
  TF_ASSIGN_OR_RETURN(*result.mutable_data(),
                      local_service_->RegisterReplicatedBuffers(
                          std::move(replicated_buffer),
                          absl::StrCat("TransferToServer literal of shape ",
                                       ::xla::ShapeUtil::HumanString(shape))));

  return result;
}

}  // namespace xla
<commit_msg>[XLA] Print out shapes' layouts in local_client's "shape/layout doesn't match" error.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/client/local_client.h"

#include <utility>

#include "absl/memory/memory.h"
#include "llvm/ADT/Triple.h"
#include "tensorflow/compiler/xla/client/xla_computation.h"
#include "tensorflow/compiler/xla/service/backend.h"
#include "tensorflow/compiler/xla/service/service_executable_run_options.h"
#include "tensorflow/compiler/xla/service/source_map_util.h"
#include "tensorflow/compiler/xla/service/stream_pool.h"
#include "tensorflow/compiler/xla/status_macros.h"

using xla::source_map_util::InvalidParameterArgument;

namespace xla {

namespace {
StatusOr<StreamPool::Ptr> BorrowStreamForDevice(int device_ordinal,
                                                Backend* backend) {
  if (device_ordinal < 0) {
    device_ordinal = backend->default_device_ordinal();
  }
  return backend->BorrowStream(device_ordinal);
}
}  // namespace

LocalExecutable::LocalExecutable(std::unique_ptr<Executable> executable,
                                 Backend* backend,
                                 ExecutableBuildOptions build_options)
    : executable_(std::move(executable)),
      backend_(backend),
      build_options_(std::move(build_options)) {
  CHECK_GE(build_options_.device_ordinal(), 0)
      << "Must have a valid device ordinal that the executable was built for.";
}

Status LocalExecutable::ValidateExecutionOptions(
    const absl::Span<const ShapedBuffer* const> arguments,
    const ExecutableRunOptions& run_options, const Backend& backend) {
  const ComputationLayout& computation_layout =
      executable_->module_config().entry_computation_layout();

  // Check argument number, shapes, and layouts.
  if (arguments.size() != computation_layout.parameter_count()) {
    return InvalidArgument(
        "invalid number of arguments for computation: expected %d, got %u",
        computation_layout.parameter_count(), arguments.size());
  }
  for (int i = 0; i < arguments.size(); ++i) {
    if (!computation_layout.parameter_layout(i).MatchesLayoutInShape(
            arguments[i]->on_host_shape())) {
      return InvalidParameterArgument(
          executable_.get(), i,
          "Argument does not match host shape or layout of computation "
          "parameter "
          "%d: want %s, got %s",
          i,
          ShapeUtil::HumanStringWithLayout(
              computation_layout.parameter_layout(i).shape()),
          ShapeUtil::HumanStringWithLayout(arguments[i]->on_host_shape()));
    }
  }

  if (run_options.stream() != nullptr) {
    if (!run_options.stream()->ok()) {
      return InvalidArgument("stream is uninitialized or in an error state");
    }

    // Check stream matches service platform.
    const se::Platform* stream_platform =
        run_options.stream()->parent()->platform();
    if (stream_platform != backend_->platform()) {
      return InvalidArgument(
          "stream is for platform %s, but service targets platform %s",
          stream_platform->Name(), backend_->platform()->Name());
    }

    // Cannot specify device_ordinal with a stream. The stream determines these
    // values.
    if (run_options.device_ordinal() != -1) {
      return InvalidArgument(
          "cannot set both device ordinal and stream options in "
          "ExecutableRunOptions; the stream determines the device ordinal");
    }
  }

  // Verify that the device the executable was built for is equivalent
  // to the device it will run on.
  int run_device_ordinal = run_options.device_ordinal();
  if (run_device_ordinal == -1) {
    run_device_ordinal = run_options.stream() != nullptr
                             ? run_options.stream()->parent()->device_ordinal()
                             : backend_->default_device_ordinal();
  }
  TF_ASSIGN_OR_RETURN(bool devices_equivalent,
                      backend_->devices_equivalent(
                          run_device_ordinal, build_options_.device_ordinal()));
  if (!devices_equivalent) {
    TF_ASSIGN_OR_RETURN(se::StreamExecutor * run_executor,
                        backend_->stream_executor(run_device_ordinal));
    TF_ASSIGN_OR_RETURN(se::StreamExecutor * build_executor,
                        backend_->stream_executor(build_device_ordinal()));
    return InvalidArgument(
        "executable is built for device %s of type \"%s\"; cannot run it on "
        "device %s of type \"%s\"",
        backend_->device_name(build_device_ordinal()),
        build_executor->GetDeviceDescription().name(),
        backend_->device_name(run_device_ordinal),
        run_executor->GetDeviceDescription().name());
  }

  if (!run_options.allocator()) {
    return InvalidArgument("an allocator must be provided to ExecuteLocally");
  }

  if (run_options.allocator()->platform() != backend.platform()) {
    return InvalidArgument(
        "allocator platform (%s) does not match service platform (%s)",
        run_options.allocator()->platform()->Name(),
        backend.platform()->Name());
  }

  return Status::OK();
}

StatusOr<ScopedShapedBuffer> LocalExecutable::Run(
    const absl::Span<const ShapedBuffer* const> arguments,
    ExecutableRunOptions run_options) {
  TF_RETURN_IF_ERROR(
      ValidateExecutionOptions(arguments, run_options, *backend_));

  StreamPool::Ptr stream;
  if (run_options.stream() == nullptr) {
    // NB!  The lifetime of `stream` needs to match the lifetime of
    // `actual_options` (otherwise we will end up using a returned stream in
    // ExecuteOnStreamWrapper), which is why it isn't declared in the inner "if"
    // scope.
    TF_ASSIGN_OR_RETURN(
        stream, BorrowStreamForDevice(run_options.device_ordinal(), backend_));
    run_options.set_stream(stream.get());
  }
  if (run_options.allocator() == nullptr) {
    run_options.set_allocator(backend_->memory_allocator());
  }

  // For local client execution on CPU backends:
  // *) The thread pool used for eigen CPU ops is from
  //    ExecutableRunOptions.eigen_intra_op_thread_pool.
  // *) The thread pool used for XLA CPU ops is from
  //    backend_->eigen_intra_op_thread_pool().
  ServiceExecutableRunOptions service_options(
      run_options, backend_->StreamBorrower(),
      backend_->eigen_intra_op_thread_pool());

  if (executable_->dumping_snapshot()) {
    return ExecuteAndDump(&service_options, arguments);
  }
  return executable_->ExecuteOnStreamWrapper(
      &service_options, run_options.execution_profile(), arguments);
}

StatusOr<ScopedShapedBuffer> LocalExecutable::ExecuteAndDump(
    const ServiceExecutableRunOptions* run_options,
    const absl::Span<const ShapedBuffer* const> arguments) {
  executable_->hlo_snapshot()->set_execution_platform(
      backend_->platform()->Name());
  TF_RETURN_IF_ERROR(RecordArguments(arguments, executable_->hlo_snapshot()));
  TF_ASSIGN_OR_RETURN(
      ScopedShapedBuffer result,
      executable_->ExecuteOnStream(run_options, arguments,
                                   /*hlo_execution_profile=*/nullptr));
  TF_RETURN_IF_ERROR(RecordResult(&result, executable_->hlo_snapshot()));
  TF_RETURN_IF_ERROR(executable_->DumpHloSnapshot());
  return std::move(result);
}

Status LocalExecutable::RecordArguments(
    const absl::Span<const ShapedBuffer* const> arguments,
    HloSnapshot* hlo_snapshot) {
  hlo_snapshot->clear_arguments();
  for (const ShapedBuffer* argument : arguments) {
    TF_ASSIGN_OR_RETURN(Literal literal, LiteralFromShapedBuffer(*argument));
    *hlo_snapshot->add_arguments() = literal.ToProto();
  }
  return Status::OK();
}

Status LocalExecutable::RecordResult(const ShapedBuffer* result,
                                     HloSnapshot* hlo_snapshot) {
  hlo_snapshot->clear_result();
  TF_ASSIGN_OR_RETURN(Literal literal, LiteralFromShapedBuffer(*result));
  *hlo_snapshot->mutable_result() = literal.ToProto();
  return Status::OK();
}

StatusOr<Literal> LocalExecutable::LiteralFromShapedBuffer(
    const ShapedBuffer& shaped_buffer) {
  TF_ASSIGN_OR_RETURN(auto stream,
                      backend_->BorrowStream(shaped_buffer.device_ordinal()));
  return backend_->transfer_manager()->TransferLiteralFromDevice(stream.get(),
                                                                 shaped_buffer);
}

se::Platform* LocalClient::platform() const {
  return local_service_->backend().platform();
}

int LocalClient::device_count() const {
  return local_service_->backend().device_count();
}

bool LocalClient::device_ordinal_supported(int device_ordinal) const {
  return local_service_->backend().device_ordinal_supported(device_ordinal);
}

int LocalClient::default_device_ordinal() const {
  return local_service_->backend().default_device_ordinal();
}

const Backend& LocalClient::backend() const {
  return local_service_->backend();
}

Backend* LocalClient::mutable_backend() {
  return local_service_->mutable_backend();
}

StatusOr<std::unique_ptr<LocalExecutable>> LocalClient::Compile(
    const XlaComputation& computation,
    const absl::Span<const Shape* const> argument_layouts,
    const ExecutableBuildOptions& options) {
  ExecutableBuildOptions updated_options = options;
  if (options.device_ordinal() == -1) {
    updated_options.set_device_ordinal(default_device_ordinal());
    VLOG(3) << "Set device ordinal to default value of: "
            << updated_options.device_ordinal();
  }
  TF_ASSIGN_OR_RETURN(std::unique_ptr<Executable> executable,
                      local_service_->CompileExecutable(
                          computation, argument_layouts, updated_options));
  return absl::WrapUnique(new LocalExecutable(std::move(executable),
                                              local_service_->mutable_backend(),
                                              updated_options));
}

StatusOr<ScopedShapedBuffer> LocalClient::LiteralToShapedBuffer(
    const Literal& literal, int device_ordinal,
    DeviceMemoryAllocator* allocator) {
  if (allocator == nullptr) {
    allocator = backend().memory_allocator();
  }
  TF_ASSIGN_OR_RETURN(auto scoped_buffer,
                      backend().transfer_manager()->AllocateScopedShapedBuffer(
                          literal.shape(), allocator, device_ordinal));
  TF_ASSIGN_OR_RETURN(auto stream,
                      mutable_backend()->BorrowStream(device_ordinal));
  TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralToDevice(
      stream.get(), literal, scoped_buffer));
  return std::move(scoped_buffer);
}

StatusOr<Literal> LocalClient::ShapedBufferToLiteral(
    const ShapedBuffer& shaped_buffer) {
  TF_ASSIGN_OR_RETURN(auto stream, mutable_backend()->BorrowStream(
                                       shaped_buffer.device_ordinal()));
  return backend().transfer_manager()->TransferLiteralFromDevice(stream.get(),
                                                                 shaped_buffer);
}

StatusOr<const ShapedBuffer*> LocalClient::GlobalDataToShapedBuffer(
    const GlobalDataHandle& data, int replica_number) {
  return local_service_->GlobalDataToShapedBuffer(data, replica_number);
}

Status LocalClient::TransferToInfeedLocal(const Literal& literal,
                                          int device_ordinal) {
  TF_ASSIGN_OR_RETURN(se::StreamExecutor * executor,
                      backend().stream_executor(device_ordinal));
  return backend().transfer_manager()->TransferLiteralToInfeed(executor,
                                                               literal);
}

StatusOr<Literal> LocalClient::TransferFromOutfeedLocal(const Shape& shape,
                                                        int device_ordinal) {
  TF_ASSIGN_OR_RETURN(se::StreamExecutor * executor,
                      backend().stream_executor(device_ordinal));
  auto literal = Literal::CreateFromShape(shape);
  TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralFromOutfeed(
      executor, shape, &literal));
  return std::move(literal);
}

StatusOr<int> LocalClient::ReplicaNumberToDeviceOrdinal(int replica_number) {
  return local_service_->ReplicaNumberToDeviceOrdinal(replica_number);
}

StatusOr<TransferToServerResponse> LocalClient::TransferToLocalServer(
    const ::xla::BorrowingLiteral& literal, int device_oridinal) {
  const ::xla::Shape& shape = literal.shape();

  TF_ASSIGN_OR_RETURN(
      ::xla::ScopedShapedBuffer shaped_buffer,
      backend().transfer_manager()->AllocateScopedShapedBuffer(
          shape, backend().memory_allocator(), device_oridinal));
  TF_ASSIGN_OR_RETURN(auto stream,
                      mutable_backend()->BorrowStream(device_oridinal));
  TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralToDevice(
      stream.get(), literal, shaped_buffer));
  std::vector<::xla::ScopedShapedBuffer> replicated_buffer;
  replicated_buffer.emplace_back(std::move(shaped_buffer));
  ::xla::TransferToServerResponse result;
  TF_ASSIGN_OR_RETURN(*result.mutable_data(),
                      local_service_->RegisterReplicatedBuffers(
                          std::move(replicated_buffer),
                          absl::StrCat("TransferToServer literal of shape ",
                                       ::xla::ShapeUtil::HumanString(shape))));

  return result;
}

}  // namespace xla
<|endoftext|>


<commit_before>#include "sapsi.h"

void server_routine(uint32_t nclients, CSocket* socket, bool cardinality) {
	//cout << "Starting server for " << nclients << " clients on address " << address << ":" << port << endl;

	CSocket* sockfds = socket;//(CSocket*) malloc(sizeof(CSocket) * nclients);
	uint32_t* neles = (uint32_t*) malloc(sizeof(uint32_t) * nclients);
	uint8_t** csets = (uint8_t**) malloc(sizeof(uint8_t*) * nclients);
	uint32_t temp, maskbytelen, intersectsize, minset, i, j;
	CBitVector* intersection = new CBitVector[nclients];

#ifndef BATCH
	cout << "Connections with all " << nclients << " clients established" << endl;
#endif

	/* Receive the input sizes and bit lengths for all clients */
	for(i = 0; i < nclients; i++) {
		sockfds[i].Receive(neles+i, sizeof(uint32_t));
		sockfds[i].Receive(&temp, sizeof(uint32_t));
		if(i == 0) { maskbytelen = temp; minset = neles[i];}
		if(neles[i] < minset) minset = neles[i];
#ifndef BATCH
		cout << "Client " << i << " holds " << neles[i] << " elements of length " << (temp * 8) << "-bit" << endl;
#endif
		intersection[i].ResizeinBytes(ceil_divide(neles[i], 8));
		intersection[i].Reset();
		assert(maskbytelen == temp);

	}
#ifndef BATCH
	cout <<"Receiving the client's elements" << endl;
#endif

	/* Receive the permuted and masked sets of all clients */
	for(i = 0; i < nclients; i++) {
		temp = sizeof(uint8_t) * neles[i] * maskbytelen;
		csets[i] = (uint8_t*) malloc(temp);
		sockfds[i].Receive(csets[i], temp);
	}
#ifndef BATCH
	cout << "Computing intersection for the clients" << endl;
#endif
	/* Compute Intersection */
	intersectsize = compute_intersection(nclients, neles, csets, intersection, maskbytelen);

	/* Enter at which position an intersection was found */
#ifndef BATCH
	cout << "sending all " << intersectsize << " intersecting elements to the clients" << endl;
#endif
	/* Send the intersection size and intersecting elements to all clients */
	for(i = 0; i < nclients; i++) {
		sockfds[i].Send(&intersectsize, sizeof(uint32_t));
		if(!cardinality)
			sockfds[i].Send(intersection[i].GetArr(), ceil_divide(neles[i], 8));
	}

	/* Cleanup */
	free(neles);
}

/*
 * compute the intersection using a hash table - is optimized for the two-party case,
 * for the n-party case a BF-based approach makes more sense.
 */
//TODO currently only works for 128 bit masks
uint32_t compute_intersection(uint32_t nclients, uint32_t* neles, uint8_t** csets, CBitVector* intersection, uint32_t entrybytelen) {
    // Create the GHashTable
    GHashTable *map = NULL, *tmpmap = NULL;
    GHashTableIter iter;
	timeval begin, end;

    map = g_hash_table_new_full(
    		g_int64_hash, g_int64_equal,
		    NULL, // no cleanup for key
		    NULL // cleanup value
		    );

    uint32_t i, j, intersectsize, ctr = 0, k;
    uint64_t* tmpval;
    uint64_t* tmpkey = (uint64_t*) malloc(sizeof(uint64_t));
    uint64_t* query;
#ifndef BATCH
    cout << "Inserting the items into the hash table " << endl;
#endif
    gettimeofday(&begin, NULL);
    for(i=0;i<neles[0];i++) {
#ifdef DEBUG
    	cout << "Inserted item: " << (hex) << ((uint64_t*) csets[0])[2*i] << " "<< ((uint64_t*) csets[0])[2*i+1] << (dec) << endl;
#endif
    	tmpval = (uint64_t*) malloc(2*sizeof(uint64_t));
    	tmpval[0] = (((uint64_t*)csets[0])[2*i+1]);
    	tmpval[1] = i;
	    g_hash_table_insert(map,(void*) &((uint64_t*)csets[0])[2*i], tmpval);//&(((uint64_t*)csets[0])[2*i+1]));
    }
#ifdef DEBUG
    g_hash_table_foreach( map, printKeyValue, NULL );
#endif
    gettimeofday(&end, NULL);
#ifdef TIMING
    cout << "Insertion took " << getMillies(begin, end) << " ms" << endl;
#endif
    gettimeofday(&begin, NULL);

#ifdef DEBUG
    cout << "Checking for duplicates " << endl;
#endif
    for(i = 1; i < nclients; i++) {
    	tmpmap = g_hash_table_new_full(
    			g_int64_hash, g_int64_equal,
    		    NULL, // no cleanup for key
    		    NULL // cleanup value
    		    );
    	for(j = 0; j < neles[i]; j++) {
#ifdef DEBUG
    		cout << "Checking for Key: " << (hex) << ((uint64_t*) csets[i])[2*j] << " "<< ((uint64_t*) csets[i])[2*j+1] << (dec) << endl;
#endif
    		if(g_hash_table_lookup_extended(map, (void*) &(((uint64_t*)csets[i])[2*j]),
    				NULL, (void**) &query) && (*query == ((uint64_t*)csets[i])[2*j+1])) {
#ifdef DEBUG
    			cout << "Key was found" << endl;
#endif
    	    	tmpval = (uint64_t*) malloc((i+2)*sizeof(uint64_t));
    	    	tmpval[0] = (((uint64_t*)csets[i])[2*j+1]);
    	    	for(k = 1; k < i+1; k++) {
    	    		tmpval[k] = query[k];
    	    	}
    	    	tmpval[i+1] = j;
    			g_hash_table_insert(tmpmap,(void*) &(((uint64_t*)csets[i])[2*j]), tmpval);//&(((uint64_t*)csets[i])[2*j+1]));

    		} else {
#ifdef DEBUG
    			cout << "Key not found" << endl;
#endif
    		}
    	}
    	//Delete map
    	g_hash_table_destroy(map);
    	map = tmpmap;
    }
    gettimeofday(&end, NULL);
#ifdef TIMING
    cout << "Checking took " << getMillies(begin, end) << " ms" << endl;
#endif
    gettimeofday(&begin, NULL);

    intersectsize = g_hash_table_size(map);

    //intersect = (uint8_t*) malloc(sizeof(uint8_t) * intersectsize * entrybytelen);

#ifdef DEBUG
    cout << "Intersection contains the elements: " << endl;
#endif
    g_hash_table_iter_init (&iter, map);
    //Iterate over all key / element pairs and store them in the intersection
    while(g_hash_table_iter_next (&iter, (void**) &tmpkey, (void**) &tmpval)) {
#ifdef DEBUG
    	cout << (hex) << tmpkey[0] << " " << tmpval[0] << (dec)<< endl;
#endif
    	for(i = 0; i < nclients; i++) {
    		intersection[i].SetBit(tmpval[i+1], 1);
    	}
    }
    gettimeofday(&end, NULL);
#ifdef TIMING
    cout << "Iterating took " << getMillies(begin, end) << " ms" << endl;
#endif

    g_hash_table_destroy(map);

    //free(tmpval);
    //free(tmpkey);
#ifdef DEBUG
    cout << "returning" << endl;
#endif
	return intersectsize;
}

uint32_t client_routine(uint32_t neles, task_ctx ectx, uint32_t* matches,
		crypto* crypt_env, CSocket* socket, uint32_t ntasks, bool cardinality) {
	uint32_t maskbytelen, intersectsize, i, matchctr;

	uint8_t* masks;
	uint32_t *perm, *invperm;
	CBitVector inIntersection(neles);

	//TODO works only fine for equally sized sets, if one set is bigger than the other, this will fail!
	maskbytelen = 16;//ceil_divide(crypt_env->get_seclvl().statbits + 2*ceil_log2(neles), 8);

	masks = (uint8_t*) malloc(sizeof(uint8_t) * neles * maskbytelen);
	perm  = (uint32_t*) malloc(sizeof(uint32_t) * neles);
	invperm = (uint32_t*) malloc(sizeof(uint32_t) * neles);

	/* Generate the random permutation the elements */
	crypt_env->gen_rnd_perm(perm, neles);

	socket->Send((uint8_t*) &neles, sizeof(uint32_t));
	socket->Send((uint8_t*) &maskbytelen, sizeof(uint32_t));

	ectx.eles.outbytelen = maskbytelen,
	ectx.eles.nelements = neles;
	ectx.eles.output = masks;
	ectx.eles.perm = perm;
	ectx.sctx.symcrypt = crypt_env;
	ectx.sctx.keydata = (uint8_t*) const_seed;

	run_task(ntasks, ectx, hash);

	socket->Send(masks, maskbytelen * neles);

	socket->Receive(&intersectsize, sizeof(uint32_t));

	for(i = 0; i < neles; i++) {
		invperm[perm[i]] = i;
	}

	if(!cardinality) {
		socket->Receive(inIntersection.GetArr(), ceil_divide(neles, 8));

		for(i = 0, matchctr = 0; i < neles; i++) {
			if(inIntersection.GetBit(i)) {
				matches[matchctr] = invperm[i];
				matchctr++;
			}
		}
	}

	free(perm);
	free(invperm);

	return intersectsize;
}

uint32_t ttppsi(role_type role, uint32_t neles, uint32_t elebytelen, uint8_t* elements,
		uint8_t** result, crypto* crypt, CSocket* sockets, uint32_t ntasks, uint32_t nclients, bool cardinality) {

	if(role == 0) { //Start the server
		//TODO maybe rerun infinitely
		server_routine(nclients, sockets, cardinality);
		return 0;
	} else { //Start clients
		task_ctx ectx;
		ectx.eles.input1d = elements;
		ectx.eles.fixedbytelen = elebytelen;
		ectx.eles.hasvarbytelen = false;

		uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * neles);
		uint32_t intersect_size = client_routine(neles, ectx, matches, crypt, sockets, ntasks, cardinality);

		create_result_from_matches_fixed_bitlen(result, elebytelen, elements, matches, intersect_size);

		free(matches);

		return intersect_size;
	}
}

uint32_t ttppsi(role_type role, uint32_t neles, uint32_t* elebytelens, uint8_t** elements,
		uint8_t*** result, uint32_t** resbytelens, crypto* crypt, CSocket* sockets,
		uint32_t ntasks, uint32_t nclients, bool cardinality) {

	if(role == 0) { //Start the server
		//TODO maybe rerun infinitely
		server_routine(nclients, sockets, cardinality);
		return 0;
	} else { //Start clients
		task_ctx ectx;
		ectx.eles.input2d = elements;
		ectx.eles.varbytelens = elebytelens;
		ectx.eles.hasvarbytelen = true;

		uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * neles);
		uint32_t intersect_size = client_routine(neles, ectx, matches, crypt, sockets, ntasks, cardinality);

		create_result_from_matches_var_bitlen(result, resbytelens, elebytelens, elements, matches, intersect_size);

		free(matches);

		return intersect_size;
	}
}
<commit_msg>removed debug message to allow compilation<commit_after>#include "sapsi.h"

void server_routine(uint32_t nclients, CSocket* socket, bool cardinality) {
	//cout << "Starting server for " << nclients << " clients on address " << address << ":" << port << endl;

	CSocket* sockfds = socket;//(CSocket*) malloc(sizeof(CSocket) * nclients);
	uint32_t* neles = (uint32_t*) malloc(sizeof(uint32_t) * nclients);
	uint8_t** csets = (uint8_t**) malloc(sizeof(uint8_t*) * nclients);
	uint32_t temp, maskbytelen, intersectsize, minset, i, j;
	CBitVector* intersection = new CBitVector[nclients];

#ifndef BATCH
	cout << "Connections with all " << nclients << " clients established" << endl;
#endif

	/* Receive the input sizes and bit lengths for all clients */
	for(i = 0; i < nclients; i++) {
		sockfds[i].Receive(neles+i, sizeof(uint32_t));
		sockfds[i].Receive(&temp, sizeof(uint32_t));
		if(i == 0) { maskbytelen = temp; minset = neles[i];}
		if(neles[i] < minset) minset = neles[i];
#ifndef BATCH
		cout << "Client " << i << " holds " << neles[i] << " elements of length " << (temp * 8) << "-bit" << endl;
#endif
		intersection[i].ResizeinBytes(ceil_divide(neles[i], 8));
		intersection[i].Reset();
		assert(maskbytelen == temp);

	}
#ifndef BATCH
	cout <<"Receiving the client's elements" << endl;
#endif

	/* Receive the permuted and masked sets of all clients */
	for(i = 0; i < nclients; i++) {
		temp = sizeof(uint8_t) * neles[i] * maskbytelen;
		csets[i] = (uint8_t*) malloc(temp);
		sockfds[i].Receive(csets[i], temp);
	}
#ifndef BATCH
	cout << "Computing intersection for the clients" << endl;
#endif
	/* Compute Intersection */
	intersectsize = compute_intersection(nclients, neles, csets, intersection, maskbytelen);

	/* Enter at which position an intersection was found */
#ifndef BATCH
	cout << "sending all " << intersectsize << " intersecting elements to the clients" << endl;
#endif
	/* Send the intersection size and intersecting elements to all clients */
	for(i = 0; i < nclients; i++) {
		sockfds[i].Send(&intersectsize, sizeof(uint32_t));
		if(!cardinality)
			sockfds[i].Send(intersection[i].GetArr(), ceil_divide(neles[i], 8));
	}

	/* Cleanup */
	free(neles);
}

/*
 * compute the intersection using a hash table - is optimized for the two-party case,
 * for the n-party case a BF-based approach makes more sense.
 */
//TODO currently only works for 128 bit masks
uint32_t compute_intersection(uint32_t nclients, uint32_t* neles, uint8_t** csets, CBitVector* intersection, uint32_t entrybytelen) {
    // Create the GHashTable
    GHashTable *map = NULL, *tmpmap = NULL;
    GHashTableIter iter;
	timeval begin, end;

    map = g_hash_table_new_full(
    		g_int64_hash, g_int64_equal,
		    NULL, // no cleanup for key
		    NULL // cleanup value
		    );

    uint32_t i, j, intersectsize, ctr = 0, k;
    uint64_t* tmpval;
    uint64_t* tmpkey = (uint64_t*) malloc(sizeof(uint64_t));
    uint64_t* query;
#ifndef BATCH
    cout << "Inserting the items into the hash table " << endl;
#endif
    gettimeofday(&begin, NULL);
    for(i=0;i<neles[0];i++) {
#ifdef DEBUG
    	cout << "Inserted item: " << (hex) << ((uint64_t*) csets[0])[2*i] << " "<< ((uint64_t*) csets[0])[2*i+1] << (dec) << endl;
#endif
    	tmpval = (uint64_t*) malloc(2*sizeof(uint64_t));
    	tmpval[0] = (((uint64_t*)csets[0])[2*i+1]);
    	tmpval[1] = i;
	    g_hash_table_insert(map,(void*) &((uint64_t*)csets[0])[2*i], tmpval);//&(((uint64_t*)csets[0])[2*i+1]));
    }
    gettimeofday(&end, NULL);
#ifdef TIMING
    cout << "Insertion took " << getMillies(begin, end) << " ms" << endl;
#endif
    gettimeofday(&begin, NULL);

#ifdef DEBUG
    cout << "Checking for duplicates " << endl;
#endif
    for(i = 1; i < nclients; i++) {
    	tmpmap = g_hash_table_new_full(
    			g_int64_hash, g_int64_equal,
    		    NULL, // no cleanup for key
    		    NULL // cleanup value
    		    );
    	for(j = 0; j < neles[i]; j++) {
#ifdef DEBUG
    		cout << "Checking for Key: " << (hex) << ((uint64_t*) csets[i])[2*j] << " "<< ((uint64_t*) csets[i])[2*j+1] << (dec) << endl;
#endif
    		if(g_hash_table_lookup_extended(map, (void*) &(((uint64_t*)csets[i])[2*j]),
    				NULL, (void**) &query) && (*query == ((uint64_t*)csets[i])[2*j+1])) {
#ifdef DEBUG
    			cout << "Key was found" << endl;
#endif
    	    	tmpval = (uint64_t*) malloc((i+2)*sizeof(uint64_t));
    	    	tmpval[0] = (((uint64_t*)csets[i])[2*j+1]);
    	    	for(k = 1; k < i+1; k++) {
    	    		tmpval[k] = query[k];
    	    	}
    	    	tmpval[i+1] = j;
    			g_hash_table_insert(tmpmap,(void*) &(((uint64_t*)csets[i])[2*j]), tmpval);//&(((uint64_t*)csets[i])[2*j+1]));

    		} else {
#ifdef DEBUG
    			cout << "Key not found" << endl;
#endif
    		}
    	}
    	//Delete map
    	g_hash_table_destroy(map);
    	map = tmpmap;
    }
    gettimeofday(&end, NULL);
#ifdef TIMING
    cout << "Checking took " << getMillies(begin, end) << " ms" << endl;
#endif
    gettimeofday(&begin, NULL);

    intersectsize = g_hash_table_size(map);

    //intersect = (uint8_t*) malloc(sizeof(uint8_t) * intersectsize * entrybytelen);

#ifdef DEBUG
    cout << "Intersection contains the elements: " << endl;
#endif
    g_hash_table_iter_init (&iter, map);
    //Iterate over all key / element pairs and store them in the intersection
    while(g_hash_table_iter_next (&iter, (void**) &tmpkey, (void**) &tmpval)) {
#ifdef DEBUG
    	cout << (hex) << tmpkey[0] << " " << tmpval[0] << (dec)<< endl;
#endif
    	for(i = 0; i < nclients; i++) {
    		intersection[i].SetBit(tmpval[i+1], 1);
    	}
    }
    gettimeofday(&end, NULL);
#ifdef TIMING
    cout << "Iterating took " << getMillies(begin, end) << " ms" << endl;
#endif

    g_hash_table_destroy(map);

    //free(tmpval);
    //free(tmpkey);
#ifdef DEBUG
    cout << "returning" << endl;
#endif
	return intersectsize;
}

uint32_t client_routine(uint32_t neles, task_ctx ectx, uint32_t* matches,
		crypto* crypt_env, CSocket* socket, uint32_t ntasks, bool cardinality) {
	uint32_t maskbytelen, intersectsize, i, matchctr;

	uint8_t* masks;
	uint32_t *perm, *invperm;
	CBitVector inIntersection(neles);

	//TODO works only fine for equally sized sets, if one set is bigger than the other, this will fail!
	maskbytelen = 16;//ceil_divide(crypt_env->get_seclvl().statbits + 2*ceil_log2(neles), 8);

	masks = (uint8_t*) malloc(sizeof(uint8_t) * neles * maskbytelen);
	perm  = (uint32_t*) malloc(sizeof(uint32_t) * neles);
	invperm = (uint32_t*) malloc(sizeof(uint32_t) * neles);

	/* Generate the random permutation the elements */
	crypt_env->gen_rnd_perm(perm, neles);

	socket->Send((uint8_t*) &neles, sizeof(uint32_t));
	socket->Send((uint8_t*) &maskbytelen, sizeof(uint32_t));

	ectx.eles.outbytelen = maskbytelen,
	ectx.eles.nelements = neles;
	ectx.eles.output = masks;
	ectx.eles.perm = perm;
	ectx.sctx.symcrypt = crypt_env;
	ectx.sctx.keydata = (uint8_t*) const_seed;

	run_task(ntasks, ectx, hash);

	socket->Send(masks, maskbytelen * neles);

	socket->Receive(&intersectsize, sizeof(uint32_t));

	for(i = 0; i < neles; i++) {
		invperm[perm[i]] = i;
	}

	if(!cardinality) {
		socket->Receive(inIntersection.GetArr(), ceil_divide(neles, 8));

		for(i = 0, matchctr = 0; i < neles; i++) {
			if(inIntersection.GetBit(i)) {
				matches[matchctr] = invperm[i];
				matchctr++;
			}
		}
	}

	free(perm);
	free(invperm);

	return intersectsize;
}

uint32_t ttppsi(role_type role, uint32_t neles, uint32_t elebytelen, uint8_t* elements,
		uint8_t** result, crypto* crypt, CSocket* sockets, uint32_t ntasks, uint32_t nclients, bool cardinality) {

	if(role == 0) { //Start the server
		//TODO maybe rerun infinitely
		server_routine(nclients, sockets, cardinality);
		return 0;
	} else { //Start clients
		task_ctx ectx;
		ectx.eles.input1d = elements;
		ectx.eles.fixedbytelen = elebytelen;
		ectx.eles.hasvarbytelen = false;

		uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * neles);
		uint32_t intersect_size = client_routine(neles, ectx, matches, crypt, sockets, ntasks, cardinality);

		create_result_from_matches_fixed_bitlen(result, elebytelen, elements, matches, intersect_size);

		free(matches);

		return intersect_size;
	}
}

uint32_t ttppsi(role_type role, uint32_t neles, uint32_t* elebytelens, uint8_t** elements,
		uint8_t*** result, uint32_t** resbytelens, crypto* crypt, CSocket* sockets,
		uint32_t ntasks, uint32_t nclients, bool cardinality) {

	if(role == 0) { //Start the server
		//TODO maybe rerun infinitely
		server_routine(nclients, sockets, cardinality);
		return 0;
	} else { //Start clients
		task_ctx ectx;
		ectx.eles.input2d = elements;
		ectx.eles.varbytelens = elebytelens;
		ectx.eles.hasvarbytelen = true;

		uint32_t* matches = (uint32_t*) malloc(sizeof(uint32_t) * neles);
		uint32_t intersect_size = client_routine(neles, ectx, matches, crypt, sockets, ntasks, cardinality);

		create_result_from_matches_var_bitlen(result, resbytelens, elebytelens, elements, matches, intersect_size);

		free(matches);

		return intersect_size;
	}
}
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2014-2016 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#include <gtest/gtest.h>

#include <DO/Sara/Core/MultiArray.hpp>

#include "../AssertHelpers.hpp"

using namespace DO::Sara;
using namespace std;

// ========================================================================== //
// Test for the 2D case.
class TestIterator2D : public testing::Test
{
protected:
  using Image = MultiArray<Vector2i, 2, RowMajor>;
  Image image;

  TestIterator2D() : testing::Test()
  {
    image.resize(5, 10);
    for (auto i = 0; i < image.rows(); ++i)
      for (auto j = 0; j < image.cols(); ++j)
        image(i,j) = Vector2i(i,j);
  }

  virtual ~TestIterator2D() {}
};

class TestRangeIterator2D : public TestIterator2D {};

TEST_F(TestRangeIterator2D, test_row_major_prefix_increment)
{
  auto it = image.begin_array();
  for (auto i = 0; i < image.rows(); ++i)
  {
    for (auto j = 0; j < image.cols(); ++j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      ++it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestRangeIterator2D, test_row_major_postfix_increment)
{
  auto it = image.begin_array();
  for (auto i = 0; i < image.rows(); ++i)
    for (auto j = 0; j < image.cols(); ++j)
      ASSERT_MATRIX_EQ(*(it++), Vector2i(i,j));
}

TEST_F(TestRangeIterator2D, test_row_major_prefix_decrement)
{
  auto it = image.begin_array();
  it += image.sizes() - Vector2i::Ones();

  for (auto i = image.rows()-1; i >= 0; --i)
  {
    for (auto j = image.cols()-1; j >= 0; --j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      --it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestRangeIterator2D, test_row_major_postfix_decrement)
{
  auto it = image.begin_array();
  it += image.sizes() - Vector2i::Ones();

  for (auto i = image.rows()-1; i >= 0; --i)
    for (auto j = image.cols()-1; j >= 0; --j)
      ASSERT_MATRIX_EQ(*(it--), Vector2i(i,j));
}

TEST_F(TestRangeIterator2D, test_special_dereferencing_operator)
{
  auto it = image.begin_array();
  ASSERT_MATRIX_EQ(it(Vector2i(1,2)), Vector2i(1,2));
  ASSERT_MATRIX_EQ(it(1,2), Vector2i(1,2));
}

TEST_F(TestRangeIterator2D, test_const_multiarray_iterator)
{
  const auto& const_image = image;
  auto it = const_image.begin_array();
  while (!it.end())
    ++it;
}

TEST_F(TestRangeIterator2D, test_equality_and_inequality_comparisons)
{
  const auto& const_image = image;

  // Equalities.
  EXPECT_EQ(image.begin_array(), const_image.begin_array());
  EXPECT_EQ(image.begin_array(), image.begin_array()++);
  EXPECT_EQ(image.begin_array(), image.begin());
  EXPECT_EQ(image.begin_array(), image.data());

  EXPECT_MATRIX_EQ(*image.begin_array(), *const_image.begin_array());

  // Inequalities.
  EXPECT_NE(image.begin_array(), ++image.begin_array());
  EXPECT_NE(image.begin_array(), image.data()+1);

  EXPECT_NE(image.begin_array(), ++const_image.begin_array());
  EXPECT_NE(image.begin_array(), const_image.begin()+1);
  EXPECT_NE(image.begin_array(), const_image.data()+1);
}

// =============================================================================
// Test on subarray iterator in 2D.
class TestSubrangeIterator2D : public TestIterator2D
{
protected:
  Vector2i start;
  Vector2i end;

  TestSubrangeIterator2D() : TestIterator2D()
  {
    start << 1, 2;
    end << 4, 8;
  }

};

TEST_F(TestSubrangeIterator2D, test_row_major_prefix_increment)
{
  auto it = image.begin_subarray(start, end);
  for (auto i = start(0); i < end(0); ++i)
  {
    for (auto j = start(1); j < end(1); ++j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      ++it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestSubrangeIterator2D, test_row_major_postfix_increment)
{
  auto it = image.begin_subarray(start, end);
  for (auto i = start(0); i < end(0); ++i)
    for (auto j = start(1); j < end(1); ++j)
      ASSERT_MATRIX_EQ(*(it++), Vector2i(i,j));
}

TEST_F(TestSubrangeIterator2D, test_row_major_prefix_decrement)
{
  auto it = image.begin_subarray(start, end);
  it += end - start - Vector2i::Ones();

  for (auto i = end(0)-1; i >= start(0); --i)
  {
    for (auto j = end(1)-1; j >= start(1); --j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      --it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestSubrangeIterator2D, test_row_major_postfix_decrement)
{
  auto it = image.begin_subarray(start, end);
  it += end - start - Vector2i::Ones();

  for (auto i = end(0)-1; i >= start(0); --i)
    for (auto j = end(1)-1; j >= start(1); --j)
      ASSERT_MATRIX_EQ(*(it--), Vector2i(i,j));
}

TEST_F(TestSubrangeIterator2D, test_special_dereferencing_operator)
{
  auto it = image.begin_subarray(start, end);

  auto relative_position = Vector2i{ 2, -1 };
  auto absolute_position = Vector2i{ start + relative_position };

  ASSERT_MATRIX_EQ(it(relative_position), absolute_position);
  ASSERT_MATRIX_EQ(it(relative_position), absolute_position);
}

TEST_F(TestSubrangeIterator2D, test_const_multiarray_iterator)
{
  const Image& const_image = image;
  auto it = const_image.begin_subarray(start, end);
  while (!it.end())
    ++it;
}

TEST_F(TestSubrangeIterator2D, test_equality_and_inequality_comparisons)
{
  const Image& const_image = image;

  // Equalities.
  EXPECT_EQ(image.begin_subarray(start, end),
            const_image.begin_subarray(start, end));
  EXPECT_EQ(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.begin_array());
  EXPECT_EQ(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.begin());
  EXPECT_EQ(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.data());

  EXPECT_MATRIX_EQ(*image.begin_subarray(Vector2i::Zero(), image.sizes()),
                   *const_image.begin_array());

  // Inequalities.
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            ++image.begin_array());
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.data()+1);

  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            ++const_image.begin_array());
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            const_image.begin()+1);
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            const_image.data()+1);
}

// =============================================================================
// Test on 2D axis iterator.
class TestAxisIterator2D : public TestIterator2D {};

TEST_F(TestAxisIterator2D, test_equality_and_inequality_comparisons)
{
  const Image& const_image = image;
  auto it = image.begin_array();

  // Check equalities.
  EXPECT_EQ(it.x(), image.begin_array());
  EXPECT_EQ(it.x(), image.begin_array()++);
  EXPECT_EQ(it.x(), image.begin());
  EXPECT_EQ(it.x(), image.data());
  EXPECT_EQ(it.x(), it.y());

  EXPECT_EQ(it.x(), const_image.begin_array());
  EXPECT_EQ(it.x(), const_image.begin_array()++);
  EXPECT_EQ(it.x(), const_image.begin());
  EXPECT_EQ(it.x(), const_image.data());
  EXPECT_EQ(it.x(), const_image.begin_array().y());

  EXPECT_MATRIX_EQ(*it.x(), *it.y());

  // Inequalities.
  EXPECT_NE(it.x(), ++image.begin_array());
  EXPECT_NE(it.x(), image.begin()+1);
  EXPECT_NE(it.x(), image.data()+1);

  EXPECT_NE(it.x(), ++const_image.begin_array());
  EXPECT_NE(it.x(), const_image.begin()+1);
  EXPECT_NE(it.x(), const_image.data()+1);
}

TEST_F(TestAxisIterator2D, test_iterations)
{
  auto it = image.begin_array();
  EXPECT_EQ(++it.x(), image.begin() + image.stride(0));
  EXPECT_EQ(--it.x(), image.begin());
}

TEST_F(TestAxisIterator2D, test_arithmetic_operations)
{
  auto it = image.begin_array();

  // Addition.
  it.x() += 2;
  EXPECT_EQ(it, image.begin() + image.stride(0) * 2);

  // Subtraction.
  it.x() -= 2;
  EXPECT_EQ(it, image.begin());

  // Out of range.
  EXPECT_THROW(it.x() -= 1, std::out_of_range);
  EXPECT_THROW(it.x() += image.rows(), std::out_of_range);
}

// =============================================================================
// Test for the 3D case.
class TestIterators3D : public testing::Test
{
protected:
  using Volume = MultiArray<Vector3i, 3, RowMajor>;
  Volume volume;

  TestIterators3D()
    : testing::Test()
  {
    volume.resize(2, 5, 7);
    for (auto i = 0; i < volume.rows(); ++i)
      for (auto j = 0; j < volume.cols(); ++j)
        for (auto k = 0; k < volume.depth(); ++k)
          volume(i,j,k) = Vector3i{ i, j, k };
  }

  virtual ~TestIterators3D() {}
};

TEST_F(TestIterators3D, test_row_major_increment)
{
  auto it = volume.begin_array();
  for (auto i = 0; i < volume.rows(); ++i)
  {
    for (auto j = 0; j < volume.cols(); ++j)
    {
      for (auto k = 0; k < volume.depth(); ++k)
      {
        ASSERT_MATRIX_EQ(*it, Vector3i(i,j,k));
        ASSERT_MATRIX_EQ(it.position(), Vector3i(i,j,k));
        ASSERT_EQ(
          it.operator->(),
          volume.data() + jump(Vector3i(i,j,k), volume.strides()));
        ++it;
      }
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestIterators3D, test_row_major_decrement)
{
  auto it = volume.begin_array();
  it += volume.sizes() - Vector3i::Ones();

  for (auto i = volume.rows() - 1; i >= 0; --i)
  {
    for (auto j = volume.cols() - 1; j >= 0; --j)
    {
      for (auto k = volume.depth() - 1; k >= 0; --k)
      {
        ASSERT_MATRIX_EQ(*it, Vector3i(i,j,k));
        ASSERT_MATRIX_EQ(it.position(), Vector3i(i,j,k));
        ASSERT_EQ(
          it.operator->(),
          volume.data() + jump(Vector3i(i,j,k), volume.strides()));
        --it;
      }
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestIterators3D, test_special_dereferencing_operator)
{
  auto it = volume.begin_array();
  EXPECT_MATRIX_EQ(it(Vector3i(1,2,4)), Vector3i(1,2,4));
  EXPECT_MATRIX_EQ(it(1,2,4), Vector3i(1,2,4));
}

TEST_F(TestIterators3D, test_delta)
{
  auto it = volume.begin_array();
  const int X = 0;
  const int Y = 1;
  int dx = 1;
  int dy = 1;

  EXPECT_MATRIX_EQ(it.delta(X, dx, Y, dy), Vector3i(0 + dx, 0 + dy, 0));

  auto value = it.delta<X, Y>(dx, dy);
  EXPECT_MATRIX_EQ(value, Vector3i(0 + dx, 0 + dy, 0));
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>WIP: replace gtest with boost test.<commit_after>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2014-2016 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#define BOOST_TEST_MODULE "Core/ArrayIterators/Iterator Classes"
#include <boost/test/unit_test.hpp>

#include <DO/Sara/Core/MultiArray.hpp>

#include "../AssertHelpers.hpp"

using namespace DO::Sara;
using namespace std;

// ========================================================================== //
// Test for the 2D case.
class TestIterator2D : public testing::Test
{
protected:
  using Image = MultiArray<Vector2i, 2, RowMajor>;
  Image image;

  TestIterator2D() : testing::Test()
  {
    image.resize(5, 10);
    for (auto i = 0; i < image.rows(); ++i)
      for (auto j = 0; j < image.cols(); ++j)
        image(i,j) = Vector2i(i,j);
  }

  virtual ~TestIterator2D() {}
};

class TestRangeIterator2D : public TestIterator2D {};

TEST_F(TestRangeIterator2D, test_row_major_prefix_increment)
{
  auto it = image.begin_array();
  for (auto i = 0; i < image.rows(); ++i)
  {
    for (auto j = 0; j < image.cols(); ++j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      ++it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestRangeIterator2D, test_row_major_postfix_increment)
{
  auto it = image.begin_array();
  for (auto i = 0; i < image.rows(); ++i)
    for (auto j = 0; j < image.cols(); ++j)
      ASSERT_MATRIX_EQ(*(it++), Vector2i(i,j));
}

TEST_F(TestRangeIterator2D, test_row_major_prefix_decrement)
{
  auto it = image.begin_array();
  it += image.sizes() - Vector2i::Ones();

  for (auto i = image.rows()-1; i >= 0; --i)
  {
    for (auto j = image.cols()-1; j >= 0; --j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      --it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestRangeIterator2D, test_row_major_postfix_decrement)
{
  auto it = image.begin_array();
  it += image.sizes() - Vector2i::Ones();

  for (auto i = image.rows()-1; i >= 0; --i)
    for (auto j = image.cols()-1; j >= 0; --j)
      ASSERT_MATRIX_EQ(*(it--), Vector2i(i,j));
}

TEST_F(TestRangeIterator2D, test_special_dereferencing_operator)
{
  auto it = image.begin_array();
  ASSERT_MATRIX_EQ(it(Vector2i(1,2)), Vector2i(1,2));
  ASSERT_MATRIX_EQ(it(1,2), Vector2i(1,2));
}

TEST_F(TestRangeIterator2D, test_const_multiarray_iterator)
{
  const auto& const_image = image;
  auto it = const_image.begin_array();
  while (!it.end())
    ++it;
}

TEST_F(TestRangeIterator2D, test_equality_and_inequality_comparisons)
{
  const auto& const_image = image;

  // Equalities.
  EXPECT_EQ(image.begin_array(), const_image.begin_array());
  EXPECT_EQ(image.begin_array(), image.begin_array()++);
  EXPECT_EQ(image.begin_array(), image.begin());
  EXPECT_EQ(image.begin_array(), image.data());

  BOOST_REQUIRE_EQUAL(*image.begin_array(), *const_image.begin_array());

  // Inequalities.
  EXPECT_NE(image.begin_array(), ++image.begin_array());
  EXPECT_NE(image.begin_array(), image.data()+1);

  EXPECT_NE(image.begin_array(), ++const_image.begin_array());
  EXPECT_NE(image.begin_array(), const_image.begin()+1);
  EXPECT_NE(image.begin_array(), const_image.data()+1);
}

// =============================================================================
// Test on subarray iterator in 2D.
class TestSubrangeIterator2D : public TestIterator2D
{
protected:
  Vector2i start;
  Vector2i end;

  TestSubrangeIterator2D() : TestIterator2D()
  {
    start << 1, 2;
    end << 4, 8;
  }

};

TEST_F(TestSubrangeIterator2D, test_row_major_prefix_increment)
{
  auto it = image.begin_subarray(start, end);
  for (auto i = start(0); i < end(0); ++i)
  {
    for (auto j = start(1); j < end(1); ++j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      ++it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestSubrangeIterator2D, test_row_major_postfix_increment)
{
  auto it = image.begin_subarray(start, end);
  for (auto i = start(0); i < end(0); ++i)
    for (auto j = start(1); j < end(1); ++j)
      ASSERT_MATRIX_EQ(*(it++), Vector2i(i,j));
}

TEST_F(TestSubrangeIterator2D, test_row_major_prefix_decrement)
{
  auto it = image.begin_subarray(start, end);
  it += end - start - Vector2i::Ones();

  for (auto i = end(0)-1; i >= start(0); --i)
  {
    for (auto j = end(1)-1; j >= start(1); --j)
    {
      ASSERT_MATRIX_EQ(*it, Vector2i(i,j));
      ASSERT_MATRIX_EQ(it.position(), Vector2i(i,j));
      ASSERT_EQ(
        it.operator->(),
        image.data() + jump(Vector2i(i,j), image.strides()));
      --it;
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestSubrangeIterator2D, test_row_major_postfix_decrement)
{
  auto it = image.begin_subarray(start, end);
  it += end - start - Vector2i::Ones();

  for (auto i = end(0)-1; i >= start(0); --i)
    for (auto j = end(1)-1; j >= start(1); --j)
      ASSERT_MATRIX_EQ(*(it--), Vector2i(i,j));
}

TEST_F(TestSubrangeIterator2D, test_special_dereferencing_operator)
{
  auto it = image.begin_subarray(start, end);

  auto relative_position = Vector2i{ 2, -1 };
  auto absolute_position = Vector2i{ start + relative_position };

  ASSERT_MATRIX_EQ(it(relative_position), absolute_position);
  ASSERT_MATRIX_EQ(it(relative_position), absolute_position);
}

TEST_F(TestSubrangeIterator2D, test_const_multiarray_iterator)
{
  const Image& const_image = image;
  auto it = const_image.begin_subarray(start, end);
  while (!it.end())
    ++it;
}

TEST_F(TestSubrangeIterator2D, test_equality_and_inequality_comparisons)
{
  const Image& const_image = image;

  // Equalities.
  EXPECT_EQ(image.begin_subarray(start, end),
            const_image.begin_subarray(start, end));
  EXPECT_EQ(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.begin_array());
  EXPECT_EQ(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.begin());
  EXPECT_EQ(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.data());

  BOOST_REQUIRE_EQUAL(*image.begin_subarray(Vector2i::Zero(), image.sizes()),
                   *const_image.begin_array());

  // Inequalities.
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            ++image.begin_array());
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            image.data()+1);

  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            ++const_image.begin_array());
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            const_image.begin()+1);
  EXPECT_NE(image.begin_subarray(Vector2i::Zero(), image.sizes()),
            const_image.data()+1);
}

// =============================================================================
// Test on 2D axis iterator.
class TestAxisIterator2D : public TestIterator2D {};

TEST_F(TestAxisIterator2D, test_equality_and_inequality_comparisons)
{
  const Image& const_image = image;
  auto it = image.begin_array();

  // Check equalities.
  EXPECT_EQ(it.x(), image.begin_array());
  EXPECT_EQ(it.x(), image.begin_array()++);
  EXPECT_EQ(it.x(), image.begin());
  EXPECT_EQ(it.x(), image.data());
  EXPECT_EQ(it.x(), it.y());

  EXPECT_EQ(it.x(), const_image.begin_array());
  EXPECT_EQ(it.x(), const_image.begin_array()++);
  EXPECT_EQ(it.x(), const_image.begin());
  EXPECT_EQ(it.x(), const_image.data());
  EXPECT_EQ(it.x(), const_image.begin_array().y());

  BOOST_REQUIRE_EQUAL(*it.x(), *it.y());

  // Inequalities.
  EXPECT_NE(it.x(), ++image.begin_array());
  EXPECT_NE(it.x(), image.begin()+1);
  EXPECT_NE(it.x(), image.data()+1);

  EXPECT_NE(it.x(), ++const_image.begin_array());
  EXPECT_NE(it.x(), const_image.begin()+1);
  EXPECT_NE(it.x(), const_image.data()+1);
}

TEST_F(TestAxisIterator2D, test_iterations)
{
  auto it = image.begin_array();
  EXPECT_EQ(++it.x(), image.begin() + image.stride(0));
  EXPECT_EQ(--it.x(), image.begin());
}

TEST_F(TestAxisIterator2D, test_arithmetic_operations)
{
  auto it = image.begin_array();

  // Addition.
  it.x() += 2;
  EXPECT_EQ(it, image.begin() + image.stride(0) * 2);

  // Subtraction.
  it.x() -= 2;
  EXPECT_EQ(it, image.begin());

  // Out of range.
  EXPECT_THROW(it.x() -= 1, std::out_of_range);
  EXPECT_THROW(it.x() += image.rows(), std::out_of_range);
}

// =============================================================================
// Test for the 3D case.
class TestIterators3D : public testing::Test
{
protected:
  using Volume = MultiArray<Vector3i, 3, RowMajor>;
  Volume volume;

  TestIterators3D()
    : testing::Test()
  {
    volume.resize(2, 5, 7);
    for (auto i = 0; i < volume.rows(); ++i)
      for (auto j = 0; j < volume.cols(); ++j)
        for (auto k = 0; k < volume.depth(); ++k)
          volume(i,j,k) = Vector3i{ i, j, k };
  }

  virtual ~TestIterators3D() {}
};

TEST_F(TestIterators3D, test_row_major_increment)
{
  auto it = volume.begin_array();
  for (auto i = 0; i < volume.rows(); ++i)
  {
    for (auto j = 0; j < volume.cols(); ++j)
    {
      for (auto k = 0; k < volume.depth(); ++k)
      {
        ASSERT_MATRIX_EQ(*it, Vector3i(i,j,k));
        ASSERT_MATRIX_EQ(it.position(), Vector3i(i,j,k));
        ASSERT_EQ(
          it.operator->(),
          volume.data() + jump(Vector3i(i,j,k), volume.strides()));
        ++it;
      }
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestIterators3D, test_row_major_decrement)
{
  auto it = volume.begin_array();
  it += volume.sizes() - Vector3i::Ones();

  for (auto i = volume.rows() - 1; i >= 0; --i)
  {
    for (auto j = volume.cols() - 1; j >= 0; --j)
    {
      for (auto k = volume.depth() - 1; k >= 0; --k)
      {
        ASSERT_MATRIX_EQ(*it, Vector3i(i,j,k));
        ASSERT_MATRIX_EQ(it.position(), Vector3i(i,j,k));
        ASSERT_EQ(
          it.operator->(),
          volume.data() + jump(Vector3i(i,j,k), volume.strides()));
        --it;
      }
    }
  }
  EXPECT_TRUE(it.end());
}

TEST_F(TestIterators3D, test_special_dereferencing_operator)
{
  auto it = volume.begin_array();
  BOOST_REQUIRE_EQUAL(it(Vector3i(1,2,4)), Vector3i(1,2,4));
  BOOST_REQUIRE_EQUAL(it(1,2,4), Vector3i(1,2,4));
}

TEST_F(TestIterators3D, test_delta)
{
  auto it = volume.begin_array();
  const int X = 0;
  const int Y = 1;
  int dx = 1;
  int dy = 1;

  BOOST_REQUIRE_EQUAL(it.delta(X, dx, Y, dy), Vector3i(0 + dx, 0 + dy, 0));

  auto value = it.delta<X, Y>(dx, dy);
  BOOST_REQUIRE_EQUAL(value, Vector3i(0 + dx, 0 + dy, 0));
}
<|endoftext|>


<commit_before>// Test that the always/never instrument lists apply.
// RUN: echo "fun:main" > %tmp-always.txt
// RUN: echo "fun:__xray*" > %tmp-never.txt
// RUN: %clangxx_xray \
// RUN:     -fxray-never-instrument=%tmp-never.txt \
// RUN:     -fxray-always-instrument=%tmp-always.txt \
// RUN:     %s -o %t
// RUN: %llvm_xray extract -symbolize %t | \
// RUN:    FileCheck %s --check-prefix NOINSTR
// RUN: %llvm_xray extract -symbolize %t | \
// RUN:    FileCheck %s --check-prefix ALWAYSINSTR

// NOINSTR-NOT: {{.*__xray_NeverInstrumented.*}}
int __xray_NeverInstrumented() {
  return 0;
}

// ALWAYSINSTR: {{.*function-name:.*main.*}}
int main(int argc, char *argv[]) {
  return __xray_NeverInstrumented();
}
<commit_msg>[XRay][compiler-rt] Only run test in x86_64 linux.<commit_after>// Test that the always/never instrument lists apply.
// RUN: echo "fun:main" > %tmp-always.txt
// RUN: echo "fun:__xray*" > %tmp-never.txt
// RUN: %clangxx_xray \
// RUN:     -fxray-never-instrument=%tmp-never.txt \
// RUN:     -fxray-always-instrument=%tmp-always.txt \
// RUN:     %s -o %t
// RUN: %llvm_xray extract -symbolize %t | \
// RUN:    FileCheck %s --check-prefix NOINSTR
// RUN: %llvm_xray extract -symbolize %t | \
// RUN:    FileCheck %s --check-prefix ALWAYSINSTR
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree

// NOINSTR-NOT: {{.*__xray_NeverInstrumented.*}}
int __xray_NeverInstrumented() {
  return 0;
}

// ALWAYSINSTR: {{.*function-name:.*main.*}}
int main(int argc, char *argv[]) {
  return __xray_NeverInstrumented();
}
<|endoftext|>