libvisual  0.5.0
lv_random.cpp
1 /* Libvisual - The audio visualisation framework.
2  *
3  * Copyright (C) 2012 Libvisual team
4  * 2004-2006 Dennis Smit
5  *
6  * Authors: Chong Kai Xiong <kaixiong@codeleft.sg>
7  8 Dennis Smit <ds@nerds-incorporated.org>
8  * Vitaly V. Bursov <vitalyvb@ukr.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as
12  * published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  */
24 
25 #include "config.h"
26 #include "lv_random.h"
27 #include "lv_common.h"
28 #include <random>
29 
30 namespace LV {
31 
32  typedef std::minstd_rand Generator;
33 
34  class RandomContext::Impl
35  {
36  public:
37 
38  Generator generator;
39  };
40 
42  : m_impl (new Impl)
43  {
44  set_seed (seed);
45  }
46 
48  : m_impl {std::move (rhs.m_impl)}
49  {
50  // empty
51  }
52 
54  {
55  // empty
56  }
57 
58  RandomContext& RandomContext::operator= (RandomContext&& rhs)
59  {
60  m_impl.swap (rhs.m_impl);
61  return *this;
62  }
63 
64  void RandomContext::set_seed (Seed seed)
65  {
66  m_impl->generator.seed (seed);
67  }
68 
70  {
71  return m_impl->generator ();
72  }
73 
74  uint32_t RandomContext::get_int (unsigned int min, unsigned int max)
75  {
76  #if VISUAL_RANDOM_FAST_FP_RND
77  // FIXME: Test this to see if this is really faster or produce
78  // better distributed numbers
79 
80  // Uses fast floating number generator and two divisions elimitated.
81  // More than 2 times faster than original.
82  float fm = min; // +10% speedup...
83 
84  return get_float () * (max - min + 1) + fm;
85  #else
86  return get_int () % (max - min + 1) + min;
87  #endif
88  }
89 
91  {
92  uint32_t irnd = m_impl->generator ();
93 
94  #if VISUAL_RANDOM_FAST_FP_RND
95  union {
96  unsigned int i[2];
97  double d;
98  } value;
99 
100  // This saves floating point division (20 clocks on AXP, 38 on P4)
101  // and introduces store-to-load data size mismatch penalty and
102  // substraction op.
103  // Faster on AXP anyway :)
104  value.i[0] = (irnd << 20);
105  value.i[1] = 0x3ff00000 | (irnd >> 12);
106  return value.d - 1.0;
107  #else
108  return double (irnd) / Generator::max ();
109  #endif
110  }
111 
113  {
114  uint32_t irnd = m_impl->generator ();
115 
116  #if VISUAL_RANDOM_FAST_FP_RND
117  // Saves floating point division. Introduces substraction. Yet faster! :)
118 
119  union {
120  unsigned int i;
121  float f;
122  } value;
123 
124  value.i = 0x3f800000 | (t >> 9);
125  return value.f - 1.0f;
126  #else
127  return float (irnd) / Generator::max ();
128  #endif
129  }
130 
131 } // LV namespace