Tenncor
serialize.hpp
Go to the documentation of this file.
1 
9 #include "pbm/data.hpp"
10 
11 #include "eteq/generated/opcode.hpp"
12 #include "eteq/generated/dtype.hpp"
13 
14 #include "eteq/coord.hpp"
15 #include "eteq/constant.hpp"
16 #include "eteq/variable.hpp"
17 #include "eteq/functor.hpp"
18 
19 #ifndef ETEQ_SERIALIZE_HPP
20 #define ETEQ_SERIALIZE_HPP
21 
22 namespace eteq
23 {
24 
25 static std::unordered_set<size_t> non_bijectives =
26 {
27  egen::REDUCE_SUM,
28  egen::REDUCE_PROD,
29  egen::REDUCE_MIN,
30  egen::REDUCE_MAX,
31  egen::EXTEND,
32 };
33 
34 static bool is_big_endian(void)
35 {
36  union
37  {
38  uint16_t _;
39  char bytes[2];
40  } twob = { 0x0001 };
41 
42  return twob.bytes[0] == 0;
43 }
44 
46 struct EADSaver final : public pbm::iSaver
47 {
49  std::string save_leaf (teq::iLeaf* leaf) override
50  {
51  char* data = (char*) leaf->data();
52  size_t nelems = leaf->shape().n_elems();
53  size_t nbytes = egen::type_size((egen::_GENERATED_DTYPE) leaf->type_code());
54  if (is_big_endian() && nbytes > 1)
55  {
56  size_t totalbytes = nelems * nbytes;
57  std::string out(totalbytes, '\0');
58  for (size_t i = 0; i < totalbytes; ++i)
59  {
60  size_t elemi = i / nbytes;
61  size_t outi = (elemi + 1) * nbytes - (i % nbytes);
62  out[outi] = data[i];
63  }
64  return out;
65  }
66  return std::string(data, nelems * nbytes);
67  }
68 
70  std::vector<double> save_shaper (const teq::CoordptrT& mapper) override
71  {
72  std::vector<double> out;
73  mapper->access(
74  [&out](const teq::MatrixT& mat)
75  {
76  for (teq::RankT i = 0; i < teq::mat_dim; ++i)
77  {
78  for (teq::RankT j = 0; j < teq::mat_dim; ++j)
79  {
80  out.push_back(mat[i][j]);
81  }
82  }
83  });
84  return out;
85  }
86 
88  std::vector<double> save_coorder (const teq::CoordptrT& mapper) override
89  {
90  if (nullptr == mapper)
91  {
92  return std::vector<double>();
93  }
94  teq::CoordT coord;
95  mapper->forward(coord.begin(), coord.begin());
96  return std::vector<double>(coord.begin(), coord.end());
97  }
98 };
99 
100 #define _OUT_GENERIC(realtype)leaf = is_const?\
101 teq::TensptrT(Constant<realtype>::get((realtype*) pb, shape)):\
102 teq::TensptrT(Variable<realtype>::get((realtype*) pb, shape, label));
103 
104 #define _OUT_GENFUNC(realtype){\
105 ArgsT<realtype> eargs;eargs.reserve(args.size());\
106 std::transform(args.begin(), args.end(), std::back_inserter(eargs),\
107 [](teq::FuncArg arg){\
108  return FuncArg<realtype>(\
109  NodeConverters<realtype>::to_node(arg.get_tensor()),\
110  arg.get_shaper(),\
111  std::static_pointer_cast<CoordMap>(arg.get_coorder()));\
112 });\
113 func = teq::TensptrT(\
114 Functor<realtype>::get(teq::Opcode{opname, egen::get_op(opname)},eargs));}
115 
117 struct EADLoader final : public pbm::iLoader
118 {
120  teq::TensptrT generate_leaf (const char* pb, teq::Shape shape,
121  std::string typelabel, std::string label, bool is_const) override
122  {
123  teq::TensptrT leaf;
124  egen::_GENERATED_DTYPE gencode = egen::get_type(typelabel);
125  size_t nbytes = egen::type_size(gencode);
126  if (is_big_endian() && nbytes > 1)
127  {
128  size_t totalbytes = shape.n_elems() * nbytes;
129  std::string out(totalbytes, '\0');
130  for (size_t i = 0; i < totalbytes; ++i)
131  {
132  size_t elemi = i / nbytes;
133  size_t outi = (elemi + 1) * nbytes - (i % nbytes);
134  out[outi] = pb[i];
135  }
136  pb = out.c_str();
137  TYPE_LOOKUP(_OUT_GENERIC, gencode)
138  }
139  else
140  {
141  TYPE_LOOKUP(_OUT_GENERIC, gencode)
142  }
143  return leaf;
144  }
145 
147  teq::TensptrT generate_func (std::string opname, teq::ArgsT args) override
148  {
149  if (args.empty())
150  {
151  logs::fatalf("cannot generate func %s without args", opname.c_str());
152  }
153  size_t gencode = egen::BAD_TYPE;
154  auto arg = args[0].get_tensor().get();
155  if (auto leaf = dynamic_cast<teq::iLeaf*>(arg))
156  {
157  gencode = leaf->type_code();
158  }
159  else if (auto func = dynamic_cast<teq::iOperableFunc*>(arg))
160  {
161  gencode = func->type_code();
162  }
163  else
164  {
165  logs::fatalf("cannot generate func from non-eteq tensor arg %s",
166  arg->to_string().c_str());
167  }
168  teq::TensptrT func = nullptr;
169  TYPE_LOOKUP(_OUT_GENFUNC, (egen::_GENERATED_DTYPE) gencode);
170  return func;
171  }
172 
174  teq::CoordptrT generate_shaper (std::vector<double> coord) override
175  {
176  if (teq::mat_dim * teq::mat_dim != coord.size())
177  {
178  logs::fatal("cannot deserialize non-matrix shape map");
179  }
180  return std::make_shared<teq::CoordMap>(
181  [&](teq::MatrixT fwd)
182  {
183  for (teq::RankT i = 0; i < teq::mat_dim; ++i)
184  {
185  for (teq::RankT j = 0; j < teq::mat_dim; ++j)
186  {
187  fwd[i][j] = coord[i * teq::mat_dim + j];
188  }
189  }
190  });
191  }
192 
195  std::string opname, std::vector<double> coord) override
196  {
197  if (0 == coord.size()) // is identity
198  {
199  return nullptr;
200  }
201  if (teq::rank_cap + 1 < coord.size())
202  {
203  logs::fatal("cannot deserialize non-vector coordinate map");
204  }
205  bool is_bijective = false == estd::has(non_bijectives, egen::get_op(opname));
206  teq::CoordT indices;
207  auto cit = coord.begin();
208  std::copy(cit, cit + teq::rank_cap, indices.begin());
209  return std::make_shared<CoordMap>(indices, is_bijective);
210  }
211 };
212 
213 #undef _OUT_GENERIC
214 
215 }
216 
217 #endif // ETEQ_SERIALIZE_HPP
std::array< CDimT, rank_cap > CoordT
Definition: shape.hpp:56
const RankT rank_cap
Number of dimsensions in a shape/coordinate.
Definition: shape.hpp:47
args
Definition: csv_to_png.py:105
PBM Marshaller implementation for saving ETEQ Nodes.
Definition: serialize.hpp:46
Definition: constant.hpp:17
std::vector< FuncArg > ArgsT
Type of functor arguments.
Definition: funcarg.hpp:101
uint8_t RankT
Type used for shape rank.
Definition: shape.hpp:23
Definition: shape.hpp:62
std::shared_ptr< iCoordMap > CoordptrT
Type of iCoordMap smartpointer.
Definition: coord.hpp:106
virtual size_t type_code(void) const =0
Return data type encoding.
const RankT mat_dim
Number of rows and columns for the homogeneous matrix.
Definition: matops.hpp:22
teq::CoordptrT generate_coorder(std::string opname, std::vector< double > coord) override
Implementation of iLoader.
Definition: serialize.hpp:194
static std::unordered_set< size_t > non_bijectives
Definition: serialize.hpp:25
std::vector< double > save_coorder(const teq::CoordptrT &mapper) override
Implementation of iSaver.
Definition: serialize.hpp:88
PBM Unmarshaller implementation for loading ETEQ Nodes.
Definition: serialize.hpp:117
std::vector< double > save_shaper(const teq::CoordptrT &mapper) override
Implementation of iSaver.
Definition: serialize.hpp:70
#define _OUT_GENERIC(realtype)
Definition: serialize.hpp:100
teq::TensptrT generate_leaf(const char *pb, teq::Shape shape, std::string typelabel, std::string label, bool is_const) override
Implementation of iLoader.
Definition: serialize.hpp:120
std::shared_ptr< iTensor > TensptrT
Tensor smart pointer.
Definition: itensor.hpp:51
static bool is_big_endian(void)
Definition: serialize.hpp:34
teq::TensptrT generate_func(std::string opname, teq::ArgsT args) override
Implementation of iLoader.
Definition: serialize.hpp:147
std::string save_leaf(teq::iLeaf *leaf) override
Implementation of iSaver.
Definition: serialize.hpp:49
Interface for building implementations of leaves, functors, shaper, and coorder.
Definition: data.hpp:43
virtual void * data(void)=0
Return pointer to internal data.
Interface for saving implementations of leaves, shaper, and coorder.
Definition: data.hpp:30
teq::CoordptrT generate_shaper(std::vector< double > coord) override
Implementation of iLoader.
Definition: serialize.hpp:174
#define _OUT_GENFUNC(realtype)
Definition: serialize.hpp:104
double[mat_dim][mat_dim] MatrixT
Coordinate transformation matrix (using homogeneous)
Definition: matops.hpp:28
NElemT n_elems(void) const
Return the total number of elements represented by the shape.
Definition: shape.hpp:118
Leaf of the graph commonly representing the variable in an equation.
Definition: ileaf.hpp:19
virtual const Shape & shape(void) const =0
Return the shape held by this tensor.