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.

JSC_util.h 11KB

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