home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / calc / part11 < prev    next >
Encoding:
Text File  |  1992-05-09  |  29.4 KB  |  1,088 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  3. Subject: v26i037: CALC - An arbitrary precision C-like calculator, Part11/21
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  8. Posting-Number: Volume 26, Issue 37
  9. Archive-Name: calc/part11
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 11 (of 21)."
  18. # Contents:  zmul.c
  19. # Wrapped by dbell@elm on Tue Feb 25 15:21:09 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'zmul.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'zmul.c'\"
  23. else
  24. echo shar: Extracting \"'zmul.c'\" \(27389 characters\)
  25. sed "s/^X//" >'zmul.c' <<'END_OF_FILE'
  26. X/*
  27. X * Copyright (c) 1992 David I. Bell
  28. X * Permission is granted to use, distribute, or modify this source,
  29. X * provided that this copyright notice remains intact.
  30. X *
  31. X * Faster than usual multiplying and squaring routines.
  32. X * The algorithm used is the reasonably simple one from Knuth, volume 2,
  33. X * section 4.3.3.  These recursive routines are of speed O(N^1.585)
  34. X * instead of O(N^2).  The usual multiplication and (almost usual) squaring
  35. X * algorithms are used for small numbers.  On a 386 with its compiler, the
  36. X * two algorithms are equal in speed at about 100 decimal digits.
  37. X */
  38. X
  39. X#include <stdio.h>
  40. X#include "math.h"
  41. X
  42. X
  43. XLEN _mul2_ = MUL_ALG2;        /* size of number to use multiply algorithm 2 */
  44. XLEN _sq2_ = SQ_ALG2;        /* size of number to use square algorithm 2 */
  45. X
  46. X
  47. X#if 0
  48. Xstatic char *abortmsg = "Calculation aborted";
  49. Xstatic char *memmsg = "Not enough memory";
  50. X#endif
  51. X
  52. Xstatic HALF *tempbuf;        /* temporary buffer for multiply and square */
  53. X
  54. Xstatic LEN domul proto((HALF *v1, LEN size1, HALF *v2, LEN size2, HALF *ans));
  55. Xstatic LEN dosquare proto((HALF *vp, LEN size, HALF *ans));
  56. X
  57. X
  58. X/*
  59. X * Multiply two numbers using the following formula recursively:
  60. X *    (A*S+B)*(C*S+D) = (S^2+S)*A*C + S*(A-B)*(D-C) + (S+1)*B*D
  61. X * where S is a power of 2^16, and so multiplies by it are shifts, and
  62. X * A,B,C,D are the left and right halfs of the numbers to be multiplied.
  63. X */
  64. Xvoid
  65. Xzmul(z1, z2, res)
  66. X    ZVALUE z1, z2;        /* numbers to multiply */
  67. X    ZVALUE *res;        /* result of multiplication */
  68. X{
  69. X    LEN len;        /* size of array */
  70. X
  71. X    if (iszero(z1) || iszero(z2)) {
  72. X        *res = _zero_;
  73. X        return;
  74. X    }
  75. X    if (isunit(z1)) {
  76. X        zcopy(z2, res);
  77. X        res->sign = (z1.sign != z2.sign);
  78. X        return;
  79. X    }
  80. X    if (isunit(z2)) {
  81. X        zcopy(z1, res);
  82. X        res->sign = (z1.sign != z2.sign);
  83. X        return;
  84. X    }
  85. X
  86. X    /*
  87. X     * Allocate a temporary buffer for the recursion levels to use.
  88. X     * An array needs to be allocated large enough for all of the
  89. X     * temporary results to fit in.  This size is about twice the size
  90. X     * of the largest original number, since each recursion level uses
  91. X     * the size of its given number, and whose size is 1/2 the size of
  92. X     * the previous level.  The sum of the infinite series is 2.
  93. X     * Add some extra words because of rounding when dividing by 2
  94. X     * and also because of the extra word that each multiply needs.
  95. X     */
  96. X    len = z1.len;
  97. X    if (len < z2.len)
  98. X        len = z2.len;
  99. X    len = 2 * len + 64;
  100. X    tempbuf = zalloctemp(len);
  101. X
  102. X    res->sign = (z1.sign != z2.sign);
  103. X    res->v = alloc(z1.len + z2.len + 1);
  104. X    res->len = domul(z1.v, z1.len, z2.v, z2.len, res->v);
  105. X}
  106. X
  107. X
  108. X/*
  109. X * Recursive routine to multiply two numbers by splitting them up into
  110. X * two numbers of half the size, and using the results of multiplying the
  111. X * subpieces.  The result is placed in the indicated array, which must be
  112. X * large enough for the result plus one extra word (size1 + size2 + 1).
  113. X * Returns the actual size of the result with leading zeroes stripped.
  114. X * This also uses a temporary array which must be twice as large as
  115. X * one more than the size of the number at the top level recursive call.
  116. X */
  117. Xstatic LEN
  118. Xdomul(v1, size1, v2, size2, ans)
  119. X    HALF *v1;        /* first number */
  120. X    LEN size1;        /* size of first number */
  121. X    HALF *v2;        /* second number */
  122. X    LEN size2;        /* size of second number */
  123. X    HALF *ans;        /* location for result */
  124. X{
  125. X    LEN shift;        /* amount numbers are shifted by */
  126. X    LEN sizeA;        /* size of left half of first number */
  127. X    LEN sizeB;        /* size of right half of first number */
  128. X    LEN sizeC;        /* size of left half of second number */
  129. X    LEN sizeD;        /* size of right half of second number */
  130. X    LEN sizeAB;        /* size of subtraction of A and B */
  131. X    LEN sizeDC;        /* size of subtraction of D and C */
  132. X    LEN sizeABDC;        /* size of product of above two results */
  133. X    LEN subsize;        /* size of difference of halfs */
  134. X    LEN copysize;        /* size of number left to copy */
  135. X    LEN sizetotal;        /* total size of product */
  136. X    LEN len;        /* temporary length */
  137. X    HALF *baseA;        /* base of left half of first number */
  138. X    HALF *baseB;        /* base of right half of first number */
  139. X    HALF *baseC;        /* base of left half of second number */
  140. X    HALF *baseD;        /* base of right half of second number */
  141. X    HALF *baseAB;        /* base of result of subtraction of A and B */
  142. X    HALF *baseDC;        /* base of result of subtraction of D and C */
  143. X    HALF *baseABDC;        /* base of product of above two results */
  144. X    HALF *baseAC;        /* base of product of A and C */
  145. X    HALF *baseBD;        /* base of product of B and D */
  146. X    FULL carry;        /* carry digit for small multiplications */
  147. X    FULL carryACBD;        /* carry from addition of A*C and B*D */
  148. X    FULL digit;        /* single digit multiplying by */
  149. X    HALF *temp;        /* base for temporary calculations */
  150. X    BOOL neg;        /* whether imtermediate term is negative */
  151. X    register HALF *hd, *h1, *h2;    /* for inner loops */
  152. X    SIUNION sival;        /* for addition of digits */
  153. X
  154. X    /*
  155. X     * Trim the numbers of leading zeroes and initialize the
  156. X     * estimated size of the result.
  157. X     */
  158. X    hd = &v1[size1 - 1];
  159. X    while ((*hd == 0) && (size1 > 1)) {
  160. X        hd--;
  161. X        size1--;
  162. X    }
  163. X    hd = &v2[size2 - 1];
  164. X    while ((*hd == 0) && (size2 > 1)) {
  165. X        hd--;
  166. X        size2--;
  167. X    }
  168. X    sizetotal = size1 + size2;
  169. X
  170. X    /*
  171. X     * First check for zero answer.
  172. X     */
  173. X    if (((size1 == 1) && (*v1 == 0)) || ((size2 == 1) && (*v2 == 0))) {
  174. X        *ans = 0;
  175. X        return 1;
  176. X    }
  177. X
  178. X    /*
  179. X     * Exchange the two numbers if necessary to make the number of
  180. X     * digits of the first number be greater than or equal to the
  181. X     * second number.
  182. X     */
  183. X    if (size1 < size2) {
  184. X        len = size1; size1 = size2; size2 = len;
  185. X        hd = v1; v1 = v2; v2 = hd;
  186. X    }
  187. X
  188. X    /*
  189. X     * If the smaller number has only a few digits, then calculate
  190. X     * the result in the normal manner in order to avoid the overhead
  191. X     * of the recursion for small numbers.  The number of digits where
  192. X     * the algorithm changes is settable from 2 to maxint.
  193. X     */
  194. X    if (size2 < _mul2_) {
  195. X        /*
  196. X         * First clear the top part of the result, and then multiply
  197. X         * by the lowest digit to get the first partial sum.  Later
  198. X         * products will then add into this result.
  199. X         */
  200. X        hd = &ans[size1];
  201. X        len = size2;
  202. X        while (len--)
  203. X            *hd++ = 0;
  204. X
  205. X        digit = *v2++;
  206. X        h1 = v1;
  207. X        hd = ans;
  208. X        carry = 0;
  209. X        len = size1;
  210. X        while (len >= 4) {    /* expand the loop some */
  211. X            len -= 4;
  212. X            sival.ivalue = ((FULL) *h1++) * digit + carry;
  213. X            *hd++ = sival.silow;
  214. X            carry = sival.sihigh;
  215. X            sival.ivalue = ((FULL) *h1++) * digit + carry;
  216. X            *hd++ = sival.silow;
  217. X            carry = sival.sihigh;
  218. X            sival.ivalue = ((FULL) *h1++) * digit + carry;
  219. X            *hd++ = sival.silow;
  220. X            carry = sival.sihigh;
  221. X            sival.ivalue = ((FULL) *h1++) * digit + carry;
  222. X            *hd++ = sival.silow;
  223. X            carry = sival.sihigh;
  224. X        }
  225. X        while (len--) {
  226. X            sival.ivalue = ((FULL) *h1++) * digit + carry;
  227. X            *hd++ = sival.silow;
  228. X            carry = sival.sihigh;
  229. X        }
  230. X        *hd = (HALF)carry;
  231. X
  232. X        /*
  233. X         * Now multiply by the remaining digits of the second number,
  234. X         * adding each product into the final result.
  235. X         */
  236. X        h2 = ans;
  237. X        while (--size2 > 0) {
  238. X            digit = *v2++;
  239. X            h1 = v1;
  240. X            hd = ++h2;
  241. X            if (digit == 0)
  242. X                continue;
  243. X            carry = 0;
  244. X            len = size1;
  245. X            while (len >= 4) {    /* expand the loop some */
  246. X                len -= 4;
  247. X                sival.ivalue = ((FULL) *h1++) * digit
  248. X                    + ((FULL) *hd) + carry;
  249. X                *hd++ = sival.silow;
  250. X                carry = sival.sihigh;
  251. X                sival.ivalue = ((FULL) *h1++) * digit
  252. X                    + ((FULL) *hd) + carry;
  253. X                *hd++ = sival.silow;
  254. X                carry = sival.sihigh;
  255. X                sival.ivalue = ((FULL) *h1++) * digit
  256. X                    + ((FULL) *hd) + carry;
  257. X                *hd++ = sival.silow;
  258. X                carry = sival.sihigh;
  259. X                sival.ivalue = ((FULL) *h1++) * digit
  260. X                    + ((FULL) *hd) + carry;
  261. X                *hd++ = sival.silow;
  262. X                carry = sival.sihigh;
  263. X            }
  264. X            while (len--) {
  265. X                sival.ivalue = ((FULL) *h1++) * digit
  266. X                    + ((FULL) *hd) + carry;
  267. X                *hd++ = sival.silow;
  268. X                carry = sival.sihigh;
  269. X            }
  270. X            while (carry) {
  271. X                sival.ivalue = ((FULL) *hd) + carry;
  272. X                *hd++ = sival.silow;
  273. X                carry = sival.sihigh;
  274. X            }
  275. X        }
  276. X
  277. X        /*
  278. X         * Now return the true size of the number.
  279. X         */
  280. X        len = sizetotal;
  281. X        hd = &ans[len - 1];
  282. X        while ((*hd == 0) && (len > 1)) {
  283. X            hd--;
  284. X            len--;
  285. X        }
  286. X        return len;
  287. X    }
  288. X
  289. X    /*
  290. X     * Need to multiply by a large number.
  291. X     * Allocate temporary space for calculations, and calculate the
  292. X     * value for the shift.  The shift value is 1/2 the size of the
  293. X     * larger (first) number (rounded up).  The amount of temporary
  294. X     * space needed is twice the size of the shift, plus one more word
  295. X     * for the multiply to use.
  296. X     */
  297. X    shift = (size1 + 1) / 2;
  298. X    temp = tempbuf;
  299. X    tempbuf += (2 * shift) + 1;
  300. X
  301. X    /*
  302. X     * Determine the sizes and locations of all the numbers.
  303. X     * The value of sizeC can be negative, and this is checked later.
  304. X     * The value of sizeD is limited by the full size of the number.
  305. X     */
  306. X    baseA = v1 + shift;
  307. X    baseB = v1;
  308. X    baseC = v2 + shift;
  309. X    baseD = v2;
  310. X    baseAB = ans;
  311. X    baseDC = ans + shift;
  312. X    baseAC = ans + shift * 2;
  313. X    baseBD = ans;
  314. X
  315. X    sizeA = size1 - shift;
  316. X    sizeC = size2 - shift;
  317. X
  318. X    sizeB = shift;
  319. X    hd = &baseB[shift - 1];
  320. X    while ((*hd == 0) && (sizeB > 1)) {
  321. X        hd--;
  322. X        sizeB--;
  323. X    }
  324. X
  325. X    sizeD = shift;
  326. X    if (sizeD > size2)
  327. X        sizeD = size2;
  328. X    hd = &baseD[sizeD - 1];
  329. X    while ((*hd == 0) && (sizeD > 1)) {
  330. X        hd--;
  331. X        sizeD--;
  332. X    }
  333. X
  334. X    /*
  335. X     * If the smaller number has a high half of zero, then calculate
  336. X     * the result by breaking up the first number into two numbers
  337. X     * and combining the results using the obvious formula:
  338. X     *    (A*S+B) * D = (A*D)*S + B*D
  339. X     */
  340. X    if (sizeC <= 0) {
  341. X        len = domul(baseB, sizeB, baseD, sizeD, ans);
  342. X        hd = &ans[len];
  343. X        len = sizetotal - len;
  344. X        while (len--)
  345. X            *hd++ = 0;
  346. X
  347. X        /*
  348. X         * Add the second number into the first number, shifted
  349. X         * over at the correct position.
  350. X         */
  351. X        len = domul(baseA, sizeA, baseD, sizeD, temp);
  352. X        h1 = temp;
  353. X        hd = ans + shift;
  354. X        carry = 0;
  355. X        while (len--) {
  356. X            sival.ivalue = ((FULL) *h1++) + ((FULL) *hd) + carry;
  357. X            *hd++ = sival.silow;
  358. X            carry = sival.sihigh;
  359. X        }
  360. X        while (carry) {
  361. X            sival.ivalue = ((FULL) *hd) + carry;
  362. X            *hd++ = sival.silow;
  363. X            carry = sival.sihigh;
  364. X        }
  365. X
  366. X        /*
  367. X         * Determine the final size of the number and return it.
  368. X         */
  369. X        len = sizetotal;
  370. X        hd = &ans[len - 1];
  371. X        while ((*hd == 0) && (len > 1)) {
  372. X            hd--;
  373. X            len--;
  374. X        }
  375. X        tempbuf = temp;
  376. X        return len;
  377. X    }
  378. X
  379. X    /*
  380. X     * Now we know that the high halfs of the numbers are nonzero,
  381. X     * so we can use the complete formula.
  382. X     *    (A*S+B)*(C*S+D) = (S^2+S)*A*C + S*(A-B)*(D-C) + (S+1)*B*D.
  383. X     * The steps are done in the following order:
  384. X     *    A-B
  385. X     *    D-C
  386. X     *    (A-B)*(D-C)
  387. X     *    S^2*A*C + B*D
  388. X     *    (S^2+S)*A*C + (S+1)*B*D                (*)
  389. X     *    (S^2+S)*A*C + S*(A-B)*(D-C) + (S+1)*B*D
  390. X     *
  391. X     * Note: step (*) above can produce a result which is larger than
  392. X     * the final product will be, and this is where the extra word
  393. X     * needed in the product comes from.  After the final subtraction is
  394. X     * done, the result fits in the expected size.  Using the extra word
  395. X     * is easier than suppressing the carries and borrows everywhere.
  396. X     *
  397. X     * Begin by forming the product (A-B)*(D-C) into a temporary
  398. X     * location that we save until the final step.  Do each subtraction
  399. X     * at positions 0 and S.  Be very careful about the relative sizes
  400. X     * of the numbers since this result can be negative.  For the first
  401. X     * step calculate the absolute difference of A and B into a temporary
  402. X     * location at position 0 of the result.  Negate the sign if A is
  403. X     * smaller than B.
  404. X     */
  405. X    neg = FALSE;
  406. X    if (sizeA == sizeB) {
  407. X        len = sizeA;
  408. X        h1 = &baseA[len - 1];
  409. X        h2 = &baseB[len - 1];
  410. X        while ((len > 1) && (*h1 == *h2)) {
  411. X            len--;
  412. X            h1--;
  413. X            h2--;
  414. X        }
  415. X    }
  416. X    if ((sizeA > sizeB) || ((sizeA == sizeB) && (*h1 > *h2)))
  417. X    {
  418. X        h1 = baseA;
  419. X        h2 = baseB;
  420. X        sizeAB = sizeA;
  421. X        subsize = sizeB;
  422. X    } else {
  423. X        neg = !neg;
  424. X        h1 = baseB;
  425. X        h2 = baseA;
  426. X        sizeAB = sizeB;
  427. X        subsize = sizeA;
  428. X    }
  429. X    copysize = sizeAB - subsize;
  430. X
  431. X    hd = baseAB;
  432. X    carry = 0;
  433. X    while (subsize--) {
  434. X        sival.ivalue = BASE1 - ((FULL) *h1++) + ((FULL) *h2++) + carry;
  435. X        *hd++ = BASE1 - sival.silow;
  436. X        carry = sival.sihigh;
  437. X    }
  438. X    while (copysize--) {
  439. X        sival.ivalue = (BASE1 - ((FULL) *h1++)) + carry;
  440. X        *hd++ = BASE1 - sival.silow;
  441. X        carry = sival.sihigh;
  442. X    }
  443. X
  444. X    hd = &baseAB[sizeAB - 1];
  445. X    while ((*hd == 0) && (sizeAB > 1)) {
  446. X        hd--;
  447. X        sizeAB--;
  448. X    }
  449. X
  450. X    /*
  451. X     * This completes the calculation of abs(A-B).  For the next step
  452. X     * calculate the absolute difference of D and C into a temporary
  453. X     * location at position S of the result.  Negate the sign if C is
  454. X     * larger than D.
  455. X     */
  456. X    if (sizeC == sizeD) {
  457. X        len = sizeC;
  458. X        h1 = &baseC[len - 1];
  459. X        h2 = &baseD[len - 1];
  460. X        while ((len > 1) && (*h1 == *h2)) {
  461. X            len--;
  462. X            h1--;
  463. X            h2--;
  464. X        }
  465. X    }
  466. X    if ((sizeC > sizeD) || ((sizeC == sizeD) && (*h1 > *h2)))
  467. X    {
  468. X        neg = !neg;
  469. X        h1 = baseC;
  470. X        h2 = baseD;
  471. X        sizeDC = sizeC;
  472. X        subsize = sizeD;
  473. X    } else {
  474. X        h1 = baseD;
  475. X        h2 = baseC;
  476. X        sizeDC = sizeD;
  477. X        subsize = sizeC;
  478. X    }
  479. X    copysize = sizeDC - subsize;
  480. X
  481. X    hd = baseDC;
  482. X    carry = 0;
  483. X    while (subsize--) {
  484. X        sival.ivalue = BASE1 - ((FULL) *h1++) + ((FULL) *h2++) + carry;
  485. X        *hd++ = BASE1 - sival.silow;
  486. X        carry = sival.sihigh;
  487. X    }
  488. X    while (copysize--) {
  489. X        sival.ivalue = (BASE1 - ((FULL) *h1++)) + carry;
  490. X        *hd++ = BASE1 - sival.silow;
  491. X        carry = sival.sihigh;
  492. X    }
  493. X    hd = &baseDC[sizeDC - 1];
  494. X    while ((*hd == 0) && (sizeDC > 1)) {
  495. X        hd--;
  496. X        sizeDC--;
  497. X    }
  498. X
  499. X    /*
  500. X     * This completes the calculation of abs(D-C).  Now multiply
  501. X     * together abs(A-B) and abs(D-C) into a temporary location,
  502. X     * which is preserved until the final steps.
  503. X     */
  504. X    baseABDC = temp;
  505. X    sizeABDC = domul(baseAB, sizeAB, baseDC, sizeDC, baseABDC);
  506. X
  507. X    /*
  508. X     * Now calculate B*D and A*C into one of their two final locations.
  509. X     * Make sure the high order digits of the products are zeroed since
  510. X     * this initializes the final result.  Be careful about this zeroing
  511. X     * since the size of the high order words might be smaller than
  512. X     * the shift size.  Do B*D first since the multiplies use one more
  513. X     * word than the size of the product.  Also zero the final extra
  514. X     * word in the result for possible carries to use.
  515. X     */
  516. X    len = domul(baseB, sizeB, baseD, sizeD, baseBD);
  517. X    hd = &baseBD[len];
  518. X    len = shift * 2 - len;
  519. X    while (len--)
  520. X        *hd++ = 0;
  521. X
  522. X    len = domul(baseA, sizeA, baseC, sizeC, baseAC);
  523. X    hd = &baseAC[len];
  524. X    len = sizetotal - shift * 2 - len + 1;
  525. X    while (len--)
  526. X        *hd++ = 0;
  527. X
  528. X    /*
  529. X     * Now add in A*C and B*D into themselves at the other shifted
  530. X     * position that they need.  This addition is tricky in order to
  531. X     * make sure that the two additions cannot interfere with each other.
  532. X     * Therefore we first add in the top half of B*D and the lower half
  533. X     * of A*C.  The sources and destinations of these two additions
  534. X     * overlap, and so the same answer results from the two additions,
  535. X     * thus only two pointers suffice for both additions.  Keep the
  536. X     * final carry from these additions for later use since we cannot
  537. X     * afford to change the top half of A*C yet.
  538. X     */
  539. X    h1 = baseBD + shift;
  540. X    h2 = baseAC;
  541. X    carryACBD = 0;
  542. X    len = shift;
  543. X    while (len--) {
  544. X        sival.ivalue = ((FULL) *h1) + ((FULL) *h2) + carryACBD;
  545. X        *h1++ = sival.silow;
  546. X        *h2++ = sival.silow;
  547. X        carryACBD = sival.sihigh;
  548. X    }
  549. X
  550. X    /*
  551. X     * Now add in the bottom half of B*D and the top half of A*C.
  552. X     * These additions are straightforward, except that A*C should
  553. X     * be done first because of possible carries from B*D, and the
  554. X     * top half of A*C might not exist.  Add in one of the carries
  555. X     * from the previous addition while we are at it.
  556. X     */
  557. X    h1 = baseAC + shift;
  558. X    hd = baseAC;
  559. X    carry = carryACBD;
  560. X    len = sizetotal - 3 * shift;
  561. X    while (len--) {
  562. X        sival.ivalue = ((FULL) *h1++) + ((FULL) *hd) + carry;
  563. X        *hd++ = sival.silow;
  564. X        carry = sival.sihigh;
  565. X    }
  566. X    while (carry) {
  567. X        sival.ivalue = ((FULL) *hd) + carry;
  568. X        *hd++ = sival.silow;
  569. X        carry = sival.sihigh;
  570. X    }
  571. X
  572. X    h1 = baseBD;
  573. X    hd = baseBD + shift;
  574. X    carry = 0;
  575. X    len = shift;
  576. X    while (len--) {
  577. X        sival.ivalue = ((FULL) *h1++) + ((FULL) *hd) + carry;
  578. X        *hd++ = sival.silow;
  579. X        carry = sival.sihigh;
  580. X    }
  581. X    while (carry) {
  582. X        sival.ivalue = ((FULL) *hd) + carry;
  583. X        *hd++ = sival.silow;
  584. X        carry = sival.sihigh;
  585. X    }
  586. X
  587. X    /*
  588. X     * Now finally add in the other delayed carry from the
  589. X     * above addition.
  590. X     */
  591. X    hd = baseAC + shift;
  592. X    while (carryACBD) {
  593. X        sival.ivalue = ((FULL) *hd) + carryACBD;
  594. X        *hd++ = sival.silow;
  595. X        carryACBD = sival.sihigh;
  596. X    }
  597. X
  598. X    /*
  599. X     * Now finally add or subtract (A-B)*(D-C) into the final result at
  600. X     * the correct position (S), according to whether it is positive or
  601. X     * negative.  When subtracting, the answer cannot go negative.
  602. X     */
  603. X    h1 = baseABDC;
  604. X    hd = ans + shift;
  605. X    carry = 0;
  606. X    len = sizeABDC;
  607. X    if (neg) {
  608. X        while (len--) {
  609. X            sival.ivalue = BASE1 - ((FULL) *hd) +
  610. X                ((FULL) *h1++) + carry;
  611. X            *hd++ = BASE1 - sival.silow;
  612. X            carry = sival.sihigh;
  613. X        }
  614. X        while (carry) {
  615. X            sival.ivalue = BASE1 - ((FULL) *hd) + carry;
  616. X            *hd++ = BASE1 - sival.silow;
  617. X            carry = sival.sihigh;
  618. X        }
  619. X    } else {
  620. X        while (len--) {
  621. X            sival.ivalue = ((FULL) *h1++) + ((FULL) *hd) + carry;
  622. X            *hd++ = sival.silow;
  623. X            carry = sival.sihigh;
  624. X        }
  625. X        while (carry) {
  626. X            sival.ivalue = ((FULL) *hd) + carry;
  627. X            *hd++ = sival.silow;
  628. X            carry = sival.sihigh;
  629. X        }
  630. X    }
  631. X
  632. X    /*
  633. X     * Finally determine the size of the final result and return that.
  634. X     */
  635. X    len = sizetotal;
  636. X    hd = &ans[len - 1];
  637. X    while ((*hd == 0) && (len > 1)) {
  638. X        hd--;
  639. X        len--;
  640. X    }
  641. X    tempbuf = temp;
  642. X    return len;
  643. X}
  644. X
  645. X
  646. X/*
  647. X * Square a number by using the following formula recursively:
  648. X *    (A*S+B)^2 = (S^2+S)*A^2 + (S+1)*B^2 - S*(A-B)^2
  649. X * where S is a power of 2^16, and so multiplies by it are shifts,
  650. X * and A and B are the left and right halfs of the number to square.
  651. X */
  652. Xvoid
  653. Xzsquare(z, res)
  654. X    ZVALUE z, *res;
  655. X{
  656. X    LEN len;
  657. X
  658. X    if (iszero(z)) {
  659. X        *res = _zero_;
  660. X        return;
  661. X    }
  662. X    if (isunit(z)) {
  663. X        *res = _one_;
  664. X        return;
  665. X    }
  666. X
  667. X    /*
  668. X     * Allocate a temporary array if necessary for the recursion to use.
  669. X     * The array needs to be allocated large enough for all of the
  670. X     * temporary results to fit in.  This size is about 3 times the
  671. X     * size of the original number, since each recursion level uses 3/2
  672. X     * of the size of its given number, and whose size is 1/2 the size
  673. X     * of the previous level.  The sum of the infinite series is 3.
  674. X     * Allocate some extra words for rounding up the sizes.
  675. X     */
  676. X    len = 3 * z.len + 32;
  677. X    tempbuf = zalloctemp(len);
  678. X
  679. X    res->sign = 0;
  680. X    res->v = alloc(z.len * 2);
  681. X    res->len = dosquare(z.v, z.len, res->v);
  682. X}
  683. X
  684. X
  685. X/*
  686. X * Recursive routine to square a number by splitting it up into two numbers
  687. X * of half the size, and using the results of squaring the subpieces.
  688. X * The result is placed in the indicated array, which must be large
  689. X * enough for the result (size * 2).  Returns the size of the result.
  690. X * This uses a temporary array which must be 3 times as large as the
  691. X * size of the number at the top level recursive call.
  692. X */
  693. Xstatic LEN
  694. Xdosquare(vp, size, ans)
  695. X    HALF *vp;        /* value to be squared */
  696. X    LEN size;        /* length of value to square */
  697. X    HALF *ans;        /* location for result */
  698. X{
  699. X    LEN shift;        /* amount numbers are shifted by */
  700. X    LEN sizeA;        /* size of left half of number to square */
  701. X    LEN sizeB;        /* size of right half of number to square */
  702. X    LEN sizeAA;        /* size of square of left half */
  703. X    LEN sizeBB;        /* size of square of right half */
  704. X    LEN sizeAABB;        /* size of sum of squares of A and B */
  705. X    LEN sizeAB;        /* size of difference of A and B */
  706. X    LEN sizeABAB;        /* size of square of difference of A and B */
  707. X    LEN subsize;        /* size of difference of halfs */
  708. X    LEN copysize;        /* size of number left to copy */
  709. X    LEN sumsize;        /* size of sum */
  710. X    LEN sizetotal;        /* total size of square */
  711. X    LEN len;        /* temporary length */
  712. X    LEN len1;        /* another temporary length */
  713. X    FULL carry;        /* carry digit for small multiplications */
  714. X    FULL digit;        /* single digit multiplying by */
  715. X    HALF *temp;        /* base for temporary calculations */
  716. X    HALF *baseA;        /* base of left half of number */
  717. X    HALF *baseB;        /* base of right half of number */
  718. X    HALF *baseAA;        /* base of square of left half of number */
  719. X    HALF *baseBB;        /* base of square of right half of number */
  720. X    HALF *baseAABB;        /* base of sum of squares of A and B */
  721. X    HALF *baseAB;        /* base of difference of A and B */
  722. X    HALF *baseABAB;        /* base of square of difference of A and B */
  723. X    register HALF *hd, *h1, *h2, *h3;    /* for inner loops */
  724. X    SIUNION sival;        /* for addition of digits */
  725. X
  726. X    /*
  727. X     * First trim the number of leading zeroes.
  728. X     */
  729. X    hd = &vp[size - 1];
  730. X    while ((*hd == 0) && (size > 1)) {
  731. X        size--;
  732. X        hd--;
  733. X    }
  734. X    sizetotal = size + size;
  735. X
  736. X    /*
  737. X     * If the number has only a small number of digits, then use the
  738. X     * (almost) normal multiplication method.  Multiply each halfword
  739. X     * only by those halfwards further on in the number.  Missed terms
  740. X     * will then be the same pairs of products repeated, and the squares
  741. X     * of each halfword.  The first case is handled by doubling the
  742. X     * result.  The second case is handled explicitly.  The number of
  743. X     * digits where the algorithm changes is settable from 2 to maxint.
  744. X     */
  745. X    if (size < _sq2_) {
  746. X        hd = ans;
  747. X        len = sizetotal;
  748. X        while (len--)
  749. X            *hd++ = 0;
  750. X
  751. X        h2 = vp;
  752. X        hd = ans + 1;
  753. X        for (len = size; len--; hd += 2) {
  754. X            digit = (FULL) *h2++;
  755. X            if (digit == 0)
  756. X                continue;
  757. X            h3 = h2;
  758. X            h1 = hd;
  759. X            carry = 0;
  760. X            len1 = len;
  761. X            while (len1 >= 4) {    /* expand the loop some */
  762. X                len1 -= 4;
  763. X                sival.ivalue = (digit * ((FULL) *h3++))
  764. X                    + ((FULL) *h1) + carry;
  765. X                *h1++ = sival.silow;
  766. X                sival.ivalue = (digit * ((FULL) *h3++))
  767. X                    + ((FULL) *h1) + ((FULL) sival.sihigh);
  768. X                *h1++ = sival.silow;
  769. X                sival.ivalue = (digit * ((FULL) *h3++))
  770. X                    + ((FULL) *h1) + ((FULL) sival.sihigh);
  771. X                *h1++ = sival.silow;
  772. X                sival.ivalue = (digit * ((FULL) *h3++))
  773. X                    + ((FULL) *h1) + ((FULL) sival.sihigh);
  774. X                *h1++ = sival.silow;
  775. X                carry = sival.sihigh;
  776. X            }
  777. X            while (len1--) {
  778. X                sival.ivalue = (digit * ((FULL) *h3++))
  779. X                    + ((FULL) *h1) + carry;
  780. X                *h1++ = sival.silow;
  781. X                carry = sival.sihigh;
  782. X            }
  783. X            while (carry) {
  784. X                sival.ivalue = ((FULL) *h1) + carry;
  785. X                *h1++ = sival.silow;
  786. X                carry = sival.sihigh;
  787. X            }
  788. X        }
  789. X
  790. X        /*
  791. X         * Now double the result.
  792. X         * There is no final carry to worry about because we
  793. X         * handle all digits of the result which must fit.
  794. X         */
  795. X        carry = 0;
  796. X        hd = ans;
  797. X        len = sizetotal;
  798. X        while (len--) {
  799. X            digit = ((FULL) *hd);
  800. X            sival.ivalue = digit + digit + carry;
  801. X            *hd++ = sival.silow;
  802. X            carry = sival.sihigh;
  803. X        }
  804. X
  805. X        /*
  806. X         * Now add in the squares of each halfword.
  807. X         */
  808. X        carry = 0;
  809. X        hd = ans;
  810. X        h3 = vp;
  811. X        len = size;
  812. X        while (len--) {
  813. X            digit = ((FULL) *h3++);
  814. X            sival.ivalue = digit * digit + ((FULL) *hd) + carry;
  815. X            *hd++ = sival.silow;
  816. X            carry = sival.sihigh;
  817. X            sival.ivalue = ((FULL) *hd) + carry;
  818. X            *hd++ = sival.silow;
  819. X            carry = sival.sihigh;
  820. X        }
  821. X        while (carry) {
  822. X            sival.ivalue = ((FULL) *hd) + carry;
  823. X            *hd++ = sival.silow;
  824. X            carry = sival.sihigh;
  825. X        }
  826. X
  827. X        /*
  828. X         * Finally return the size of the result.
  829. X         */
  830. X        len = sizetotal;
  831. X        hd = &ans[len - 1];
  832. X        while ((*hd == 0) && (len > 1)) {
  833. X            len--;
  834. X            hd--;
  835. X        }
  836. X        return len;
  837. X    }
  838. X
  839. X    /*
  840. X     * The number to be squared is large.
  841. X     * Allocate temporary space and determine the sizes and
  842. X     * positions of the values to be calculated.
  843. X     */
  844. X    temp = tempbuf;
  845. X    tempbuf += (3 * (size + 1) / 2);
  846. X
  847. X    sizeA = size / 2;
  848. X    sizeB = size - sizeA;
  849. X    shift = sizeB;
  850. X    baseA = vp + sizeB;
  851. X    baseB = vp;
  852. X    baseAA = &ans[shift * 2];
  853. X    baseBB = ans;
  854. X    baseAABB = temp;
  855. X    baseAB = temp;
  856. X    baseABAB = &temp[shift];
  857. X
  858. X    /*
  859. X     * Trim the second number of leading zeroes.
  860. X     */
  861. X    hd = &baseB[sizeB - 1];
  862. X    while ((*hd == 0) && (sizeB > 1)) {
  863. X        sizeB--;
  864. X        hd--;
  865. X    }
  866. X
  867. X    /*
  868. X     * Now to proceed to calculate the result using the formula.
  869. X     *    (A*S+B)^2 = (S^2+S)*A^2 + (S+1)*B^2 - S*(A-B)^2.
  870. X     * The steps are done in the following order:
  871. X     *    S^2*A^2 + B^2
  872. X     *    A^2 + B^2
  873. X     *    (S^2+S)*A^2 + (S+1)*B^2
  874. X     *    (A-B)^2
  875. X     *    (S^2+S)*A^2 + (S+1)*B^2 - S*(A-B)^2.
  876. X     *
  877. X     * Begin by forming the squares of two the halfs concatenated
  878. X     * together in the final result location.  Make sure that the
  879. X     * highest words of the results are zero.
  880. X     */
  881. X    sizeBB = dosquare(baseB, sizeB, baseBB);
  882. X    hd = &baseBB[sizeBB];
  883. X    len = shift * 2 - sizeBB;
  884. X    while (len--)
  885. X        *hd++ = 0;
  886. X
  887. X    sizeAA = dosquare(baseA, sizeA, baseAA);
  888. X    hd = &baseAA[sizeAA];
  889. X    len = sizetotal - shift * 2 - sizeAA;
  890. X    while (len--)
  891. X        *hd++ = 0;
  892. X
  893. X    /*
  894. X     * Sum the two squares into a temporary location.
  895. X     */
  896. X    if (sizeAA >= sizeBB) {
  897. X        h1 = baseAA;
  898. X        h2 = baseBB;
  899. X        sizeAABB = sizeAA;
  900. X        sumsize = sizeBB;
  901. X    } else {
  902. X        h1 = baseBB;
  903. X        h2 = baseAA;
  904. X        sizeAABB = sizeBB;
  905. X        sumsize = sizeAA;
  906. X    }
  907. X    copysize = sizeAABB - sumsize;
  908. X
  909. X    hd = baseAABB;
  910. X    carry = 0;
  911. X    while (sumsize--) {
  912. X        sival.ivalue = ((FULL) *h1++) + ((FULL) *h2++) + carry;
  913. X        *hd++ = sival.silow;
  914. X        carry = sival.sihigh;
  915. X    }
  916. X    while (copysize--) {
  917. X        sival.ivalue = ((FULL) *h1++) + carry;
  918. X        *hd++ = sival.silow;
  919. X        carry = sival.sihigh;
  920. X    }
  921. X    if (carry) {
  922. X        *hd = (HALF)carry;
  923. X        sizeAABB++;
  924. X    }
  925. X
  926. X    /*
  927. X     * Add the sum back into the previously calculated squares
  928. X     * shifted over to the proper location.
  929. X     */
  930. X    h1 = baseAABB;
  931. X    hd = ans + shift;
  932. X    carry = 0;
  933. X    len = sizeAABB;
  934. X    while (len--) {
  935. X        sival.ivalue = ((FULL) *hd) + ((FULL) *h1++) + carry;
  936. X        *hd++ = sival.silow;
  937. X        carry = sival.sihigh;
  938. X    }
  939. X    while (carry) {
  940. X        sival.ivalue = ((FULL) *hd) + carry;
  941. X        *hd++ = sival.silow;
  942. X        carry = sival.sihigh;
  943. X    }
  944. X
  945. X    /*
  946. X     * Calculate the absolute value of the difference of the two halfs
  947. X     * into a temporary location.
  948. X     */
  949. X    if (sizeA == sizeB) {
  950. X        len = sizeA;
  951. X        h1 = &baseA[len - 1];
  952. X        h2 = &baseB[len - 1];
  953. X        while ((len > 1) && (*h1 == *h2)) {
  954. X            len--;
  955. X            h1--;
  956. X            h2--;
  957. X        }
  958. X    }
  959. X    if ((sizeA > sizeB) || ((sizeA == sizeB) && (*h1 > *h2)))
  960. X    {
  961. X        h1 = baseA;
  962. X        h2 = baseB;
  963. X        sizeAB = sizeA;
  964. X        subsize = sizeB;
  965. X    } else {
  966. X        h1 = baseB;
  967. X        h2 = baseA;
  968. X        sizeAB = sizeB;
  969. X        subsize = sizeA;
  970. X    }
  971. X    copysize = sizeAB - subsize;
  972. X
  973. X    hd = baseAB;
  974. X    carry = 0;
  975. X    while (subsize--) {
  976. X        sival.ivalue = BASE1 - ((FULL) *h1++) + ((FULL) *h2++) + carry;
  977. X        *hd++ = BASE1 - sival.silow;
  978. X        carry = sival.sihigh;
  979. X    }
  980. X    while (copysize--) {
  981. X        sival.ivalue = (BASE1 - ((FULL) *h1++)) + carry;
  982. X        *hd++ = BASE1 - sival.silow;
  983. X        carry = sival.sihigh;
  984. X    }
  985. X
  986. X    hd = &baseAB[sizeAB - 1];
  987. X    while ((*hd == 0) && (sizeAB > 1)) {
  988. X        sizeAB--;
  989. X        hd--;
  990. X    }
  991. X
  992. X    /*
  993. X     * Now square the number into another temporary location,
  994. X     * and subtract that from the final result.
  995. X     */
  996. X    sizeABAB = dosquare(baseAB, sizeAB, baseABAB);
  997. X
  998. X    h1 = baseABAB;
  999. X    hd = ans + shift;
  1000. X    carry = 0;
  1001. X    while (sizeABAB--) {
  1002. X        sival.ivalue = BASE1 - ((FULL) *hd) + ((FULL) *h1++) + carry;
  1003. X        *hd++ = BASE1 - sival.silow;
  1004. X        carry = sival.sihigh;
  1005. X    }
  1006. X    while (carry) {
  1007. X        sival.ivalue = BASE1 - ((FULL) *hd) + carry;
  1008. X        *hd++ = BASE1 - sival.silow;
  1009. X        carry = sival.sihigh;
  1010. X    }
  1011. X
  1012. X    /*
  1013. X     * Return the size of the result.
  1014. X     */
  1015. X    len = sizetotal;
  1016. X    hd = &ans[len - 1];
  1017. X    while ((*hd == 0) && (len > 1)) {
  1018. X        len--;
  1019. X        hd--;
  1020. X    }
  1021. X    tempbuf = temp;
  1022. X    return len;
  1023. X}
  1024. X
  1025. X
  1026. X/*
  1027. X * Return a pointer to a buffer to be used for holding a temporary number.
  1028. X * The buffer will be at least as large as the specified number of HALFs,
  1029. X * and remains valid until the next call to this routine.  The buffer cannot
  1030. X * be freed by the caller.  There is only one temporary buffer, and so as to
  1031. X * avoid possible conflicts this is only used by the lowest level routines
  1032. X * such as divide, multiply, and square.
  1033. X */
  1034. XHALF *
  1035. Xzalloctemp(len)
  1036. X    LEN len;        /* required number of HALFs in buffer */
  1037. X{
  1038. X    HALF *hp;
  1039. X    static LEN buflen;    /* current length of temp buffer */
  1040. X    static HALF *bufptr;    /* pointer to current temp buffer */
  1041. X
  1042. X    if (len <= buflen)
  1043. X        return bufptr;
  1044. X
  1045. X    /*
  1046. X     * We need to grow the temporary buffer.
  1047. X     * First free any existing buffer, and then allocate the new one.
  1048. X     * While we are at it, make the new buffer bigger than necessary
  1049. X     * in order to reduce the number of reallocations.
  1050. X     */
  1051. X    len += 100;
  1052. X    if (buflen) {
  1053. X        buflen = 0;
  1054. X        free(bufptr);
  1055. X    }
  1056. X    hp = (HALF *) malloc(len * sizeof(HALF));
  1057. X    if (hp == NULL)
  1058. X        error("No memory for temp buffer");
  1059. X    bufptr = hp;
  1060. X    buflen = len;
  1061. X    return hp;
  1062. X}
  1063. X
  1064. X/* END CODE */
  1065. END_OF_FILE
  1066. if test 27389 -ne `wc -c <'zmul.c'`; then
  1067.     echo shar: \"'zmul.c'\" unpacked with wrong size!
  1068. fi
  1069. # end of 'zmul.c'
  1070. fi
  1071. echo shar: End of archive 11 \(of 21\).
  1072. cp /dev/null ark11isdone
  1073. MISSING=""
  1074. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  1075.     if test ! -f ark${I}isdone ; then
  1076.     MISSING="${MISSING} ${I}"
  1077.     fi
  1078. done
  1079. if test "${MISSING}" = "" ; then
  1080.     echo You have unpacked all 21 archives.
  1081.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1082. else
  1083.     echo You still need to unpack the following archives:
  1084.     echo "        " ${MISSING}
  1085. fi
  1086. ##  End of shell archive.
  1087. exit 0
  1088.