Annotation of OpenXM_contrib2/asir2000/engine/Q.c, Revision 1.2
1.2 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2000/engine/Q.c,v 1.1.1.1 1999/12/03 07:39:08 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]);
! 345: }
1.1 noro 346: }
347:
348: void factorial(n,r)
349: int n;
350: Q *r;
351: {
352: Q t,iq,s;
353: unsigned int i,m,m0;
354: unsigned int c;
355:
356: if ( !n )
357: *r = ONE;
358: else if ( n < 0 )
359: *r = 0;
360: else {
361: for ( i = 1, t = ONE; (int)i <= n; ) {
362: for ( m0 = m = 1, c = 0; ((int)i <= n) && !c; i++ ) {
363: m0 = m; DM(m0,i,c,m)
364: }
365: if ( c ) {
366: m = m0; i--;
367: }
368: UTOQ(m,iq); mulq(t,iq,&s); t = s;
369: }
370: *r = t;
371: }
372: }
373:
374: void invl(a,mod,ar)
375: Q a,mod,*ar;
376: {
377: Q f1,f2,a1,a2,q,m,s;
378: N qn,rn;
379:
380: a1 = ONE; a2 = 0;
381: DUPQ(a,f1); SGN(f1) = 1; f2 = mod;
382:
383: while ( 1 ) {
384: divn(NM(f1),NM(f2),&qn,&rn);
385: if ( !qn )
386: q = 0;
387: else
388: NTOQ(qn,1,q);
389:
390: f1 = f2;
391: if ( !rn )
392: break;
393: else
394: NTOQ(rn,1,f2);
395:
396: mulq(a2,q,&m); subq(a1,m,&s); a1 = a2;
397: if ( !s )
398: a2 = 0;
399: else
400: remq(s,mod,&a2);
401: }
402: if ( SGN(a) < 0 )
403: chsgnq(a2,&m);
404: else
405: m = a2;
406:
407: if ( SGN(m) >= 0 )
408: *ar = m;
409: else
410: addq(m,mod,ar);
411: }
412:
413: int kara_mag=100;
414:
415: void kmuln(n1,n2,nr)
416: N n1,n2,*nr;
417: {
418: N n,t,s,m,carry;
419: int d,d1,d2,len,i,l;
420: int *r,*r0;
421:
422: if ( !n1 || !n2 ) {
423: *nr = 0; return;
424: }
425: d1 = PL(n1); d2 = PL(n2);
426: if ( (d1 < kara_mag) || (d2 < kara_mag) ) {
427: muln(n1,n2,nr); return;
428: }
429: if ( d1 < d2 ) {
430: n = n1; n1 = n2; n2 = n;
431: d = d1; d1 = d2; d2 = d;
432: }
433: if ( d2 > (d1+1)/2 ) {
434: kmulnmain(n1,n2,nr); return;
435: }
436: d = (d1/d2)+((d1%d2)!=0);
437: len = (d+1)*d2;
438: r0 = (int *)ALLOCA(len*sizeof(int));
439: bzero((char *)r0,len*sizeof(int));
440: for ( carry = 0, i = 0, r = r0; i < d; i++, r += d2 ) {
441: extractn(n1,i*d2,d2,&m);
442: if ( m ) {
443: kmuln(m,n2,&t);
444: addn(t,carry,&s);
445: copyn(s,d2,r);
446: extractn(s,d2,d2,&carry);
447: } else {
448: copyn(carry,d2,r);
449: carry = 0;
450: }
451: }
452: copyn(carry,d2,r);
453: for ( l = len - 1; !r0[l]; l-- );
454: l++;
455: *nr = t = NALLOC(l); PL(t) = l;
456: bcopy((char *)r0,(char *)BD(t),l*sizeof(int));
457: }
458:
459: void extractn(n,index,len,nr)
460: N n;
461: int index,len;
462: N *nr;
463: {
464: unsigned int *m;
465: int l;
466: N t;
467:
468: if ( !n ) {
469: *nr = 0; return;
470: }
471: m = BD(n)+index;
472: if ( (l = PL(n)-index) >= len ) {
473: for ( l = len - 1; (l >= 0) && !m[l]; l-- );
474: l++;
475: }
476: if ( l <= 0 ) {
477: *nr = 0; return;
478: } else {
479: *nr = t = NALLOC(l); PL(t) = l;
480: bcopy((char *)m,(char *)BD(t),l*sizeof(int));
481: }
482: }
483:
484: void copyn(n,len,p)
485: N n;
486: int len;
487: int *p;
488: {
489: if ( n )
490: bcopy((char *)BD(n),(char *)p,MIN(PL(n),len)*sizeof(int));
491: }
492:
493: void dupn(n,p)
494: N n;
495: N p;
496: {
497: if ( n )
498: bcopy((char *)n,(char *)p,(1+PL(n))*sizeof(int));
499: }
500:
501: void kmulnmain(n1,n2,nr)
502: N n1,n2,*nr;
503: {
504: int d1,d2,h,sgn,sgn1,sgn2,len;
505: N n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
506:
507: d1 = PL(n1); d2 = PL(n2); h = (d1+1)/2;
508: extractn(n1,0,h,&n1lo); extractn(n1,h,d1-h,&n1hi);
509: extractn(n2,0,h,&n2lo); extractn(n2,h,d2-h,&n2hi);
510: kmuln(n1hi,n2hi,&hi); kmuln(n1lo,n2lo,&lo);
511: len = PL(hi)+2*h; t1 = NALLOC(len); PL(t1) = len;
512: bzero((char *)BD(t1),len*sizeof(int));
513: if ( lo )
514: bcopy((char *)BD(lo),(char *)BD(t1),PL(lo)*sizeof(int));
515: if ( hi )
516: bcopy((char *)BD(hi),(char *)(BD(t1)+2*h),PL(hi)*sizeof(int));
517:
518: addn(hi,lo,&mid1);
519: sgn1 = subn(n1hi,n1lo,&s1); sgn2 = subn(n2lo,n2hi,&s2);
520: kmuln(s1,s2,&mid2); sgn = sgn1*sgn2;
521: if ( sgn > 0 )
522: addn(mid1,mid2,&mid);
523: else
524: subn(mid1,mid2,&mid);
525: if ( mid ) {
526: len = PL(mid)+h; t2 = NALLOC(len); PL(t2) = len;
527: bzero((char *)BD(t2),len*sizeof(int));
528: bcopy((char *)BD(mid),(char *)(BD(t2)+h),PL(mid)*sizeof(int));
529: addn(t1,t2,nr);
530: } else
531: *nr = t1;
532: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>