glpgmp.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. /* glpgmp.c */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  6. * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
  7. * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
  8. * E-mail: <mao@gnu.org>.
  9. *
  10. * GLPK is free software: you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  18. * License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************/
  23. #define _GLPSTD_STDIO
  24. #include "glpdmp.h"
  25. #include "glpgmp.h"
  26. #define xfault xerror
  27. #ifdef HAVE_GMP /* use GNU MP bignum library */
  28. int gmp_pool_count(void) { return 0; }
  29. void gmp_free_mem(void) { return; }
  30. #else /* use GLPK bignum module */
  31. static DMP *gmp_pool = NULL;
  32. static int gmp_size = 0;
  33. static unsigned short *gmp_work = NULL;
  34. void *gmp_get_atom(int size)
  35. { if (gmp_pool == NULL)
  36. gmp_pool = dmp_create_pool();
  37. return dmp_get_atom(gmp_pool, size);
  38. }
  39. void gmp_free_atom(void *ptr, int size)
  40. { xassert(gmp_pool != NULL);
  41. dmp_free_atom(gmp_pool, ptr, size);
  42. return;
  43. }
  44. int gmp_pool_count(void)
  45. { if (gmp_pool == NULL)
  46. return 0;
  47. else
  48. return dmp_in_use(gmp_pool).lo;
  49. }
  50. unsigned short *gmp_get_work(int size)
  51. { xassert(size > 0);
  52. if (gmp_size < size)
  53. { if (gmp_size == 0)
  54. { xassert(gmp_work == NULL);
  55. gmp_size = 100;
  56. }
  57. else
  58. { xassert(gmp_work != NULL);
  59. xfree(gmp_work);
  60. }
  61. while (gmp_size < size) gmp_size += gmp_size;
  62. gmp_work = xcalloc(gmp_size, sizeof(unsigned short));
  63. }
  64. return gmp_work;
  65. }
  66. void gmp_free_mem(void)
  67. { if (gmp_pool != NULL) dmp_delete_pool(gmp_pool);
  68. if (gmp_work != NULL) xfree(gmp_work);
  69. gmp_pool = NULL;
  70. gmp_size = 0;
  71. gmp_work = NULL;
  72. return;
  73. }
  74. /*====================================================================*/
  75. mpz_t _mpz_init(void)
  76. { /* initialize x, and set its value to 0 */
  77. mpz_t x;
  78. x = gmp_get_atom(sizeof(struct mpz));
  79. x->val = 0;
  80. x->ptr = NULL;
  81. return x;
  82. }
  83. void mpz_clear(mpz_t x)
  84. { /* free the space occupied by x */
  85. mpz_set_si(x, 0);
  86. xassert(x->ptr == NULL);
  87. /* free the number descriptor */
  88. gmp_free_atom(x, sizeof(struct mpz));
  89. return;
  90. }
  91. void mpz_set(mpz_t z, mpz_t x)
  92. { /* set the value of z from x */
  93. struct mpz_seg *e, *ee, *es;
  94. if (z != x)
  95. { mpz_set_si(z, 0);
  96. z->val = x->val;
  97. xassert(z->ptr == NULL);
  98. for (e = x->ptr, es = NULL; e != NULL; e = e->next)
  99. { ee = gmp_get_atom(sizeof(struct mpz_seg));
  100. memcpy(ee->d, e->d, 12);
  101. ee->next = NULL;
  102. if (z->ptr == NULL)
  103. z->ptr = ee;
  104. else
  105. es->next = ee;
  106. es = ee;
  107. }
  108. }
  109. return;
  110. }
  111. void mpz_set_si(mpz_t x, int val)
  112. { /* set the value of x to val */
  113. struct mpz_seg *e;
  114. /* free existing segments, if any */
  115. while (x->ptr != NULL)
  116. { e = x->ptr;
  117. x->ptr = e->next;
  118. gmp_free_atom(e, sizeof(struct mpz_seg));
  119. }
  120. /* assign new value */
  121. if (val == 0x80000000)
  122. { /* long format is needed */
  123. x->val = -1;
  124. x->ptr = e = gmp_get_atom(sizeof(struct mpz_seg));
  125. memset(e->d, 0, 12);
  126. e->d[1] = 0x8000;
  127. e->next = NULL;
  128. }
  129. else
  130. { /* short format is enough */
  131. x->val = val;
  132. }
  133. return;
  134. }
  135. double mpz_get_d(mpz_t x)
  136. { /* convert x to a double, truncating if necessary */
  137. struct mpz_seg *e;
  138. int j;
  139. double val, deg;
  140. if (x->ptr == NULL)
  141. val = (double)x->val;
  142. else
  143. { xassert(x->val != 0);
  144. val = 0.0;
  145. deg = 1.0;
  146. for (e = x->ptr; e != NULL; e = e->next)
  147. { for (j = 0; j <= 5; j++)
  148. { val += deg * (double)((int)e->d[j]);
  149. deg *= 65536.0;
  150. }
  151. }
  152. if (x->val < 0) val = - val;
  153. }
  154. return val;
  155. }
  156. double mpz_get_d_2exp(int *exp, mpz_t x)
  157. { /* convert x to a double, truncating if necessary (i.e. rounding
  158. towards zero), and returning the exponent separately;
  159. the return value is in the range 0.5 <= |d| < 1 and the
  160. exponent is stored to *exp; d*2^exp is the (truncated) x value;
  161. if x is zero, the return is 0.0 and 0 is stored to *exp;
  162. this is similar to the standard C frexp function */
  163. struct mpz_seg *e;
  164. int j, n, n1;
  165. double val;
  166. if (x->ptr == NULL)
  167. val = (double)x->val, n = 0;
  168. else
  169. { xassert(x->val != 0);
  170. val = 0.0, n = 0;
  171. for (e = x->ptr; e != NULL; e = e->next)
  172. { for (j = 0; j <= 5; j++)
  173. { val += (double)((int)e->d[j]);
  174. val /= 65536.0, n += 16;
  175. }
  176. }
  177. if (x->val < 0) val = - val;
  178. }
  179. val = frexp(val, &n1);
  180. *exp = n + n1;
  181. return val;
  182. }
  183. void mpz_swap(mpz_t x, mpz_t y)
  184. { /* swap the values x and y efficiently */
  185. int val;
  186. void *ptr;
  187. val = x->val, ptr = x->ptr;
  188. x->val = y->val, x->ptr = y->ptr;
  189. y->val = val, y->ptr = ptr;
  190. return;
  191. }
  192. static void normalize(mpz_t x)
  193. { /* normalize integer x that includes removing non-significant
  194. (leading) zeros and converting to short format, if possible */
  195. struct mpz_seg *es, *e;
  196. /* if the integer is in short format, it remains unchanged */
  197. if (x->ptr == NULL)
  198. { xassert(x->val != 0x80000000);
  199. goto done;
  200. }
  201. xassert(x->val == +1 || x->val == -1);
  202. /* find the last (most significant) non-zero segment */
  203. es = NULL;
  204. for (e = x->ptr; e != NULL; e = e->next)
  205. { if (e->d[0] || e->d[1] || e->d[2] ||
  206. e->d[3] || e->d[4] || e->d[5]) es = e;
  207. }
  208. /* if all segments contain zeros, the integer is zero */
  209. if (es == NULL)
  210. { mpz_set_si(x, 0);
  211. goto done;
  212. }
  213. /* remove non-significant (leading) zero segments */
  214. while (es->next != NULL)
  215. { e = es->next;
  216. es->next = e->next;
  217. gmp_free_atom(e, sizeof(struct mpz_seg));
  218. }
  219. /* convert the integer to short format, if possible */
  220. e = x->ptr;
  221. if (e->next == NULL && e->d[1] <= 0x7FFF &&
  222. !e->d[2] && !e->d[3] && !e->d[4] && !e->d[5])
  223. { int val;
  224. val = (int)e->d[0] + ((int)e->d[1] << 16);
  225. if (x->val < 0) val = - val;
  226. mpz_set_si(x, val);
  227. }
  228. done: return;
  229. }
  230. void mpz_add(mpz_t z, mpz_t x, mpz_t y)
  231. { /* set z to x + y */
  232. static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL };
  233. struct mpz_seg dumx, dumy, *ex, *ey, *ez, *es, *ee;
  234. int k, sx, sy, sz;
  235. unsigned int t;
  236. /* if [x] = 0 then [z] = [y] */
  237. if (x->val == 0)
  238. { xassert(x->ptr == NULL);
  239. mpz_set(z, y);
  240. goto done;
  241. }
  242. /* if [y] = 0 then [z] = [x] */
  243. if (y->val == 0)
  244. { xassert(y->ptr == NULL);
  245. mpz_set(z, x);
  246. goto done;
  247. }
  248. /* special case when both [x] and [y] are in short format */
  249. if (x->ptr == NULL && y->ptr == NULL)
  250. { int xval = x->val, yval = y->val, zval = x->val + y->val;
  251. xassert(xval != 0x80000000 && yval != 0x80000000);
  252. if (!(xval > 0 && yval > 0 && zval <= 0 ||
  253. xval < 0 && yval < 0 && zval >= 0))
  254. { mpz_set_si(z, zval);
  255. goto done;
  256. }
  257. }
  258. /* convert [x] to long format, if necessary */
  259. if (x->ptr == NULL)
  260. { xassert(x->val != 0x80000000);
  261. if (x->val >= 0)
  262. { sx = +1;
  263. t = (unsigned int)(+ x->val);
  264. }
  265. else
  266. { sx = -1;
  267. t = (unsigned int)(- x->val);
  268. }
  269. ex = &dumx;
  270. ex->d[0] = (unsigned short)t;
  271. ex->d[1] = (unsigned short)(t >> 16);
  272. ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
  273. ex->next = NULL;
  274. }
  275. else
  276. { sx = x->val;
  277. xassert(sx == +1 || sx == -1);
  278. ex = x->ptr;
  279. }
  280. /* convert [y] to long format, if necessary */
  281. if (y->ptr == NULL)
  282. { xassert(y->val != 0x80000000);
  283. if (y->val >= 0)
  284. { sy = +1;
  285. t = (unsigned int)(+ y->val);
  286. }
  287. else
  288. { sy = -1;
  289. t = (unsigned int)(- y->val);
  290. }
  291. ey = &dumy;
  292. ey->d[0] = (unsigned short)t;
  293. ey->d[1] = (unsigned short)(t >> 16);
  294. ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
  295. ey->next = NULL;
  296. }
  297. else
  298. { sy = y->val;
  299. xassert(sy == +1 || sy == -1);
  300. ey = y->ptr;
  301. }
  302. /* main fragment */
  303. sz = sx;
  304. ez = es = NULL;
  305. if (sx > 0 && sy > 0 || sx < 0 && sy < 0)
  306. { /* [x] and [y] have identical signs -- addition */
  307. t = 0;
  308. for (; ex || ey; ex = ex->next, ey = ey->next)
  309. { if (ex == NULL) ex = &zero;
  310. if (ey == NULL) ey = &zero;
  311. ee = gmp_get_atom(sizeof(struct mpz_seg));
  312. for (k = 0; k <= 5; k++)
  313. { t += (unsigned int)ex->d[k];
  314. t += (unsigned int)ey->d[k];
  315. ee->d[k] = (unsigned short)t;
  316. t >>= 16;
  317. }
  318. ee->next = NULL;
  319. if (ez == NULL)
  320. ez = ee;
  321. else
  322. es->next = ee;
  323. es = ee;
  324. }
  325. if (t)
  326. { /* overflow -- one extra digit is needed */
  327. ee = gmp_get_atom(sizeof(struct mpz_seg));
  328. ee->d[0] = 1;
  329. ee->d[1] = ee->d[2] = ee->d[3] = ee->d[4] = ee->d[5] = 0;
  330. ee->next = NULL;
  331. xassert(es != NULL);
  332. es->next = ee;
  333. }
  334. }
  335. else
  336. { /* [x] and [y] have different signs -- subtraction */
  337. t = 1;
  338. for (; ex || ey; ex = ex->next, ey = ey->next)
  339. { if (ex == NULL) ex = &zero;
  340. if (ey == NULL) ey = &zero;
  341. ee = gmp_get_atom(sizeof(struct mpz_seg));
  342. for (k = 0; k <= 5; k++)
  343. { t += (unsigned int)ex->d[k];
  344. t += (0xFFFF - (unsigned int)ey->d[k]);
  345. ee->d[k] = (unsigned short)t;
  346. t >>= 16;
  347. }
  348. ee->next = NULL;
  349. if (ez == NULL)
  350. ez = ee;
  351. else
  352. es->next = ee;
  353. es = ee;
  354. }
  355. if (!t)
  356. { /* |[x]| < |[y]| -- result in complement coding */
  357. sz = - sz;
  358. t = 1;
  359. for (ee = ez; ee != NULL; ee = ee->next)
  360. for (k = 0; k <= 5; k++)
  361. { t += (0xFFFF - (unsigned int)ee->d[k]);
  362. ee->d[k] = (unsigned short)t;
  363. t >>= 16;
  364. }
  365. }
  366. }
  367. /* contruct and normalize result */
  368. mpz_set_si(z, 0);
  369. z->val = sz;
  370. z->ptr = ez;
  371. normalize(z);
  372. done: return;
  373. }
  374. void mpz_sub(mpz_t z, mpz_t x, mpz_t y)
  375. { /* set z to x - y */
  376. if (x == y)
  377. mpz_set_si(z, 0);
  378. else
  379. { y->val = - y->val;
  380. mpz_add(z, x, y);
  381. if (y != z) y->val = - y->val;
  382. }
  383. return;
  384. }
  385. void mpz_mul(mpz_t z, mpz_t x, mpz_t y)
  386. { /* set z to x * y */
  387. struct mpz_seg dumx, dumy, *ex, *ey, *es, *e;
  388. int sx, sy, k, nx, ny, n;
  389. unsigned int t;
  390. unsigned short *work, *wx, *wy;
  391. /* if [x] = 0 then [z] = 0 */
  392. if (x->val == 0)
  393. { xassert(x->ptr == NULL);
  394. mpz_set_si(z, 0);
  395. goto done;
  396. }
  397. /* if [y] = 0 then [z] = 0 */
  398. if (y->val == 0)
  399. { xassert(y->ptr == NULL);
  400. mpz_set_si(z, 0);
  401. goto done;
  402. }
  403. /* special case when both [x] and [y] are in short format */
  404. if (x->ptr == NULL && y->ptr == NULL)
  405. { int xval = x->val, yval = y->val, sz = +1;
  406. xassert(xval != 0x80000000 && yval != 0x80000000);
  407. if (xval < 0) xval = - xval, sz = - sz;
  408. if (yval < 0) yval = - yval, sz = - sz;
  409. if (xval <= 0x7FFFFFFF / yval)
  410. { mpz_set_si(z, sz * (xval * yval));
  411. goto done;
  412. }
  413. }
  414. /* convert [x] to long format, if necessary */
  415. if (x->ptr == NULL)
  416. { xassert(x->val != 0x80000000);
  417. if (x->val >= 0)
  418. { sx = +1;
  419. t = (unsigned int)(+ x->val);
  420. }
  421. else
  422. { sx = -1;
  423. t = (unsigned int)(- x->val);
  424. }
  425. ex = &dumx;
  426. ex->d[0] = (unsigned short)t;
  427. ex->d[1] = (unsigned short)(t >> 16);
  428. ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
  429. ex->next = NULL;
  430. }
  431. else
  432. { sx = x->val;
  433. xassert(sx == +1 || sx == -1);
  434. ex = x->ptr;
  435. }
  436. /* convert [y] to long format, if necessary */
  437. if (y->ptr == NULL)
  438. { xassert(y->val != 0x80000000);
  439. if (y->val >= 0)
  440. { sy = +1;
  441. t = (unsigned int)(+ y->val);
  442. }
  443. else
  444. { sy = -1;
  445. t = (unsigned int)(- y->val);
  446. }
  447. ey = &dumy;
  448. ey->d[0] = (unsigned short)t;
  449. ey->d[1] = (unsigned short)(t >> 16);
  450. ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
  451. ey->next = NULL;
  452. }
  453. else
  454. { sy = y->val;
  455. xassert(sy == +1 || sy == -1);
  456. ey = y->ptr;
  457. }
  458. /* determine the number of digits of [x] */
  459. nx = n = 0;
  460. for (e = ex; e != NULL; e = e->next)
  461. for (k = 0; k <= 5; k++)
  462. { n++;
  463. if (e->d[k]) nx = n;
  464. }
  465. xassert(nx > 0);
  466. /* determine the number of digits of [y] */
  467. ny = n = 0;
  468. for (e = ey; e != NULL; e = e->next)
  469. for (k = 0; k <= 5; k++)
  470. { n++;
  471. if (e->d[k]) ny = n;
  472. }
  473. xassert(ny > 0);
  474. /* we need working array containing at least nx+ny+ny places */
  475. work = gmp_get_work(nx+ny+ny);
  476. /* load digits of [x] */
  477. wx = &work[0];
  478. for (n = 0; n < nx; n++) wx[ny+n] = 0;
  479. for (n = 0, e = ex; e != NULL; e = e->next)
  480. for (k = 0; k <= 5; k++, n++)
  481. if (e->d[k]) wx[ny+n] = e->d[k];
  482. /* load digits of [y] */
  483. wy = &work[nx+ny];
  484. for (n = 0; n < ny; n++) wy[n] = 0;
  485. for (n = 0, e = ey; e != NULL; e = e->next)
  486. for (k = 0; k <= 5; k++, n++)
  487. if (e->d[k]) wy[n] = e->d[k];
  488. /* compute [x] * [y] */
  489. bigmul(nx, ny, wx, wy);
  490. /* construct and normalize result */
  491. mpz_set_si(z, 0);
  492. z->val = sx * sy;
  493. es = NULL;
  494. k = 6;
  495. for (n = 0; n < nx+ny; n++)
  496. { if (k > 5)
  497. { e = gmp_get_atom(sizeof(struct mpz_seg));
  498. e->d[0] = e->d[1] = e->d[2] = 0;
  499. e->d[3] = e->d[4] = e->d[5] = 0;
  500. e->next = NULL;
  501. if (z->ptr == NULL)
  502. z->ptr = e;
  503. else
  504. es->next = e;
  505. es = e;
  506. k = 0;
  507. }
  508. es->d[k++] = wx[n];
  509. }
  510. normalize(z);
  511. done: return;
  512. }
  513. void mpz_neg(mpz_t z, mpz_t x)
  514. { /* set z to 0 - x */
  515. mpz_set(z, x);
  516. z->val = - z->val;
  517. return;
  518. }
  519. void mpz_abs(mpz_t z, mpz_t x)
  520. { /* set z to the absolute value of x */
  521. mpz_set(z, x);
  522. if (z->val < 0) z->val = - z->val;
  523. return;
  524. }
  525. void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y)
  526. { /* divide x by y, forming quotient q and/or remainder r
  527. if q = NULL then quotient is not stored; if r = NULL then
  528. remainder is not stored
  529. the sign of quotient is determined as in algebra while the
  530. sign of remainder is the same as the sign of dividend:
  531. +26 : +7 = +3, remainder is +5
  532. -26 : +7 = -3, remainder is -5
  533. +26 : -7 = -3, remainder is +5
  534. -26 : -7 = +3, remainder is -5 */
  535. struct mpz_seg dumx, dumy, *ex, *ey, *es, *e;
  536. int sx, sy, k, nx, ny, n;
  537. unsigned int t;
  538. unsigned short *work, *wx, *wy;
  539. /* divide by zero is not allowed */
  540. if (y->val == 0)
  541. { xassert(y->ptr == NULL);
  542. xfault("mpz_div: divide by zero not allowed\n");
  543. }
  544. /* if [x] = 0 then [q] = [r] = 0 */
  545. if (x->val == 0)
  546. { xassert(x->ptr == NULL);
  547. if (q != NULL) mpz_set_si(q, 0);
  548. if (r != NULL) mpz_set_si(r, 0);
  549. goto done;
  550. }
  551. /* special case when both [x] and [y] are in short format */
  552. if (x->ptr == NULL && y->ptr == NULL)
  553. { int xval = x->val, yval = y->val;
  554. xassert(xval != 0x80000000 && yval != 0x80000000);
  555. if (q != NULL) mpz_set_si(q, xval / yval);
  556. if (r != NULL) mpz_set_si(r, xval % yval);
  557. goto done;
  558. }
  559. /* convert [x] to long format, if necessary */
  560. if (x->ptr == NULL)
  561. { xassert(x->val != 0x80000000);
  562. if (x->val >= 0)
  563. { sx = +1;
  564. t = (unsigned int)(+ x->val);
  565. }
  566. else
  567. { sx = -1;
  568. t = (unsigned int)(- x->val);
  569. }
  570. ex = &dumx;
  571. ex->d[0] = (unsigned short)t;
  572. ex->d[1] = (unsigned short)(t >> 16);
  573. ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
  574. ex->next = NULL;
  575. }
  576. else
  577. { sx = x->val;
  578. xassert(sx == +1 || sx == -1);
  579. ex = x->ptr;
  580. }
  581. /* convert [y] to long format, if necessary */
  582. if (y->ptr == NULL)
  583. { xassert(y->val != 0x80000000);
  584. if (y->val >= 0)
  585. { sy = +1;
  586. t = (unsigned int)(+ y->val);
  587. }
  588. else
  589. { sy = -1;
  590. t = (unsigned int)(- y->val);
  591. }
  592. ey = &dumy;
  593. ey->d[0] = (unsigned short)t;
  594. ey->d[1] = (unsigned short)(t >> 16);
  595. ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
  596. ey->next = NULL;
  597. }
  598. else
  599. { sy = y->val;
  600. xassert(sy == +1 || sy == -1);
  601. ey = y->ptr;
  602. }
  603. /* determine the number of digits of [x] */
  604. nx = n = 0;
  605. for (e = ex; e != NULL; e = e->next)
  606. for (k = 0; k <= 5; k++)
  607. { n++;
  608. if (e->d[k]) nx = n;
  609. }
  610. xassert(nx > 0);
  611. /* determine the number of digits of [y] */
  612. ny = n = 0;
  613. for (e = ey; e != NULL; e = e->next)
  614. for (k = 0; k <= 5; k++)
  615. { n++;
  616. if (e->d[k]) ny = n;
  617. }
  618. xassert(ny > 0);
  619. /* if nx < ny then [q] = 0 and [r] = [x] */
  620. if (nx < ny)
  621. { if (r != NULL) mpz_set(r, x);
  622. if (q != NULL) mpz_set_si(q, 0);
  623. goto done;
  624. }
  625. /* we need working array containing at least nx+ny+1 places */
  626. work = gmp_get_work(nx+ny+1);
  627. /* load digits of [x] */
  628. wx = &work[0];
  629. for (n = 0; n < nx; n++) wx[n] = 0;
  630. for (n = 0, e = ex; e != NULL; e = e->next)
  631. for (k = 0; k <= 5; k++, n++)
  632. if (e->d[k]) wx[n] = e->d[k];
  633. /* load digits of [y] */
  634. wy = &work[nx+1];
  635. for (n = 0; n < ny; n++) wy[n] = 0;
  636. for (n = 0, e = ey; e != NULL; e = e->next)
  637. for (k = 0; k <= 5; k++, n++)
  638. if (e->d[k]) wy[n] = e->d[k];
  639. /* compute quotient and remainder */
  640. xassert(wy[ny-1] != 0);
  641. bigdiv(nx-ny, ny, wx, wy);
  642. /* construct and normalize quotient */
  643. if (q != NULL)
  644. { mpz_set_si(q, 0);
  645. q->val = sx * sy;
  646. es = NULL;
  647. k = 6;
  648. for (n = ny; n <= nx; n++)
  649. { if (k > 5)
  650. { e = gmp_get_atom(sizeof(struct mpz_seg));
  651. e->d[0] = e->d[1] = e->d[2] = 0;
  652. e->d[3] = e->d[4] = e->d[5] = 0;
  653. e->next = NULL;
  654. if (q->ptr == NULL)
  655. q->ptr = e;
  656. else
  657. es->next = e;
  658. es = e;
  659. k = 0;
  660. }
  661. es->d[k++] = wx[n];
  662. }
  663. normalize(q);
  664. }
  665. /* construct and normalize remainder */
  666. if (r != NULL)
  667. { mpz_set_si(r, 0);
  668. r->val = sx;
  669. es = NULL;
  670. k = 6;
  671. for (n = 0; n < ny; n++)
  672. { if (k > 5)
  673. { e = gmp_get_atom(sizeof(struct mpz_seg));
  674. e->d[0] = e->d[1] = e->d[2] = 0;
  675. e->d[3] = e->d[4] = e->d[5] = 0;
  676. e->next = NULL;
  677. if (r->ptr == NULL)
  678. r->ptr = e;
  679. else
  680. es->next = e;
  681. es = e;
  682. k = 0;
  683. }
  684. es->d[k++] = wx[n];
  685. }
  686. normalize(r);
  687. }
  688. done: return;
  689. }
  690. void mpz_gcd(mpz_t z, mpz_t x, mpz_t y)
  691. { /* set z to the greatest common divisor of x and y */
  692. /* in case of arbitrary integers GCD(x, y) = GCD(|x|, |y|), and,
  693. in particular, GCD(0, 0) = 0 */
  694. mpz_t u, v, r;
  695. mpz_init(u);
  696. mpz_init(v);
  697. mpz_init(r);
  698. mpz_abs(u, x);
  699. mpz_abs(v, y);
  700. while (mpz_sgn(v))
  701. { mpz_div(NULL, r, u, v);
  702. mpz_set(u, v);
  703. mpz_set(v, r);
  704. }
  705. mpz_set(z, u);
  706. mpz_clear(u);
  707. mpz_clear(v);
  708. mpz_clear(r);
  709. return;
  710. }
  711. int mpz_cmp(mpz_t x, mpz_t y)
  712. { /* compare x and y; return a positive value if x > y, zero if
  713. x = y, or a nefative value if x < y */
  714. static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL };
  715. struct mpz_seg dumx, dumy, *ex, *ey;
  716. int cc, sx, sy, k;
  717. unsigned int t;
  718. if (x == y)
  719. { cc = 0;
  720. goto done;
  721. }
  722. /* special case when both [x] and [y] are in short format */
  723. if (x->ptr == NULL && y->ptr == NULL)
  724. { int xval = x->val, yval = y->val;
  725. xassert(xval != 0x80000000 && yval != 0x80000000);
  726. cc = (xval > yval ? +1 : xval < yval ? -1 : 0);
  727. goto done;
  728. }
  729. /* special case when [x] and [y] have different signs */
  730. if (x->val > 0 && y->val <= 0 || x->val == 0 && y->val < 0)
  731. { cc = +1;
  732. goto done;
  733. }
  734. if (x->val < 0 && y->val >= 0 || x->val == 0 && y->val > 0)
  735. { cc = -1;
  736. goto done;
  737. }
  738. /* convert [x] to long format, if necessary */
  739. if (x->ptr == NULL)
  740. { xassert(x->val != 0x80000000);
  741. if (x->val >= 0)
  742. { sx = +1;
  743. t = (unsigned int)(+ x->val);
  744. }
  745. else
  746. { sx = -1;
  747. t = (unsigned int)(- x->val);
  748. }
  749. ex = &dumx;
  750. ex->d[0] = (unsigned short)t;
  751. ex->d[1] = (unsigned short)(t >> 16);
  752. ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
  753. ex->next = NULL;
  754. }
  755. else
  756. { sx = x->val;
  757. xassert(sx == +1 || sx == -1);
  758. ex = x->ptr;
  759. }
  760. /* convert [y] to long format, if necessary */
  761. if (y->ptr == NULL)
  762. { xassert(y->val != 0x80000000);
  763. if (y->val >= 0)
  764. { sy = +1;
  765. t = (unsigned int)(+ y->val);
  766. }
  767. else
  768. { sy = -1;
  769. t = (unsigned int)(- y->val);
  770. }
  771. ey = &dumy;
  772. ey->d[0] = (unsigned short)t;
  773. ey->d[1] = (unsigned short)(t >> 16);
  774. ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
  775. ey->next = NULL;
  776. }
  777. else
  778. { sy = y->val;
  779. xassert(sy == +1 || sy == -1);
  780. ey = y->ptr;
  781. }
  782. /* main fragment */
  783. xassert(sx > 0 && sy > 0 || sx < 0 && sy < 0);
  784. cc = 0;
  785. for (; ex || ey; ex = ex->next, ey = ey->next)
  786. { if (ex == NULL) ex = &zero;
  787. if (ey == NULL) ey = &zero;
  788. for (k = 0; k <= 5; k++)
  789. { if (ex->d[k] > ey->d[k]) cc = +1;
  790. if (ex->d[k] < ey->d[k]) cc = -1;
  791. }
  792. }
  793. if (sx < 0) cc = - cc;
  794. done: return cc;
  795. }
  796. int mpz_sgn(mpz_t x)
  797. { /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
  798. int s;
  799. s = (x->val > 0 ? +1 : x->val < 0 ? -1 : 0);
  800. return s;
  801. }
  802. int mpz_out_str(void *_fp, int base, mpz_t x)
  803. { /* output x on stream fp, as a string in given base; the base
  804. may vary from 2 to 36;
  805. return the number of bytes written, or if an error occurred,
  806. return 0 */
  807. FILE *fp = _fp;
  808. mpz_t b, y, r;
  809. int n, j, nwr = 0;
  810. unsigned char *d;
  811. static char *set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  812. if (!(2 <= base && base <= 36))
  813. xfault("mpz_out_str: base = %d; invalid base\n", base);
  814. mpz_init(b);
  815. mpz_set_si(b, base);
  816. mpz_init(y);
  817. mpz_init(r);
  818. /* determine the number of digits */
  819. mpz_abs(y, x);
  820. for (n = 0; mpz_sgn(y) != 0; n++)
  821. mpz_div(y, NULL, y, b);
  822. if (n == 0) n = 1;
  823. /* compute the digits */
  824. d = xmalloc(n);
  825. mpz_abs(y, x);
  826. for (j = 0; j < n; j++)
  827. { mpz_div(y, r, y, b);
  828. xassert(0 <= r->val && r->val < base && r->ptr == NULL);
  829. d[j] = (unsigned char)r->val;
  830. }
  831. /* output the integer to the stream */
  832. if (fp == NULL) fp = stdout;
  833. if (mpz_sgn(x) < 0)
  834. fputc('-', fp), nwr++;
  835. for (j = n-1; j >= 0; j--)
  836. fputc(set[d[j]], fp), nwr++;
  837. if (ferror(fp)) nwr = 0;
  838. mpz_clear(b);
  839. mpz_clear(y);
  840. mpz_clear(r);
  841. xfree(d);
  842. return nwr;
  843. }
  844. /*====================================================================*/
  845. mpq_t _mpq_init(void)
  846. { /* initialize x, and set its value to 0/1 */
  847. mpq_t x;
  848. x = gmp_get_atom(sizeof(struct mpq));
  849. x->p.val = 0;
  850. x->p.ptr = NULL;
  851. x->q.val = 1;
  852. x->q.ptr = NULL;
  853. return x;
  854. }
  855. void mpq_clear(mpq_t x)
  856. { /* free the space occupied by x */
  857. mpz_set_si(&x->p, 0);
  858. xassert(x->p.ptr == NULL);
  859. mpz_set_si(&x->q, 0);
  860. xassert(x->q.ptr == NULL);
  861. /* free the number descriptor */
  862. gmp_free_atom(x, sizeof(struct mpq));
  863. return;
  864. }
  865. void mpq_canonicalize(mpq_t x)
  866. { /* remove any factors that are common to the numerator and
  867. denominator of x, and make the denominator positive */
  868. mpz_t f;
  869. xassert(x->q.val != 0);
  870. if (x->q.val < 0)
  871. { mpz_neg(&x->p, &x->p);
  872. mpz_neg(&x->q, &x->q);
  873. }
  874. mpz_init(f);
  875. mpz_gcd(f, &x->p, &x->q);
  876. if (!(f->val == 1 && f->ptr == NULL))
  877. { mpz_div(&x->p, NULL, &x->p, f);
  878. mpz_div(&x->q, NULL, &x->q, f);
  879. }
  880. mpz_clear(f);
  881. return;
  882. }
  883. void mpq_set(mpq_t z, mpq_t x)
  884. { /* set the value of z from x */
  885. if (z != x)
  886. { mpz_set(&z->p, &x->p);
  887. mpz_set(&z->q, &x->q);
  888. }
  889. return;
  890. }
  891. void mpq_set_si(mpq_t x, int p, unsigned int q)
  892. { /* set the value of x to p/q */
  893. if (q == 0)
  894. xfault("mpq_set_si: zero denominator not allowed\n");
  895. mpz_set_si(&x->p, p);
  896. xassert(q <= 0x7FFFFFFF);
  897. mpz_set_si(&x->q, q);
  898. return;
  899. }
  900. double mpq_get_d(mpq_t x)
  901. { /* convert x to a double, truncating if necessary */
  902. int np, nq;
  903. double p, q;
  904. p = mpz_get_d_2exp(&np, &x->p);
  905. q = mpz_get_d_2exp(&nq, &x->q);
  906. return ldexp(p / q, np - nq);
  907. }
  908. void mpq_set_d(mpq_t x, double val)
  909. { /* set x to val; there is no rounding, the conversion is exact */
  910. int s, n, d, j;
  911. double f;
  912. mpz_t temp;
  913. xassert(-DBL_MAX <= val && val <= +DBL_MAX);
  914. mpq_set_si(x, 0, 1);
  915. if (val > 0.0)
  916. s = +1;
  917. else if (val < 0.0)
  918. s = -1;
  919. else
  920. goto done;
  921. f = frexp(fabs(val), &n);
  922. /* |val| = f * 2^n, where 0.5 <= f < 1.0 */
  923. mpz_init(temp);
  924. while (f != 0.0)
  925. { f *= 16.0, n -= 4;
  926. d = (int)f;
  927. xassert(0 <= d && d <= 15);
  928. f -= (double)d;
  929. /* x := 16 * x + d */
  930. mpz_set_si(temp, 16);
  931. mpz_mul(&x->p, &x->p, temp);
  932. mpz_set_si(temp, d);
  933. mpz_add(&x->p, &x->p, temp);
  934. }
  935. mpz_clear(temp);
  936. /* x := x * 2^n */
  937. if (n > 0)
  938. { for (j = 1; j <= n; j++)
  939. mpz_add(&x->p, &x->p, &x->p);
  940. }
  941. else if (n < 0)
  942. { for (j = 1; j <= -n; j++)
  943. mpz_add(&x->q, &x->q, &x->q);
  944. mpq_canonicalize(x);
  945. }
  946. if (s < 0) mpq_neg(x, x);
  947. done: return;
  948. }
  949. void mpq_add(mpq_t z, mpq_t x, mpq_t y)
  950. { /* set z to x + y */
  951. mpz_t p, q;
  952. mpz_init(p);
  953. mpz_init(q);
  954. mpz_mul(p, &x->p, &y->q);
  955. mpz_mul(q, &x->q, &y->p);
  956. mpz_add(p, p, q);
  957. mpz_mul(q, &x->q, &y->q);
  958. mpz_set(&z->p, p);
  959. mpz_set(&z->q, q);
  960. mpz_clear(p);
  961. mpz_clear(q);
  962. mpq_canonicalize(z);
  963. return;
  964. }
  965. void mpq_sub(mpq_t z, mpq_t x, mpq_t y)
  966. { /* set z to x - y */
  967. mpz_t p, q;
  968. mpz_init(p);
  969. mpz_init(q);
  970. mpz_mul(p, &x->p, &y->q);
  971. mpz_mul(q, &x->q, &y->p);
  972. mpz_sub(p, p, q);
  973. mpz_mul(q, &x->q, &y->q);
  974. mpz_set(&z->p, p);
  975. mpz_set(&z->q, q);
  976. mpz_clear(p);
  977. mpz_clear(q);
  978. mpq_canonicalize(z);
  979. return;
  980. }
  981. void mpq_mul(mpq_t z, mpq_t x, mpq_t y)
  982. { /* set z to x * y */
  983. mpz_mul(&z->p, &x->p, &y->p);
  984. mpz_mul(&z->q, &x->q, &y->q);
  985. mpq_canonicalize(z);
  986. return;
  987. }
  988. void mpq_div(mpq_t z, mpq_t x, mpq_t y)
  989. { /* set z to x / y */
  990. mpz_t p, q;
  991. if (mpq_sgn(y) == 0)
  992. xfault("mpq_div: zero divisor not allowed\n");
  993. mpz_init(p);
  994. mpz_init(q);
  995. mpz_mul(p, &x->p, &y->q);
  996. mpz_mul(q, &x->q, &y->p);
  997. mpz_set(&z->p, p);
  998. mpz_set(&z->q, q);
  999. mpz_clear(p);
  1000. mpz_clear(q);
  1001. mpq_canonicalize(z);
  1002. return;
  1003. }
  1004. void mpq_neg(mpq_t z, mpq_t x)
  1005. { /* set z to 0 - x */
  1006. mpq_set(z, x);
  1007. mpz_neg(&z->p, &z->p);
  1008. return;
  1009. }
  1010. void mpq_abs(mpq_t z, mpq_t x)
  1011. { /* set z to the absolute value of x */
  1012. mpq_set(z, x);
  1013. mpz_abs(&z->p, &z->p);
  1014. xassert(mpz_sgn(&x->q) > 0);
  1015. return;
  1016. }
  1017. int mpq_cmp(mpq_t x, mpq_t y)
  1018. { /* compare x and y; return a positive value if x > y, zero if
  1019. x = y, or a nefative value if x < y */
  1020. mpq_t temp;
  1021. int s;
  1022. mpq_init(temp);
  1023. mpq_sub(temp, x, y);
  1024. s = mpq_sgn(temp);
  1025. mpq_clear(temp);
  1026. return s;
  1027. }
  1028. int mpq_sgn(mpq_t x)
  1029. { /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
  1030. int s;
  1031. s = mpz_sgn(&x->p);
  1032. xassert(mpz_sgn(&x->q) > 0);
  1033. return s;
  1034. }
  1035. int mpq_out_str(void *_fp, int base, mpq_t x)
  1036. { /* output x on stream fp, as a string in given base; the base
  1037. may vary from 2 to 36; output is in the form 'num/den' or if
  1038. the denominator is 1 then just 'num';
  1039. if the parameter fp is a null pointer, stdout is assumed;
  1040. return the number of bytes written, or if an error occurred,
  1041. return 0 */
  1042. FILE *fp = _fp;
  1043. int nwr;
  1044. if (!(2 <= base && base <= 36))
  1045. xfault("mpq_out_str: base = %d; invalid base\n", base);
  1046. if (fp == NULL) fp = stdout;
  1047. nwr = mpz_out_str(fp, base, &x->p);
  1048. if (x->q.val == 1 && x->q.ptr == NULL)
  1049. ;
  1050. else
  1051. { fputc('/', fp), nwr++;
  1052. nwr += mpz_out_str(fp, base, &x->q);
  1053. }
  1054. if (ferror(fp)) nwr = 0;
  1055. return nwr;
  1056. }
  1057. #endif
  1058. /* eof */