Annotation of OpenXM_contrib2/asir2000/engine/Q.c, Revision 1.10
1.4 noro 1: /*
2: * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
3: * All rights reserved.
4: *
5: * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
6: * non-exclusive and royalty-free license to use, copy, modify and
7: * redistribute, solely for non-commercial and non-profit purposes, the
8: * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
9: * conditions of this Agreement. For the avoidance of doubt, you acquire
10: * only a limited right to use the SOFTWARE hereunder, and FLL or any
11: * third party developer retains all rights, including but not limited to
12: * copyrights, in and to the SOFTWARE.
13: *
14: * (1) FLL does not grant you a license in any way for commercial
15: * purposes. You may use the SOFTWARE only for non-commercial and
16: * non-profit purposes only, such as academic, research and internal
17: * business use.
18: * (2) The SOFTWARE is protected by the Copyright Law of Japan and
19: * international copyright treaties. If you make copies of the SOFTWARE,
20: * with or without modification, as permitted hereunder, you shall affix
21: * to all such copies of the SOFTWARE the above copyright notice.
22: * (3) An explicit reference to this SOFTWARE and its copyright owner
23: * shall be made on your publication or presentation in any form of the
24: * results obtained by use of the SOFTWARE.
25: * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
1.5 noro 26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.4 noro 27: * for such modification or the source code of the modified part of the
28: * SOFTWARE.
29: *
30: * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
31: * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
32: * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
33: * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
34: * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
35: * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
36: * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
37: * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
38: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
39: * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
40: * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
41: * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
42: * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
43: * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
44: * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
45: * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
46: * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
47: *
1.10 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2000/engine/Q.c,v 1.9 2002/08/14 04:49:52 noro Exp $
1.4 noro 49: */
1.1 noro 50: #include "ca.h"
51: #include "base.h"
52: #include "inline.h"
53:
1.7 noro 54: void addq(Q n1,Q n2,Q *nr)
1.1 noro 55: {
1.10 ! noro 56: N nm,dn,nm1,nm2,nm3,dn0,dn1,dn2,g,g1,g0,m;
! 57: int sgn;
! 58: unsigned t,t1;
! 59:
! 60: if ( !n1 )
! 61: *nr = n2;
! 62: else if ( !n2 )
! 63: *nr = n1;
! 64: else if ( INT(n1) )
! 65: if ( INT(n2) ) {
! 66: nm1 = NM(n1); nm2 = NM(n2);
! 67: if ( SGN(n1) == SGN(n2) ) {
! 68: if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
! 69: t1 = BD(nm1)[0]; t = t1+BD(nm2)[0];
! 70: if ( t < t1 ) {
! 71: m = NALLOC(2); PL(m) = 2; BD(m)[0] = t; BD(m)[1] = 1;
! 72: } else
! 73: UTON(t,m);
! 74: } else
! 75: addn(NM(n1),NM(n2),&m);
! 76: NTOQ(m,SGN(n1),*nr);
! 77: } else {
! 78: if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
! 79: t1 = BD(nm1)[0]; t = t1-BD(nm2)[0];
! 80: if ( !t )
! 81: sgn = 0;
! 82: else if ( t > t1 ) {
! 83: sgn = -1; t = -((int)t); UTON(t,m);
! 84: } else {
! 85: sgn = 1; UTON(t,m);
! 86: }
! 87: } else
! 88: sgn = subn(NM(n1),NM(n2),&m);
! 89: if ( sgn ) {
! 90: if ( SGN(n1) == sgn )
! 91: NTOQ(m,1,*nr);
! 92: else
! 93: NTOQ(m,-1,*nr);
! 94: } else
! 95: *nr = 0;
! 96: }
! 97: } else {
! 98: kmuln(NM(n1),DN(n2),&m);
! 99: if ( SGN(n1) == SGN(n2) ) {
! 100: sgn = SGN(n1); addn(m,NM(n2),&nm);
! 101: } else
! 102: sgn = SGN(n1)*subn(m,NM(n2),&nm);
! 103: if ( sgn ) {
! 104: dn = DN(n2); NDTOQ(nm,dn,sgn,*nr);
! 105: } else
! 106: *nr = 0;
! 107: }
! 108: else if ( INT(n2) ) {
! 109: kmuln(NM(n2),DN(n1),&m);
! 110: if ( SGN(n1) == SGN(n2) ) {
! 111: sgn = SGN(n1); addn(m,NM(n1),&nm);
! 112: } else
! 113: sgn = SGN(n1)*subn(NM(n1),m,&nm);
! 114: if ( sgn ) {
! 115: dn = DN(n1); NDTOQ(nm,dn,sgn,*nr);
! 116: } else
! 117: *nr = 0;
! 118: } else {
! 119: gcdn(DN(n1),DN(n2),&g); divsn(DN(n1),g,&dn1); divsn(DN(n2),g,&dn2);
! 120: kmuln(NM(n1),dn2,&nm1); kmuln(NM(n2),dn1,&nm2);
! 121: if ( SGN(n1) == SGN(n2) ) {
! 122: sgn = SGN(n1); addn(nm1,nm2,&nm3);
! 123: } else
! 124: sgn = SGN(n1)*subn(nm1,nm2,&nm3);
! 125: if ( sgn ) {
! 126: gcdn(nm3,g,&g1); divsn(nm3,g1,&nm); divsn(g,g1,&g0);
! 127: kmuln(dn1,dn2,&dn0); kmuln(g0,dn0,&dn);
! 128: if ( UNIN(dn) )
! 129: NTOQ(nm,sgn,*nr);
! 130: else
! 131: NDTOQ(nm,dn,sgn,*nr);
! 132: } else
! 133: *nr = 0;
! 134: }
1.1 noro 135: }
136:
1.7 noro 137: void subq(Q n1,Q n2,Q *nr)
1.1 noro 138: {
1.10 ! noro 139: Q m;
1.1 noro 140:
1.10 ! noro 141: if ( !n1 )
! 142: if ( !n2 )
! 143: *nr = 0;
! 144: else {
! 145: DUPQ(n2,*nr); SGN(*nr) = -SGN(n2);
! 146: }
! 147: else if ( !n2 )
! 148: *nr = n1;
! 149: else if ( n1 == n2 )
! 150: *nr = 0;
! 151: else {
! 152: DUPQ(n2,m); SGN(m) = -SGN(n2); addq(n1,m,nr);
! 153: }
1.1 noro 154: }
155:
1.7 noro 156: void mulq(Q n1,Q n2,Q *nr)
1.1 noro 157: {
1.10 ! noro 158: N nm,nm1,nm2,dn,dn1,dn2,g;
! 159: int sgn;
! 160: unsigned u,l;
! 161:
! 162: if ( !n1 || !n2 ) *nr = 0;
! 163: else if ( INT(n1) )
! 164: if ( INT(n2) ) {
! 165: nm1 = NM(n1); nm2 = NM(n2);
! 166: if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
! 167: DM(BD(NM(n1))[0],BD(NM(n2))[0],u,l)
! 168: if ( u ) {
! 169: nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = l; BD(nm)[1] = u;
! 170: } else {
! 171: nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = l;
! 172: }
! 173: } else
! 174: kmuln(nm1,nm2,&nm);
! 175: sgn = (SGN(n1)==SGN(n2)?1:-1); NTOQ(nm,sgn,*nr);
! 176: } else {
! 177: gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn);
! 178: kmuln(nm1,NM(n2),&nm); sgn = SGN(n1)*SGN(n2);
! 179: if ( UNIN(dn) )
! 180: NTOQ(nm,sgn,*nr);
! 181: else
! 182: NDTOQ(nm,dn,sgn,*nr);
! 183: }
! 184: else if ( INT(n2) ) {
! 185: gcdn(NM(n2),DN(n1),&g); divsn(NM(n2),g,&nm2); divsn(DN(n1),g,&dn);
! 186: kmuln(nm2,NM(n1),&nm); sgn = SGN(n1)*SGN(n2);
! 187: if ( UNIN(dn) )
! 188: NTOQ(nm,sgn,*nr);
! 189: else
! 190: NDTOQ(nm,dn,sgn,*nr);
! 191: } else {
! 192: gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn2);
! 193: gcdn(DN(n1),NM(n2),&g); divsn(DN(n1),g,&dn1); divsn(NM(n2),g,&nm2);
! 194: kmuln(nm1,nm2,&nm); kmuln(dn1,dn2,&dn); sgn = SGN(n1) * SGN(n2);
! 195: if ( UNIN(dn) )
! 196: NTOQ(nm,sgn,*nr);
! 197: else
! 198: NDTOQ(nm,dn,sgn,*nr);
! 199: }
1.1 noro 200: }
201:
1.7 noro 202: void divq(Q n1,Q n2,Q *nq)
1.1 noro 203: {
1.10 ! noro 204: Q m;
1.1 noro 205:
1.10 ! noro 206: if ( !n2 ) {
! 207: error("division by 0");
! 208: *nq = 0;
! 209: return;
! 210: } else if ( !n1 )
! 211: *nq = 0;
! 212: else if ( n1 == n2 )
! 213: *nq = ONE;
! 214: else {
! 215: invq(n2,&m); mulq(n1,m,nq);
! 216: }
1.6 noro 217: }
218:
1.7 noro 219: void divsq(Q n1,Q n2,Q *nq)
1.6 noro 220: {
1.10 ! noro 221: int sgn;
! 222: N tn;
1.6 noro 223:
1.10 ! noro 224: if ( !n2 ) {
! 225: error("division by 0");
! 226: *nq = 0;
! 227: return;
! 228: } else if ( !n1 )
! 229: *nq = 0;
! 230: else if ( n1 == n2 )
! 231: *nq = ONE;
! 232: else {
! 233: divsn(NM(n1),NM(n2),&tn);
! 234: sgn = SGN(n1)*SGN(n2);
! 235: NTOQ(tn,sgn,*nq);
! 236: }
1.1 noro 237: }
238:
1.7 noro 239: void invq(Q n,Q *nr)
1.1 noro 240: {
1.10 ! noro 241: N nm,dn;
1.1 noro 242:
1.10 ! noro 243: if ( INT(n) )
! 244: if ( UNIN(NM(n)) )
! 245: if ( SGN(n) > 0 )
! 246: *nr = ONE;
! 247: else {
! 248: nm = ONEN; NTOQ(nm,SGN(n),*nr);
! 249: }
! 250: else {
! 251: nm = ONEN; dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
! 252: }
! 253: else if ( UNIN(NM(n)) ) {
! 254: nm = DN(n); NTOQ(nm,SGN(n),*nr);
! 255: } else {
! 256: nm = DN(n); dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
! 257: }
1.1 noro 258: }
259:
1.7 noro 260: void chsgnq(Q n,Q *nr)
1.1 noro 261: {
1.10 ! noro 262: Q t;
1.1 noro 263:
1.10 ! noro 264: if ( !n )
! 265: *nr = 0;
! 266: else {
! 267: DUPQ(n,t); SGN(t) = -SGN(t); *nr = t;
! 268: }
1.1 noro 269: }
270:
1.7 noro 271: void pwrq(Q n1,Q n,Q *nr)
1.1 noro 272: {
1.10 ! noro 273: N nm,dn;
! 274: int sgn;
1.1 noro 275:
1.10 ! noro 276: if ( !n || UNIQ(n1) )
! 277: *nr = ONE;
! 278: else if ( !n1 )
! 279: *nr = 0;
! 280: else if ( !INT(n) ) {
! 281: error("can't calculate fractional power."); *nr = 0;
! 282: } else if ( MUNIQ(n1) )
! 283: *nr = BD(NM(n))[0]%2 ? n1 : ONE;
! 284: else if ( PL(NM(n)) > 1 ) {
! 285: error("exponent too big."); *nr = 0;
! 286: } else {
! 287: sgn = ((SGN(n1)>0)||EVENN(NM(n))?1:-1);
! 288: pwrn(NM(n1),BD(NM(n))[0],&nm);
! 289: if ( INT(n1) ) {
! 290: if ( UNIN(nm) )
! 291: if ( sgn == 1 )
! 292: *nr = ONE;
! 293: else
! 294: NTOQ(ONEN,sgn,*nr);
! 295: else if ( SGN(n) > 0 )
! 296: NTOQ(nm,sgn,*nr);
! 297: else
! 298: NDTOQ(ONEN,nm,sgn,*nr);
! 299: } else {
! 300: pwrn(DN(n1),BD(NM(n))[0],&dn);
! 301: if ( SGN(n) > 0 )
! 302: NDTOQ(nm,dn,sgn,*nr);
! 303: else if ( UNIN(nm) )
! 304: NTOQ(dn,sgn,*nr);
! 305: else
! 306: NDTOQ(dn,nm,sgn,*nr);
! 307: }
! 308: }
1.1 noro 309: }
310:
1.7 noro 311: int cmpq(Q q1,Q q2)
1.1 noro 312: {
1.10 ! noro 313: int sgn;
! 314: N t,s;
1.1 noro 315:
1.10 ! noro 316: if ( !q1 )
! 317: if ( !q2 )
! 318: return ( 0 );
! 319: else
! 320: return ( -SGN(q2) );
! 321: else if ( !q2 )
! 322: return ( SGN(q1) );
! 323: else if ( SGN(q1) != SGN(q2) )
! 324: return ( SGN(q1) );
! 325: else if ( INT(q1) )
! 326: if ( INT(q2) ) {
! 327: sgn = cmpn(NM(q1),NM(q2));
! 328: if ( !sgn )
! 329: return ( 0 );
! 330: else
! 331: return ( SGN(q1)==sgn?1:-1 );
! 332: } else {
! 333: kmuln(NM(q1),DN(q2),&t); sgn = cmpn(t,NM(q2));
! 334: return ( SGN(q1) * sgn );
! 335: }
! 336: else if ( INT(q2) ) {
! 337: kmuln(NM(q2),DN(q1),&t); sgn = cmpn(NM(q1),t);
! 338: return ( SGN(q1) * sgn );
! 339: } else {
! 340: kmuln(NM(q1),DN(q2),&t); kmuln(NM(q2),DN(q1),&s); sgn = cmpn(t,s);
! 341: return ( SGN(q1) * sgn );
! 342: }
1.1 noro 343: }
344:
1.7 noro 345: void remq(Q n,Q m,Q *nr)
1.1 noro 346: {
1.10 ! noro 347: N q,r,s;
1.1 noro 348:
1.10 ! noro 349: if ( !n ) {
! 350: *nr = 0;
! 351: return;
! 352: }
! 353: divn(NM(n),NM(m),&q,&r);
! 354: if ( !r )
! 355: *nr = 0;
! 356: else if ( SGN(n) > 0 )
! 357: NTOQ(r,1,*nr);
! 358: else {
! 359: subn(NM(m),r,&s); NTOQ(s,1,*nr);
! 360: }
1.1 noro 361: }
362:
1.2 noro 363: /* t = [nC0 nC1 ... nCn] */
364:
1.7 noro 365: void mkbc(int n,Q *t)
1.1 noro 366: {
1.10 ! noro 367: int i;
! 368: N c,d;
1.1 noro 369:
1.10 ! noro 370: for ( t[0] = ONE, i = 1; i <= n/2; i++ ) {
! 371: c = NALLOC(1); PL(c) = 1; BD(c)[0] = n-i+1;
! 372: kmuln(NM(t[i-1]),c,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
! 373: }
! 374: for ( ; i <= n; i++ )
! 375: t[i] = t[n-i];
1.2 noro 376: }
377:
378: /*
379: * Dx^k*x^l = W(k,l,0)*x^l*Dx^k+W(k,l,1)*x^(l-1)*x^(k-1)*+...
380: *
381: * t = [W(k,l,0) W(k,l,1) ... W(k,l,min(k,l)]
382: * where W(k,l,i) = i! * kCi * lCi
383: */
384:
1.7 noro 385: void mkwc(int k,int l,Q *t)
1.2 noro 386: {
1.10 ! noro 387: int i,n,up,low;
! 388: N nm,d,c;
1.2 noro 389:
1.10 ! noro 390: n = MIN(k,l);
! 391: for ( t[0] = ONE, i = 1; i <= n; i++ ) {
! 392: DM(k-i+1,l-i+1,up,low);
! 393: if ( up ) {
! 394: nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = low; BD(nm)[1] = up;
! 395: } else {
! 396: nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = low;
! 397: }
! 398: kmuln(NM(t[i-1]),nm,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
! 399: }
1.3 noro 400: }
401:
402: /* mod m table */
403: /* XXX : should be optimized */
404:
1.7 noro 405: void mkwcm(int k,int l,int m,int *t)
1.3 noro 406: {
1.10 ! noro 407: int i,n;
! 408: Q *s;
1.3 noro 409:
1.10 ! noro 410: n = MIN(k,l);
! 411: s = (Q *)ALLOCA((n+1)*sizeof(Q));
! 412: mkwc(k,l,s);
! 413: for ( i = 0; i <= n; i++ ) {
! 414: t[i] = rem(NM(s[i]),m);
! 415: }
1.1 noro 416: }
417:
1.8 noro 418: #if 0
1.7 noro 419: void factorial(int n,Q *r)
1.1 noro 420: {
1.10 ! noro 421: Q t,iq,s;
! 422: unsigned int i,m,m0;
! 423: unsigned int c;
! 424:
! 425: if ( !n )
! 426: *r = ONE;
! 427: else if ( n < 0 )
! 428: *r = 0;
! 429: else {
! 430: for ( i = 1, t = ONE; (int)i <= n; ) {
! 431: for ( m0 = m = 1, c = 0; ((int)i <= n) && !c; i++ ) {
! 432: m0 = m; DM(m0,i,c,m)
! 433: }
! 434: if ( c ) {
! 435: m = m0; i--;
! 436: }
! 437: UTOQ(m,iq); mulq(t,iq,&s); t = s;
! 438: }
! 439: *r = t;
! 440: }
1.8 noro 441: }
442: #endif
443:
444: void partial_factorial(int s,int e,N *r);
445:
446: void factorial(int n,Q *r)
447: {
1.10 ! noro 448: N nm;
1.8 noro 449:
1.10 ! noro 450: if ( !n )
! 451: *r = ONE;
! 452: else if ( n < 0 )
! 453: *r = 0;
! 454: else {
! 455: partial_factorial(1,n,&nm);
! 456: NTOQ(nm,1,*r);
! 457: }
1.8 noro 458: }
459:
460: /* s*(s+1)*...*e */
461: void partial_factorial(int s,int e,N *r)
462: {
1.10 ! noro 463: unsigned int len,i,m,m0,c;
! 464: unsigned int *p,*p1,*p2;
! 465: N nm,r1,r2;
! 466:
! 467: /* XXX */
! 468: if ( e-s > 2000 ) {
! 469: m = (e+s)/2;
! 470: partial_factorial(s,m,&r1);
! 471: partial_factorial(m+1,e,&r2);
! 472: kmuln(r1,r2,r);
! 473: return;
! 474: }
! 475: /* find i s.t. 2^(i-1) < m <= 2^i */
! 476: for ( i = 0, m = 1; m < e; m <<=1, i++ );
! 477: /* XXX estimate of word length of the result */
! 478: len = (i*(e-s+1)+1+31)/32;
! 479: p = ALLOCA((len+1)*sizeof(int));
! 480: p1 = ALLOCA((len+1)*sizeof(int));
! 481: p[0] = s;
! 482: len = 1;
! 483: for ( i = s+1; (int)i <= e; ) {
! 484: for ( m0 = m = 1, c = 0; ((int)i <= e) && !c; i++ ) {
! 485: m0 = m; DM(m0,i,c,m)
! 486: }
! 487: if ( c ) {
! 488: m = m0; i--;
! 489: }
! 490: bzero(p1,(len+1)*sizeof(int));
! 491: muln_1(p,len,m,p1);
! 492: if ( p1[len] )
! 493: len++;
! 494: p2 = p; p = p1; p1 = p2;
! 495: }
! 496: *r = nm = NALLOC(len);
! 497: bcopy(p,BD(nm),sizeof(int)*len);
! 498: PL(nm) = len;
1.1 noro 499: }
500:
1.7 noro 501: void invl(Q a,Q mod,Q *ar)
1.1 noro 502: {
1.10 ! noro 503: Q f1,f2,a1,a2,q,m,s;
! 504: N qn,rn;
1.1 noro 505:
1.10 ! noro 506: a1 = ONE; a2 = 0;
! 507: DUPQ(a,f1); SGN(f1) = 1; f2 = mod;
1.1 noro 508:
1.10 ! noro 509: while ( 1 ) {
! 510: divn(NM(f1),NM(f2),&qn,&rn);
! 511: if ( !qn )
! 512: q = 0;
! 513: else
! 514: NTOQ(qn,1,q);
! 515:
! 516: f1 = f2;
! 517: if ( !rn )
! 518: break;
! 519: else
! 520: NTOQ(rn,1,f2);
! 521:
! 522: mulq(a2,q,&m); subq(a1,m,&s); a1 = a2;
! 523: if ( !s )
! 524: a2 = 0;
! 525: else
! 526: remq(s,mod,&a2);
! 527: }
! 528: if ( SGN(a) < 0 )
! 529: chsgnq(a2,&m);
! 530: else
! 531: m = a2;
! 532:
! 533: if ( SGN(m) >= 0 )
! 534: *ar = m;
! 535: else
! 536: addq(m,mod,ar);
1.1 noro 537: }
538:
539: int kara_mag=100;
540:
1.7 noro 541: void kmuln(N n1,N n2,N *nr)
1.1 noro 542: {
1.10 ! noro 543: N n,t,s,m,carry;
! 544: int d,d1,d2,len,i,l;
! 545: int *r,*r0;
! 546:
! 547: if ( !n1 || !n2 ) {
! 548: *nr = 0; return;
! 549: }
! 550: d1 = PL(n1); d2 = PL(n2);
! 551: if ( (d1 < kara_mag) || (d2 < kara_mag) ) {
! 552: muln(n1,n2,nr); return;
! 553: }
! 554: if ( d1 < d2 ) {
! 555: n = n1; n1 = n2; n2 = n;
! 556: d = d1; d1 = d2; d2 = d;
! 557: }
! 558: if ( d2 > (d1+1)/2 ) {
! 559: kmulnmain(n1,n2,nr); return;
! 560: }
! 561: d = (d1/d2)+((d1%d2)!=0);
! 562: len = (d+1)*d2;
! 563: r0 = (int *)ALLOCA(len*sizeof(int));
! 564: bzero((char *)r0,len*sizeof(int));
! 565: for ( carry = 0, i = 0, r = r0; i < d; i++, r += d2 ) {
! 566: extractn(n1,i*d2,d2,&m);
! 567: if ( m ) {
! 568: kmuln(m,n2,&t);
! 569: addn(t,carry,&s);
! 570: copyn(s,d2,r);
! 571: extractn(s,d2,d2,&carry);
! 572: } else {
! 573: copyn(carry,d2,r);
! 574: carry = 0;
! 575: }
! 576: }
! 577: copyn(carry,d2,r);
! 578: for ( l = len - 1; !r0[l]; l-- );
! 579: l++;
! 580: *nr = t = NALLOC(l); PL(t) = l;
! 581: bcopy((char *)r0,(char *)BD(t),l*sizeof(int));
1.1 noro 582: }
583:
1.7 noro 584: void extractn(N n,int index,int len,N *nr)
1.1 noro 585: {
1.10 ! noro 586: unsigned int *m;
! 587: int l;
! 588: N t;
! 589:
! 590: if ( !n ) {
! 591: *nr = 0; return;
! 592: }
! 593: m = BD(n)+index;
! 594: if ( (l = PL(n)-index) >= len ) {
! 595: for ( l = len - 1; (l >= 0) && !m[l]; l-- );
! 596: l++;
! 597: }
! 598: if ( l <= 0 ) {
! 599: *nr = 0; return;
! 600: } else {
! 601: *nr = t = NALLOC(l); PL(t) = l;
! 602: bcopy((char *)m,(char *)BD(t),l*sizeof(int));
! 603: }
1.1 noro 604: }
605:
1.7 noro 606: void copyn(N n,int len,int *p)
1.1 noro 607: {
1.10 ! noro 608: if ( n )
! 609: bcopy((char *)BD(n),(char *)p,MIN(PL(n),len)*sizeof(int));
1.1 noro 610: }
611:
1.7 noro 612: void dupn(N n,N p)
1.1 noro 613: {
1.10 ! noro 614: if ( n )
! 615: bcopy((char *)n,(char *)p,(1+PL(n))*sizeof(int));
1.1 noro 616: }
617:
1.7 noro 618: void kmulnmain(N n1,N n2,N *nr)
1.1 noro 619: {
1.10 ! noro 620: int d1,d2,h,sgn,sgn1,sgn2,len;
! 621: N n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
1.1 noro 622:
1.10 ! noro 623: d1 = PL(n1); d2 = PL(n2); h = (d1+1)/2;
! 624: extractn(n1,0,h,&n1lo); extractn(n1,h,d1-h,&n1hi);
! 625: extractn(n2,0,h,&n2lo); extractn(n2,h,d2-h,&n2hi);
! 626: kmuln(n1hi,n2hi,&hi); kmuln(n1lo,n2lo,&lo);
! 627: len = PL(hi)+2*h; t1 = NALLOC(len); PL(t1) = len;
! 628: bzero((char *)BD(t1),len*sizeof(int));
! 629: if ( lo )
! 630: bcopy((char *)BD(lo),(char *)BD(t1),PL(lo)*sizeof(int));
! 631: if ( hi )
! 632: bcopy((char *)BD(hi),(char *)(BD(t1)+2*h),PL(hi)*sizeof(int));
! 633:
! 634: addn(hi,lo,&mid1);
! 635: sgn1 = subn(n1hi,n1lo,&s1); sgn2 = subn(n2lo,n2hi,&s2);
! 636: kmuln(s1,s2,&mid2); sgn = sgn1*sgn2;
! 637: if ( sgn > 0 )
! 638: addn(mid1,mid2,&mid);
! 639: else
! 640: subn(mid1,mid2,&mid);
! 641: if ( mid ) {
! 642: len = PL(mid)+h; t2 = NALLOC(len); PL(t2) = len;
! 643: bzero((char *)BD(t2),len*sizeof(int));
! 644: bcopy((char *)BD(mid),(char *)(BD(t2)+h),PL(mid)*sizeof(int));
! 645: addn(t1,t2,nr);
! 646: } else
! 647: *nr = t1;
1.1 noro 648: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>