26 #if defined (HAVE_CONFIG_H)
51 rand *rand::s_instance =
nullptr;
54 : m_current_distribution (uniform_dist), m_use_old_generators (false),
57 initialize_ranlib_generators ();
59 initialize_mersenne_twister ();
69 s_instance =
new rand ();
79 union d2i {
double d; int32_t i[2]; };
99 force_to_fit_range (int32_t i, int32_t lo, int32_t hi)
101 assert (hi > lo && lo >= 0);
103 i = (i > 0 ? i : -i);
114 rand::do_seed (
double s)
116 m_use_old_generators =
true;
119 union d2i {
double d; int32_t i[2]; };
128 i1 = force_to_fit_range (u.i[0], 1, 2147483563);
129 i0 = force_to_fit_range (u.i[1], 1, 2147483399);
133 i0 = force_to_fit_range (u.i[0], 1, 2147483563);
134 i1 = force_to_fit_range (u.i[1], 1, 2147483399);
144 m_use_old_generators =
true;
145 initialize_ranlib_generators ();
149 rand::do_state (
const std::string&
d)
151 return m_rand_states[
d.empty () ? m_current_distribution : get_dist_id (
d)];
157 m_use_old_generators =
false;
159 int old_dist = m_current_distribution;
161 int new_dist = (
d.empty () ? m_current_distribution : get_dist_id (
d));
165 if (old_dist != new_dist)
166 saved_state = get_internal_state ();
168 set_internal_state (s);
170 m_rand_states[new_dist] = get_internal_state ();
172 if (old_dist != new_dist)
173 m_rand_states[old_dist] = saved_state;
177 rand::do_reset (
const std::string&
d)
179 m_use_old_generators =
false;
181 int old_dist = m_current_distribution;
183 int new_dist = (
d.empty () ? m_current_distribution : get_dist_id (
d));
187 if (old_dist != new_dist)
188 saved_state = get_internal_state ();
191 m_rand_states[new_dist] = get_internal_state ();
193 if (old_dist != new_dist)
194 m_rand_states[old_dist] = saved_state;
198 rand::do_distribution ()
202 switch (m_current_distribution)
213 retval =
"exponential";
225 (*current_liboctave_error_handler)
226 (
"rand: invalid distribution ID = %d", m_current_distribution);
234 rand::do_distribution (
const std::string&
d)
236 int id = get_dist_id (
d);
261 (*current_liboctave_error_handler)
262 (
"rand: invalid distribution ID = %d", id);
268 rand::do_uniform_distribution ()
270 switch_to_generator (uniform_dist);
272 F77_FUNC (setcgn, SETCGN) (uniform_dist);
276 rand::do_normal_distribution ()
278 switch_to_generator (normal_dist);
280 F77_FUNC (setcgn, SETCGN) (normal_dist);
284 rand::do_exponential_distribution ()
286 switch_to_generator (expon_dist);
288 F77_FUNC (setcgn, SETCGN) (expon_dist);
292 rand::do_poisson_distribution ()
294 switch_to_generator (poisson_dist);
296 F77_FUNC (setcgn, SETCGN) (poisson_dist);
300 rand::do_gamma_distribution ()
302 switch_to_generator (gamma_dist);
304 F77_FUNC (setcgn, SETCGN) (gamma_dist);
309 rand::uniform<double> ()
313 if (m_use_old_generators)
323 rand::normal<double> ()
327 if (m_use_old_generators)
337 rand::exponential<double> ()
341 if (m_use_old_generators)
351 rand::poisson<double> (
double a)
355 if (m_use_old_generators)
374 rand::gamma<double> (
double a)
378 if (m_use_old_generators)
386 retval = rand_gamma<double> (a);
396 if (m_use_old_generators)
409 if (m_use_old_generators)
422 if (m_use_old_generators)
431 OCTAVE_API float rand::poisson<float> (
float a)
435 if (m_use_old_generators)
460 if (m_use_old_generators)
468 retval = rand_gamma<float> (a);
473 template <
typename T>
475 rand::do_scalar (T a)
479 switch (m_current_distribution)
482 retval = uniform<T> ();
486 retval = normal<T> ();
490 retval = exponential<T> ();
494 retval = poisson<T> (a);
498 retval = gamma<T> (a);
502 (*current_liboctave_error_handler)
503 (
"rand: invalid distribution ID = %d", m_current_distribution);
507 if (! m_use_old_generators)
513 template OCTAVE_API double rand::do_scalar<double> (
double);
514 template OCTAVE_API float rand::do_scalar<float> (
float);
516 template <
typename T>
529 (*current_liboctave_error_handler) (
"rand: invalid negative argument");
540 rand::do_nd_array (
const dim_vector& dims,
double a)
555 rand::do_float_nd_array (
const dim_vector& dims,
float a)
575 rand::initialize_ranlib_generators ()
578 int stored_distribution = m_current_distribution;
579 F77_FUNC (setcgn, SETCGN) (uniform_dist);
581 int hour = tm.hour () + 1;
582 int minute = tm.min () + 1;
583 int second = tm.sec () + 1;
585 int32_t s0 = tm.mday () * hour * minute * second;
586 int32_t s1 = hour * minute * second;
588 s0 = force_to_fit_range (s0, 1, 2147483563);
589 s1 = force_to_fit_range (s1, 1, 2147483399);
592 F77_FUNC (setcgn, SETCGN) (stored_distribution);
596 rand::initialize_mersenne_twister ()
601 s = get_internal_state ();
602 m_rand_states[uniform_dist] = s;
605 s = get_internal_state ();
606 m_rand_states[normal_dist] = s;
609 s = get_internal_state ();
610 m_rand_states[expon_dist] = s;
613 s = get_internal_state ();
614 m_rand_states[poisson_dist] = s;
617 s = get_internal_state ();
618 m_rand_states[gamma_dist] = s;
622 set_internal_state (m_rand_states[m_current_distribution]);
626 rand::get_internal_state ()
638 m_rand_states[m_current_distribution] = get_internal_state ();
642 rand::get_dist_id (
const std::string&
d)
644 int retval = unknown_dist;
646 if (
d ==
"uniform" ||
d ==
"rand")
647 retval = uniform_dist;
648 else if (
d ==
"normal" ||
d ==
"randn")
649 retval = normal_dist;
650 else if (
d ==
"exponential" ||
d ==
"rande")
652 else if (
d ==
"poisson" ||
d ==
"randp")
653 retval = poisson_dist;
654 else if (
d ==
"gamma" ||
d ==
"randg")
658 (
"rand: invalid distribution '%s'",
d.c_str ());
668 const uint32_t *sdata =
reinterpret_cast <const uint32_t *
> (s.
data ());
677 rand::switch_to_generator (
int dist)
679 if (dist != m_current_distribution)
681 m_current_distribution = dist;
683 set_internal_state (m_rand_states[dist]);
693 switch (m_current_distribution)
696 if (m_use_old_generators)
703 if (m_use_old_generators)
710 if (m_use_old_generators)
717 if (m_use_old_generators)
734 if (m_use_old_generators)
742 rand_gamma<double> (a,
len, v);
746 (*current_liboctave_error_handler)
747 (
"rand: invalid distribution ID = %d", m_current_distribution);
762 switch (m_current_distribution)
765 if (m_use_old_generators)
772 if (m_use_old_generators)
779 if (m_use_old_generators)
786 if (m_use_old_generators)
803 if (m_use_old_generators)
811 rand_gamma<float> (a,
len, v);
815 (*current_liboctave_error_handler)
816 (
"rand: invalid distribution ID = %d", m_current_distribution);
825 OCTAVE_END_NAMESPACE(
octave)
T * fortran_vec()
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Vector representing the dimensions (size) of an Array.
static void uniform_distribution()
static void exponential_distribution()
static bool instance_ok()
static void gamma_distribution()
static void normal_distribution()
static void poisson_distribution()
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
subroutine getsd(iseed1, iseed2)
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE * x
float_format native_float_format()
@ flt_fmt_ieee_big_endian
void get_mersenne_twister_state(uint32_t *save)
double rand_uniform< double >()
void set_mersenne_twister_state(const uint32_t *save)
double rand_normal< double >()
void init_mersenne_twister(const uint32_t s)
float rand_normal< float >()
float rand_exponential< float >()
double rand_exponential< double >()
float rand_uniform< float >()
template void rand_poisson< double >(double, octave_idx_type, double *)
template void rand_poisson< float >(float, octave_idx_type, float *)
subroutine setall(iseed1, iseed2)
subroutine setsd(iseed1, iseed2)
subroutine fignpoi(mu, result)
subroutine fgennor(av, sd, result)
subroutine dgenunf(low, high, result)
subroutine fgenexp(av, result)
subroutine dgengam(a, r, result)
subroutine dgenexp(av, result)
subroutine fgengam(a, r, result)
subroutine fgenunf(low, high, result)
subroutine dgennor(av, sd, result)
subroutine dignpoi(mu, result)
F77_RET_T F77_FUNC(xerbla, XERBLA)(F77_CONST_CHAR_ARG_DEF(s_arg