Annotation of OpenXM_contrib2/asir2000/engine/Q.c, Revision 1.3
1.3 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2000/engine/Q.c,v 1.2 2000/04/05 08:32:17 noro Exp $ */
1.1 noro 2: #include "ca.h"
3: #include "base.h"
4: #include "inline.h"
5:
6: void addq(n1,n2,nr)
7: Q n1,n2,*nr;
8: {
9: N nm,dn,nm1,nm2,nm3,dn0,dn1,dn2,g,g1,g0,m;
10: int sgn;
11: unsigned t,t1;
12:
13: if ( !n1 )
14: *nr = n2;
15: else if ( !n2 )
16: *nr = n1;
17: else if ( INT(n1) )
18: if ( INT(n2) ) {
19: nm1 = NM(n1); nm2 = NM(n2);
20: if ( SGN(n1) == SGN(n2) ) {
21: if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
22: t1 = BD(nm1)[0]; t = t1+BD(nm2)[0];
23: if ( t < t1 ) {
24: m = NALLOC(2); PL(m) = 2; BD(m)[0] = t; BD(m)[1] = 1;
25: } else
26: UTON(t,m);
27: } else
28: addn(NM(n1),NM(n2),&m);
29: NTOQ(m,SGN(n1),*nr);
30: } else {
31: if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
32: t1 = BD(nm1)[0]; t = t1-BD(nm2)[0];
33: if ( !t )
34: sgn = 0;
35: else if ( t > t1 ) {
36: sgn = -1; t = -((int)t); UTON(t,m);
37: } else {
38: sgn = 1; UTON(t,m);
39: }
40: } else
41: sgn = subn(NM(n1),NM(n2),&m);
42: if ( sgn ) {
43: if ( SGN(n1) == sgn )
44: NTOQ(m,1,*nr);
45: else
46: NTOQ(m,-1,*nr);
47: } else
48: *nr = 0;
49: }
50: } else {
51: kmuln(NM(n1),DN(n2),&m);
52: if ( SGN(n1) == SGN(n2) ) {
53: sgn = SGN(n1); addn(m,NM(n2),&nm);
54: } else
55: sgn = SGN(n1)*subn(m,NM(n2),&nm);
56: if ( sgn ) {
57: dn = DN(n2); NDTOQ(nm,dn,sgn,*nr);
58: } else
59: *nr = 0;
60: }
61: else if ( INT(n2) ) {
62: kmuln(NM(n2),DN(n1),&m);
63: if ( SGN(n1) == SGN(n2) ) {
64: sgn = SGN(n1); addn(m,NM(n1),&nm);
65: } else
66: sgn = SGN(n1)*subn(NM(n1),m,&nm);
67: if ( sgn ) {
68: dn = DN(n1); NDTOQ(nm,dn,sgn,*nr);
69: } else
70: *nr = 0;
71: } else {
72: gcdn(DN(n1),DN(n2),&g); divsn(DN(n1),g,&dn1); divsn(DN(n2),g,&dn2);
73: kmuln(NM(n1),dn2,&nm1); kmuln(NM(n2),dn1,&nm2);
74: if ( SGN(n1) == SGN(n2) ) {
75: sgn = SGN(n1); addn(nm1,nm2,&nm3);
76: } else
77: sgn = SGN(n1)*subn(nm1,nm2,&nm3);
78: if ( sgn ) {
79: gcdn(nm3,g,&g1); divsn(nm3,g1,&nm); divsn(g,g1,&g0);
80: kmuln(dn1,dn2,&dn0); kmuln(g0,dn0,&dn);
81: if ( UNIN(dn) )
82: NTOQ(nm,sgn,*nr);
83: else
84: NDTOQ(nm,dn,sgn,*nr);
85: } else
86: *nr = 0;
87: }
88: }
89:
90: void subq(n1,n2,nr)
91: Q n1,n2,*nr;
92: {
93: Q m;
94:
95: if ( !n1 )
96: if ( !n2 )
97: *nr = 0;
98: else {
99: DUPQ(n2,*nr); SGN(*nr) = -SGN(n2);
100: }
101: else if ( !n2 )
102: *nr = n1;
103: else if ( n1 == n2 )
104: *nr = 0;
105: else {
106: DUPQ(n2,m); SGN(m) = -SGN(n2); addq(n1,m,nr);
107: }
108: }
109:
110: void mulq(n1,n2,nr)
111: Q n1,n2,*nr;
112: {
113: N nm,nm1,nm2,dn,dn1,dn2,g;
114: int sgn;
115: unsigned u,l;
116:
117: if ( !n1 || !n2 ) *nr = 0;
118: else if ( INT(n1) )
119: if ( INT(n2) ) {
120: nm1 = NM(n1); nm2 = NM(n2);
121: if ( PL(nm1) == 1 && PL(nm2) == 1 ) {
122: DM(BD(NM(n1))[0],BD(NM(n2))[0],u,l)
123: if ( u ) {
124: nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = l; BD(nm)[1] = u;
125: } else {
126: nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = l;
127: }
128: } else
129: kmuln(nm1,nm2,&nm);
130: sgn = (SGN(n1)==SGN(n2)?1:-1); NTOQ(nm,sgn,*nr);
131: } else {
132: gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn);
133: kmuln(nm1,NM(n2),&nm); sgn = SGN(n1)*SGN(n2);
134: if ( UNIN(dn) )
135: NTOQ(nm,sgn,*nr);
136: else
137: NDTOQ(nm,dn,sgn,*nr);
138: }
139: else if ( INT(n2) ) {
140: gcdn(NM(n2),DN(n1),&g); divsn(NM(n2),g,&nm2); divsn(DN(n1),g,&dn);
141: kmuln(nm2,NM(n1),&nm); sgn = SGN(n1)*SGN(n2);
142: if ( UNIN(dn) )
143: NTOQ(nm,sgn,*nr);
144: else
145: NDTOQ(nm,dn,sgn,*nr);
146: } else {
147: gcdn(NM(n1),DN(n2),&g); divsn(NM(n1),g,&nm1); divsn(DN(n2),g,&dn2);
148: gcdn(DN(n1),NM(n2),&g); divsn(DN(n1),g,&dn1); divsn(NM(n2),g,&nm2);
149: kmuln(nm1,nm2,&nm); kmuln(dn1,dn2,&dn); sgn = SGN(n1) * SGN(n2);
150: if ( UNIN(dn) )
151: NTOQ(nm,sgn,*nr);
152: else
153: NDTOQ(nm,dn,sgn,*nr);
154: }
155: }
156:
157: void divq(n1,n2,nq)
158: Q n1,n2,*nq;
159: {
160: Q m;
161:
162: if ( !n2 ) {
163: error("division by 0");
164: *nq = 0;
165: return;
166: } else if ( !n1 )
167: *nq = 0;
168: else if ( n1 == n2 )
169: *nq = ONE;
170: else {
171: invq(n2,&m); mulq(n1,m,nq);
172: }
173: }
174:
175: void invq(n,nr)
176: Q n,*nr;
177: {
178: N nm,dn;
179:
180: if ( INT(n) )
181: if ( UNIN(NM(n)) )
182: if ( SGN(n) > 0 )
183: *nr = ONE;
184: else {
185: nm = ONEN; NTOQ(nm,SGN(n),*nr);
186: }
187: else {
188: nm = ONEN; dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
189: }
190: else if ( UNIN(NM(n)) ) {
191: nm = DN(n); NTOQ(nm,SGN(n),*nr);
192: } else {
193: nm = DN(n); dn = NM(n); NDTOQ(nm,dn,SGN(n),*nr);
194: }
195: }
196:
197: void chsgnq(n,nr)
198: Q n,*nr;
199: {
200: Q t;
201:
202: if ( !n )
203: *nr = 0;
204: else {
205: DUPQ(n,t); SGN(t) = -SGN(t); *nr = t;
206: }
207: }
208:
209: void pwrq(n1,n,nr)
210: Q n1,n,*nr;
211: {
212: N nm,dn;
213: int sgn;
214:
215: if ( !n || UNIQ(n1) )
216: *nr = ONE;
217: else if ( !n1 )
218: *nr = 0;
219: else if ( !INT(n) ) {
220: error("can't calculate fractional power."); *nr = 0;
221: } else if ( MUNIQ(n1) )
222: *nr = BD(NM(n))[0]%2 ? n1 : ONE;
223: else if ( PL(NM(n)) > 1 ) {
224: error("exponent too big."); *nr = 0;
225: } else {
226: sgn = ((SGN(n1)>0)||EVENN(NM(n))?1:-1);
227: pwrn(NM(n1),BD(NM(n))[0],&nm);
228: if ( INT(n1) ) {
229: if ( UNIN(nm) )
230: if ( sgn == 1 )
231: *nr = ONE;
232: else
233: NTOQ(ONEN,sgn,*nr);
234: else if ( SGN(n) > 0 )
235: NTOQ(nm,sgn,*nr);
236: else
237: NDTOQ(ONEN,nm,sgn,*nr);
238: } else {
239: pwrn(DN(n1),BD(NM(n))[0],&dn);
240: if ( SGN(n) > 0 )
241: NDTOQ(nm,dn,sgn,*nr);
242: else if ( UNIN(nm) )
243: NTOQ(dn,sgn,*nr);
244: else
245: NDTOQ(dn,nm,sgn,*nr);
246: }
247: }
248: }
249:
250: int cmpq(q1,q2)
251: Q q1,q2;
252: {
253: int sgn;
254: N t,s;
255:
256: if ( !q1 )
257: if ( !q2 )
258: return ( 0 );
259: else
260: return ( -SGN(q2) );
261: else if ( !q2 )
262: return ( SGN(q1) );
263: else if ( SGN(q1) != SGN(q2) )
264: return ( SGN(q1) );
265: else if ( INT(q1) )
266: if ( INT(q2) ) {
267: sgn = cmpn(NM(q1),NM(q2));
268: if ( !sgn )
269: return ( 0 );
270: else
271: return ( SGN(q1)==sgn?1:-1 );
272: } else {
273: kmuln(NM(q1),DN(q2),&t); sgn = cmpn(t,NM(q2));
274: return ( SGN(q1) * sgn );
275: }
276: else if ( INT(q2) ) {
277: kmuln(NM(q2),DN(q1),&t); sgn = cmpn(NM(q1),t);
278: return ( SGN(q1) * sgn );
279: } else {
280: kmuln(NM(q1),DN(q2),&t); kmuln(NM(q2),DN(q1),&s); sgn = cmpn(t,s);
281: return ( SGN(q1) * sgn );
282: }
283: }
284:
285: void remq(n,m,nr)
286: Q n,m;
287: Q *nr;
288: {
289: N q,r,s;
290:
291: if ( !n ) {
292: *nr = 0;
293: return;
294: }
295: divn(NM(n),NM(m),&q,&r);
296: if ( !r )
297: *nr = 0;
298: else if ( SGN(n) > 0 )
299: NTOQ(r,1,*nr);
300: else {
301: subn(NM(m),r,&s); NTOQ(s,1,*nr);
302: }
303: }
304:
1.2 noro 305: /* t = [nC0 nC1 ... nCn] */
306:
1.1 noro 307: void mkbc(n,t)
308: int n;
309: Q *t;
310: {
311: int i;
312: N c,d;
313:
314: for ( t[0] = ONE, i = 1; i <= n/2; i++ ) {
315: c = NALLOC(1); PL(c) = 1; BD(c)[0] = n-i+1;
316: kmuln(NM(t[i-1]),c,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
317: }
318: for ( ; i <= n; i++ )
319: t[i] = t[n-i];
1.2 noro 320: }
321:
322: /*
323: * Dx^k*x^l = W(k,l,0)*x^l*Dx^k+W(k,l,1)*x^(l-1)*x^(k-1)*+...
324: *
325: * t = [W(k,l,0) W(k,l,1) ... W(k,l,min(k,l)]
326: * where W(k,l,i) = i! * kCi * lCi
327: */
328:
329: void mkwc(k,l,t)
330: int k,l;
331: Q *t;
332: {
333: int i,n,up,low;
334: N nm,d,c;
335:
336: n = MIN(k,l);
337: for ( t[0] = ONE, i = 1; i <= n; i++ ) {
338: DM(k-i+1,l-i+1,up,low);
339: if ( up ) {
340: nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = low; BD(nm)[1] = up;
341: } else {
342: nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = low;
343: }
344: kmuln(NM(t[i-1]),nm,&d); divin(d,i,&c); NTOQ(c,1,t[i]);
1.3 ! noro 345: }
! 346: }
! 347:
! 348: /* mod m table */
! 349: /* XXX : should be optimized */
! 350:
! 351: void mkwcm(k,l,m,t)
! 352: int k,l,m;
! 353: int *t;
! 354: {
! 355: int i,n;
! 356: Q *s;
! 357:
! 358: n = MIN(k,l);
! 359: s = (Q *)ALLOCA((n+1)*sizeof(Q));
! 360: mkwc(k,l,s);
! 361: for ( i = 0; i <= n; i++ ) {
! 362: t[i] = rem(NM(s[i]),m);
1.2 noro 363: }
1.1 noro 364: }
365:
366: void factorial(n,r)
367: int n;
368: Q *r;
369: {
370: Q t,iq,s;
371: unsigned int i,m,m0;
372: unsigned int c;
373:
374: if ( !n )
375: *r = ONE;
376: else if ( n < 0 )
377: *r = 0;
378: else {
379: for ( i = 1, t = ONE; (int)i <= n; ) {
380: for ( m0 = m = 1, c = 0; ((int)i <= n) && !c; i++ ) {
381: m0 = m; DM(m0,i,c,m)
382: }
383: if ( c ) {
384: m = m0; i--;
385: }
386: UTOQ(m,iq); mulq(t,iq,&s); t = s;
387: }
388: *r = t;
389: }
390: }
391:
392: void invl(a,mod,ar)
393: Q a,mod,*ar;
394: {
395: Q f1,f2,a1,a2,q,m,s;
396: N qn,rn;
397:
398: a1 = ONE; a2 = 0;
399: DUPQ(a,f1); SGN(f1) = 1; f2 = mod;
400:
401: while ( 1 ) {
402: divn(NM(f1),NM(f2),&qn,&rn);
403: if ( !qn )
404: q = 0;
405: else
406: NTOQ(qn,1,q);
407:
408: f1 = f2;
409: if ( !rn )
410: break;
411: else
412: NTOQ(rn,1,f2);
413:
414: mulq(a2,q,&m); subq(a1,m,&s); a1 = a2;
415: if ( !s )
416: a2 = 0;
417: else
418: remq(s,mod,&a2);
419: }
420: if ( SGN(a) < 0 )
421: chsgnq(a2,&m);
422: else
423: m = a2;
424:
425: if ( SGN(m) >= 0 )
426: *ar = m;
427: else
428: addq(m,mod,ar);
429: }
430:
431: int kara_mag=100;
432:
433: void kmuln(n1,n2,nr)
434: N n1,n2,*nr;
435: {
436: N n,t,s,m,carry;
437: int d,d1,d2,len,i,l;
438: int *r,*r0;
439:
440: if ( !n1 || !n2 ) {
441: *nr = 0; return;
442: }
443: d1 = PL(n1); d2 = PL(n2);
444: if ( (d1 < kara_mag) || (d2 < kara_mag) ) {
445: muln(n1,n2,nr); return;
446: }
447: if ( d1 < d2 ) {
448: n = n1; n1 = n2; n2 = n;
449: d = d1; d1 = d2; d2 = d;
450: }
451: if ( d2 > (d1+1)/2 ) {
452: kmulnmain(n1,n2,nr); return;
453: }
454: d = (d1/d2)+((d1%d2)!=0);
455: len = (d+1)*d2;
456: r0 = (int *)ALLOCA(len*sizeof(int));
457: bzero((char *)r0,len*sizeof(int));
458: for ( carry = 0, i = 0, r = r0; i < d; i++, r += d2 ) {
459: extractn(n1,i*d2,d2,&m);
460: if ( m ) {
461: kmuln(m,n2,&t);
462: addn(t,carry,&s);
463: copyn(s,d2,r);
464: extractn(s,d2,d2,&carry);
465: } else {
466: copyn(carry,d2,r);
467: carry = 0;
468: }
469: }
470: copyn(carry,d2,r);
471: for ( l = len - 1; !r0[l]; l-- );
472: l++;
473: *nr = t = NALLOC(l); PL(t) = l;
474: bcopy((char *)r0,(char *)BD(t),l*sizeof(int));
475: }
476:
477: void extractn(n,index,len,nr)
478: N n;
479: int index,len;
480: N *nr;
481: {
482: unsigned int *m;
483: int l;
484: N t;
485:
486: if ( !n ) {
487: *nr = 0; return;
488: }
489: m = BD(n)+index;
490: if ( (l = PL(n)-index) >= len ) {
491: for ( l = len - 1; (l >= 0) && !m[l]; l-- );
492: l++;
493: }
494: if ( l <= 0 ) {
495: *nr = 0; return;
496: } else {
497: *nr = t = NALLOC(l); PL(t) = l;
498: bcopy((char *)m,(char *)BD(t),l*sizeof(int));
499: }
500: }
501:
502: void copyn(n,len,p)
503: N n;
504: int len;
505: int *p;
506: {
507: if ( n )
508: bcopy((char *)BD(n),(char *)p,MIN(PL(n),len)*sizeof(int));
509: }
510:
511: void dupn(n,p)
512: N n;
513: N p;
514: {
515: if ( n )
516: bcopy((char *)n,(char *)p,(1+PL(n))*sizeof(int));
517: }
518:
519: void kmulnmain(n1,n2,nr)
520: N n1,n2,*nr;
521: {
522: int d1,d2,h,sgn,sgn1,sgn2,len;
523: N n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
524:
525: d1 = PL(n1); d2 = PL(n2); h = (d1+1)/2;
526: extractn(n1,0,h,&n1lo); extractn(n1,h,d1-h,&n1hi);
527: extractn(n2,0,h,&n2lo); extractn(n2,h,d2-h,&n2hi);
528: kmuln(n1hi,n2hi,&hi); kmuln(n1lo,n2lo,&lo);
529: len = PL(hi)+2*h; t1 = NALLOC(len); PL(t1) = len;
530: bzero((char *)BD(t1),len*sizeof(int));
531: if ( lo )
532: bcopy((char *)BD(lo),(char *)BD(t1),PL(lo)*sizeof(int));
533: if ( hi )
534: bcopy((char *)BD(hi),(char *)(BD(t1)+2*h),PL(hi)*sizeof(int));
535:
536: addn(hi,lo,&mid1);
537: sgn1 = subn(n1hi,n1lo,&s1); sgn2 = subn(n2lo,n2hi,&s2);
538: kmuln(s1,s2,&mid2); sgn = sgn1*sgn2;
539: if ( sgn > 0 )
540: addn(mid1,mid2,&mid);
541: else
542: subn(mid1,mid2,&mid);
543: if ( mid ) {
544: len = PL(mid)+h; t2 = NALLOC(len); PL(t2) = len;
545: bzero((char *)BD(t2),len*sizeof(int));
546: bcopy((char *)BD(mid),(char *)(BD(t2)+h),PL(mid)*sizeof(int));
547: addn(t1,t2,nr);
548: } else
549: *nr = t1;
550: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>