CASM  1.1.0
A Clusters Approach to Statistical Mechanics
CASM_math.cc
Go to the documentation of this file.
1 #include "casm/misc/CASM_math.hh"
2 
3 #include <map>
4 
5 #include "casm/global/eigen.hh"
6 
7 namespace CASM {
8 //*******************************************************************************************
9 
10 int round(double val) {
11  return int(val < 0 ? floor(val + 0.5) : ceil(val - 0.5));
12 };
13 
14 //*******************************************************************************************
15 
16 double ran0(int &idum) {
17  int IA = 16807;
18  int IM = 2147483647;
19  int IQ = 127773;
20  int IR = 2836;
21  int MASK = 123459876;
22  double AM = 1.0 / IM;
23 
24  // minimal random number generator of Park and Miller
25  // returns uniform random deviate between 0.0 and 1.0
26  // set or rest idum to any integer value (except the
27  // unlikely value MASK) to initialize the sequence: idum must
28  // not be altered between calls for successive deviates
29  // in a sequence
30 
31  int k;
32  idum = idum ^ MASK; // XOR the two integers
33  k = idum / IQ;
34  idum = IA * (idum - k * IQ) - IR * k;
35  if (idum < 0) {
36  idum = idum + IM;
37  }
38  double ran = AM * idum;
39  idum = idum ^ MASK;
40  return ran;
41 }
42 
43 //*******************************************************************************************
44 
45 int dl_string_dist(const std::string &a, const std::string &b) {
46  // "infinite" distance is just the max possible distance
47  int max_val = a.size() + b.size();
48 
49  // make and initialize the character array indices
50  std::map<char, int> DA;
51 
52  // make the distance matrix H
53  Eigen::MatrixXi H(a.size() + 2, b.size() + 2);
54 
55  // initialize the left and top edges of H
56  H(0, 0) = max_val;
57  for (int i = 0; i <= a.size(); ++i) {
58  DA[a[i]] = 0;
59  H(i + 1, 0) = max_val;
60  H(i + 1, 1) = i;
61  }
62  for (int j = 0; j <= b.size(); ++j) {
63  DA[b[j]] = 0;
64  H(0, j + 1) = max_val;
65  H(1, j + 1) = j;
66  }
67 
68  // fill in the distance matrix H
69  // look at each character in a
70  for (int i = 1; i <= a.size(); ++i) {
71  int DB = 0;
72  // look at each character in b
73  for (int j = 1; j <= b.size(); ++j) {
74  int i1 = DA[b[j - 1]];
75  int j1 = DB;
76  int cost;
77  if (a[i - 1] == b[j - 1]) {
78  cost = 0;
79  DB = j;
80  } else
81  cost = 1;
82  H(i + 1, j + 1) = min(min(H(i, j) + cost, // substitution
83  H(i + 1, j) + 1), // insertion
84  min(H(i, j + 1) + 1, // deletion
85  H(i1, j1) + (i - i1 - 1) + 1 + (j - j1 - 1)));
86  }
87  DA[a[i - 1]] = i;
88  }
89  return H(a.size() + 1, b.size() + 1);
90 }
91 
92 //*******************************************************************************************
94 int gcf(int i1, int i2) {
95  i1 = std::abs(i1);
96  i2 = std::abs(i2);
97  while (i1 != i2 && i1 != 1 && i2 != 1) {
98  if (i1 < i2) {
99  i2 -= i1;
100  } else {
101  i1 -= i2;
102  }
103  }
104  if (i1 == 1) {
105  return i1;
106  } else {
107  return i2;
108  }
109 }
110 
111 //*******************************************************************************************
113 int lcm(int i1, int i2) { return std::abs(i1 * (i2 / gcf(i1, i2))); }
114 
115 //*******************************************************************************************
116 // This evaluates Gaussians using the formula:
117 // f(x) = a*e^(-(x-b)^2/(c^2))
118 //*******************************************************************************************
119 
120 double gaussian(double a, double x, double b, double c) {
121  return a * exp(-((x - b) * (x - b)) / (c * c));
122 }
123 
124 //*******************************************************************************************
125 // This calculates Gaussian moments given by the integral:
126 // m = \int_{\infty}^{\infty} dx
127 // x^pow*exp[-x^2/(2*sigma^2)]/(\sqrt(2*\pi)*sigma)
128 //*******************************************************************************************
129 
130 double gaussian_moment(int expon, double sigma) {
131  if (expon % 2) return 0.0;
132 
133  double m = pow(sigma, expon);
134 
135  expon -= 1;
136  while (expon - 2 > 0) {
137  m *= double(expon);
138  expon -= 2;
139  }
140  return m;
141 }
142 
143 //*******************************************************************************************
144 // This calculates Gaussian moments given by the integral:
145 // m = \int_{\infty}^{\infty} dx
146 // x^pow*exp[-(x-x0)^2/(2*sigma^2)]/(\sqrt(2*\pi)*sigma)
147 //*******************************************************************************************
148 
149 double gaussian_moment(int expon, double sigma, double x0) {
150  double m = 0;
151  for (int i = 0; i <= expon; i++) {
152  m += nchoosek(expon, i) * gaussian_moment(i, sigma) * pow(x0, expon - i);
153  }
154 
155  return m;
156 }
157 
158 //*******************************************************************************************
159 // finds rational number that approximates 'val' to within 'tol' --
160 // -- almost_int(double(denominator)*val, tol) == true OR
161 // almost_int(val/double(numerator), tol) == true OR
162 // -- denominator is always positive
163 // -- sign(numerator)=sign(val)
164 // -- if(almost_zero(val,tol)) --> numerator = 0, denominator = 1
165 void nearest_rational_number(double val, long &numerator, long &denominator,
166  double tol) {
167  if (almost_zero(val, tol)) {
168  numerator = 0;
169  denominator = 1;
170  return;
171  }
172  long sgn(val < 0 ? -1 : 1);
173  val = std::abs(val);
174  double tdenom, tnum;
175  long lim(max(long(100), long(1 / (10 * tol))));
176  for (long i = 1; i < lim + 1; i++) {
177  tdenom = double(i) / val;
178  tnum = val / double(i);
179  if (tdenom > 1 && almost_zero(tdenom - round(tdenom), tol)) {
180  numerator = sgn * i;
181  denominator = round(tdenom);
182  return;
183  } else if (tnum > 1 && almost_zero(tnum - round(tnum), tol)) {
184  denominator = i;
185  numerator = sgn * round(tnum);
186  return;
187  }
188  }
189 }
190 
191 //*******************************************************************************************
192 /* Finds best irrational number approximation of double 'val' and
193  * returns tex-formated string that contains irrational approximation
194  * searches numbers of the form (x/y)^(1/z), where x and y range from 1 to 'lim'
195  * z ranges from 1 to 'max_pow'
196  */
197 //*******************************************************************************************
198 
199 std::string irrational_to_tex_string(double val, int lim, int max_pow) {
200  std::stringstream tstr;
201  if (almost_zero(round(val) - val)) {
202  tstr << round(val);
203  return tstr.str();
204  }
205  if (val < 0) {
206  tstr << '-';
207  val = std::abs(val);
208  }
209  double tval(val), tdenom, tnum;
210  int idenom, inum;
211  for (int ipow = 1; ipow < max_pow + 1; ipow++) {
212  for (int i = 1; i < lim + 1; i++) {
213  tdenom = double(i) / tval;
214  tnum = tval / double(i);
215  if (tdenom > 1 && almost_zero(std::abs(tdenom - round(tdenom)))) {
216  inum = i;
217  idenom = round(tdenom);
218  } else if (tnum > 1 && almost_zero(std::abs(tnum - round(tnum)))) {
219  idenom = i;
220  inum = round(tnum);
221  } else {
222  continue;
223  }
224 
225  if (ipow == 1) {
226  tstr << inum << '/' << idenom;
227  return tstr.str();
228  }
229  if (ipow == 2) {
230  tstr << "\\sqrt{" << inum;
231  if (idenom != 1) tstr << '/' << idenom;
232  tstr << '}';
233  return tstr.str();
234  } else {
235  tstr << '(' << inum;
236  if (idenom != 1) tstr << '/' << idenom;
237  tstr << ")^{1/" << ipow << "}";
238  return tstr.str();
239  }
240  }
241  tval *= val;
242  }
243  tstr << val;
244  return tstr.str();
245 }
246 
247 //*******************************************************************************************
248 std::string to_sequential_string(Index i, Index max_i,
249  char prepend_char /*='0'*/) {
250  max_i = max(i, max_i);
251  Index length = 1;
252  while (max_i /= 10) length++;
253 
254  std::string tresult = std::to_string(i);
255 
256  std::string result(length - tresult.size(), prepend_char);
257  return result.append(tresult);
258 }
259 
260 //*******************************************************************************************
261 // John G 010413
262 int mod(int a, int b) {
263  if (b < 0) return mod(-a, -b);
264 
265  int ret = a % b;
266  if (ret < 0) ret += b;
267  return ret;
268 }
269 
270 //*******************************************************************************************
271 
272 double cuberoot(double number) {
273  if (number < 0) {
274  return -pow(-number, 1.0 / 3);
275  }
276 
277  else {
278  return pow(number, 1.0 / 3);
279  }
280 }
281 
282 } // namespace CASM
std::string to_string(ENUM val)
Return string representation of enum class.
Definition: io_traits.hh:172
Eigen::CwiseUnaryOp< decltype(Local::round_l< typename Derived::Scalar >), const Derived > round(const Eigen::MatrixBase< Derived > &val)
Round Eigen::MatrixXd.
Main CASM namespace.
Definition: APICommand.hh:8
double gaussian_moment(int expon, double sigma)
Definition: CASM_math.cc:130
void nearest_rational_number(double val, long &numerator, long &denominator, double tol=TOL)
Definition: CASM_math.cc:165
double cuberoot(double number)
Definition: CASM_math.cc:272
IntType nchoosek(IntType n, IntType k)
Definition: CASM_math.hh:207
std::string to_sequential_string(Index i, Index max_i, char prepend_char='0')
Definition: CASM_math.cc:248
int sgn(T val)
Definition: CASM_math.hh:180
int lcm(const Array< int > &series)
Find least common multiple.
bool almost_zero(const T &val, double tol=TOL)
If T is not integral, use std::abs(val) < tol;.
Definition: CASM_math.hh:104
int dl_string_dist(const std::string &a, const std::string &b)
Computes the Damerescau-Levenshtein distance – the number of edits (deletions, insertions,...
Definition: CASM_math.cc:45
T min(const T &A, const T &B)
Definition: CASM_math.hh:88
std::string irrational_to_tex_string(double val, int lim, int max_pow=2)
Definition: CASM_math.cc:199
int mod(int a, int b)
Definition: CASM_math.cc:262
double gaussian(double a, double x, double b, double c)
Definition: CASM_math.cc:120
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
double ran0(int &idum)
Definition: CASM_math.cc:16
int gcf(int i1, int i2)
Find greatest common factor.
Definition: CASM_math.cc:94
T max(const T &A, const T &B)
Definition: CASM_math.hh:95
double length(const Eigen::MatrixBase< Derived > &value)