Annotation of OpenXM_contrib2/asir2000/engine/igcdhack.c, Revision 1.3
1.2 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.3 ! noro 26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.2 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.3 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2000/engine/igcdhack.c,v 1.2 2000/08/21 08:31:27 noro Exp $
1.2 noro 49: */
1.1 noro 50: #if 0
51: #include "base.h"
52:
53: #define SWAP(a,b,Type) { Type temp=a; a = b; b = temp; }
54: #define SIGNED_VAL(a,s) ((s)>0?(a): -(a))
55: #endif
56:
57: #undef FULLSET
58:
59:
60: static int negate_nbd( b, l )
61: int *b, l;
62: /* It is assumed that l > 0 and b[0] != 0 */
63: {
64: int i, nz;
65:
66: *b = BASE - *b;
67: for ( nz = i = 1 ; i < l; ) {
68: b++, i++;
69: if ( (*b ^= BMASK) != 0 ) nz = i;
70: }
71: return nz;
72: }
73:
74: /****************/
75: /****************/
76:
77: static int abs_U_V_maxrshift( u, lu, v, lv, a )
78: int *u, lu, *v, lv, *a;
79: /*
80: * Compute | U - V | >> (as much as possible) in a[], where U = u[0:lu-1]
81: * and V = v[0:lv-1]. Value returned is the length of the result
82: * multiplied by the sign of (U-V).
83: */
84: {
85: int sign, rsh, t, b, i, i_1, l, *p = a;
86:
87: /* first, determine U <, ==, > V */
88: sign = 1;
89: if ( lu == lv ) {
90: int i;
91:
92: for ( i = lu -1; i >= 0; i-- ) {
93: if ( u[i] == v[i] ) continue;
94: lu = lv = i + 1;
95: if ( u[i] > v[i] ) goto U_V;
96: else goto swap;
97: }
98: return 0;
99: } else if ( lu > lv ) goto U_V;
100: swap:
101: SWAP( lu, lv, int ); SWAP( u, v, int * );
102: sign = -1;
103: U_V: /* U > V, i.e., (lu > lv) || (lu == lv && u[lu-1] > v[lv-1]) */
104: for ( i = 0; i < lv; i++ ) if ( u[i] != v[i] ) break;
105: if ( i != 0 ) u += i, lu -= i, v += i, lv -= i;
106: if ( lv == 0 ) { /* no more pv[], and lu > 0 */
107: i = trailingzeros_nbd( u, &rsh );
108: i = rshift_nbd( u, lu, rsh, i, a );
109: return SIGNED_VAL( i, sign );
110: }
111: /**/
112: if ( (t = u[0] - v[0]) >= 0 ) b = 0;
113: else b = 1, t += BASE;
114: TRAILINGZEROS( t, rsh );
115: /**/
116: if ( rsh != 0 ) {
117: int w, lsh = BSH - rsh;
118:
119: /* subtract v[*] from u[*] */
120: for ( i = 1, l = 0; i < lv; i++, t = w >> rsh ) {
121: if ( (w = u[i] - v[i] - b) >= 0 ) b = 0;
122: else b = 1, w += BASE;
123: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
124: }
125: /* subtraction of V completed. Note there may exist non-0 borrow b */
126: if ( i >= lu ) /* lu == lv, and b==0 is implied */ goto chk_nz;
127: /* we still have (lu-i) elms in U */
128: if ( b != 0 ) { /* non-zero borrow */
129: if ( (w = u[i++] -1) != 0 ) t |= ((w << lsh) & BMASK);
130: if ( i >= lu ) { /* lu == lv+1. The M.S. word w may beome 0 */
131: if ( w != 0 ) {
132: *p++ = t;
133: l = lv;
134: t = w >> rsh;
135: } else lu--;
136: goto chk_nz;
137: }
138: *p++ = t;
139: if ( w < 0 ) {
140: while ( (w = u[i++]) == 0 ) *p++ = BMASK;
141: w -= 1;
142: *p++ = (BMASK >> rsh) | ((w << lsh) & BMASK);
143: }
144: t = w >> rsh;
145: }
146: for ( ; i < lu; i++, t = w >> rsh ) *p++ = t | (((w = u[i]) << lsh) & BMASK);
147: l = i -1;
148: chk_nz:
149: if ( t != 0 ) *p = t, l = /*1 + (p - a)*/ lu;
150: goto ret_nz;
151: }
152: /* rsh == 0 : need not be right-shifted */
153: *p++ = t, l = 1;
154: for ( i = 1; i < lv; ) {
155: if ( (t = u[i] - v[i] - b) >= 0 ) b = 0;
156: else b = 1, t += BASE;
157: i++;
158: if ( (*p++ = t) != 0 ) l = i;
159: }
160: if ( i >= lu ) /* lu == lv, and b==0 is implied */ goto ret_nz;
161: if ( b != 0 ) { /* non-zero borrow */
162: t = u[i++] -1;
163: if ( i >= lu ) /* lu == lv+1. The M.S. word w may beome 0 */ goto chk_nz;
164: if ( t < 0 ) {
165: do *p++ = BMASK; while ( (t = u[i++]) == 0 );
166: t -= 1;
167: if ( i >= lu ) {
168: l = lu;
169: if ( t == 0 ) l--;
170: else *p = t;
171: goto ret_nz;
172: }
173: }
174: *p++ = t;
175: }
176: for ( ; i < lu; i++ ) *p++ = u[i];
177: l = lu;
178: /**/
179: ret_nz:
180: return SIGNED_VAL( l, sign );
181: }
182:
183: /****************/
184: /****************/
185:
186: #ifdef CALL
187: static int aV_plus_c(), aV_plus_c_sh();
188: #endif
189: static int abs_U_aV_c(), abs_U_aV_c_sh();
190: static int abs_aVplusc_U(), abs_aVplusc_U_sh();
191:
192: static int abs_U_aV_maxrshift( u, lu, a, v, lv, ans )
193: int *u, lu, a, *v, lv, *ans;
194: {
195: int i, t, c, rsh, l, *p = ans, w, lsh;
196: int hi;
197:
198: if ( a == 1 ) return( (l = abs_U_V_maxrshift( u, lu, v, lv, ans )) >= 0 ? l : -l );
199: /**/
200: for ( l = lu <= lv ? lu : lv, i = c = 0; i < l; ) {
201: DMA( a, v[i], c, hi, t, not_used );
202: c = hi;
203: if ( (t -= u[i++]) != 0 ) goto non0w;
204: }
205: /**/
206: if ( i < lv ) { /* no more u[] elm.'s, and we still have non-zero v[] elm's */
207: do {
208: DMA( a, v[i], c, hi, t, not_used );
209: i++, c = hi;
210: } while ( t == 0 );
211: TRAILINGZEROS( t, rsh );
212: v += i, lv -= i;
213: #ifdef CALL
214: if ( rsh == 0 ) {
215: *p++ = t;
216: return( aV_plus_c( a, v, lv, c, p ) + 1 );
217: } else return aV_plus_c_sh( a, v, lv, c, rsh, t, ans );
218: #else
219: i = 0;
220: if ( rsh == 0 ) {
221: *p++ = t;
222: for ( ; i < lv; i++, c = hi, *p++ = t ) { DMA( a, v[i], c, hi, t, not_used ); }
223: if ( c == 0 ) return( i + 1 );
224: *p = c;
225: return( i + 2 );
226: } else {
227: for ( lsh = BSH - rsh; i < lv; i++, c = hi, t = w >> rsh ) {
228: DMA( a, v[i], c, hi, w, not_used );
229: *p++ = t | ((w << lsh) & BMASK);
230: }
231: if ( c != 0 ) {
232: *p++ = t | ((c << lsh) & BMASK);
233: i++;
234: t = c >> rsh;
235: }
236: if ( t == 0 ) return i;
237: *p = t;
238: return( i + 1 );
239: }
240: #endif
241: }
242: /* no more v[] elm.'s */
243: if ( i >= lu ) {
244: if ( c == 0 ) return 0;
245: c_sh:
246: while ( (c&1) == 0 ) c >>= 1;
247: *p = c;
248: return 1;
249: }
250: t = u[i++] - c;
251: if ( i >= lu ) {
252: if ( t == 0 ) return 0;
253: c = t < 0 ? -t : t;
254: goto c_sh;
255: } else if ( t == 0 ) {
256: while ( (t = u[i++]) == 0 ) ;
257: c = 0;
258: } else if ( t < 0 ) t += BASE, c = 1;
259: else c = 0;
260: /* diff turned out to be > 0 */
261: u += i, lu -= i;
262: TRAILINGZEROS( t, rsh );
263: i = 0;
264: if ( rsh == 0 ) {
265: *p++ = t;
266: if ( c != 0 ) {
267: for ( ; i < lu; *p++ = BMASK ) if ( (t = u[i++]) != 0 ) break;
268: t--;
269: if ( i >= lu && t == 0 ) return i;
270: *p++ = t;
271: }
272: for ( ; i < lu; i++ ) *p++ = u[i];
273: } else { /* rsh != 0 */
274: lsh = BSH - rsh;
275: if ( c != 0 ) { /* there still exists u[] elms.'s because diff is known to be > 0 */
276: if ( (w = u[i++]) == 0 ) {
277: *p++ = t | ((BMASK << lsh) & BMASK);
278: for ( ; (w = u[i++]) == 0; *p++ = BMASK ) ;
279: t = BMASK >> rsh;
280: }
281: w--;
282: *p++ = t | ((w << lsh) & BMASK);
283: t = w >> rsh;
284: }
285: for ( ; i < lu; i++, t = w >> rsh ) *p++ = t | (((w = u[i]) << lsh) & BMASK);
286: if ( t == 0 ) return( i );
287: *p = t;
288: }
289: return( i + 1 );
290: /**/
291: non0w:
292: u += i, lu -= i, v += i, lv -= i;
293: /* | t + BASE*(c + a*v[0:lv-1] - u[0:lu-1] | */
294: if ( lv < lu ) { /* a*V < U if lv<lu-1, and very likely if lv==lu-1 */
295: t = -t; /* We shall compute U - a*V */
296: if ( t < 0 ) t += BASE, c++;
297: } else /* a*V > U if lv>lu, and very likely even if lv==lu */
298: if ( t < 0 ) t += BASE, c--;
299: TRAILINGZEROS( t, rsh );
300: return( rsh == 0 ? (lv < lu ? abs_U_aV_c( t, u, lu, a, v, lv, c, ans ) :
301: abs_aVplusc_U( t, a, v, lv, c, u, lu, ans )) :
302: lv < lu ? abs_U_aV_c_sh( t, u, lu, a, v, lv, c, rsh, ans ) :
303: abs_aVplusc_U_sh( t, a, v, lv, c, u, lu, rsh, ans ) );
304: }
305:
306: /*********/
307:
308: static int aV_plus_c( a, v, lv, c, p )
309: int a, *v, lv, c, *p;
310: /*
311: * Compute (a*V + c) in p[], where V = v[0:lv-1].
312: */
313: {
314: int i, t;
315: int hi;
316:
317: for ( i = 0; i < lv; i++, *p++ = t, c = hi ) { DMA( a, v[i], c, hi, t, not_used); }
318: if ( c == 0 ) return i;
319: *p = c;
320: return( i + 1 );
321: }
322:
323: static int aV_plus_c_sh( a, v, lv, c, rsh, t, p )
324: int a, *v, lv, c, rsh, *p;
325: /*
326: * Compute (t + BASE*((a*V + c) >> rsh)) in p[], where V = v[0:lv-1].
327: */
328: {
329: int i, w, lsh = BSH - rsh;
330: int hi;
331:
332: for ( i = 0; i < lv; i++, c = hi, t = w >> rsh ) {
333: DMA( a, v[i], c, hi, w, not_used );
334: *p++ = t | ((w << lsh) & BMASK);
335: }
336: if ( c != 0 ) {
337: *p++ = t | ((c << lsh) & BMASK);
338: i++;
339: t = c >> rsh;
340: }
341: if ( t == 0 ) return i;
342: *p = t;
343: return( i + 1 );
344: }
345:
346: /*********/
347:
348: static int abs_aVplusc_U( t, a, v, lv, c, u, lu, ans )
349: int t, a, *v, lv, c, *u, lu, *ans;
350: /* compute | t + BASE*(a*V+c - U) | in ans[], where V=v[0:lv-1], U=u[0:lu-1],
351: * and a > 1, -1 <= c < BASE, lv >= lu >=0 && t != 0 are assumed.
352: */
353: {
354: int i, l, b, *p = ans;
355: int hi;
356:
357: *p++ = t, l = 1;
358: if ( c < 0 ) c = 0, b = 1;
359: else b = 0;
360: for ( i = 0; i < lu; *p++ = t ) {
361: DMA( a, v[i], c, hi, t, not_used );
362: t -= u[i++], c = hi;
363: if ( b != 0 ) t--;
364: b = 0;
365: if ( t > 0 ) l = i + 1;
366: else if ( t < 0 ) {
367: t += BASE, l = i + 1;
368: if ( c != 0 ) c--;
369: else b = 1;
370: }
371: }
372: /* at this point, i == lu and we have written (i+1) entries in ans[] */
373: if ( i >= lv ) { /* no more elms in v[] */
374: if ( b != 0 ) {
375: if ( i == 0 ) { ans[i] = BASE - t; return 1; }
376: l = negate_nbd( ans, i ); /* <================ */
377: /* if ( (t = BMASK ^ ans[i]) == 0 ) return l;*/
378: if ( (t ^= BMASK) == 0 ) return l;
379: ans[i] = t;
380: return( i + 1 );
381: }
382: if ( c == 0 ) return l;
383: *p = c;
384: return( i + 2 );
385: }
386: /* diff turned out to be > 0 */
387: if ( b != 0 ) { /* c == 0 */
388: while ( (b = v[i++]) == 0 ) *p++ = BMASK;
389: DM( a, b, hi, t );
390: if ( t != 0 ) t--, c = hi;
391: else t = BMASK, c = hi - 1;
392: *p++ - t;
393: }
394: #ifdef CALL
395: return( aV_plus_c( a, &v[i], lv - i, c, p ) + i +1 );
396: #else
397: for ( ; i < lv; i++, *p++ = t, c = hi ) { DMA( a, v[i], c, hi, t, not_used );}
398: if ( c == 0 ) return( i + 1 );
399: *p = c;
400: return( i + 2 );
401: #endif
402: }
403:
404: static int abs_aVplusc_U_sh( t, a, v, lv, c, u, lu, rsh, ans )
405: int t, a, *v, lv, c, *u, lu, rsh, *ans;
406: {
407: int i, l, w, b, lsh = BSH - rsh, *p = ans;
408: int hi;
409:
410: if ( c < 0 ) c = 0, b = 1;
411: else b = 0;
412: for ( i = 0; i < lu; t = w >> rsh ) {
413: DMA( a, v[i], c, hi, w, not_used );
414: w -= u[i++], c = hi;
415: if ( b != 0 ) w--;
416: b = 0;
417: if ( w < 0 ) {
418: w += BASE;
419: if ( c != 0 ) c--;
420: else b = 1;
421: }
422: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
423: }
424: /* at this point, i == lu and we have written i entries in ans[] */
425: if ( i >= lv ) {
426: if ( b != 0 ) { /* diff turned out to be < 0 */
427: if ( i == 0 ) {
428: *p = (BASE >> rsh) - t;
429: return 1;
430: }
431: l = negate_nbd( ans, i ); /* <================ */
432: if ( (t ^= (BMASK >> rsh)) == 0 ) return l;
433: *p = t;
434: return( i + 1 );
435: }
436: if ( c == 0 ) {
437: if ( t == 0 ) return l;
438: *p = t;
439: return( i + 1 );
440: }
441: *p++ = t | ((c << lsh) & BMASK);
442: if ( (t = c >> rsh) == 0 ) return( i + 1 );
443: *p = t;
444: return( i + 2 );
445: }
446: /* lv >= lu+1 = i+1, and diff is > 0 */
447: if ( b != 0 ) { /* c == 0 */
448: if ( (w = v[i++]) == 0 ) {
449: *p++ = t | ((BMASK << lsh) & BMASK);
450: while ( (w = v[i++]) == 0 ) *p++ = BMASK;
451: t = BMASK >> rsh;
452: } else {
453: DM( a, w, c, b );
454: if ( b != 0 ) b--;
455: else b = BMASK, c--;
456: *p++ = t | ((b << lsh) & BMASK);
457: t = b >> rsh;
458: }
459: }
460: /**/
461: #ifdef CALL
462: return( aV_plus_c_sh( a, &v[i], lv - i, c, rsh, t, p ) + i );
463: #else
464: for ( ; i < lv; i++, t = w >> rsh, c = hi ) {
465: DMA( a, v[i], c, hi, w, not_used );
466: *p++ = t | ((w << lsh) & BMASK);
467: }
468: if ( c != 0 ) {
469: *p++ = t | ((c << lsh) & BMASK);
470: i++, t = c >> rsh;
471: }
472: if ( t == 0 ) return i;
473: *p = t;
474: return( i + 1 );
475: #endif
476: }
477:
478: /*********/
479:
480: static int abs_U_aV_c( t, u, lu, a, v, lv, c, ans )
481: int t, *u, lu, a, *v, lv, c, *ans;
482: /* compute | t + BASE*(U - a*V - c) | in ans[], where U = u[0:lu-1], V = v[0:lv-1],
483: * c is <= BASE-1, and lu >= lv+1 && t != 0 assumed.
484: */
485: {
486: int i, w, l, *p = ans;
487: int hi;
488:
489: *p++ = t, l = 1;
490: for ( i = 0; i < lv; *p++ = t ) {
491: DMA( a, v[i], c, hi, w, not_used );
492: t = u[i] - w;
493: i++, c = hi;
494: if ( t != 0 ) l = i + 1;
495: if ( t < 0 ) t += BASE, c++;
496: }
497: /* at this point, i == lv */
498: if ( lu == lv+1 ) {
499: if ( (t = u[i]) == c ) return l;
500: else if ( t > c ) { *p = t - c; return( lu + 1 ); }
501: l = negate_nbd( ans, lu ); /* <================ */
502: if ( (c -= (t + 1)) == 0 ) return l;
503: *p = c;
504: return( lu + 1 );
505: }
506: /* lu >= lv+2 and the diff turned out to be >= 0 */
507: if ( c != 0 ) {
508: /* note c <= BASE. If c == BASE, we must care about the length of the result
509: of the case when lu == lv+2 && u[lu-2:lu-1]=u[i:i+1] == BASE */
510: if ( c >= BASE && i+2 == lu && u[i+1] == 1 ) {
511: /* m.s. word of the diff becomes 0 */
512: if ( (t = u[i] - (c & BMASK)) == 0 ) return l;
513: *p = t;
514: return lu;
515: }
516: for ( ; 1; c = 1, *p++ = t + BASE ) if ( (t = u[i++] - c) >= 0 ) break;
517: if ( t == 0 && i >= lu ) return lu;
518: *p++ = t;
519: }
520: for ( ; i < lu; i++ ) *p++ = u[i];
521: return( lu + 1 );
522: }
523:
524: static int abs_U_aV_c_sh( t, u, lu, a, v, lv, c, rsh, ans )
525: int t, *u, lu, a, *v, lv, c, rsh, *ans;
526: /* r-shift version of the above */
527: {
528: int i, w, l, lsh = BSH - rsh, *p = ans;
529: int hi;
530:
531: for ( l = i = 0; i < lv; t = w >> rsh ) {
532: DMA( a, v[i], c, hi, w, not_used );
533: w = u[i] - w, c = hi;
534: i++;
535: if ( w < 0 ) w += BASE, c++;
536: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
537: }
538: /* at this point, i == lv, and we have written lv elm.s in ans[] */
539: if ( lu == lv+1 ) {
540: if ( (w = u[i] - c) == 0 ) {
541: if ( t == 0 ) return l;
542: *p = t;
543: return lu; /* == lv+1 */
544: } else if ( w > 0 ) {
545: l0: *p++ = t | ((w << lsh) & BMASK);
546: if ( (w >>= rsh) == 0 ) return lu; /* == lv+1 */
547: *p = w;
548: return( lu + 1 );
549: }
550: /* diff turned out to be < 0 */
551: w = - w - 1;
552: if ( lv == 0 ) { /* lu == 1 */
553: t = (BASE >> rsh) - t;
554: if ( w != 0 ) goto l0;
555: *p = t;
556: return 1;
557: }
558: l = negate_nbd( ans, lv ); /* <================ */
559: t ^= (BMASK >> rsh);
560: if ( w != 0 ) goto l0;
561: if ( t == 0 ) return l;
562: *p = t;
563: return lu; /* == lv + 1 */
564: }
565: /* now, lu >= lv+2 == i+2 */
566: if ( c != 0 ) {
567: /* note c <= BASE. If c == BASE, we must care about the length of the result
568: of the case when lu == lv+2 && u[lu-2:lu-1]=u[i:i+1] == BASE */
569: if ( c >= BASE && i+2 == lu && t == 0 && u[i] == 0 && u[i+1] == 1 )
570: return l; /* m.s. word of the diff has become 0 */
571: for ( ; 1; t = w >> rsh, c = 1 ) {
572: if ( (w = u[i++] - c) >= 0 ) break;
573: w += BASE;
574: *p++ = t | ((w << lsh) & BMASK);
575: }
576: t |= ((w << lsh) & BMASK);
577: w >>= rsh;
578: if ( i >= lu ) {
579: if ( w != 0 ) {
580: *p++ = t;
581: *p = w;
582: return( lu + 1 );
583: } else if ( t == 0 ) return( i - 1 );
584: else { *p = t; return i; }
585: }
586: *p++ = t;
587: t = w;
588: }
589: for ( ; i < lu; i++, t = w >> rsh ) *p++ = t | (((w = u[i]) << lsh) & BMASK);
590: if ( t == 0 ) return i;
591: *p = t;
592: return( i + 1 );
593: }
594:
595: /****************/
596: /****************/
597: #ifdef FULLSET
598: static int abs_axU_V_maxrshift(), abs_axU_bxV_maxrshift();
599:
600: static int abs_aU_bV_maxrshift( a, u, lu, b, v, lv, ans )
601: int a, *u, lu, b, *v, lv, *ans;
602: /*
603: * Compute | a*U - b*V | >> (as much as possible) in ans[], where U=u[0:lu-1]
604: * and V=v[0:lv-1].
605: */
606: {
607: if ( a == 1 ) return abs_U_aV_maxrshift( u, lu, b, v, lv, ans );
608: else if ( b == 1 ) return abs_U_aV_maxrshift( v, lv, a, u, lu, ans );
609: else if ( a == b ) return abs_axU_V_maxrshift( a, u, lu, v, lv, ans );
610: return abs_axU_bxV_maxrshift( a, u, lu, b, v, lv, ans );
611: }
612:
613: static int abs_axU_V_maxrshift( a, u, lu, v, lv, ans )
614: int a, *u, lu, *v, lv, *ans;
615: /*
616: * Compute a*| U - V | >> (as much as possible) in ans[], where U=u[0:lu-1]
617: * and V=v[0:lv-1], 0 < a < 2^BASE.
618: */
619: {
620: int i, l, b, c, t, rsh, *p = ans, lsh, w, x;
621: int hi;
622:
623: if ( lu > lv ) goto U_V;
624: else if ( lu < lv ) goto swap;
625: else {
626: for ( i = lu; i-- > 0; ) {
627: if ( u[i] == v[i] ) continue;
628: lu = lv = i + 1;
629: if ( u[i] > v[i] ) goto U_V;
630: else goto swap;
631: }
632: return 0;
633: }
634: swap:
635: SWAP( lu, lv, int ); SWAP( u, v, int * );
636: U_V:
637: for ( b = c = i = 0; i < lv; ) {
638: if ( (w = u[i] - v[i] - b) < 0 ) w += BASE, b = 1;
639: else b = 0;
640: DMA( a, w, c, hi, t, not_used );
641: i++, c = hi;
642: if ( t != 0 ) goto non0w;
643: }
644: while ( i < lu ) {
645: if ( (w = u[i] - b) < 0 ) w += BASE, b = 1;
646: else b = 0;
647: DMA( a, w, c, hi, t, not_used );
648: i++, c = hi;
649: if ( t != 0 ) goto non0w;
650: }
651: if ( b != 0 ) c -= a;
652: else if ( c == 0 ) return 0;
653: while ( (c&1) == 0 ) c >>= 1;
654: *p = c;
655: return 1;
656: /**/
657: non0w:
658: u += i, lu -= i, v += i, lv -= i;
659: TRAILINGZEROS( t, rsh );
660: i = 0;
661: if ( rsh == 0 ) {
662: *p++ = t, l = 0;
663: for ( ; i < lv; c = hi ) {
664: if ( (w = u[i] - v[i] - b) < 0 ) w += BASE, b = 1;
665: else b = 0;
666: DMA( a, w, c, hi, t, not_used );
667: i++;
668: if ( (*p++ = t) != 0 ) l = i;
669: }
670: for ( ; i < lu; c = hi ) {
671: if ( (w = u[i] - b) < 0 ) w += BASE, b = 1;
672: else b = 1;
673: DMA( a, w, c, hi, t, not_used );
674: i++;
675: if ( (*p++ = t) != 0 ) l = i;
676: }
677: if ( b != 0 ) c -= a;
678: if ( c == 0 ) return( l + 1 );
679: *p = c;
680: return( i + 2 );
681: } else {
682: for ( lsh = BSH - rsh, l = 0; i < lv; c = hi, t = x >> rsh ) {
683: if ( (w = u[i] - v[i] - b) < 0 ) w += BASE, b = 1;
684: else b = 0;
685: DMA( a, w, c, hi, x, not_used );
686: i++;
687: if ( (*p++ = t | ((x << lsh) & BMASK)) != 0 ) l = i;
688: }
689: for ( ; i < lu; i++, c = hi, t = x >> rsh ) {
690: if ( (w = u[i] - b) < 0 ) w += BASE, b = 1;
691: else b = 0;
692: DMA( a, w, c, hi, x, not_used );
693: i++;
694: if ( (*p++ = t | ((x << lsh) & BMASK)) != 0 ) l = i;
695: }
696: if ( b != 0 ) c -= a;
697: if ( c != 0 ) {
698: *p++ = t | ((c << lsh) & BMASK);
699: i++, t = c >> rsh;
700: } else if ( t == 0 ) return l;
701: if ( t == 0 ) return( i );
702: *p = t;
703: return( i + 1 );
704: }
705: }
706: #endif /* FULLSET */
707:
708: static int abs_axU_bxV_maxrshift( a, u, lu, b, v, lv, ans )
709: int a, *u, lu, b, *v, lv, *ans;
710: /*
711: * Compute | a*U - b*V | >> (as much as possible) in ans[], where U=u[0:lu-1]
712: * and V=v[0:lv-1], 0 < a, b < 2^BASE.
713: */
714: {
715: int i, l, c, d, s, t, w, rsh, *p = ans, lsh;
716: int hi;
717: static int bw_int32();
718:
719: BitWidth( a, c ); BitWidth( u[lu -1], s );
720: BitWidth( b, d ); BitWidth( v[lv -1], t );
721: if ( lu < lv || lu == lv && (c + s) < (d + t) ) {
722: SWAP( a, b, int ); SWAP( lu, lv, int ); SWAP( u, v, int * );
723: }
724: for ( i = c = d = 0; i < lv; ) {
725: DMA( a, u[i], c, hi, t, not_used ); /* 0 <= c <= 2^BSH -2 */
726: c = hi;
727: DMA( b, v[i], d, hi, s, not_used ); /* 0 <= d <= 2^BSH -1 */
728: i++, d = hi;
729: if ( (t -= s) == 0 ) continue;
730: else if ( t < 0 ) {
731: t += BASE;
732: if ( c != 0 ) c--;
733: else d++;
734: }
735: goto non0w;
736: }
737: if ( i >= lu ) { /* no more elm.'s in u[] and v[] */
738: only_c:
739: if ( (c -= d) == 0 ) return 0;
740: else if ( c < 0 ) c = -c;
741: sh_onlyc:
742: /* TRAILINGZEROS( c, rsh ); */
743: while ( (c&1) == 0 ) c >>= 1;
744: *p = c;
745: return 1;
746: }
747: /* there is at least one more elm. in u[] */
748: DMA( a, u[i], c, hi, t, not_used );
749: i++, c = hi;
750: if ( i >= lu ) { /* in this case, diff still can be <= 0 */
751: if ( hi == 0 ) { c = t; goto only_c; }
752: if ( (t -= d) == 0 ) { c = hi; goto sh_onlyc; }
753: else if ( t < 0 ) t += BASE, hi--;
754: TRAILINGZEROS( t, rsh );
755: if ( rsh == 0 ) *p++ = t;
756: else {
757: *p++ = t | ((hi << (BSH - rsh)) & BMASK);
758: hi >>= rsh;
759: }
760: if ( hi == 0 ) return 1;
761: *p = hi;
762: return 2;
763: } /* diff turned out to be > 0 */ else if ( (t -= d) > 0 ) d = 0;
764: else if ( t < 0 ) t += BASE, d = 1;
765: else {
766: while ( i < lu ) {
767: DMA( a, u[i], c, hi, t, not_used );
768: i++, c = hi;
769: if ( t != 0 ) break;
770: }
771: }
772: u += i, lu -= i;
773: TRAILINGZEROS( t, rsh );
774: l = i = 0;
775: if ( rsh == 0 ) {
776: *p++ = t;
777: goto no_more_v;
778: } else goto no_more_v_sh;
779: /**/
780: non0w:
781: u += i, lu -= i, v += i, lv -= i;
782: TRAILINGZEROS( t, rsh );
783: i = 0;
784: if ( rsh == 0 ) {
785: *p++ = t, l = 0;
786: for ( ; i < lv; *p++ = t ) {
787: DMA( a, u[i], c, hi, t, not_used );
788: c = hi;
789: DMA( b, v[i], d, hi, s, not_used );
790: i++, d = hi;
791: if ( (t -= s) == 0 ) continue;
792: else if ( t < 0 ) {
793: t += BASE;
794: if ( c != 0 ) c--;
795: else d++;
796: }
797: l = i;
798: }
799: no_more_v:
800: if ( i >= lu ) {
801: final_c_d:
802: if ( (c -= d) == 0 ) return( l + 1 );
803: else if ( c < 0 ) {
804: l = negate_nbd( ans, i + 1 ); /* <================ */
805: if ( (c = -c - 1) == 0 ) return l;
806: }
807: *p = c;
808: return( i + 2 );
809: }
810: /* a*u[i:lu-1] + c - d */
811: if ( c >= d ) c -= d;
812: else {
813: DMA( a, u[i], c, hi, t, not_used );
814: if ( i+1 >= lu ) {
815: if ( hi == 0 ) { c = t; goto final_c_d; }
816: if ( (t -= d) < 0 ) t += BASE, c = hi - 1;
817: else c = hi;
818: i++, *p++ = t;
819: goto final_c;
820: }
821: i++, c = hi;
822: if ( (t -= d) >= 0 ) *p++ = t;
823: else {
824: *p++ = t + BASE;
825: if ( c != 0 ) c--;
826: else {
827: for ( ; i < lu; *p++ = BMASK ) {
828: DMA( a, u[i], c, hi, t, not_used );
829: i++, c = hi;
830: if ( t == 0 ) continue;
831: *p++ = t - 1;
832: goto aU;
833: }
834: c--;
835: goto final_c;
836: }
837: }
838: }
839: /*** return( aV_plus_c( a, &u[i], lu - i, c, p ) + i + 1 ); ***/
840: aU:
841: for ( ; i < lu; i++, c = hi, *p++ = t ) { DMA( a, u[i], c, hi, t, not_used ); }
842: final_c:
843: if ( c == 0 ) return( i + 1 );
844: *p = c;
845: return( i + 2 );
846: } else { /* rsh != 0 */
847: for ( lsh = BSH - rsh; i < lv; t = w >> rsh ) {
848: DMA( a, u[i], c, hi, w, not_used );
849: c = hi;
850: DMA( b, v[i], d, hi, s, not_used );
851: i++, d = hi;
852: if ( (w -= s) < 0 ) {
853: w += BASE;
854: if ( c != 0 ) c--;
855: else d++;
856: }
857: if ( (*p++ = t | ((w << lsh) & BMASK)) != 0 ) l = i;
858: }
859: no_more_v_sh:
860: if ( i >= lu ) {
861: final_c_d_sh:
862: if ( (c -= d) == 0 )
863: if ( t == 0 ) return l;
864: else { *p = t; return( i + 1 ); }
865: else if ( c < 0 ) {
866: if ( i == 0 ) t = (BASE >> rsh) - t;
867: else {
868: l = negate_nbd( ans, i ); /* <================ */
869: /* t = (BASE >> rsh) - t;*/
870: t ^= ((BMASK >> rsh));
871: }
872: c = -c -1;
873: }
874: *p++ = t | ((c << lsh) & BMASK);
875: if ( (c >>= rsh) == 0 ) return( i + 1 );
876: *p = c;
877: return( i + 2 );
878: } else if ( c >= d ) c -= d;
879: else {
880: DMA( a, u[i], c, hi, w, not_used );
881: if ( i+1 >= lu ) {
882: if ( hi == 0 ) { c = w; goto final_c_d_sh; }
883: if ( (w -= d) < 0 ) w += BASE, c = hi - 1;
884: else c = hi;
885: i++, *p++ = t | ((w << lsh) & BMASK);
886: t = w >> rsh;
887: goto final_c_sh;
888: }
889: i++, c = hi;
890: if ( (w -= d) >= 0 ) { *p++ = t | ((w << lsh) & BMASK); t = w >> rsh; }
891: else {
892: w += BASE;
893: *p++ = t | ((w << lsh) & BMASK);
894: t = w >> rsh;
895: if ( c != 0 ) c--;
896: else {
897: while ( i < lu ) {
898: DMA( a, u[i], c, hi, w, not_used );
899: i++, c = hi;
900: if ( w == 0 ) {
901: *p++ = t | ((BMASK << lsh) & BMASK);
902: t = BMASK >> rsh;
903: continue;
904: } else {
905: w--;
906: *p++ = t | ((w << lsh) & BMASK);
907: t = w >> rsh;
908: goto aU_sh;
909: }
910: }
911: c--;
912: goto final_c_sh;
913: }
914: }
915: }
916: /*** return( aV_plus_c_sh( a, &u[i], lu - i, c, rsh, t ) + i ); ***/
917: aU_sh:
918: for ( ; i < lu; i++, c = hi, t = w >> rsh ) {
919: DMA( a, u[i], c, hi, w, not_used );
920: *p++ = t | ((w << lsh) & BMASK);
921: }
922: final_c_sh:
923: if ( c != 0 ) {
924: *p++ = t | ((c << lsh) & BMASK);
925: i++, t = c >> rsh;
926: }
927: if ( t == 0 ) return i;
928: *p = t;
929: return( i + 1 );
930: }
931: }
932: /****************/
933: /****************/
934: #ifdef FULLSET
935: static int UplusV_maxrshift(), aUplusV_maxrshift(), axUplusV_maxrshift(), aUplusbV_maxrshift();
936:
937: static int aU_plus_bV_maxrshift( a, u, lu, b, v, lv, ans )
938: int a, *u, lu, b, *v, lv, *ans;
939: {
940: if ( a == 1 )
941: return( b == 1 ? UplusV_maxrshift( u, lu, v, lv, ans ) :
942: aUplusV_maxrshift( b, v, lv, u, lu, ans ) );
943: else if ( b == 1 ) return aUplusV_maxrshift( a, u, lu, v, lv, ans );
944: else if ( a == b ) return axUplusV_maxrshift( a, u, lu, v, lv, ans );
945: return aUplusbV_maxrshift( a, u, lu, b, v, lv, ans );
946: }
947:
948: static int UplusV_maxrshift( u, lu, v, lv, ans )
949: int *u, lu, *v, lv, *ans;
950: /*
951: * Compute ( (U + V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
952: * V=v[0:lv-1], and 0 < a < BASE.
953: */
954: {
955: int i, t, c, rsh, *p = ans;
956: int hi;
957:
958: if ( lu < lv ) { SWAP( lu, lv, int ); SWAP( u, v, int * ); }
959: for ( c = i = 0; i < lv; ) {
960: t = (c += (u[i] + v[i])) & BMASK;
961: /* 0 <= c <= 2*(2^BSH -1) + 1 = 2^BSH + (2^BSH -1) */
962: i++, c >>= BSH;
963: if ( t != 0 ) goto non0w;
964: }
965: while ( i < lu ) {
966: t = (c += u[i]) & BMASK;
967: i++, c >>= BSH;
968: if ( t != 0 ) goto non0w;
969: }
970: *p = c;
971: return 1;
972: /**/
973: non0w:
974: u += i, lu -= i, v += i, lv -= i;
975: TRAILINGZEROS( t, rsh );
976: i = 0;
977: if ( rsh == 0 ) {
978: *p++ = t;
979: for ( ; i < lv; i++, c >>= BSH ) *p++ = (c += (u[i] + v[i])) & BMASK;
980: if ( c != 0 ) {
981: while ( i < lu )
982: if ( (c = u[i++] + 1) >= BASE ) *p++ = c & BMASK;
983: else {
984: *p++ = c;
985: goto cpu;
986: }
987: *p = 1; /* == c */
988: return( lu + 2 );
989: }
990: cpu:
991: for ( ; i < lu; i++ ) *p++ = u[i];
992: return( lu + 1 );
993: } else {
994: int lsh = BSH - rsh;
995:
996: for ( ; i < lv; i++, c >>= BSH ) {
997: c += (u[i] + v[i]);
998: *p++ = t | ((c << lsh) & BMASK);
999: t = (c & BMASK) >> rsh;
1000: }
1001: if ( c != 0 ) {
1002: while ( i < lu ) {
1003: c = u[i++] + 1;
1004: *p++ = t | ((c << lsh) & BMASK);
1005: t = (c & BMASK) >> rsh;
1006: if ( (c >>= BSH) == 0 ) goto cpu_sh;
1007: }
1008: *p = t | (1 << lsh);
1009: return( lu + 1 );
1010: }
1011: cpu_sh:
1012: for ( ; i < lu; t = c >> rsh ) *p++ = t | (((c = u[i++]) << lsh) & BMASK);
1013: if ( t == 0 ) return( lu );
1014: *p = t;
1015: return( lu + 1 );
1016: }
1017: }
1018:
1019: static int aUplusV_maxrshift( a, u, lu, v, lv, ans )
1020: int a, *u, lu, *v, lv, *ans;
1021: /*
1022: * Compute ( (a*U + V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
1023: * V=v[0:lv-1], and 1 < a < BASE.
1024: */
1025: {
1026: int i, l, t, c, rsh, *p = ans, w, lsh;
1027: int hi;
1028:
1029: for ( l = lu < lv ? lu : lv, c = i = 0; i < l; ) {
1030: /* Note that (carry in a*U[*]) <= 2^BSH-2 because {(2^j-1)}^2 + (2^j-2)
1031: * = 2^j*(2^j -2)+(2^j -1), and the following c is <= 2^j -1 because
1032: * {(2^j -1)}^2 + (2^j -1) + (2^j -1) = 2^j*(2^j -1) + (2^j -1).
1033: * ^^^^^^carry^^^^^^ pv[?].
1034: */
1035: c += v[i];
1036: DMA( a, u[i], c, hi, t, not_used );
1037: i++, c = hi;
1038: if ( t != 0 ) goto non0sum;
1039: }
1040: if ( i >= lu ) { /* compute (c + v[i:lv-1]) */
1041: while ( i < lv ) {
1042: t = (c += v[i++]) & BMASK;
1043: c >>= BSH;
1044: if ( t != 0 ) goto non0w_v;
1045: }
1046: *p = 1;
1047: return 1;
1048: non0w_v:
1049: v += i, lv -= i;
1050: i = 0;
1051: TRAILINGZEROS( t, rsh );
1052: if ( rsh == 0 ) {
1053: *p++ = t;
1054: L_addv:
1055: if ( c != 0 ) {
1056: while ( i < lv )
1057: if ( (c = u[i++] + 1) >= BASE ) *p++ = c & BMASK;
1058: else {
1059: *p++ = c;
1060: goto cpv;
1061: }
1062: *p = 1; /* == c */
1063: return( lv + 2 );
1064: }
1065: cpv:
1066: for ( ; i < lv; i++ ) *p++ = v[i];
1067: return( lv + 1 );
1068: } else {
1069: lsh = BSH - rsh;
1070: L_addv_sh:
1071: if ( c != 0 ) {
1072: while ( i < lv ) {
1073: c += v[i++];
1074: *p++ = t | ((c << lsh) & BMASK);
1075: t = (c & BMASK) >> rsh;
1076: if ( (c >>= BSH) == 0 ) goto cpv_sh;
1077: }
1078: *p = t | (1 << lsh);
1079: return( lv + 1 );
1080: }
1081: cpv_sh:
1082: for ( ; i < lv; t = c >> rsh ) *p++ = t | (((c = v[i++]) << lsh) & BMASK);
1083: if ( t == 0 ) return( lv );
1084: *p = t;
1085: return( lv + 1 );
1086: }
1087: } else { /* i >= lv, and compute (c + a*u[i:lu-1]) */
1088: while ( i < lu ) {
1089: DMA( a, u[i], c, hi, t, not_used );
1090: i++, c = hi;
1091: if ( t != 0 ) goto non0w_u;
1092: }
1093: TRAILINGZEROS( c, rsh );
1094: *p = c;
1095: return 1;
1096: /**/
1097: non0w_u:
1098: u += i, lu -= i;
1099: TRAILINGZEROS( t, rsh );
1100: i = 0;
1101: if ( rsh == 0 ) {
1102: *p++ = t;
1103: L_addu:
1104: #ifdef CALL
1105: return( aV_plus_c( a, u, lv, c, p ) + 1 );
1106: #else
1107: for ( ; i < lu; i++, *p++ = t, c = hi ) { DMA( a, u[i], c, hi, t, not_used ); }
1108: if ( c == 0 ) return( lu + 1 );
1109: *p = c;
1110: return( lu + 2 );
1111: #endif
1112: } else {
1113: lsh = BSH - rsh;
1114: L_addu_sh:
1115: #ifdef CALL
1116: return aV_plus_c_sh( a, u, lu, c, rsh, t, p );
1117: #else
1118: for ( ; i < lu; i++, c = hi, t = w >> rsh ) {
1119: DMA( a, u[i], c, hi, w, not_used );
1120: *p++ = t | ((w << lsh) & BMASK);
1121: }
1122: if ( c != 0 ) {
1123: *p++ = t | ((c << lsh) & BMASK);
1124: i++, t = c >> rsh;
1125: }
1126: if ( t == 0 ) return i;
1127: *p = t;
1128: return( i + 1 );
1129: #endif
1130: }
1131: }
1132: /**/
1133: non0sum:
1134: u += i, lu -= i, v += i, lv -= i, l -= i;
1135: TRAILINGZEROS( t, rsh );
1136: i = 0;
1137: if ( rsh == 0 ) {
1138: *p++ = t;
1139: for ( ; i < l; i++, *p++ = t, c = hi ) {
1140: c += v[i];
1141: DMA( a, u[i], c, hi, t, not_used );
1142: }
1143: if ( i >= lu ) /* compute (c + v[i:lv-1]). note i may be >= lv */ goto L_addv;
1144: else /* i >= lv, and compute (c + u[i:lu-1]) */ goto L_addu;
1145: } else {
1146: lsh = BSH - rsh;
1147: for ( ; i < l; i++, c = hi, t = w >> rsh ) {
1148: c += v[i];
1149: DMA( a, u[i], c, hi, w, not_used );
1150: *p++ = t | ((w << lsh) & BMASK);
1151: }
1152: if ( i >= lu ) /* compute (c + v[i:lv-1]) >> rsh. note i may be >= lv */ goto L_addv_sh;
1153: else /* i >= lv, and compute (c + u[i:lu-1]) >> rsh */ goto L_addu_sh;
1154: }
1155: }
1156:
1157:
1158: static int axUplusV_maxrshift( a, u, lu, v, lv, ans )
1159: int a, *u, lu, *v, lv, *ans;
1160: /*
1161: * Compute ( a*(U + V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
1162: * V=v[0:lv-1], and 1 < a < BASE.
1163: */
1164: {
1165: int i, t, c, d, rsh, w, *p = ans, lsh, x;
1166: int hi;
1167:
1168: if ( lu < lv ) { SWAP( lu, lv, int ); SWAP( u, v, int * ); }
1169: for ( i = c = d = 0; i < lv; ) {
1170: w = (d += (u[i] + v[i])) & BMASK;
1171: DMA( a, w, c, hi, t, not_used );
1172: i++, d >>= BSH, c = hi;
1173: if ( t != 0 ) goto non0w;
1174: }
1175: while ( i < lu ) {
1176: w = (d += u[i++]) & BMASK;
1177: DMA( a, w, c, hi, t, not_used );
1178: d >>= BSH, c = hi;
1179: if ( t != 0 ) goto non0w;
1180: }
1181: if ( d != 0 ) c += a;
1182: TRAILINGZEROS( c, rsh );
1183: if ( rsh != 0 || c <= BMASK ) { *p = c; return 1; }
1184: *p++ = c & BMASK;
1185: *p = c >> BSH;
1186: return 2;
1187: /**/
1188: non0w:
1189: u += i, lu -= i, v += i, lv -= i;
1190: TRAILINGZEROS( t, rsh );
1191: i = 0;
1192: if ( rsh == 0 ) {
1193: *p++ = t;
1194: for ( ; i < lv; i++, d >>= BSH, *p++ = t, c = hi ) {
1195: w = (d += (u[i] + v[i])) & BMASK;
1196: DMA( a, w, c, hi, t, not_used );
1197: }
1198: for ( ; i < lu; d >>= BSH, *p++ = t, c = hi ) {
1199: w = (d += u[i++]) & BMASK;
1200: DMA( a, w, c, hi, t, not_used );
1201: }
1202: if ( d != 0 ) c += a;
1203: if ( c == 0 ) return( lu + 1 );
1204: *p++ = c & BMASK;
1205: if ( (c >>= BSH) == 0 ) return( lu + 2 );
1206: *p = c;
1207: return( lu + 3 );
1208: } else {
1209: for ( lsh = BSH - rsh; i < lv; i++, d >>= BSH, t = x >> rsh, c = hi ) {
1210: w = (d += (u[i] + v[i])) & BMASK;
1211: DMA( a, w, c, hi, x, not_used );
1212: *p++ = t | ((x << lsh) & BMASK);
1213: }
1214: for ( ; i < lu; d >>= BSH, t = x >> rsh, c = hi ) {
1215: w = (d += u[i++]) & BMASK;
1216: DMA( a, w, c, hi, x, not_used );
1217: *p++ = t | ((x << lsh) & BMASK);
1218: }
1219: if ( d != 0 ) c += a;
1220: t |= ((c << lsh) & BMASK);
1221: c >>= rsh;
1222: if ( c != 0 ) {
1223: *p++ = t;
1224: *p = c;
1225: return( lu + 2 );
1226: } else if ( t == 0 ) return lu;
1227: *p = t;
1228: return( lu + 1 );
1229: }
1230: }
1231: #endif /* FULLSET */
1232:
1233: static int aUplusbV_maxrshift( a, u, lu, b, v, lv, ans )
1234: int a, *u, lu, b, *v, lv, *ans;
1235: /*
1236: * Compute ( (a*U + b*V) >> (as much as possible) ) in ans[], where U=u[0:lu-1],
1237: * V=v[0:lv-1], and 0 < a,b < BASE.
1238: */
1239: {
1240: int i, c, d, s, t, w, rsh, *p = ans, lsh;
1241: int hi;
1242:
1243: if ( lu < lv ) { SWAP( a, b, int ); SWAP( lu, lv, int ); SWAP( u, v, int * ); }
1244: for ( c = d = i = 0; i < lv; ) {
1245: DMA( a, u[i], c, hi, t, not_used ); /* 0 <= c <= 2^BSH -1 */
1246: c = hi;
1247: DMA( b, v[i], d, hi, s, not_used ); /* 0 <= d <= 2^BSH -2 */
1248: i++, d = hi, t += s;
1249: if ( t > BMASK ) c++, t &= BMASK;
1250: if ( t != 0 ) goto non0w;
1251: }
1252: c += d;
1253: for ( d = 0; i < lu; ) {
1254: DMA( a, u[i], c, hi, t, not_used );
1255: i++, c = hi;
1256: if ( t != 0 ) goto non0w;
1257: }
1258: TRAILINGZEROS( c, rsh );
1259: if ( rsh != 0 || c <= BMASK ) { *p = c; return 1; }
1260: *p++ = c & BMASK;
1261: *p = 1;
1262: return 2;
1263: /**/
1264: non0w:
1265: u += i, lu -= i, v += i, lv -= i;
1266: TRAILINGZEROS( t, rsh );
1267: i = 0;
1268: if ( rsh == 0 ) {
1269: *p++ = t;
1270: for ( ; i < lv; i++, *p++ = t ) {
1271: DMA( a, u[i], c, hi, t, not_used );
1272: c = hi;
1273: DMA( b, v[i], d, hi, s, not_used );
1274: d = hi, t += s;
1275: if ( t > BMASK ) c++, t &= BMASK;
1276: }
1277: c += d;
1278: for ( ; i < lu; i++, *p++ = t, c = hi ) {
1279: DMA( a, u[i], c, hi, t, not_used );
1280: }
1281: if ( c == 0 ) return( lu + 1 );
1282: else if ( c <= BMASK ) { *p = c; return( lu + 2 ); }
1283: *p++ = c & BMASK;
1284: *p = 1;
1285: return( lu + 3 );
1286: } else {
1287: for ( lsh = BSH - rsh; i < lv; i++, t = w >> rsh ) {
1288: DMA( a, u[i], c, hi, w, not_used );
1289: c = hi;
1290: DMA( b, v[i], d, hi, s, not_used );
1291: d = hi, w += s;
1292: if ( w > BMASK ) c++, w &= BMASK;
1293: *p++ = t | ((w << lsh) & BMASK);
1294: }
1295: c += d; /* <= 2^BSH + (2^BSH - 3) */
1296: for ( ; i < lu; i++, c = hi, t = w >> rsh ) {
1297: DMA( a, u[i], c, hi, w, not_used );
1298: *p++ = t | ((w << lsh) & BMASK);
1299: }
1300: if ( c == 0 ) {
1301: if ( t == 0 ) return lu;
1302: *p = t;
1303: return( lu + 1 );
1304: }
1305: *p++ = t | ((c << lsh) & BMASK);
1306: if ( (c >>= rsh) == 0 ) return( lu + 1 );
1307: *p = c;
1308: return( lu + 2 );
1309: }
1310: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>