Xmipp  v3.23.11-Nereus
xmipp_marsaglia.h
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: David Strelak (davidstrelak@gmail.com)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #ifndef XMIPPCORE_CORE_XMIPP_MARSAGLIA_H_
27 #define XMIPPCORE_CORE_XMIPP_MARSAGLIA_H_
28 
57 template <typename T>
58 class Marsaglia
59 {
60 private:
61  char* random_vector; // read the data right here
62  T* T_random_vector;
63  long pointer_in_memory;
64  FileName fn_rand;
65  long vector_size;
66  long Number_of_Numbers;
67 
68 public:
79  Marsaglia(const FileName& fn_in, int No_Numbers)
80  {
81  Init(fn_in, No_Numbers);
82  }
83 
86  {}
87 
90  void Init(const FileName& fn_in, int No_Numbers)
91  {
92  int Type_size; // sizeof(type)
93 
94  pointer_in_memory = 0;
95  Number_of_Numbers = No_Numbers; // initialize class variable
96  Type_size = sizeof(T);
97 
98  std::ifstream in(fn_in.c_str());
99  in.seekg(0, std::ios::end); // End of file
100  std::streampos sp = in.tellg(); // Size of file
101  if (sp < Number_of_Numbers * Type_size)
102  REPORT_ERROR(ERR_IO_SIZE, (std::string) "Marsaglia::Init: File " + fn_in +
103  "is too small");
104  else
105  {
106  // get a random number to set the file pointer at a random position
108 
109  random_vector = new char[(Number_of_Numbers * Type_size)];
110  T_random_vector = (T*) random_vector;
111  in.seekg((std::streampos) FLOOR(rnd_unif(0.f, (double)(sp -
112  (std::streamoff)(Number_of_Numbers * Type_size)))), std::ios::beg);
113  in.read(random_vector, (Number_of_Numbers * Type_size));
114 
115  in.close();
116  }
117  if (typeid(double) == typeid(T))
118  Verify_double();
119  }
120 
127  {
128  if (pointer_in_memory >= Number_of_Numbers)
129  pointer_in_memory = (int) FLOOR(rnd_unif(0.f, (double)
130  (Number_of_Numbers - 1)));
131  return (T_random_vector[pointer_in_memory++]);
132  }
133 
137  {
138  if (typeid(double) != typeid(T) && typeid(double) != typeid(T))
140  "Marsaglia: I do not know how to calculate integer logs");
141 
142  for (int hh = 0; hh < Number_of_Numbers; hh++)
143  if (T_random_vector[hh] == 0.)
144  T_random_vector[hh] = -1e+20f;
145  else
146  T_random_vector[hh] = log(T_random_vector[hh]);
147  }
148 
151  void mul(T mul_cte)
152  {
153  for (int hh = 0; hh < Number_of_Numbers; hh++)
154  T_random_vector[hh] *= mul_cte;
155  }
156 
159  void operator&= (T mod_cte)
160  {
161  for (int hh = 0; hh < Number_of_Numbers; hh++)
162  T_random_vector[hh] &= mod_cte;
163  }
164 
167  void add(T add_cte)
168  {
169  for (int hh = 0; hh < Number_of_Numbers; hh++)
170  T_random_vector[hh] += add_cte;
171  }
172 
175  void M_max(const FileName& fn_in, T m_max)
176  {
177  int Type_size; // sizeof(type)
178  Type_size = sizeof(T);
179 
180  std::ifstream in(fn_in.c_str());
181  in.seekg(0, std::ios::end); // End of file
182  std::streampos sp = in.tellg(); // Size of file
183  T power_of_2 = (T) NEXT_POWER_OF_2(m_max);
184  if (power_of_2 == m_max)
185  power_of_2 = (T) NEXT_POWER_OF_2(m_max + 1);
186  T mask = power_of_2 - 1;
187  T aux_number;
188 
189  // get a random number to set the file pointer at a random position
190  in.seekg((std::streampos) FLOOR(rnd_unif(0.f, (double)(sp -
191  (std::streamoff)(Number_of_Numbers*Type_size)))), std::ios::beg);
192  for (int ii = 0; ii < Number_of_Numbers;)
193  {
194  aux_number = T_random_vector[ii];
195  aux_number &= mask;
196  if (aux_number > m_max ||
197  (T_random_vector[ii] <= 0) && (aux_number == 0))
198  {
199  if (in.eof())
200  in.seekg((std::streampos) FLOOR(rnd_unif(0.f, (double)
201  (sp - (std::streamoff)(Number_of_Numbers*Type_size)))),
202  std::ios::beg);
203  in.read((char*) &(T_random_vector[ii]), Type_size);
204  }
205  else
206  {
207  T_random_vector[ii] = aux_number * (T) SGN(T_random_vector[ii]);
208  ii++;
209  }
210  }
211  in.close();
212  }
213 
214 private:
224  void Verify_double()
225  {
226  unsigned int* int_random_vector;
227  long long MaxInteger;
228  static_assert(sizeof(double) != sizeof(int), "I do not know how to make the double correction");
229  MaxInteger = (long long) pow(2.0, sizeof(unsigned int) * 8.0);
230  int_random_vector = (unsigned int*) random_vector;
231  for (int hh = 0; hh < Number_of_Numbers; hh++)
232  T_random_vector[hh] = (T)((double) int_random_vector[hh] /
233  (double) MaxInteger);
234  }
235 };
236 
237 #endif /* XMIPPCORE_CORE_XMIPP_MARSAGLIA_H_ */
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void add(T add_cte)
void mul(T mul_cte)
void M_max(const FileName &fn_in, T m_max)
Marsaglia(const FileName &fn_in, int No_Numbers)
void Init(const FileName &fn_in, int No_Numbers)
double rnd_unif()
#define FLOOR(x)
Definition: xmipp_macros.h:240
void log(Image< double > &op)
int in
double * f
Marsaglia()
Empty constructor.
void operator &=(T mod_cte)
#define NEXT_POWER_OF_2(x)
Definition: xmipp_macros.h:374
Incorrect file size.
Definition: xmipp_error.h:145
unsigned int randomize_random_generator()
Incorrect type received.
Definition: xmipp_error.h:190
#define SGN(x)
Definition: xmipp_macros.h:155
void Marsaglia_log()