You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ABACUS_Utils.h 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: ABACUS_util.h
  6. Purpose: Defines basic math functions.
  7. ***********************************************************/
  8. #ifndef ABACUS_UTIL_H
  9. #define ABACUS_UTIL_H
  10. #include "ABACUS.h"
  11. typedef double DP;
  12. // Global constants
  13. const double PI = 3.141592653589793238462643;
  14. const double sqrtPI = sqrt(PI);
  15. const double twoPI = 2.0*PI;
  16. const double logtwoPI = log(twoPI);
  17. const double Euler_Mascheroni = 0.577215664901532860606;
  18. const double Gamma_min_0p5 = -2.0 * sqrt(PI);
  19. const std::complex<double> II(0.0,1.0); // Shorthand for i
  20. const DP MACHINE_EPS = std::numeric_limits<DP>::epsilon();
  21. const DP MACHINE_EPS_SQ = pow(MACHINE_EPS, 2.0);
  22. // Now for some basic math utilities:
  23. namespace ABACUS {
  24. // Inexplicably missing string functions in standard library:
  25. inline std::string DP_to_string (DP value) {
  26. std::stringstream s;
  27. s << std::setprecision(16) << value;
  28. return s.str();
  29. }
  30. inline std::string replace(const std::string& str,
  31. const std::string& from,
  32. const std::string& to) {
  33. std::string repl = str;
  34. size_t start_pos = repl.find(from);
  35. if(start_pos < std::string::npos)
  36. repl.replace(start_pos, from.length(), to);
  37. return repl;
  38. }
  39. inline std::string replace_all(const std::string& str,
  40. const std::string& from,
  41. const std::string& to) {
  42. std::string repl = str;
  43. if(from.empty())
  44. return repl;
  45. size_t start_pos = 0;
  46. while((start_pos = repl.find(from, start_pos)) != std::string::npos) {
  47. repl.replace(start_pos, from.length(), to);
  48. start_pos += to.length();
  49. }
  50. return repl;
  51. }
  52. // File checks:
  53. inline unsigned int count_lines(std::string filename)
  54. {
  55. std::ifstream infile(filename);
  56. return(std::count(std::istreambuf_iterator<char>(infile),
  57. std::istreambuf_iterator<char>(), '\n'));
  58. }
  59. inline bool file_exists (const char* filename)
  60. {
  61. std::fstream file;
  62. file.open(filename);
  63. bool exists = !file.fail();
  64. file.close();
  65. return(exists);
  66. }
  67. // Error handler:
  68. inline void ABACUSerror (const std::string error_text)
  69. // my error handler
  70. {
  71. std::cerr << "Run-time error... " << std::endl;
  72. std::cerr << error_text << std::endl;
  73. std::cerr << "Exiting to system..." << std::endl;
  74. exit(1);
  75. }
  76. struct Divide_by_zero {};
  77. // Basics: min, max, fabs
  78. template<class T>
  79. inline const T max (const T& a, const T& b) { return a > b ? (a) : (b); }
  80. template<class T>
  81. inline const T min (const T& a, const T& b) { return a > b ? (b) : (a); }
  82. template<class T>
  83. inline const T fabs (const T& a) { return a >= 0 ? (a) : (-a); }
  84. inline long long int pow_lli (const long long int& base, const int& exp)
  85. {
  86. long long int answer = base;
  87. if (exp == 0) answer = 1LL;
  88. else for (int i = 1; i < exp; ++i) answer *= base;
  89. return(answer);
  90. }
  91. inline unsigned long long int pow_ulli (const unsigned long long int& base, const int& exp)
  92. {
  93. unsigned long long int answer = base;
  94. if (exp == 0) answer = 1ULL;
  95. for (int i = 1; i < exp; ++i) answer *= base;
  96. return(answer);
  97. }
  98. inline int fact (const int& N)
  99. {
  100. int ans = 0;
  101. if (N < 0) {
  102. std::cerr << "Error: factorial of negative number. Exited."
  103. << std::endl;
  104. exit(1);
  105. }
  106. else if ( N == 1 || N == 0) ans = 1;
  107. else ans = N * fact(N-1);
  108. return(ans);
  109. }
  110. inline DP ln_fact (const int& N)
  111. {
  112. DP ans = 0.0;
  113. if (N < 0) {
  114. std::cerr << "Error: factorial of negative number. Exited."
  115. << std::endl;
  116. exit(1);
  117. }
  118. else if ( N == 1 || N == 0) ans = 0.0;
  119. else ans = log(DP(N)) + ln_fact(N-1);
  120. return(ans);
  121. }
  122. inline long long int fact_lli (const int& N)
  123. {
  124. long long int ans = 0;
  125. if (N < 0) {
  126. std::cerr << "Error: factorial of negative number. Exited."
  127. << std::endl;
  128. exit(1);
  129. }
  130. else if ( N == 1 || N == 0) ans = 1;
  131. else ans = fact_lli(N-1) * N;
  132. return(ans);
  133. }
  134. inline long long int fact_ulli (const int& N)
  135. {
  136. unsigned long long int ans = 0;
  137. if (N < 0) {
  138. std::cerr << "Error: factorial of negative number. Exited."
  139. << std::endl;
  140. exit(1);
  141. }
  142. else if ( N == 1 || N == 0) ans = 1;
  143. else ans = fact_ulli(N-1) * N;
  144. return(ans);
  145. }
  146. inline int choose (const int& N1, const int& N2)
  147. {
  148. // returns N1 choose N2
  149. int ans = 0;
  150. if (N1 < N2) {
  151. std::cout << "Error: N1 smaller than N2 in choose. Exited."
  152. << std::endl;
  153. exit(1);
  154. }
  155. else if (N1 == N2) ans = 1;
  156. else if (N1 < 12) ans = fact(N1)/(fact(N2) * fact(N1 - N2));
  157. else {
  158. ans = 1;
  159. int mult = N1;
  160. while (mult > max(N2, N1 - N2)) ans *= mult--;
  161. ans /= fact(min(N2, N1 - N2));
  162. }
  163. return(ans);
  164. }
  165. inline DP ln_choose (const int& N1, const int& N2)
  166. {
  167. // returns the log of N1 choose N2
  168. DP ans = 0.0;
  169. if (N1 < N2) {
  170. std::cout << "Error: N1 smaller than N2 in choose. Exited."
  171. << std::endl;
  172. exit(1);
  173. }
  174. else if (N1 == N2) ans = 0.0;
  175. else ans = ln_fact(N1) - ln_fact(N2) - ln_fact(N1 - N2);
  176. return(ans);
  177. }
  178. inline long long int choose_lli (const int& N1, const int& N2)
  179. {
  180. // returns N1 choose N2
  181. long long int ans = 0;
  182. if (N1 < N2) {
  183. std::cout << "Error: N1 smaller than N2 in choose. Exited."
  184. << std::endl;
  185. exit(1);
  186. }
  187. else if (N1 == N2) ans = 1;
  188. else if (N1 < 12) ans = fact_lli(N1)/(fact_lli(N2) * fact_lli(N1 - N2));
  189. else {
  190. // Make sure that N2 is less than or equal to N1/2; if not, just switch
  191. int N2_min = min(N2, N1 - N2);
  192. ans = 1;
  193. for (int i = 0; i < N2_min; ++i) {
  194. ans *= (N1 - i);
  195. ans /= i + 1;
  196. }
  197. }
  198. return(ans);
  199. }
  200. inline unsigned long long int choose_ulli (const int& N1, const int& N2)
  201. {
  202. // returns N1 choose N2
  203. unsigned long long int ans = 0;
  204. if (N1 < N2) {
  205. std::cout << "Error: N1 smaller than N2 in choose. Exited."
  206. << std::endl;
  207. exit(1);
  208. }
  209. else if (N1 == N2) ans = 1;
  210. else if (N1 < 12) ans = fact_ulli(N1)/(fact_ulli(N2) * fact_ulli(N1 - N2));
  211. else {
  212. // Make sure that N2 is less than or equal to N1/2; if not, just switch
  213. int N2_min = min(N2, N1 - N2);
  214. ans = 1;
  215. for (int i = 0; i < N2_min; ++i) {
  216. ans *= (N1 - i);
  217. ans /= i + 1;
  218. }
  219. }
  220. return(ans);
  221. }
  222. inline DP SIGN (const DP &a, const DP &b)
  223. {
  224. return b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a);
  225. }
  226. inline DP sign_of (const DP& a)
  227. {
  228. return (a >= 0.0 ? 1.0 : -1.0);
  229. }
  230. inline int sgn_int (const int& a)
  231. {
  232. return (a >= 0) ? 1 : -1;
  233. }
  234. inline int sgn_DP (const DP& a)
  235. {
  236. return (a >= 0) ? 1 : -1;
  237. }
  238. template<class T>
  239. inline void SWAP (T& a, T& b) {T dum = a; a = b; b = dum;}
  240. inline int kronecker (int a, int b)
  241. {
  242. return a == b ? 1 : 0;
  243. }
  244. template<class T>
  245. inline bool is_nan (const T& a)
  246. {
  247. return(!((a < T(0.0)) || (a >= T(0.0))));
  248. }
  249. inline std::complex<DP> atan_cx(const std::complex<DP>& x)
  250. {
  251. return(-0.5 * II * log((1.0 + II* x)/(1.0 - II* x)));
  252. }
  253. /**************** Gamma function *******************/
  254. inline std::complex<double> ln_Gamma (std::complex<double> z)
  255. {
  256. // Implementation of Lanczos method with g = 9.
  257. // Coefficients from Godfrey 2001.
  258. if (real(z) < 0.5) return(log(PI/(sin(PI*z))) - ln_Gamma(1.0 - z));
  259. else {
  260. std::complex<double> series = 1.000000000000000174663
  261. + 5716.400188274341379136/z
  262. - 14815.30426768413909044/(z + 1.0)
  263. + 14291.49277657478554025/(z + 2.0)
  264. - 6348.160217641458813289/(z + 3.0)
  265. + 1301.608286058321874105/(z + 4.0)
  266. - 108.1767053514369634679/(z + 5.0)
  267. + 2.605696505611755827729/(z + 6.0)
  268. - 0.7423452510201416151527e-2 / (z + 7.0)
  269. + 0.5384136432509564062961e-7 / (z + 8.0)
  270. - 0.4023533141268236372067e-8 / (z + 9.0);
  271. return(0.5 * logtwoPI + (z - 0.5) * log(z + 8.5)
  272. - (z + 8.5) + log(series));
  273. }
  274. return(log(0.0)); // never called
  275. }
  276. inline std::complex<double> ln_Gamma_old (std::complex<double> z)
  277. {
  278. // Implementation of Lanczos method with g = 9.
  279. // Coefficients from Godfrey 2001.
  280. if (real(z) < 0.5) return(log(PI/(sin(PI*z))) - ln_Gamma(1.0 - z));
  281. else {
  282. int g = 9;
  283. double p[11] = { 1.000000000000000174663,
  284. 5716.400188274341379136,
  285. -14815.30426768413909044,
  286. 14291.49277657478554025,
  287. -6348.160217641458813289,
  288. 1301.608286058321874105,
  289. -108.1767053514369634679,
  290. 2.605696505611755827729,
  291. -0.7423452510201416151527e-2,
  292. 0.5384136432509564062961e-7,
  293. -0.4023533141268236372067e-8 };
  294. std::complex<double> z_min_1 = z - 1.0;
  295. std::complex<double> series = p[0];
  296. for (int i = 1; i < g+2; ++i)
  297. series += p[i]/(z_min_1 + std::complex<double>(i));
  298. return(0.5 * logtwoPI
  299. + (z_min_1 + 0.5) * log(z_min_1 + std::complex<double>(g) + 0.5)
  300. - (z_min_1 + std::complex<double>(g) + 0.5) + log(series));
  301. }
  302. return(log(0.0)); // never called
  303. }
  304. inline std::complex<double> ln_Gamma_2 (std::complex<double> z)
  305. {
  306. // Implementation of Lanczos method with g = 7.
  307. if (real(z) < 0.5) return(log(PI/(sin(PI*z)) - ln_Gamma(1.0 - z)));
  308. else {
  309. int g = 7;
  310. double p[9] = {
  311. 0.99999999999980993,
  312. 676.5203681218851,
  313. -1259.1392167224028,
  314. 771.32342877765313,
  315. -176.61502916214059,
  316. 12.507343278686905,
  317. -0.13857109526572012,
  318. 9.9843695780195716e-6,
  319. 1.5056327351493116e-7
  320. };
  321. std::complex<double> z_min_1 = z - 1.0;
  322. std::complex<double> series = p[0];
  323. for (int i = 1; i < g+2; ++i)
  324. series += p[i]/(z_min_1 + std::complex<double>(i));
  325. return(0.5 * logtwoPI
  326. + (z_min_1 + 0.5) * log(z_min_1 + std::complex<double>(g) + 0.5)
  327. - (z_min_1 + std::complex<double>(g) + 0.5) + log(series));
  328. }
  329. return(log(0.0)); // never called
  330. }
  331. /********** Partition numbers **********/
  332. inline long long int Partition_Function (int n)
  333. {
  334. // Returns the value of the partition function p(n),
  335. // giving the number of partitions of n into integers.
  336. if (n < 0) ABACUSerror("Calling Partition_Function for n < 0.");
  337. else if (n == 0 || n == 1) return(1LL);
  338. else if (n == 2) return(2LL);
  339. else if (n == 3) return(3LL);
  340. else { // do recursion using pentagonal numbers
  341. long long int pn = 0LL;
  342. int pentnrplus, pentnrmin; // pentagonal numbers
  343. for (int i = 1; true; ++i) {
  344. pentnrplus = (i * (3*i - 1))/2;
  345. pentnrmin = (i * (3*i + 1))/2;
  346. if (n - pentnrplus >= 0) pn += (i % 2 ? 1LL : -1LL) * Partition_Function (n - pentnrplus);
  347. if (n - pentnrmin >= 0) pn += (i % 2 ? 1LL : -1LL) * Partition_Function (n - pentnrmin);
  348. else break;
  349. }
  350. return(pn);
  351. }
  352. return(-1LL); // never called
  353. }
  354. /********** Sorting **********/
  355. template <class T>
  356. void QuickSort (T* V, int l, int r)
  357. {
  358. int i = l, j = r;
  359. T pivot = V[l + (r-l)/2];
  360. while (i <= j) {
  361. while (V[i] < pivot) i++;
  362. while (V[j] > pivot) j--;
  363. if (i <= j) {
  364. std::swap(V[i],V[j]);
  365. i++;
  366. j--;
  367. }
  368. };
  369. if (l < j) QuickSort(V, l, j);
  370. if (i < r) QuickSort(V, i, r);
  371. }
  372. template <class T>
  373. void QuickSort (T* V, int* index, int l, int r)
  374. {
  375. int i = l, j = r;
  376. T pivot = V[l + (r-l)/2];
  377. while (i <= j) {
  378. while (V[i] < pivot) i++;
  379. while (V[j] > pivot) j--;
  380. if (i <= j) {
  381. std::swap(V[i],V[j]);
  382. std::swap(index[i],index[j]);
  383. i++;
  384. j--;
  385. }
  386. };
  387. if (l < j) QuickSort(V, index, l, j);
  388. if (i < r) QuickSort(V, index, i, r);
  389. }
  390. } // namespace ABACUS
  391. #endif