/* Floating point remainder. c = remainder after dividing b by a. If n = integer part of b/a, rounded toward zero, then qremain(a,b,c) gives c = b - n * a. */ #include "qhead.h" #include "mconf.h" extern QELT qzero[]; #ifdef ANSIPROT int subm( QELT *, QELT * ); int shup1( QELT * ), shdn1( QELT * ), shup16( QELT * ), shup8( QELT * ); int cmpm( QELT *, QELT * ); #else int cmpm(), subm(), shdn1(), shup1(), shup16(), shup8(); int qcmp(), qclear(), qmov(); #endif static QELT quot[NQ+1]; int qremain( a, b, c ) QELT a[], b[], c[]; { QELT den[NQ+1], num[NQ+1]; QELT j; int i; if( qcmp(a,qzero) == 0 ) { mtherr( "qremain", SING ); qclear( c ); return 0; } den[NQ] = 0; qmov( a, den ); den[0] = 0; num[NQ] = 0; qmov( b, num ); num[0] = 0; /* Execute divide steps until num < den. Least significant integer quotient bits left in quot[]. */ quot[NQ] = 0; qclear( quot ); while( qcmp(num,den) >= 0 ) { if( cmpm(den,num) <= 0 ) { subm(den, num); j = 1; } else { j = 0; } shup1(quot); quot[NQ] |= j; shup1(num); num[1] -= 1; } /* Normalize. */ while( num[2] != 0 ) { shdn1( num ); num[1] += 1; } i = 0; do { if( num[3] & SIGNBIT ) goto normok; #if WORDSIZE == 32 else if( (num[3] & 0xffff0000) == 0 ) #else else if( num[3] == 0 ) #endif { shup16(num); num[1] -= 16; i += 16; } #if WORDSIZE == 32 else if( (num[3] & 0xff000000) == 0 ) #else else if( (num[3] & 0xff00) == 0 ) #endif { shup8(num); num[1] -= 8; i += 8; } else { shup1(num); num[1] -= 1; i += 1; } } while( i<=NBITS ); qclear(num); normok: /* Sign of remainder = sign of numerator. */ num[0] = b[0]; qmov( num, c ); return 0; }