Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
SOFIE_common.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_SOFIE_COMMON
2#define TMVA_SOFIE_SOFIE_COMMON
3
4#include "ROOT/RSpan.hxx"
5
6#include <algorithm>
7#include <cassert>
8#include <complex>
9#include <cstdint>
10#include <cstring>
11#include <iomanip>
12#include <iostream>
13#include <limits>
14#include <map>
15#include <memory>
16#include <regex>
17#include <set>
18#include <sstream>
19#include <stdexcept>
20#include <string>
21#include <type_traits>
22#include <vector>
23
25
26enum class ETensorType{
27 UNDEFINED = 0, FLOAT = 1, UINT8 = 2, INT8 = 3, UINT16 = 4, INT16 = 5, INT32 = 6, INT64 = 7, STRING = 8, BOOL = 9, //order sensitive
28 FLOAT16 = 10, DOUBLE = 11, UINT32 = 12, UINT64 = 13, COMPLEX64 = 14, COMPLEX28 = 15, BFLOAT16 = 16
29};
30
31enum class EActivationType{
32 UNDEFINED = 0, RELU = 1, SOFTMAX = 2, SIGMOID = 3, LEAKYRELU = 4, TANH = 5, ELU = 6
33};
34
35constexpr size_t GetTypeSize(ETensorType type) {
36 switch (type) {
37 case ETensorType::FLOAT: return sizeof(float);
38 case ETensorType::DOUBLE: return sizeof(double);
39 case ETensorType::UINT8: return sizeof(uint8_t);
40 case ETensorType::INT8: return sizeof(int8_t);
41 case ETensorType::UINT16: return sizeof(uint16_t);
42 case ETensorType::INT16: return sizeof(int16_t);
43 case ETensorType::INT32: return sizeof(int32_t);
44 case ETensorType::INT64: return sizeof(int64_t);
45 case ETensorType::UINT32: return sizeof(uint32_t);
46 case ETensorType::UINT64: return sizeof(uint64_t);
47 case ETensorType::BOOL: return sizeof(bool);
48 case ETensorType::STRING: return sizeof(std::string);
49 default: return 0;
50 }
51}
52
53typedef std::int64_t int_t;
54
57
58// find if a string represents a number
59bool IsInteger(const std::string & s);
60
61struct Dim{
62 bool isParam = false;
63 size_t dim = 0;
64 std::string param;
65
66 // default constructor (for I/O)
67 Dim() {}
68
69 // constructor for a parametric dimension with the option to pass a default dim value
70 // We use -1 for dim to indicate that the param dimension is an expression (e.g. "d1+d2")
71 // in case the string represents a number make Dim not parametric
72 Dim(const std::string & p, size_t d = 0) : isParam(true), dim(d), param(p)
73 {
74 if (IsInteger(p)) {
75 isParam = false;
76 dim = std::stoi(p);
77 }
78 }
79
80 // constructor for a non-parametric dimension
81 Dim(size_t d) : dim(d) {}
82
83 std::string GetVal() const {
84 // cast to int64_t for negative shape values
85 return (isParam) ? param : std::to_string(static_cast<int64_t>(dim));
86 }
87
88 std::ostream& operator<< (std::ostream& os) const {
89 os << GetVal();
90 return os;
91 }
92
93 bool operator==(const Dim& rhs) const {
94 return (isParam && rhs.isParam) ? param == rhs.param : dim == rhs.dim;
95 }
96 bool operator!=(const Dim& rhs) const {
97 return !(*this == rhs);
98 }
99};
100
101//bool operator==(const Dim& lhs, const Dim& rhs);
102inline std::ostream & operator<< (std::ostream &os, const Dim &d) {
103 os << d.GetVal();
104 return os;
105}
106
109 std::vector<Dim> shape;
110};
111
114 std::vector<size_t> shape;
115};
116
119 std::vector<Dim> shape;
120};
121
122// template traits for Tensor Shape
123template <typename T>
124struct TensorShape {};
125template<>
127 static bool IsDim() { return true; }
128};
129template<>
130struct TensorShape<size_t> {
131 static bool IsDim() { return false; }
132};
133
134// template traits for Tensor type
135template <typename T>
136struct TensorType {};
137template<>
138struct TensorType<float> {
139 static const std::string Name() { return "float"; }
140};
141template<>
143 static const std::string Name() { return "double"; }
144};
145template<>
146struct TensorType<int64_t> {
147 static const std::string Name() { return "int64_t"; }
148};
149template<>
150struct TensorType<int32_t> {
151 static const std::string Name() { return "int32_t"; }
152};
153template<>
154struct TensorType<uint32_t> {
155 static const std::string Name() { return "uint32_t"; }
156};
157template<>
158struct TensorType<uint64_t> {
159 static const std::string Name() { return "uint64_t"; }
160};
161template<>
163 static const std::string Name() { return "bool"; }
164};
165template<>
166struct TensorType<int8_t> {
167 static const std::string Name() { return "int8_t"; }
168};
169template<>
170struct TensorType<uint8_t> {
171 static const std::string Name() { return "uint8_t"; }
172};
173
175 std::string_view tensor_name;
177
178 TensorMemoryInfo split(const std::string_view new_name, size_t new_size) {
179 if (new_size > tensor_size) {
180 throw std::invalid_argument("New size exceeds available tensor size.");
181 }
184 }
185
186 // Method to merge another struct into this one
188 tensor_size += other.tensor_size;
189 }
190};
191
193
194 // ordered map with chunk_idx as key and TensorMemoryInfo as value
195 std::map<size_t, TensorMemoryInfo> total_stack;
196
197 // ordered map with chunk_idx as key and chunk_size as value
198 std::map<size_t, size_t> available_stack;
199};
200
201std::vector<Dim> ConvertShapeToDim(const std::vector<size_t> & shape);
202
203std::vector<size_t> ConvertShapeToInt(const std::vector<Dim> & shape);
204
205std::size_t ConvertShapeToLength(const std::vector<size_t> & shape);
206
207std::string ConvertShapeToString(const std::vector<size_t> & shape);
208std::string ConvertDimShapeToString(const std::vector<Dim> & shape);
209
210std::string ConvertDimShapeToLength(const std::vector<Dim> & shape);
211
212
213template<class T>
214std::string ConvertValToString(T value) {
215 std::stringstream ret;
216 ret << std::to_string(value);
217 return ret.str();
218}
219// float specialization
220template<>
221inline std::string ConvertValToString<float>(float value) {
222 std::stringstream ret;
223 // special case for infinity and Nan
224 if (std::isinf(value))
225 ret << (value > 0 ? "std::numeric_limits<float>::infinity()" :
226 "-std::numeric_limits<float>::infinity()");
227 else if (std::isnan(value))
228 ret << "std::numeric_limits<float>::quiet_NaN()";
229 else {
230 ret << std::setprecision(std::numeric_limits<float>::max_digits10);
231 ret << value;
232 }
233 return ret.str();
234}
235// double specialization
236template<>
237inline std::string ConvertValToString<double>(double value) {
238 std::stringstream ret;
239 // special case for infinity and Nan
240 if (std::isinf(value))
241 ret << (value > 0 ? "std::numeric_limits<double>::infinity()" :
242 "-std::numeric_limits<double>::infinity()");
243 else if (std::isnan(value))
244 ret << "std::numeric_limits<double>::quiet_NaN()";
245 else {
246 ret << std::setprecision(std::numeric_limits<double>::max_digits10);
247 ret << value;
248 }
249 return ret.str();
250}
251// int64_t specialization for INT64_MIN
252template<>
253inline std::string ConvertValToString<int64_t>(int64_t value) {
254 std::stringstream ret;
255 if (value == INT64_MIN)
256 ret << "INT64_MIN";
257 else
258 ret << std::to_string(value);
259 return ret.str();
260}
261
262
263// convert list of values in a string taking into account the precision
264template<class T>
265std::string ConvertValuesToString(size_t n, const T * data, size_t maxprint = -1) {
266 std::stringstream ret;
267 ret << "{ ";
268 for (size_t i = 0; i < std::min(n,maxprint); i++) {
270 if (i < n-1) ret << ", ";
271 if (i < n-1 && i == maxprint-1) ret << "..... ";
272 }
273 ret << "}";
274 return ret.str();
275}
276template<class T>
277std::string ConvertValuesToString(const std::vector<T> & data, size_t maxprint = 5) {
278 return ConvertValuesToString(data.size(), data.data(), maxprint);
279}
280
282public:
283 InitializedTensor() = default;
284 InitializedTensor(ETensorType type, std::span<std::size_t> shape, std::shared_ptr<void> data, bool typeConstant = false)
285 : fConstant(typeConstant), fType{type}, fShape{shape.begin(), shape.end()}, fData{data}
286 {
287 }
288
289 ETensorType const &type() const { return fType; }
290 std::vector<std::size_t> const &shape() const { return fShape; }
291 std::shared_ptr<void> const &sharedptr() const { return fData; }
292 // query if tensor comes from a Constant operator
293 bool IsConstantTensor() const { return fConstant;}
294 // query if tensor needs to be written in a weight file. Constant tensors are not written in a separate file
295 bool IsWeightTensor() const { return !fConstant && !fIsNotWritable;}
296 // check if a Tensor is Writable (need to be written in the file or in the generated code (e.g. as a constant tensor)
297 // if an initialized tensors is used in a constant operator at compile time does not need to be written and can be omitted in
298 // the generated code
299 bool IsNotWritable() const { return fIsNotWritable; }
300 // set not writable initialized tensors - i.e. tensor that must not be written in a file
302 // set writable initialized tensors - i.e. tensor that must be written in a file
303 void SetWritable() { fIsNotWritable = false;}
304 // set as constant (needed for non-float initialized tensors)
305 void SetConstant() { fConstant = true;}
306
307 template <class T = void>
308 T const *data() const
309 {
310 return static_cast<T const *>(fData.get());
311 }
312
313private:
314 bool fConstant = false; ///< Flag specifying if tensor is a Constant one (coming from a Constant operator)
315 bool fIsNotWritable = false; ///< Flag to indicate that tensor values do not need to be written as weight or generated code
316 ETensorType fType; ///< Encodes the type of the data
317 std::vector<std::size_t> fShape; ///< The shape of the data in terms of elements in each dimension
318 std::shared_ptr<void> fData; ///<! Transient shared data
319};
320
321template <typename T>
323 if (std::is_same<T, float>::value) return ETensorType::FLOAT;
324 if (std::is_same<T, uint8_t>::value) return ETensorType::UINT8;
325 if (std::is_same<T, int8_t>::value) return ETensorType::INT8;
326 if (std::is_same<T, uint16_t>::value) return ETensorType::UINT16;
327 if (std::is_same<T, int16_t>::value) return ETensorType::INT16;
328 if (std::is_same<T, int32_t>::value) return ETensorType::INT32;
329 if (std::is_same<T, int64_t>::value) return ETensorType::INT64;
330 if (std::is_same<T, std::string>::value) return ETensorType::STRING;
331 if (std::is_same<T, bool>::value) return ETensorType::BOOL;
332 //float16 unimplemented
333 if (std::is_same<T, double>::value) return ETensorType::DOUBLE;
334 if (std::is_same<T, uint32_t>::value) return ETensorType::UINT32;
335 if (std::is_same<T, uint64_t>::value) return ETensorType::UINT64;
336 //complex 64, 28, bfloat 16 unimplemented
337}
338
339namespace UTILITY{
340
341
342
343// clean operator and tensor names
344std::string Clean_name(std::string input_tensor_name);
345
346// Check if two shapes are equal
347bool AreSameShape(const std::vector<size_t>&, const std::vector<size_t>&);
348bool AreSameShape(const std::vector<size_t>&, const std::vector<Dim>&);
349bool AreSameShape(const std::vector<Dim>&, const std::vector<Dim>&);
350
351
352// Multidirectional broadcast a list of tensors to the same shape
353std::vector<size_t> MultidirectionalBroadcastShape(std::vector<std::vector<size_t>>);
354
355// Multidirectional broadcast two shapes to the same shape
356
357std::pair<int, std::vector<size_t>> MultidirectionalBroadcastShape(std::vector<size_t> &, std::vector<size_t> &);
358std::vector<size_t> UnidirectionalBroadcastShape(std::vector<size_t> &, std::vector<size_t> &);
359
360std::pair<int, std::vector<Dim>> MultidirectionalBroadcastShape(std::vector<Dim> &, std::vector<Dim> &);
361
362
363
364template<typename T>
365T* BroadcastConvBias(const T* data, const size_t channel, const std::vector<size_t>& targetShape) {
366 size_t size = targetShape.size();
367 if (targetShape[1] != channel) {
368 std::stringstream ss;
369 ss << "TMVA::SOFIE - Error broadcasting Conv Bias of shape {";
370 ss << std::to_string(channel);
371 ss << "} to ";
373 throw
374 std::runtime_error(ss.str());
375 }
376
378 T* newData = new T[targetLength];
379
380 if (targetLength == channel) {
381 std::copy(data, data + channel, newData);
382 return newData;
383 }
384
385 // cStride = OutDepth * outHeight * outWidth
386 size_t cStride = 1;
387 for (size_t i = 2; i < size; i++)
388 cStride *= targetShape[i];
389 // Broadcast each element of the bias to a vector of size cStride and concatenate them
390 // into a vector of size channel * cStride
391 for (size_t i = 0; i < channel; i++) {
392 std::fill(newData + i * cStride, newData + (i + 1) * cStride, data[i]);
393 }
394 // Broadcast newData[0...channel * cStride) to newData[0...batch * channel * cStride)
395 size_t batch = targetShape[0];
396 size_t bStride = channel * cStride;
397 for (size_t i = 1; i < batch; i++) {
398 std::copy(newData, newData + bStride, newData + i * bStride);
399 }
400 return newData;
401}
402
403// Broadcast a tensor from shape to targetShape according to numpy broadcasting rules
404// See more at https://numpy.org/doc/stable/user/basics.broadcasting.html
405// and https://github.com/onnx/onnx/blob/main/docs/Broadcasting.md .
406template<typename T, class ConstContT = std::span<const T>>
407void BroadcastTensor(ConstContT data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape, T *broadcastedData) {
408 // Size of the shapes (tensor input here have shapes with same sizes, we have already added the needed ones )
409 size_t size = shape.size();
410 // Current length of the broadcasted tensor
411 size_t curLength = data.size();
412 // special case when broadcasting last dimensions (initial shapes must be the same)
413 if (size > 1 && shape.front() == targetShape.front() && shape.back() == 1) {
414 size_t bsize = targetShape.back();
415 // compute the size of the data to broadcast
416 for (int k = int(size)-2; k >=0; k--) {
417 if (shape[k] != 1) break;
418 bsize *= targetShape[k];
419 }
420 for (size_t i = 0; i < curLength; i++) {
421 std::fill(broadcastedData + i*bsize, broadcastedData + (i+1)*bsize , data[i]);
422 }
423 return;
424 }
425
426 std::copy(data.begin(), data.end(), broadcastedData);
427 // Product of the previous dimensions of targetShape
428 size_t arrayNum = 1;
429 // New broadcasted data: is this needed?
431
432 for (size_t idx = 0; idx < size; idx++) {
433 size_t dim = shape[idx];
434 size_t targetDim = targetShape[idx];
435 if (dim == 1 && targetDim > 1) {
436 // Set the new length of the data
437 size_t newLength = curLength * targetDim;
438 // View the data as a list of arrayNum arrays of size arrayLength
439 size_t arrayLength = curLength / arrayNum;
440 // Broadcast each array dim times
441 if (arrayLength > 1) {
442 // If each array has at least two elements
443 for (size_t arrayIdx = 0; arrayIdx < arrayNum; arrayIdx++) {
444 for (size_t targetIdx = 0; targetIdx < targetDim; targetIdx++) {
448 newData.begin() + offset);
449 }
450 }
451 } else {
452 // If each array has one element
453 for (size_t arrayIdx = 0; arrayIdx < arrayNum; arrayIdx++) {
454 std::fill(newData.begin() + arrayIdx * targetDim,
456 }
457 }
458 // Update current length
460 // Update broadcasted data
462 }
463 // Update the number of arrays
465 }
466}
467
468// interface where we allocate a new array for broadcasted data
469template<typename T>
470T* CreateBroadcastTensor(const T* data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape, size_t targetLength) {
471 // newShape is an array of size equal to dimension along which we are broadcasting the tensor
472 T* broadcastedData = new T[targetLength];
473 size_t curLength = ConvertShapeToLength(shape);
475 return broadcastedData;
476}
477// Unidirectional broadcasting shape to targetShape// In unidirectional broadcast - only tensor B can have the shape changed not
478// tensor A - otherwise is a multidirectional broadcast
479template<typename T>
480T* UnidirectionalBroadcast(const T* data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape) {
481 // Prepend shape with ones
482 if (shape.size() < targetShape.size()) {
483 size_t targetSize = targetShape.size();
484 std::vector<size_t> newShape(targetSize, 1);
485 size_t offset = targetSize - shape.size();
486 std::copy(shape.begin(), shape.end(), newShape.begin() + offset);
488 }
490}
491
492// Unidirectional broadcasting shape to targetShape using a passed vector to avoid allocations
493template<typename T>
494void UnidirectionalBroadcast(const T* data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape, T *broadcastedData) {
495 size_t curLength = ConvertShapeToLength(shape);
496 std::span<T> inData(const_cast<T*>(data), curLength);
497 // Prepend shape with ones
498 if (shape.size() < targetShape.size()) {
499 size_t targetSize = targetShape.size();
500 std::vector<size_t> newShape(targetSize, 1);
501 size_t offset = targetSize - shape.size();
502 std::copy(shape.begin(), shape.end(), newShape.begin() + offset);
504 return;
505 }
507}
508
509/// compute stride of a tensor given its shape (assume layout is row-major)
510std::vector<size_t> ComputeStrideFromShape(const std::vector<size_t> & shape);
511std::vector<Dim> ComputeStrideFromShape(const std::vector<Dim> & shape);
512
513
514} // end namespace UTILITY
515
516namespace BLAS{
517extern "C" void sgemm_(const char * transa, const char * transb, const int * m, const int * n, const int * k,
518 const float * alpha, const float * A, const int * lda, const float * B, const int * ldb,
519 const float * beta, float * C, const int * ldc);
520}//BLAS
521
522
523//Utility functions to generate code
524void EmitNestedLoops(std::stringstream &out, size_t loopRank, const std::vector<Dim> shape);
525void CloseNestedLoops(std::stringstream &out, size_t loopRank);
526
527
528
529/// Source code of the inference helper functions to embed in generated code so
530/// that it is standalone and does not need to include TMVA/SOFIE_common.hxx.
532 std::string includes; ///< #include directives to place in the header preamble
533 std::string definitions; ///< function/type definitions to place inside the generated model namespace
534 std::string cladDefinitions; ///< Clad custom-derivative definitions to place at file scope (outside the model
535 ///< namespace) so that Clad discovers them; empty when none are needed
536};
537
538/// Return the standalone C++ source of the inference helper functions requested
539/// in `neededHelpers` (see RModel::AddNeededHelperFunction), resolving
540/// their inter-dependencies. Recognised keys are: "Im2col", "Im2col_3d",
541/// "col2im", "UnidirectionalBroadcast", "BroadcastConvBias", "Gemm_Call",
542/// "Relu", "Fill", "Copy", "ReadTensorFromStream", "SafetensorsBlob",
543/// "SafetensorsReader", "InputTensorDims", "DynamicMemory".
544///
545/// `modelNamespace` (e.g. "TMVA_SOFIE_MyModel") is the generated model namespace;
546/// the Clad pullbacks are emitted into clad::custom_derivatives::<modelNamespace>
547/// so the model stays differentiable without SOFIE_common.hxx / CladDerivator.h.
548///
549/// `sgemmAlreadyDeclared`: set true if the caller already emitted the `extern "C"`
550/// sgemm_ declaration (fNeededBlasRoutines block), so Gemm_Call skips its own and
551/// avoids a duplicate. Default false emits it, keeping the returned code self-contained.
553 const std::string & modelNamespace,
554 bool sgemmAlreadyDeclared = false);
555
556
557} // namespace TMVA::Experimental::SOFIE
558
559#endif //TMVA_SOFIE_COMMON
#define d(i)
Definition RSha256.hxx:102
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
const_iterator begin() const
std::shared_ptr< void > const & sharedptr() const
std::shared_ptr< void > fData
! Transient shared data
ETensorType fType
Encodes the type of the data.
std::vector< std::size_t > const & shape() const
std::vector< std::size_t > fShape
The shape of the data in terms of elements in each dimension.
bool fIsNotWritable
Flag to indicate that tensor values do not need to be written as weight or generated code.
bool fConstant
Flag specifying if tensor is a Constant one (coming from a Constant operator)
InitializedTensor(ETensorType type, std::span< std::size_t > shape, std::shared_ptr< void > data, bool typeConstant=false)
const Int_t n
Definition legend1.C:16
void sgemm_(const char *transa, const char *transb, const int *m, const int *n, const int *k, const float *alpha, const float *A, const int *lda, const float *B, const int *ldb, const float *beta, float *C, const int *ldc)
bool AreSameShape(const std::vector< size_t > &, const std::vector< size_t > &)
T * BroadcastConvBias(const T *data, const size_t channel, const std::vector< size_t > &targetShape)
std::vector< size_t > UnidirectionalBroadcastShape(std::vector< size_t > &, std::vector< size_t > &)
void BroadcastTensor(ConstContT data, const std::vector< size_t > &shape, const std::vector< size_t > &targetShape, T *broadcastedData)
std::string Clean_name(std::string input_tensor_name)
std::vector< size_t > MultidirectionalBroadcastShape(std::vector< std::vector< size_t > >)
T * UnidirectionalBroadcast(const T *data, const std::vector< size_t > &shape, const std::vector< size_t > &targetShape)
T * CreateBroadcastTensor(const T *data, const std::vector< size_t > &shape, const std::vector< size_t > &targetShape, size_t targetLength)
std::vector< size_t > ComputeStrideFromShape(const std::vector< size_t > &shape)
compute stride of a tensor given its shape (assume layout is row-major)
std::string ConvertDimShapeToString(const std::vector< Dim > &shape)
std::size_t ConvertShapeToLength(const std::vector< size_t > &shape)
std::string ConvertValToString< double >(double value)
std::string ConvertValuesToString(size_t n, const T *data, size_t maxprint=-1)
std::vector< Dim > ConvertShapeToDim(const std::vector< size_t > &shape)
Convert shape from integer format to dynamic one (based on Dim)
constexpr size_t GetTypeSize(ETensorType type)
ETensorType GetTemplatedType(T)
std::string ConvertValToString< float >(float value)
std::vector< size_t > ConvertShapeToInt(const std::vector< Dim > &shape)
Convert shape based on Dim to integer format.
std::string ConvertTypeToString(ETensorType type)
ETensorType ConvertStringToType(std::string type)
HelperFunctionsCode GenerateHelperFunctionsCode(const std::set< std::string > &neededHelpers, const std::string &modelNamespace, bool sgemmAlreadyDeclared=false)
Return the standalone C++ source of the inference helper functions requested in neededHelpers (see RM...
std::ostream & operator<<(std::ostream &os, const Dim &d)
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
void EmitNestedLoops(std::stringstream &out, size_t loopRank, const std::vector< Dim > shape)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
void CloseNestedLoops(std::stringstream &out, size_t loopRank)
std::string ConvertValToString(T value)
std::string ConvertValToString< int64_t >(int64_t value)
bool IsInteger(const std::string &s)
bool operator!=(const Dim &rhs) const
bool operator==(const Dim &rhs) const
Dim(const std::string &p, size_t d=0)
std::ostream & operator<<(std::ostream &os) const
Source code of the inference helper functions to embed in generated code so that it is standalone and...
std::string definitions
function/type definitions to place inside the generated model namespace
std::string cladDefinitions
Clad custom-derivative definitions to place at file scope (outside the model namespace) so that Clad ...
std::string includes
#include directives to place in the header preamble
std::map< size_t, TensorMemoryInfo > total_stack
std::map< size_t, size_t > available_stack
void merge(const TensorMemoryInfo &other)
TensorMemoryInfo split(const std::string_view new_name, size_t new_size)
TMarker m
Definition textangle.C:8