Graph Framework
Loading...
Searching...
No Matches
random.hpp
Go to the documentation of this file.
1//------------------------------------------------------------------------------
6//------------------------------------------------------------------------------
7
8#ifndef random_h
9#define random_h
10
11#include "node.hpp"
12
13namespace graph {
14//******************************************************************************
16//******************************************************************************
17//------------------------------------------------------------------------------
22//------------------------------------------------------------------------------
23 template<jit::float_scalar T, bool SAFE_MATH=false>
24 class random_state_node final : public leaf_node<T, SAFE_MATH> {
25 public:
26//------------------------------------------------------------------------------
30//------------------------------------------------------------------------------
31 static void compile_random_state(std::ostringstream &stream) {
32 stream << "struct mt_state {" << std::endl
33 << " array<uint32_t, 624> array;" << std::endl
34 << " uint16_t index;" << std::endl
35#ifdef USE_CUDA
36 << " uint16_t padding[3];" << std::endl
37#endif
38 << "};" << std::endl;
39 }
40
41//------------------------------------------------------------------------------
43//------------------------------------------------------------------------------
44 struct mt_state {
46 std::array<uint32_t, 624> array;
49#ifdef USE_CUDA
52#endif
53 };
54
55//------------------------------------------------------------------------------
60//------------------------------------------------------------------------------
61 random_state_node(const size_t size,
62 const uint32_t seed=0) :
63 leaf_node<T, SAFE_MATH> (random_state_node::to_string(), 1, false) {
64 for (uint32_t i = 0; i < size; i++) {
65 states.push_back(initialize_state(seed + i));
66 }
67 }
68
69//------------------------------------------------------------------------------
73//------------------------------------------------------------------------------
75 backend::buffer<T> result;
76 return result;
77 }
78
79//------------------------------------------------------------------------------
84//------------------------------------------------------------------------------
88
89//------------------------------------------------------------------------------
100//------------------------------------------------------------------------------
101 virtual void compile_preamble(std::ostringstream &stream,
102 jit::register_map &registers,
107 jit::preamble_map &pre_funcs,
108 int &avail_const_mem) {
109 if (!pre_funcs.contains("random_state")) {
110 pre_funcs.insert("random_state");
111
113 }
114
115 if (!visited.contains(this)) {
116 visited.insert(this);
117#ifdef SHOW_USE_COUNT
118 usage[this] = 1;
119 } else {
120 ++usage[this];
121#endif
122 }
123 }
124
125//------------------------------------------------------------------------------
133//------------------------------------------------------------------------------
135 compile(std::ostringstream &stream,
136 jit::register_map &registers,
138 const jit::register_usage &usage) {
139 return this->shared_from_this();
140 }
141
142//------------------------------------------------------------------------------
144//------------------------------------------------------------------------------
145 virtual void to_latex() const {
146 std::cout << "state";
147 }
148
149//------------------------------------------------------------------------------
155//------------------------------------------------------------------------------
156 virtual shared_leaf<T, SAFE_MATH> to_vizgraph(std::stringstream &stream,
157 jit::register_map &registers) {
158 if (registers.find(this) == registers.end()) {
159 const std::string name = jit::to_string('r', this);
160 registers[this] = name;
161 stream << " " << name
162 << " [label = \"state\", shape = box, style = \"rounded,filled\", fillcolor = black, fontcolor = white];" << std::endl;
163 }
164
165 return this->shared_from_this();
166 }
167
168//------------------------------------------------------------------------------
172//------------------------------------------------------------------------------
174 return constant<T, SAFE_MATH> (static_cast<T> (1.0));
175 }
176
177//------------------------------------------------------------------------------
181//------------------------------------------------------------------------------
182 size_t size() {
183 return states.size();
184 }
185
186//------------------------------------------------------------------------------
190//------------------------------------------------------------------------------
191 size_t get_size_bytes() {
192 return size()*sizeof(mt_state);
193 }
194
195//------------------------------------------------------------------------------
199//------------------------------------------------------------------------------
201 return states.data();
202 }
203
204 private:
206 std::vector<mt_state> states;
207
208//------------------------------------------------------------------------------
212//------------------------------------------------------------------------------
213 static std::string to_string() {
214 return "random_state";
215 }
216
217//------------------------------------------------------------------------------
222//------------------------------------------------------------------------------
223 mt_state initialize_state(const uint32_t seed) {
224 mt_state state;
225 state.array[0] = seed;
226 for (uint16_t i = 1, ie = state.array.size(); i < ie; i++) {
227 state.array[i] = 1812433253U*(state.array[i - 1]^(state.array[i - 1] >> 30)) + i;
228 }
229 state.index = 0;
230
231 return state;
232 }
233 };
234
235//------------------------------------------------------------------------------
244//------------------------------------------------------------------------------
245 template<jit::float_scalar T, bool SAFE_MATH=false>
247 const uint32_t seed=0) {
248 auto temp = std::make_shared<random_state_node<T, SAFE_MATH>> (size, seed)->reduce();
249// Test for hash collisions.
250 for (size_t i = temp->get_hash();
252 if (leaf_node<T, SAFE_MATH>::caches.nodes.find(i) ==
255 return temp;
256 } else if (temp->is_match(leaf_node<T, SAFE_MATH>::caches.nodes[i])) {
258 }
259 }
260#if defined(__clang__) || defined(__GNUC__)
262#else
263 assert(false && "Should never reach.");
264#endif
265 }
266
268 template<jit::float_scalar T, bool SAFE_MATH=false>
269 using shared_random_state = std::shared_ptr<random_state_node<T, SAFE_MATH>>;
270
271//------------------------------------------------------------------------------
279//------------------------------------------------------------------------------
280 template<jit::float_scalar T, bool SAFE_MATH=false>
282 return std::dynamic_pointer_cast<random_state_node<T, SAFE_MATH>> (x);
283 }
284
285//******************************************************************************
286// Random constant.
287//******************************************************************************
288//------------------------------------------------------------------------------
293//------------------------------------------------------------------------------
294 template<jit::float_scalar T, bool SAFE_MATH=false>
295 class random_node final : public straight_node<T, SAFE_MATH> {
296 private:
297
298//------------------------------------------------------------------------------
302//------------------------------------------------------------------------------
303 static std::string to_string() {
304 return "random";
305 }
306
307 public:
308//------------------------------------------------------------------------------
312//------------------------------------------------------------------------------
313 static void compile_random(std::ostringstream &stream) {
314 stream << "uint32_t random(";
315 if constexpr (jit::use_metal<T> ()) {
316 stream << "device ";
317 }
318 stream << "mt_state &state) {" << std::endl
319 << " const uint16_t k = state.index;" << std::endl
320 << " state.index = (k + 1) % 624;" << std::endl
321 << " uint32_t x = (state.array[k] & 0x80000000U) |" << std::endl
322 << " (state.array[state.index] & 0x7fffffffU);" << std::endl
323 << " uint32_t xA = x >> 1;" << std::endl
324 << " xA = x & 0x1U ? xA^0x9908b0dfU : xA;" << std::endl
325 << " const uint16_t j = (k + 397) % 624;" << std::endl
326 << " x = state.array[j]^xA;" << std::endl
327 << " state.array[k] = x;" << std::endl
328 << " uint32_t y = x^(x >> 11);" << std::endl
329 << " y = y^((y << 7) & 0x9d2c5680U);" << std::endl
330 << " y = y^((y << 15) & 0xefc60000U);" << std::endl
331 << " return y^(y >> 18);" << std::endl
332 << "}" << std::endl;
333 }
334
335//------------------------------------------------------------------------------
339//------------------------------------------------------------------------------
342
343//------------------------------------------------------------------------------
347//------------------------------------------------------------------------------
349 backend::buffer<T> result;
350 return result;
351 }
352
353//------------------------------------------------------------------------------
360//------------------------------------------------------------------------------
364
365//------------------------------------------------------------------------------
376//------------------------------------------------------------------------------
377 virtual void compile_preamble(std::ostringstream &stream,
378 jit::register_map &registers,
383 jit::preamble_map &pre_funcs,
384 int &avail_const_mem) {
385 if (!visited.contains(this)) {
386 this->arg->compile_preamble(stream, registers,
387 visited, usage,
389 pre_funcs, avail_const_mem);
390
391 visited.insert(this);
392#ifdef SHOW_USE_COUNT
393 usage[this] = 1;
394 } else {
395 ++usage[this];
396#endif
397 }
398
399// Need to do this after visited was checked so the random_state is created
400// first.
401 if (!pre_funcs.contains("random")) {
402 pre_funcs.insert("random");
403
405 }
406 }
407
408//------------------------------------------------------------------------------
416//------------------------------------------------------------------------------
418 compile(std::ostringstream &stream,
419 jit::register_map &registers,
421 const jit::register_usage &usage) {
422 if (registers.find(this) == registers.end()) {
423 auto a = this->arg->compile(stream, registers,
425
426 if constexpr (jit::complex_scalar<T>) {
427 registers[this] = "static_cast<"
428 + jit::get_type_string<T> ()
429 + "> (random("
430 + registers[a.get()] + "))";
431 } else {
432 registers[this] = "random(" + registers[a.get()] + ")";
433 }
434 }
435
436 return this->shared_from_this();
437 }
438
439//------------------------------------------------------------------------------
449//------------------------------------------------------------------------------
451 return false;
452 }
453
454//------------------------------------------------------------------------------
456//------------------------------------------------------------------------------
457 virtual void to_latex() const {
458 std::cout << "random(";
459 this->arg->to_latex();
460 std::cout << ")";
461 }
462
463//------------------------------------------------------------------------------
469//------------------------------------------------------------------------------
470 virtual shared_leaf<T, SAFE_MATH> to_vizgraph(std::stringstream &stream,
471 jit::register_map &registers) {
472 if (registers.find(this) == registers.end()) {
473 const std::string name = jit::to_string('r', this);
474 registers[this] = name;
475 stream << " " << name
476 << " [label = \"state\", shape = box, style = \"rounded,filled\", fillcolor = black, fontcolor = white];" << std::endl;
477
478 auto a = this->arg->to_vizgraph(stream, registers);
479 stream << " " << name << " -- " << registers[a.get()] << ";" << std::endl;
480 }
481
482 return this->shared_from_this();
483 }
484
485//------------------------------------------------------------------------------
489//------------------------------------------------------------------------------
491 return constant<T, SAFE_MATH> (static_cast<T> (1.0));
492 }
493 };
494
495//------------------------------------------------------------------------------
503//------------------------------------------------------------------------------
504 template<jit::float_scalar T, bool SAFE_MATH=false>
506 auto temp = std::make_shared<random_node<T, SAFE_MATH>> (state)->reduce();
507// Test for hash collisions.
508 for (size_t i = temp->get_hash();
510 if (leaf_node<T, SAFE_MATH>::caches.nodes.find(i) ==
513 return temp;
514 } else if (temp->is_match(leaf_node<T, SAFE_MATH>::caches.nodes[i])) {
516 }
517 }
518#if defined(__clang__) || defined(__GNUC__)
520#else
521 assert(false && "Should never reach.");
522#endif
523 }
524
526 template<jit::float_scalar T, bool SAFE_MATH=false>
527 using shared_random = std::shared_ptr<random_node<T, SAFE_MATH>>;
528
529//------------------------------------------------------------------------------
537//------------------------------------------------------------------------------
538 template<jit::float_scalar T, bool SAFE_MATH=false>
540 return std::dynamic_pointer_cast<random_node<T, SAFE_MATH>> (x);
541 }
542
543//------------------------------------------------------------------------------
550//------------------------------------------------------------------------------
551 template<jit::float_scalar T, bool SAFE_MATH=false>
553 return constant<T, SAFE_MATH> (static_cast<T> (std::numeric_limits<uint32_t>::max()));
554 }
555
556//------------------------------------------------------------------------------
566//------------------------------------------------------------------------------
567 template<jit::float_scalar T, jit::float_scalar R, bool SAFE_MATH=false>
569 const R max,
571 auto random = graph::random<T> (state);
572 return (max - min)/graph::random_scale<T> ()*random + min;
573 }
574}
575
576#endif /* random_h */
Class representing a generic buffer.
Definition backend.hpp:29
Class representing a node leaf.
Definition node.hpp:371
Class representing a random_node leaf.
Definition random.hpp:295
virtual void compile_preamble(std::ostringstream &stream, jit::register_map &registers, jit::visiter_map &visited, jit::register_usage &usage, jit::texture1d_list &textures1d, jit::texture2d_list &textures2d, jit::preamble_map &pre_funcs, int &avail_const_mem)
Compile preamble.
Definition random.hpp:377
virtual bool is_match(shared_leaf< T, SAFE_MATH > x)
Query if the nodes match.
Definition random.hpp:450
random_node(shared_random_state< T, SAFE_MATH > x)
Construct a constant node from a vector.
Definition random.hpp:340
virtual backend::buffer< T > evaluate()
Evaluate the results of random node.
Definition random.hpp:348
virtual shared_leaf< T, SAFE_MATH > get_power_exponent() const
Get the exponent of a power.
Definition random.hpp:490
virtual void to_latex() const
Convert the node to latex.
Definition random.hpp:457
static void compile_random(std::ostringstream &stream)
Write the preamble for the random function.
Definition random.hpp:313
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map &registers)
Convert the node to vizgraph.
Definition random.hpp:470
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map &registers, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition random.hpp:418
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition random.hpp:361
Random state.
Definition random.hpp:24
virtual shared_leaf< T, SAFE_MATH > to_vizgraph(std::stringstream &stream, jit::register_map &registers)
Convert the node to vizgraph.
Definition random.hpp:156
size_t size()
Get the size of the random state vector in bytes.
Definition random.hpp:182
virtual void compile_preamble(std::ostringstream &stream, jit::register_map &registers, jit::visiter_map &visited, jit::register_usage &usage, jit::texture1d_list &textures1d, jit::texture2d_list &textures2d, jit::preamble_map &pre_funcs, int &avail_const_mem)
Compile preamble.
Definition random.hpp:101
random_state_node(const size_t size, const uint32_t seed=0)
Construct a constant node from a vector.
Definition random.hpp:61
virtual shared_leaf< T, SAFE_MATH > df(shared_leaf< T, SAFE_MATH > x)
Transform node to derivative.
Definition random.hpp:85
virtual void to_latex() const
Convert the node to latex.
Definition random.hpp:145
virtual backend::buffer< T > evaluate()
Evaluate the results of random_state_node.
Definition random.hpp:74
size_t get_size_bytes()
Get the size of the random state vector in bytes.
Definition random.hpp:191
virtual shared_leaf< T, SAFE_MATH > get_power_exponent() const
Get the exponent of a power.
Definition random.hpp:173
mt_state * data()
Get the size of the random state vector in bytes.
Definition random.hpp:200
virtual shared_leaf< T, SAFE_MATH > compile(std::ostringstream &stream, jit::register_map &registers, const jit::register_map &thread_mem, const jit::register_usage &usage)
Compile the node.
Definition random.hpp:135
static void compile_random_state(std::ostringstream &stream)
Write the preamble for the random state struct.
Definition random.hpp:31
Class representing a straight node.
Definition node.hpp:1219
shared_leaf< T, SAFE_MATH > arg
Argument.
Definition node.hpp:1222
Complex scalar concept.
Definition register.hpp:25
subroutine assert(test, message)
Assert check.
Definition f_binding_test.f90:38
Name space for graph nodes.
Definition arithmetic.hpp:13
constexpr shared_leaf< T, SAFE_MATH > random_scale()
Create a random_scale constant.
Definition random.hpp:552
constexpr shared_leaf< T, SAFE_MATH > uniform_random(const R min, const R max, shared_random_state< T, SAFE_MATH > state)
Create a uniform random number.
Definition random.hpp:568
shared_random_state< T, SAFE_MATH > random_state_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a random_state node.
Definition random.hpp:281
constexpr shared_leaf< T, SAFE_MATH > zero()
Forward declare for zero.
Definition node.hpp:1154
shared_leaf< T, SAFE_MATH > random(shared_random_state< T, SAFE_MATH > state)
Define random convenience function.
Definition random.hpp:505
std::shared_ptr< random_state_node< T, SAFE_MATH > > shared_random_state
Convenience type alias for shared sqrt nodes.
Definition random.hpp:269
std::shared_ptr< random_node< T, SAFE_MATH > > shared_random
Convenience type alias for shared sqrt nodes.
Definition random.hpp:527
constexpr T i
Convenience type for imaginary constant.
Definition node.hpp:1186
shared_leaf< T, SAFE_MATH > min(shared_leaf< T, SAFE_MATH > l, shared_leaf< T, SAFE_MATH > r)
Build a max node from a condition and two leaves.
Definition logical.hpp:3266
std::shared_ptr< leaf_node< T, SAFE_MATH > > shared_leaf
Convenience type alias for shared leaf nodes.
Definition node.hpp:691
shared_random< T, SAFE_MATH > random_cast(shared_leaf< T, SAFE_MATH > x)
Cast to a random node.
Definition random.hpp:539
shared_leaf< T, SAFE_MATH > random_state(const size_t size, const uint32_t seed=0)
Define random_state convenience function.
Definition random.hpp:246
std::unordered_set< void * > visiter_map
Type alias for listing visited nodes.
Definition register.hpp:263
std::unordered_map< void *, size_t > register_usage
Type alias for counting register usage.
Definition register.hpp:261
std::unordered_set< std::string > preamble_map
Type alias for preamble defined functions.
Definition register.hpp:269
std::unordered_map< void *, std::string > register_map
Type alias for mapping node pointers to register names.
Definition register.hpp:259
std::unordered_map< void *, std::array< size_t, 2 > > texture2d_list
Type alias for indexing 2D textures.
Definition register.hpp:267
std::unordered_map< void *, size_t > texture1d_list
Type alias for indexing 1D textures.
Definition register.hpp:265
std::string to_string(const char prefix, const NODE *pointer)
Convert a graph::leaf_node pointer to a string.
Definition register.hpp:247
Base nodes of graph computation framework.
Random state structure.
Definition random.hpp:44
uint16_t index
State index.
Definition random.hpp:48
std::array< uint32_t, 624 > array
State array.
Definition random.hpp:46