#include "big.h" #include #if ! ( defined BN_LIB_GOT || defined NO_BIG_BODY ) #define BN_LIB_GOT void read_hex(FILE* stream,bele* x) { char buffer[4096]; fgets(buffer, sizeof buffer, stream); buffer[strcspn(buffer, "\n")] = 0; num_here(buffer,x); } void write_hex(FILE* stream,bele* x,int cend) { blong limit = mssb(x); blong nb_words = limit / B_P_E; if (x[PREC] == 1) fprintf(stream,"-"); fprintf(stream,"0x%0X",x[nb_words]); for (int i = nb_words - 1; i >= 0; i--) fprintf(stream,"%08X",x[i]); fprintf(stream,"%c",cend); } /* physical */ void zero_big ( bele * w ) /* set w = 0 */ { BN_TRAC( '0' ) ; bnflen ( w , S_LEN , ( bele ) 0 ) ; } void bnflen ( bele * w , unsigned sz , bele u ) { while ( sz -- ) w [ sz ] = u ; } void copy_big ( bele * w , bele * x ) { BN_TRAC( 'c' ) ; bnclen ( w , x , S_LEN ) ; } void bnclen ( bele * w , bele * x , unsigned m ) { while ( m -- ) x [ m ] = w [ m ] ; } /* big on big mathematics */ /** add_big sub_big | | raw_add_big raw_sub_big | \/ | depending on signs & add or sub | /\ | bnaddub bns_ub */ R_D add_big ( bele * w , bele * x , bele * y ) /* y = w + x */ #if ( ERROR_MODE > 1 ) || ( defined BIG_TRACE ) { BN_TRAC( '+' ) ; BN_ERR( if ) ( rawadd_big ( w , x , y ) ) BNE_FUN( "overflow in add_big" ) ; BN0 ; } BN_E rawadd_big ( bele * w , bele * x , bele * y ) #endif #if SIGNED { if ( w [ S_PREC ] != x [ S_PREC ] ) { ( bns_ub ( w , x , y ) ) ; BN_ERR( return ( 0 ) ) ; } else BN_ERR( return ) ( bnaddub ( w , x , y ) ) ; } /* returns 1 or 0 */ BN_E bnaddub ( bele * w , bele * x , bele * y ) /* y = w + x */ #endif { ublong ul = L2( 0 ) ; int m = 0 ; while ( m < S_PREC ) { y [ m ] = ( bele ) ( ul = ( ublong ) ( ul > BNFUL ) + w [ m ] + x [ m ] ) ; ++ m ; BN_SIG( y [ S_PREC ] = x [ S_PREC ] ; ) } BN_ERR( return ( ( int ) ( ul >> B_P_E ) ) ; ) } /* returns carry */ R_D sub_big ( bele * w , bele * x , bele * y ) /* y = x - w */ #if ( ERROR_MODE > 1 ) || ( defined BIG_TRACE ) { BN_TRAC( '-' ) ; BN_ERR( if ) ( rawsub_big ( w , x , y ) ) BNE_FUN( "overflow in sub_big" ) ; BN0 ; } BN_E rawsub_big ( bele * w , bele * x , bele * y ) #endif { #if SIGNED if ( w [ S_PREC ] != x [ S_PREC ] ) BN_ERR( return ) ( bnaddub ( w , x , y ) ) ; else #endif bns_ub ( w , x , y ) ; BN_ERR( return ( 0 ) ) ; } void bns_ub ( bele * w , bele * x , bele * y ) { blong li = L2( 0 ) ; bele * e_ptr ; int m = 0 ; if ( cp_abs ( w , x ) == - 1 ) /* abs w > abs x */ { BN_SIG( y [ S_PREC ] = x [ S_PREC ] ^ 1 ; ) /* carry through zero */ e_ptr = w ; w = x ; x = e_ptr ; } /* swap pointers */ BN_SIG( else y [ S_PREC ] = x [ S_PREC ] ; ) /* no change */ while ( m < S_PREC ) y [ m ++ ] = ( bele ) ( li = ( blong ) * x ++ - * w ++ - ( li < 0 ) ) ; } R_D mult_big ( bele * w , bele * x , bele * y ) /* y = x * w */ #if ( ERROR_MODE > 1 ) || ( defined BIG_TRACE ) { BN_TRAC( '*' ) ; BN_ERR( if ) ( rawmult_big ( w , x , y ) ) BNE_FUN( "overflow in mult_big" ) ; BN0 ; } /** multiply two big numbers w * x to y w [ m ] * x [ d + m - S_FRAC ] accumulates into y [ d ] and a carry the outer loop increments each element of the destination in turn starting at w [ 0 ] * x [ 0 ] to provide y [ - S_FRAC ] during each sweep the multiple is accumulated in two ublong if the destination has an index less than 0 then the answer is discarded the carry always starts the next run the inner loops are an oblique sweep, like these : outer loop starts at w [ 0 ] each sweep start at x [ 0 ] v x [ ] 0 1 2 3 4 w [ 3 ] o o o o o > y [i] i = highest element affected \ \ \ \ w [ 2 ] o o o o o > y [h] \ \ \ \ w [ 1 ] o o o o o > y [g] \ \ \ \ w [ 0 ] o o o o o > y [f] v v v v v to y [ ] a b c d e a = - S_FRAC and increments to b, c, ... */ BN_E rawmult_big ( bele * w , bele * x , bele * y ) #endif { ublong ul , lucy ; int tw , tx , ty , sw = 0 , sx = 0 , iw , ix , iy ; /* ^ tops starts indices */ bele * swap ; #if B_ROUND > 1 unsigned underrun = 0 , up ; #endif DEF_BN_( z ) ; tw = ( int ) ( blong ) mssb ( w ) >> BNSHIFT ; tx = ( int ) ( blong ) mssb ( x ) >> BNSHIFT ; if ( ( ty = tw + tx BN_FRAC( - S_FRAC ) ) >= S_PREC ) BNE1 ; if ( tw > tx ) { swap = w ; w = x ; x = swap ; iw = tw ; tw = tx ; tx = iw ; } BN_HEAP_( z ) ; BN_NHEAP( bnflen ( z , S_LEN , ( bele ) 0 ) ; ) BN_SIG( z [ S_PREC ] = w [ S_PREC ] ^ x [ S_PREC ] ; ) ul = lucy = L2( 0 ) ; /* initialise */ iy = ( BNUF( ( unsigned ) muluf < S_FRAC ? - muluf : ) - S_FRAC - 1 ) ; BNUF( sw = S_FRAC + iy + 1 ; ) /* outer loop */ while ( iy ++ < ty ) { iw = sw ; ix = sx ; /* active starts */ /* inner loop */ do { ul += ( ublong ) w [ iw ] * x [ ix ++ ] ; /* accumulate * */ lucy += ( ul >> B_P_E ) ; /* accumulate carry */ ul = ( bele ) ul ; } /* no hi carry in ul */ while ( iw -- ) ; /* while effective */ /* ^ end inner loop ^ */ #if B_ROUND > 1 if ( iy < - 1 ) underrun = underrun | ul ; if ( iy == - 1 ) { underrun = underrun | ( ul & E_SZ( 0x7FFF , 0x7FFFFFFF ) ) ; up = ul & E_SZ( 0x8000UL , L2( 0x80000000U ) ) ; } if ( ( ! iy ) && up && ( underrun || ( ( ul ^ B_ROUND ) & 1 ) ) ) if ( ! ( bele ) ++ ul ) ++ lucy ; /* round up, & carry */ #elif B_ROUND == 1 if ( ( iy == - 1 ) && ( ul & E_SZ( 0x8000UL , L2( 0x80000000U ) ) ) ) ++ lucy ; #endif BN_FRAC( if ( iy > - 1 ) ) /* if valid place */ z [ iy ] = ( bele ) ul ; /* take accumulation */ ul = lucy & E_SZ( 0xFFFF , 0xFFFFFFFF ) ; /* low carry for next */ lucy = lucy >> B_P_E ; /* high to low carry */ if ( sw < tw ) ++ sw ; else { ++ sx ; if ( ix > tx ) { -- sw ; -- tw ; ++ w ; -- tx ; } } } /* ugly , fast */ /* ^ end outer loop ^ */ if ( iy < S_PREC ) z [ iy ] = ( bele ) ul ; bnclen ( z , y , S_LEN ) ; FREE_BN_( z ) ; BN_ERR( return ( ( int ) ( ( blong ) ( ( int ) iy == S_PREC ) && ul ) ) ) ; } /** there is one engine bn_divide these functions for a user pass to it : div_big , mod_big , i_div_big & div_big_4 and these definitions, in the header, call to it : rawdiv_big_ , bndo0_ , rawmod_big_ , rawi_div_ & rawdiv_4_ definitions for the divide below */ #if FRAC #define BNZ_0 , 0 #ifndef SOFT_SIZE #define BNZ_F , s_frac #else #define BNZ_F , 1 #endif #else #define BNZ_0 #define BNZ_F #define bnend 0 #endif R_D div_big ( bele * w , bele * x , bele * y ) /* y = w / x */ { BN_TRAC( '/' ) ; BN_ERR( if ) ( rawdiv_big_( w , x , y ) ) BNE_FUN( "overflow or divide by zero in div_big" ) ; BN0 ; } R_D mod_big ( bele * w , bele * x , bele * z ) /* z = x % w */ { BN_TRAC( '%' ) ; BN_ERR( if ) ( rawmod_big_( w , x , z ) ) BNE_FUN( "divide by zero in mod_big" ) ; BN0 ; } #if FRAC R_D i_div_big ( bele * w , bele * x , bele * y ) /* y = w \ x */ { BN_TRAC( '\\' ) ; BN_ERR( if ) ( rawi_div_( w , x , y ) ) BNE_FUN( "overflow or divide by zero in i_div" ) ; BN0 ; } #endif R_D div_big_4 ( bele * w , bele * x , bele * y , bele * z ) { BN_TRAC( '4' ) ; BN_ERR( if ) ( rawdiv_4_( w , x , y , z ) ) BNE_FUN( "overflow or divide by zero in div_big_4" ) ; BN0 ; } #undef BNZ_0 #undef BNZ_F /** set the residue to the dividend bn_divide takes the active ( ( top bele length of the divisor ) + 1 ) the outer loop comprises new top answer is = ( active residue top ) divided by ( divisor top + 1 ) (1) shift up the residue to the top or ( top - 1 ) bit add new top answer into the answer at the correct bit place inner loop runs up the numbers : residue = residue - ( top answer * dividend ) if the top answer was 1 short then this is corrected by the next loop and finally test if the answer is 1 short and fix round (1) division of the ( top of divisor + 1 ) into the residue top ublong length consider a ublong as two bele here : bele,bele , and ... continues the same the top answer ranges from 0,80...0 to 1,F...FC, ratio of nearly 1 to 4 and if the top multiplier is greater than 0,F...F then the residue shift is to one bit less than the top bit places w_p divider, then divider shift y_p dividend z_p residue shifts z_s residue z_st accumulation of shift for answer shift top two elements w_t divider , after assignment does not change z_t local residue */ BN_E bn_divide ( bele * w , bele * x , bele * y , bele * z #if FRAC , int iend #endif #ifdef MDUF , int bnuf #endif ) { DEF_BN_( w2 ) ; blong w_p , y_p , z_p , z_s , z_st = - B_P_E ; /* bit places and shift */ ublong w_t , z_t , lj , lcy ; /* bit positions are w_p divider, then divider shift y_p dividend z_p residue shifts z_s residue z_st accumulation of shift for answer shift top two elements w_t divider , after assignment does not change z_t local residue */ int k , m , n ; bele * z1 ; #if FRAC int bnend ; #if B_ROUND int j ; #endif blong bnlend ; #else #define bnend 0 #define bnlend L2( 0 ) #endif #ifdef MDUF int mv , bnact , nbot = 0 ; /* move , active length , shift place */ bele * bnzx ; #else #define bnuf S_PREC #define bnact S_PREC #define bnzx zx #endif #ifndef USE_HEAP bele zx [ PREC + 1 ] ; /* 4 args is only ! FRAC */ #else bele * zx ; #endif #if FRAC bnend = iend & INT_MAX ; #endif /* set y = NULL if no division required */ if ( y == z ) y = NULL ; /* no division */ /* initialise top bit controls , divisor and residue */ if ( ( w_p = bn_msx ( w , S_PREC ) ) == - L2( 1 ) ) BNE1 ; /* return if / 0 */ if ( ( z_p = bn_msx ( x , S_PREC ) ) == - L2( 1 ) ) /* divide into 0 */ { if ( y != NULL ) bnflen ( y , S_LEN , 0 ) ; /* returns to 0 */ if ( z != NULL ) bnflen ( z , S_LEN , 0 ) ; BNE0 ; } /* return */ y_p = z_p - w_p BN_FRAC( + ( ( blong ) S_FRAC << BNSHIFT ) ) ; /* top answer place */ z_s = ( ( blong ) S_PREC + L2( 1 ) ) * B_P_E - L2( 1 ) - z_p ; /* first zx shift */ #ifdef USE_HEAP /* take w2 , zx [ LEN + 1 ] and set * z1 */ BN_HEAP_( w2 ) ; zx = ( bele * ) bn_h ( S_PREC + 1 , BY_P_E ) ; #endif z1 = & zx [ 1 ] ; /* for 1 u-f int */ #ifdef MDUF bnuf = ( unsigned ) bnuf > S_PREC ? S_PREC : bnuf ; bnact = S_PREC ; bnzx = zx ; #endif /* prepare registers */ BN_FRAC( bnlend = ( blong ) bnend << BNSHIFT ; ) k = ( int ) ( ( blong ) ( w_p = ( ( blong ) S_PREC << BNSHIFT ) - L2( 1 ) - w_p ) >> BNSHIFT ) ; bns_up ( w_p , w , w2 , S_PREC ) ; /* divisor to top of w2 */ bnclen ( x , zx , S_PREC ) ; /* dividend to residue low */ zx [ S_PREC ] = 0 ; /* extra to be empty */ if ( y != NULL ) bnflen ( y , S_PREC , 0 ) ; /* to collect answer */ /* take divisor top + 1 */ w_t = ( ublong ) w2 [ S_PREC - 1 ] + L2( 1 ) ; /* outer loop */ while ( 1 ) { /* bit and element top zx places */ lj = z_p & BNMASK ; /* mod top bit place */ m = ( int ) ( ( ublong ) z_p >> BNSHIFT ) ; /* zx element place */ /* take residue top and divide into */ z_t = ( ublong ) ( ( ( ublong ) zx [ m ] ) << ( B_P_E + BNMASK - lj ) ) | ( ( m > 0 ) ? ( ublong ) zx [ m - 1 ] << ( BNMASK - lj ) : L2( 0 ) ) | ( ( m > 1 ) ? ( ublong ) zx [ m - 2 ] >> ( L2( 1 ) + lj ) : L2( 0 ) ) ; if ( ( z_t /= w_t ) > BNFUL ) /* top divide */ { z_t >>= L2( 1 ) ; -- z_s ; ++ y_p ; } /* if larger */ z_st += z_s ; /* shift zx to top */ bns_up ( z_s , bnzx , bnzx , bnact + 1 ) ; /* residue to top */ /* test if done */ if ( y_p <= bnlend ) break ; /* MDUF business */ #ifdef MDUF if ( ( ( unsigned ) bnuf < S_PREC ) && ( ( mv = bnact - ( y_p >> BNSHIFT ) - 1 - bnuf ) > 0 ) ) { bnact -= mv ; bnzx += mv ; nbot += mv ; } #endif /* set m to top answer element place, curtail and add */ m = y_p >> BNSHIFT ; lj = y_p & BNMASK ; if ( m == bnend ) z_t &= ( BNFUL << ( B_P_E - lj ) ) ; /* mask ans */ /* add top answer at bit place, ? o-f */ if ( y != NULL ) /* if collecting */ { BN_FRAC( if ) /* o-f only if FRAC */ ( bnadd_ul ( z_t << ( y_p & BNMASK ) , y , m - 1 ) ) /* m cont */ BN_FRAC( { FREE_BN_( zx ) ; FREE_BN_( w2 ) ; BNE1 ; } ) ; } /* return if o-f */ /* run up zx subtracting multiple */ BNUF( if ( k < nbot ) k = nbot ; ) n = k ; lcy = L2( 0 ) ; /* initialise run */ do { lcy += z_t * ( ublong ) w2 [ n ] ; if ( ( bele ) lcy > zx [ n ] ) lcy += E_SZ( 0x10000UL , L2( 0x100000000U ) ) ; zx [ n ] -= ( bele ) lcy ; lcy >>= B_P_E ; } while ( ++ n < S_PREC ) ; zx [ S_PREC ] -= ( bele ) lcy ; /* top element */ /* set new top bit places and zx shift */ z_s = ( ( ( blong ) S_PREC + L2( 1 ) ) * B_P_E - L2( 1 ) ) - ( z_p = bn_msx ( zx , S_PREC + 1 ) ) ; /* residue top place */ #ifdef MDUF if ( z_p == - L2( 1 ) ) break ; #endif /* adopt new answer top place from residue shift */ y_p -= z_s ; /* new ans top place */ } /* end of outer loop */ /* test 1 short, add 1, sub from residue */ if /* if dreg >= divisor */ ( ( y_p == bnlend ) && ( BNCPABS( w2 , z1 ) > - 1 ) ) { if ( ( y != NULL ) && ( bnadd_ul ( L2( 1 ) , y , bnend ) ) ) /* + 1 */ { FREE_BN_( zx ) ; FREE_BN_( w2 ) ; BNE1 ; } ; /* return if o-f */ bns_ub ( w2 , z1 , z1 ) ; /* reduce dreg */ -- y_p ; } /* in case mod goes to source */ BN_SIG( n = w [ S_PREC ] ^ x [ S_PREC ] ; ) /* hold div sign */ /* align residue for return */ if ( z != NULL ) /* for mod */ { bns_down ( z_st , bnzx , bnzx , bnact + 1 ) ; bnclen ( z1 , z , bnact ) ; /* out */ BN_SIG( z [ S_PREC ] = x [ S_PREC ] ; ) } /* mod sign */ #if B_ROUND /* or round answer */ else { if ( ( y != NULL ) && ( iend < 0 ) ) { j = 0 ; if ( ! y_p ) { j = zx [ S_PREC ] & E_SZ( 0x8000 , 0x80000000 ) ; /* save top bit */ bns_up ( L2( 1 ) , bnzx , bnzx , bnact + 1 ) ; -- y_p ; } if ( y_p == - L2( 1 ) ) { #if B_ROUND == 1 if ( ( j || ( BNCPABS( w2 , z1 ) > - L2( 1 ) ) ) && ( bnadd_ul ( L2( 1 ) , y , 0 ) ) ) { #else if ( j || ( m = BNCPABS( w2 , z1 ) ) > - L2( 1 ) ) { if ( bnadd_ul ( ( blong ) ( ( ( y [ 0 ] ^ B_ROUND ) & 1 ) || ( m > 0 ) ) , y , 0 ) ) #endif { FREE_BN_( zx ) ; FREE_BN_( w2 ) ; BNE1 ; } } } } } /* o/f exit */ #endif BN_SIG( if ( y != NULL ) y [ S_PREC ] = n ; ) /* div sign */ FREE_BN_( zx ) ; FREE_BN_( w2 ) ; BNE0 ; } #ifdef MDUF #undef BNUF #else #undef bnact #undef bnz #undef bnufl #endif /* maths, int on big */ /** div_bintoi and rawdivbintoi div_bintoi handles error and trace it calls rawdivbintoi if error and trace code are not needed by definition, the two functions merge and are defined to the same */ R_D div_bintoi ( bele * x , int i , bele * y ) #if ( ERROR_MODE > 1 ) || ( defined BIG_TRACE ) { BN_TRAC( 'u' ) ; BN_ERR( if ) ( rawdivbintoi ( x , i , y ) ) BNE_FUN( "overflow or divide by zero in div_bintoi" ) ; BN0 ; } BN_E rawdivbintoi ( bele * x , int i , bele * y ) #endif { DEF_BN_( z ) ; #ifdef USE_HEAP BN_ERR( int r ; ) BN_HEAP_( z ) ; #endif bnflen ( z , S_LEN , ( bele ) 0 ) ; if ( i < 0 ) { z [ S_FRAC ] = ( bele ) - i ; BN_SIG( z [ S_PREC ] = 1 ; ) } /* i becomes */ else z [ S_FRAC ] = i ; /* +/- z */ BN_ERR( BN_NHEAP( return ) BN_HEAP( r = ) ) ( rawdiv_big_( x , z , y ) ) BN_HEAP( ; free ( z ) ; BN_ERR( return ( r ) ) ) ; } /** maths of int and blong on big */ /** the small add and subtract nest are here : add_int sub_int add and sub ints | | add_li | | add from a blong \ | | add_li_place add from a blong to elements / \ | | choose on signs same or different | | bnadd_ul bnsub_ul unsigned add or subtract with reversal if needed bnadd_ul requires a ublong value to be any up to 0x F...F,0 bn_divide uses this to add an element length at any bit place bnsub_ul requires a ublong value to be any up to 0x 1,0 */ R_D add_int ( int i , bele * x , bele * y ) { BN_TRAC( 'a' ) ; if ( x != y ) bnclen ( x , y , S_LEN ) ; BN_ERR( if ) ( add_li_place ( ( blong ) i , y , S_FRAC ) ) BNE_FUN( "overflow in add_int" ) ; BN0 ; } R_D sub_int ( int i , bele * x , bele * y ) { BN_TRAC( 's' ) ; if ( x != y ) bnclen ( x , y , S_LEN ) ; BN_ERR( if ) ( add_li_place ( ( blong ) - i , y , S_FRAC ) ) BNE_FUN( "overflow in sub_int" ) ; BN0 ; } BN_E add_li ( blong li , bele * x ) { BN_ERR( return ) ( add_li_place ( li , x , S_FRAC ) ) ; } BN_E add_li_place ( blong li , bele * x , int m ) { int j = 0 ; #if SIGNED j = x [ S_PREC ] ^ ( li < 0 ) ; #else j = ( li < 0 ) ; #endif if ( li < 0 ) li = - li ; /* treat negative li */ if ( m >= ( S_PREC + j ) ) return BN_ERR( ( ( int ) ( li != L2( 0 ) ) ) ) ; /* too high to count */ if ( ! j ) /* preprocess and call add */ { if ( m < - 1 ) return BN_ERR( ( 0 ) ) ; /* u-f return */ BN_ERR( return ) ( bnadd_ul ( ( ublong ) li , x , m ) ) ; BNDV ; } /* preprocess and call sub */ { if ( li == ( E_SZ( 0x10000UL , L2( 0x100000000U ) ) ) ) { ++ m ; li = L2( 1 ) ; } if ( m < 0 ) BNE0 ; if ( ( m == S_PREC ) && ( bn_msx ( x , S_PREC ) == - 1 ) ) BNE0 ; bnsub_ul ( ( ublong ) li , x , m ) ; BNE0 ; } } /** rawadd_ul adds ul to x at element place m sign of x is ignored blong must accomodate, not carry up, a carry from adding lower int so max value in ul is [ 1...1 ] [ 0...0 ] accepts m == -1 , it then ignores the u-f returns 0 on success or u-f, 1 on o-f */ int bnadd_ul ( ublong ul , bele * x , int m ) { if ( m >= S_PREC ) return ( 1 ) ; if ( m > - 1 ) /* low ul useable */ { ul += ( ublong ) x [ m ] ; x [ m ] = ( bele ) ul ; } ul >>= B_P_E ; if ( ++ m < S_PREC ) { ul += ( ublong ) x [ m ] ; x [ m ] = ( bele ) ul ; } else return ( ( int ) ( ( ublong ) ul != L2( 0 ) ) ) ; if ( ul > BNFUL ) /* if carry */ while ( ( ++ m < S_PREC ) && ( ! ( ++ x [ m ] ) ) ) ; return ( m == S_PREC ) ; } /* rawsub_ul subtracts ul from abs x at element place m ul max is [ 1 ] [ 0...0 ] sign of x changed by through zero */ void bnsub_ul ( ublong ul , bele * x , int m ) { bele cy = 0 ; int n ; n = m ; if ( x [ m ] < ul ) /* if to carry */ while ( ( ++ n < S_PREC ) && ! x [ n ] ) ; /* test up */ if ( n < S_PREC ) /* if number is there */ bns_lipos ( ul , x , m ) ; /* simple subtract */ else /* through zero */ { n = 0 ; while ( ! x [ n ] && ( n < m ) ) ++ n ; /* pass lower zeroes */ if ( n < m ) { x [ n ] = 0 - x [ n ] ; cy = E_SZ( 0xFFFF , 0xFFFFFFFF ) ; while ( ++ n < m ) /* complement ints */ x [ n ] = ~ x [ n ] ; } /* through active */ x [ m ] = ( bele ) ( ( ublong ) ul - x [ m ] + cy ) ; /* subtract with cy */ BN_SIG( x [ S_PREC ] = ! x [ S_PREC ] ; ) } } /* through zero */ /* bns_lipos subtracts ul at m when result will not pass through zero used by bnsub_ul and bn_readyx */ void bns_lipos ( ublong ul , bele * x , int m ) { x [ m ] = ( bele ) ( ul = ( ublong ) x [ m ] - ul ) ; if ( ul > E_SZ( 0xFFFFUL , L2( 0xFFFFFFFFU ) ) ) while ( ( x [ ++ m ] -- == ( bele ) 0 ) && ( m < ( S_PREC - 1 ) ) ) ; } /* cy */ /** mult_int | mult_li | bnmulul */ R_D mult_int ( int i , bele * x , bele * y ) /* x = x * n */ { BN_TRAC( 'm' ) ; BN_ERR( if ) ( mult_li ( ( blong ) i , x , y ) ) BNE_FUN( "overflow in mult_int" ) ; BN0 ; } BN_E mult_li ( blong li , bele * x , bele * y ) { BN_ERR( if ) ( bnmulul ( ( ublong ) ( li < L2( 0 ) ? - li : li ) , x , y , S_PREC ) ) BN_ERR( return ( 1 ) ) ; BN_SIG( y [ S_PREC ] = x [ S_PREC ] ^ ( li < L2( 0 ) ) ; ) BNE0 ; } unsigned bnmulul ( ublong ul , bele * x , bele * y , int sz ) { ublong cy = L2( 0 ) ; while ( sz -- ) * ( y ++ ) = ( bele ) ( ( ublong ) ( cy = ( cy >> B_P_E ) + * ( x ++ ) * ul ) ) ; return ( ( unsigned int ) ( ( ublong ) cy >> B_P_E ) ) ; } /* return the overflow */ /** int and blong divides div_int div_i_4 | | div_li div_li_4 \ / bndivul */ R_D div_int ( int i , bele * x , bele * y ) { BN_TRAC( 'd' ) ; BN_ERR( if ) ( div_li ( ( blong ) i , x , y ) ) BNE_FUN( "divide by zero in div_int" ) ; BN0 ; } #if ! ( FRAC ) R_D div_i_4 ( int i , bele * x , bele * y , int * rem ) { blong lr ; BN_TRAC( 'j' ) ; BN_ERR( if ) ( div_li_4 ( ( blong ) i , x , y , & lr ) ) BNE_FUN( "divide by zero in div_i_4" ) ; * rem = ( int ) lr ; BN0 ; } #endif BN_E div_li ( blong li , bele * x , bele * y ) { #if ! ( FRAC ) blong dummy ; BN_ERR( return ) ( div_li_4 ( li , x , y , & dummy ) ) ; } BN_E div_li_4 ( blong li , bele * x , bele * y , blong * li_rem ) { #endif ublong u ; #if ! ( FRAC ) || B_ROUND ublong r ; #endif if ( ! li ) { BN_NFRAC( * li_rem = L2( 0 ) ; ) BNE1 ; } u = li < L2( 0 ) ? - li : li ; #if ! ( FRAC ) || B_ROUND r = #endif bndivul ( L2( 0 ) , u , x , y , S_PREC ) ; #if B_ROUND bnadd_ul ( #if B_ROUND == 1 ( r << L2( 1 ) ) >= ( blong ) u #elif B_ROUND > 1 ( ( r = r << L2( 1 ) ) > u ) || ( ( r == u ) && ( y [ 0 ] ^ B_ROUND ) & 1 ) #endif , y , 0 ) ; #endif BN_NFRAC( * li_rem = ( int ) ( BN_SIG( x [ S_PREC ] ? - r : ) r ) ) ; BN_SIG( y [ S_PREC ] = x [ S_PREC ] ^ ( li < L2( 0 ) ) ; ) BNE0 ; } /** bndivul does all datum divides and is used for decimal converions ul is the divisor cy is the carry in, this is divided into the number by ul the function returns the final residue */ unsigned int bndivul ( ublong cy, ublong ul, bele * x, bele * y, int sz) { while ( sz -- ) { y [ sz ] = ( bele ) ( ( ublong ) ( cy = ( cy << B_P_E ) + x [ sz ] ) / ul ) ; cy = cy % ul ; } return ( ( unsigned int ) cy ) ; } /* return residue */ /** shifts big_shift / \ bns_up bns_down bns_up is called by bndivul, bn_divide ( 3 calls ) bns_down bndivul, bn_divide & bnin2 */ R_D big_shift ( blong shift , bele * x , bele * y ) { blong li ; #if B_ROUND ublong lh ; #if B_ROUND > 1 ublong lj ; bele mask = ( unsigned ) - 1 ; int m ; #endif #endif BN_TRAC( 'z' ) ; li = bn_msx ( x , S_PREC ) + L2( 1 ) ; if ( shift < L2( 0 ) ) { /* shift down */ if ( ( shift = - shift ) <= li ) /* shift to 0 then round */ { #if B_ROUND lh = shift - L2( 1 ) ; /* to first u-f */ lh = ( blong ) ( ( bele ) x [ ( int ) ( ( blong ) lh >> BNSHIFT ) ] >> ( ( bele ) lh & BNMASK ) ) & L2( 1 ) ; #if B_ROUND > 1 /* set lj = 1 if rounding is certain */ if ( ( shift > L2( 1 ) ) && lh ) /* if rounding is possible */ { lj = shift - L2( 1 ) ; mask >>= ( B_P_E - ( lj & BNMASK ) ) ; lj = ( blong ) ( ( bele ) x [ m = ( unsigned int ) ( ( blong ) lj >> BNSHIFT ) ] & mask ) ; if ( ! lj ) while ( m -- && ! x [ m ] ) ; lj = ( m > - 1 ) ; } /* l to r */ else lj = L2( 0 ) ; #endif #endif bns_down ( shift , x , y , S_PREC ) ; #if B_ROUND bnadd_ul ( #if B_ROUND > 1 ( ( ( y [ 0 ] ^ B_ROUND ) & 1 ) || lj ) && #endif lh , y , 0 ) ; /* cannot o-f */ #endif } else bnflen ( y , S_LEN , ( bele ) 0 ) ; } /* end of shift down */ else { /* shift up */ if ( shift <= ( ( blong ) S_PREC * B_P_E ) - li ) bns_up ( shift , x , y , S_PREC ) ; else { if ( ! li ) bnflen ( y , S_LEN , ( bele ) 0 ) ; BN_ERR( else ) BNE_FUN( "overflow in big_shift" ) ; } } BN_SIG( y [ S_PREC ] = x [ S_PREC ] ; ) BN0 ; } /** bns_up and bns_down will crash the application if shift or m exceed S_PREC * B_P_E shift , source , dest , size */ void bns_up ( ublong shift , bele * x , bele * y , int m ) { unsigned u , d ; int n , p ; bele * z ; d = B_P_E - ( u = ( unsigned int ) shift & BNMASK ) ; /* bits : up down */ n = ( int ) ( ( ublong ) shift >> BNSHIFT ) ; /* n ints */ z = y + n ; /* dest offset */ p = m - n ; /* active shift */ if ( u ) /* if bit shift */ { while ( -- p ) z [ p ] = ( x [ p ] << u ) + ( x [ p - 1 ] >> d ) ; * z = * x << u ; } else /* element shift */ { while ( p -- ) z [ p ] = x [ p ] ; } while ( n -- ) y [ n ] = 0 ; } /* fill low */ void bns_down ( ublong shift , bele * x , bele * y , int m ) { int p = - 1 , n , d , q , u ; bele * z ; u = B_P_E - ( d = ( unsigned int ) shift & BNMASK ) ; /* bits : down up */ n = ( int ) ( ( ublong ) shift >> BNSHIFT ) ; /* n ints */ q = m - ( int ) ( ( ublong ) shift >> BNSHIFT ) - 1 ; z = x + n ; /* source offset */ if ( d ) { while ( ++ p < q ) y [ p ] = ( z [ p ] >> d ) + ( z [ p + 1 ] << u ) ; y [ p ] = z [ p ] >> d ; } else { ++ q ; while ( ++ p < q ) y [ p ] = z [ p ] ; -- p ; } while ( ++ p < m ) y [ p ] = 0 ; } /** maths auxiliaries */ /** bit size primary tech mssb _ overbit _\_ bn_msx if ! ( FRAC ) ntop is defined as mssb ntop _/ bit comparisons _ bn_ubsum obitdif _/ \_ bn_ubdif a_obitdif _/ */ blong overbit ( bele * x ) #if SIGNED { blong li ; BN_NSIG( return ) ( li = bn_msx ( x , S_PREC ) + 1 ) ; BN_SIG( return ( x [ S_PREC ] ? - li : li ) ) ; } blong bnbn_uobit ( bele * x ) #endif { return ( bn_msx ( x , S_PREC ) + 1 ) ; } /* a_obitdiff ( x , y ) returns the absolute value of the unsigned over bit difference of x and y */ blong a_obitdif ( bele * x , bele * y ) { blong li ; li = bn_ubdif ( x , y ) ; return ( li < 0 ? - li : li ) ; } blong obitdif ( bele * x , bele * y ) #if SIGNED { blong li ; li = ( x [ S_PREC ] == y [ S_PREC ] ) ? bn_ubdif ( x , y ) : bn_ubsum ( x , y ) ; return ( y [ S_PREC ] ? - li : li ) ; } /** finds overbit of ( x - y ) when these have different signs */ blong bn_ubdif ( bele * x , bele * y ) #endif { blong k , li , mask ; int m = S_PREC - 1 ; unsigned sig ; bele * gt , * lt ; while ( ( x [ m ] == y [ m ] ) && ( m > - 1 ) ) -- m ; /* while ints == */ if ( m == - 1 ) return ( L2( 0 ) ) ; /* return if equal */ if ( x [ m ] > y [ m ] ) { gt = x ; lt = y ; sig = 1 ; } /* set pointers */ else { gt = y ; lt = x ; sig = 0 ; } /* find end of carry down */ if ( ( li = gt [ m ] - lt [ m ] ) == 1 ) /* test & set li */ { -- m ; while ( ( gt [ m ] == 0 ) && ( lt [ m ] == E_SZ( 0xFFFF , 0xFFFFFFFF ) ) && ( m > - 1 ) ) -- m ; if ( m == - 1 ) return ( sig ? - L2( 1 ) : L2( 1 ) ) ; li = E_SZ( 0x10000UL , L2( 0x100000000U ) ) + /* set li */ gt [ m ] - lt [ m ] ; } k = ( blong ) B_P_E * ( m + 1 ) ; mask = E_SZ( 0xFFFF8000UL , L2( 0xFFFFFFFF80000000U ) ) ; while ( ! ( li & mask ) ) { mask = mask >> 1 ; -- k ; } /* under the carry, is lt > gt */ if ( ( mask | ( blong ) gt [ m ] ) == ( mask | ( blong ) lt [ m ] ) ) { -- m ; while ( ( gt [ m ] == lt [ m ] ) && ( m > - 1 ) ) -- m ; } k = k - ( ( lt [ m ] > gt [ m ] ) && ( m > - 1 ) ) ; /* adjust */ return ( sig ? - k : k ) ; } #if SIGNED /** a_obitsum enables obitdiff to return the overbit of a difference when the argument values are of different signs it measures the overbit of the sum as it is called only by obitdiff it should be within there but I am not going to fix that */ blong bn_ubsum ( bele * x , bele * y ) { blong li ; ublong k ; int j , m ; m = S_PREC - 1 ; while ( ! ( x [ m ] || y [ m ] ) && ( m > - 1 ) ) -- m ; /* find topmost */ k = ( blong ) x [ m ] + y [ m ] ; li = ( blong ) m << E_SZ( 4 , 5 ) ; j = 0 ; /* save int place */ while ( k && ( k & 1 ) ) { k = k >> 1 ; ++ j ; } if ( k ) /* cannot carry */ { while ( k ) { k = k >> 1 ; ++ j ; } } else { -- m ; while ( ( ( k = ( x [ m ] + y [ m ] ) ) == E_SZ( 0xFFFF , ( int ) 0xFFFFFFFF ) ) && ( m > - 1 ) ) -- m ; /* while may carry */ if ( k > E_SZ( 0xFFFF , ( int ) 0xFFFFFFFF ) ) k = 1 ; else k = 0 ; } return ( li + j + k ) ; } #endif /** mssb ( x ) returns the bit place of the most significant set bit of the absolute value of x and if the compilation is signed, if x == 0 the sign is set positive mssb | bn_msx */ /* mssb is called by rawmult_big (2), kb_2_big_2, bnnum_here & bn_s_out */ blong mssb ( bele * x ) { #if SIGNED blong lh ; if ( ( lh = bn_msx ( x , S_PREC ) ) == - L2( 1 ) ) x [ S_PREC ] = 0 ; return ( lh ) ; } /* correct - 0 , ret */ #else return ( bn_msx ( x , S_PREC ) ) ; } #endif /* bn_msx is called by bn_divide (3), add_li+place, big_shift, overbit, bnbn_uobit, mssx, ntop & bn_m_00 */ blong bn_msx ( bele * x , int sz ) { bele be ; blong ul = - L2( 1 ) ; -- sz ; while ( ( sz > - 1 ) && ( ! x [ sz ] ) ) -- sz ; if ( sz == - 1 ) return ( - L2( 1 ) ) ; be = x [ sz ] ; while ( be ) { be = be >> 1 ; ++ ul ; } /* find top bit */ return ( ( blong ) ( ( ublong ) sz << BNSHIFT ) + ul ) ; } #if FRAC blong ntop ( bele * x ) { return ( bn_msx ( x , S_PREC ) - ( blong ) S_FRAC * B_P_E ) ; } #endif int cp_abs ( bele * w , bele * x ) { /* returns ( abs ( x ) - abs ( w ) ) as - 1 , 0 , 1 */ #ifndef MDUF int m = S_PREC ; #else return ( bncp_abs ( w , x , S_PREC ) ) ; } int bncp_abs ( bele * w , bele * x , int m ) { #endif while ( ( -- m > - 1 ) && ( w [ m ] == x [ m ] ) ) ; return ( ( int ) m == - 1 ? 0 : w [ m ] > x [ m ] ? - 1 : 1 ) ; } /** input and output */ /** bnin1 permits loading to a length of S_PREC + 1 , needed for pix.txt bnin1 finds the mark and sign then finds if decimal or hex provides error response copies the arguments into a structure | \ | for decimal to bn_dec_in which makes a buffer for the f-p | / bnin2, which processes its way through the input stream collecting each next character from bn2i hex input is planted into the top of the destination until o-f or end of i-p then shifted down to place and the f-p is collected and planted see comments for i-p and f-p of decimal input below inserting into i-p and f-p uses max power of 10 within an element bn_dec_in_ip and bn_dec_in_fp serve big_in and bnnum_here */ R_D big_in ( FILE * sm , int mark , bele * x , int base , int b_end ) #if ( ERROR_MODE > 1 ) || ( FRAC && SIGNED ) { BN_ERR( if ) ( bnin1 ( sm , mark , x , base , b_end #if ( FRAC && SIGNED ) , 0 #endif ) ) BNE_FUN( "fault in file input to big_in" ) ; BN0 ; } BN_E bnin1 ( FILE * sm , int mark , bele * x , int base , int b_end #if ( FRAC && SIGNED ) , int xtra /* xtra adds to the length of the target */ #endif ) #endif { int ich = 256 , bnerr ; BN_SIG( int sig = 0 ; ) BN_DEC( struct bn_in sc ; sc.ulbuff = L2( 0 ) ; ) if ( sm == NULL ) BNE1 ; /* find mark */ if ( mark ) while ( ( ( ich = fgetc ( sm ) ) != mark ) && ( ich != EOF ) ) #ifdef SHO_LEAD_IN if ( ich > 31 ) putc( ich , FILE_SM ) #endif ; if ( ich == EOF ) BNE1 ; /* read start of number */ ich = bn2i ( sm , b_end ) ; /* take sign */ if ( ( ich == '+' ) || ( ich == '-' ) ) { BN_SIG( if ( ich == '-' ) sig = 1 ; ) /* nor end yet */ ich = bn2i ( sm , b_end ) ; } /* try to find 0x */ bnflen ( x , S_LEN , ( bele ) 0 ) ; if ( ich == '0' ) { if ( ( ich = bn2i ( sm , b_end ) ) == 'x' ) { base = 16 ; ich = '0' ; } else if ( ich < 0 ) return BN_ERR( ( ich != - 2 ) ) ; } /* EOF or terminator */ bnerr = ( ! base ) ; /* not lost here */ /* call bn_dec_in or bnin & error response */ if ( ( #ifndef NO_DEC base == 10 ? bn_dec_in ( sm , x , ich , b_end ) : #endif bnin2 ( sm , x , 16 , ich , b_end #if ( FRAC && SIGNED ) , xtra #endif #ifndef NO_DEC , & sc #endif ) ) | bnerr ) BNE1 ; BN_SIG( x [ S_PREC BN_FRAC( + xtra ) ] = sig ; ) BNE0 ; } #ifndef NO_DEC /** make a decimal buffer to collect extra length of f-p, this is 3 / 16 length of f-p + 2 call bnin2, convert from buffer */ int bn_dec_in ( FILE * sm , bele * x , int ich , int b_end ) { struct bn_in sc ; #ifdef USE_HEAP int bnerr = 0 ; #if FRAC bele * d_hold ; if ( ( d_hold = ( bele * ) bn_h ( ( int ) ( ( blong ) ( L2( 3 ) * FRAC_CHAR ) / L2( 16 ) ) + L2( 2 ) , BY_P_E ) ) == NULL ) return ( 1 ) ; #endif #else #if FRAC bele d_hold [ ( int ) ( ( blong ) ( L2( 3 ) * BNASZ( FRAC ) ) / L2( 16 ) + L2( 2 ) ) ] ; #endif #endif sc.x = x ; BN_FRAC( sc.h = d_hold ; ) sc.ulbuff = L2( 0 ) ; sc.n = L2( 0 ) ; sc.m = 1 ; BN_HEAP( bnerr = ) BN_NHEAP( return ) ( bnin2 ( sm , x , 10 , ich , b_end , #if ( FRAC && SIGNED ) 0 , #endif & sc ) ) ; BN_FRAC( FREE_BN_( d_hold ) ; ) BN_HEAP( return ( bnerr ) ) ; } /* vv endif # if NO_DEC */ #endif /* ich contains first character taken, or point */ int bnin2 ( FILE * sm , bele * x , int base , int ich , int b_end #if ( FRAC && SIGNED ) , int xtra #endif #ifndef NO_DEC , struct bn_in * sc #endif ) { blong li ; int bnerr = 0 ; int got_n = 0 ; /* bnerr is used */ BN_DEC( int base_b ; ) /* pass leading zeros */ while ( ich == '0' ) { got_n = 1 ; ich = bn2i ( sm , b_end ) ; } /* initialise */ #ifndef NO_DEC base_b = ( base == 16 ) ; /* 1 for hex */ if ( base == 10 ) li = INT_CHAR ; else #endif li = BNXICH ; /* integer digits */ /* take values of integer part */ while ( ( bn_n_( ich ) < base ) && li -- ) { got_n = 1 ; BN_DEC( if ( base_b ) ) bnplant ( ( unsigned ) ich , & x [ S_FRAC BN_FRAC( BN_SIG( + xtra ) ) ] , li ) ; #ifndef NO_DEC else bnerr |= ( bn_dec_in_ip ( ich , sc ) ) ; #endif ich = bn2i ( sm , b_end ) ; } /* li is -1 at full end or too blong */ #ifndef NO_DEC if ( ! base_b ) { if ( bn_decip_end ( sc ) ) return ( 1 ) ; } /* return on i-p o-f */ else #endif if ( li != BNXICH ) bns_down ( li << L2( 2 ) , x + S_FRAC BN_SIG( BN_FRAC( + xtra ) ) , x + S_FRAC BN_SIG( BN_FRAC( + xtra ) ) , S_PREC BN_FRAC( - S_FRAC ) ) ; if ( ich == '.' ) { ich = bn2i ( sm , b_end ) ; /* take fraction part */ #if FRAC #ifndef NO_DEC if ( ! base_b ) { sc->ulbuff = sc->n = L2( 0 ) ; sc->m = S_FRAC ; li = FRAC_CHAR ; } else #endif li = ( blong ) ( S_FRAC BN_SIG( BN_FRAC( + xtra ) ) ) * BNXPE ; /* fraction digits */ while ( ( bn_n_( ich ) < base ) && li -- ) /* number and wanted */ { BN_ERR( got_n = 1 ; ) BN_DEC( if ( base_b ) ) bnplant ( ( unsigned ) ich , x , li ) ; BN_DEC( else bn_dec_in_fp ( ich , sc ) ; ) ich = bn2i ( sm , b_end ) ; } BN_DEC( if ( ! base_b ) bn_decfp_end ( sc ) ; ) #endif } /* o-f or fraction u-f */ while ( bn_n_( ich ) < base ) ich = bn2i ( sm , b_end ) ; BN_ERR( if ( ich != -2 ) bnerr = 1 ; ) /* finish */ return ( ( bnerr && b_end ) | -- got_n ) ; } /* DO I NEED bnerr ? */ /** i_end is to equal one of : ascii terminator EOF terminator 0 , which requires 10 10 10 , which requires 10 10 in the same block of white space 13 one 10 as terminator 256 as impossible value to prevent termination terminator values : 0 non parsing terminates 10 10 ( white space ignored ) 10 13 10 etc accurately */ int bn2i ( FILE * sm , int i_end ) /* function for big_in */ { int ich , rct ; if ( ! i_end ) i_end = 10 ; rct = ( i_end != 10 ) ; if ( i_end == 13 ) i_end = 10 ; do { ich = fgetc ( sm ) ; if ( ( ich == i_end ) && rct ++ ) return ( - 2 ) ; } while ( ( ich == ' ' ) || ( ( unsigned ) ( ich - 9 ) < 5 ) ) ; return ( ich ) ; } void bnplant ( unsigned ich , bele * x , blong li ) { ich = bn_n_( ich ) ; x [ ( int ) ( ( blong ) li / BNXPE ) ] |= ( bele ) ( ich << ( ( ( unsigned int ) li & E_SZ( 3L , L2( 7 ) ) ) * L2( 4 ) ) ) ; } #ifndef NO_DEC /** conversion is based upon the struct bn_in bn_dec_in_ip ( ich , & sc ) accumulates inserts digital values bn_decip_end ( & sc ) inserts any residue this and bn_dec_in_fp are for use by big_in , kb_2_big , num_here */ int bn_dec_in_ip ( int ich , struct bn_in * sc ) /* OK */ { sc->ulbuff = sc->ulbuff * L2( 10 ) + ich - L2( 48 ) ; if ( ( ++ sc->n ) % E_SZ( 4 , 9 ) ) return ( 0 ) ; if ( ( bnmulul ( E_SZ( 10000UL , L2( 1000000000U ) ) , sc->x + S_FRAC , sc->x + S_FRAC , sc->m ) ? 1 : /* I know */ bnadd_ul ( sc->ulbuff , sc->x , S_FRAC ) ) ) return ( 1 ) ; if ( sc->x [ S_FRAC + sc->m - 1 ] && ( sc->m < ( S_PREC BN_FRAC( - S_FRAC ) ) ) ) ++ sc->m ; sc->ulbuff = L2( 0 ) ; return ( 0 ) ; } int bn_decip_end ( struct bn_in * sc ) /* OK */ { ublong li = L2( 1 ) ; if ( ( sc->n % E_SZ( 4 , 9 ) ) ) { while ( ( sc->n -- ) % E_SZ( 4 , 9 ) ) li *= L2( 10 ) ; if ( ( bnmulul ( li , sc->x + S_FRAC , sc->x + S_FRAC , sc->m ) ? 1 : bnadd_ul ( sc->ulbuff , sc->x , S_FRAC ) ) ) return ( 1 ) ; } return ( 0 ) ; } /** fraction collection from an incoming stream of decimal digits bn_dec_in_fp ( ich , sc ) saves digital values into an int buffer E_SZ ( four , nine ) digits are saved one int is saved in tail of x for every three saved into sc->h bn_decfp_end ( sc ) saves any residue then inserts all */ #if FRAC void bn_dec_in_fp ( int ich , struct bn_in * sc ) { sc->ulbuff = sc->ulbuff * L2( 10 ) + ich - L2( 48 ) ; if ( ++ sc->n % E_SZ( 4 , 9 ) ) return ; if ( sc->n % E_SZ( 16 , 36 ) ) * sc->h ++ = ( bele ) sc->ulbuff ; /* store 3 in hold */ else { * sc->x ++ = ( bele ) sc->ulbuff ; -- sc->m ; } /* store 1 in x */ sc->ulbuff = L2( 0 ) ; } void bn_decfp_end ( struct bn_in * sc ) { ublong ul ; #if BIG_DAJ == 1 unsigned int rem = 0 ; #endif while ( sc->n % E_SZ( 4L , L2( 9 ) ) ) bn_dec_in_fp ( '0' , sc ) ; /* stuff until int is full */ sc->n /= E_SZ( 4L , L2( 9 ) ) ; while ( sc->n ) { if ( sc->n -- % L2( 4 ) ) { -- sc->h ; ul = * sc->h ; } else { -- sc->x ; ++ sc->m ; ul = ( blong ) * sc->x ; * sc->x = 0 ; } #if BIG_DAJ == 1 rem |= #endif bndivul ( ul , E_SZ( 10000UL , L2( 1000000000U ) ) , sc->x , sc->x , sc->m ) ; } #if BIG_DAJ == 1 bnadd_ul ( ( blong ) ( rem != 0 ) , sc->x , 0 ) ; #endif } /* v end # if FRAC */ #endif /* v end # ifndef NO_DEC */ #endif /* kb_2_big_2 this accepts kb input if a console interface has been included non parsing keys are refused on i-p count it calls bnnum_here to test for overflow if no console interface text is collected in a buffer then converted by num_here */ int kb_2_big ( bele * dest ) { return ( kb_2_big_2 ( dest , 10 ) ) ; } int kb_2_big_2 ( bele * dest , int base ) #if ( defined GET_C_POS ) && ( defined GET_CHE ) { int ich , k = 0 , ok_char = 0 , sigot = 0 , gotx = 0 , base2 , ypos ; /* count , valid = 1 , got sign , got 0x = 2 , base pos in y */ /* longs for comparisons */ blong digs = L2( 0 ) ; /* digits */ BN_FRAC( blong p_got = 0 ; ) /* got point flag */ DEF_BN_( hold ) ; /* permits [ Esc ] */ char * q ; #ifdef USE_HEAP char * asc_in ; BN_HEAP_( hold ) ; asc_in = ( char * ) bn_h ( ( int ) BNKB_CH + 1 , 1 ) ; #else char asc_in [ BNKB_CH + 1 ] ; /* assemble ascii */ #endif q = asc_in ; base2 = ! base ? 16 : base ; ypos = READ_LINE( GET_C_POS ) ; * q = 0 ; while ( 1 ) /* keystrokes */ { q [ 1 ] = 0 ; * q = ( ich = GET_CH ) ; /* get and plant */ if ( ( ich > 31 ) && ( ich < 127 ) ) putchar( ich ) ; ok_char = ( k < BNKB_CH ) ; /* prevent buffer o-f */ if ( ok_char && ! ( base || gotx ) ) /* test if 0x forced by call */ { switch ( ich ) { BN_FRAC( case '-' : ) case '+' : break ; case '0' : if ( k != sigot ) ok_char = 0 ; break ; case 'X' : case 'x' : if ( k != ( sigot + 1 ) ) ok_char = 0 ; break ; default : ok_char = 0 ; } } if ( ok_char || ( ich < 32 ) ) { if ( bn_n_( ich ) < base2 ) /* if a digit */ ok_char = /* o-f or u-f */ #if FRAC p_got ? p_got < ( ( /* f-p underflow */ #ifndef NO_DEC base2 == 10 ? FRAC_CHAR : #endif S_FRAC * E_SZ( 4 , 8 ) ) + 2 ) : #endif ( /* i-p overflow */ #ifndef NO_DEC base2 == 10 ? ( digs < ( INT_CHAR - 1 ) ) || ! bnnum_here ( asc_in , base2 , hold BNA_1 ) : #endif digs < ( ( S_PREC - S_FRAC ) * E_SZ( 4 , 8 ) ) ) ; else /* not a digit */ { switch ( ich ) { case 'X' : case 'x' : if ( ( k == 1 + sigot ) && ( asc_in [ sigot ] == '0' ) ) { base2 = 16 ; gotx = 2 ; digs = - 1 ; } /* !!!! */ else ok_char = 0 ; break ; /* base2 offset into string */ BN_SIG( case '-' : ) case '+' : if ( ! k ) sigot = 1 ; else ok_char = 0 ; break ; BN_FRAC( case '.' : if ( ! p_got ) p_got = 1 ; else ok_char = 0 ; break ; ) case ENTER_K : if ( k > ( sigot BN_FRAC( + ( p_got > 0 ) ) + gotx ) ) { bnnum_here /* convert & issue */ ( asc_in + sigot + gotx , base2 , hold BNA_1 ) ; bnclen ( hold , dest , S_LEN ) ; BN_SIG( dest [ S_PREC ] = ( * asc_in == '-' ) ; ) BN_SIG( mssb ( dest ) ; ) FREE_BN_( hold ) ; FREE_BN_( asc_in ) ; putchar( '\n' ) ; return ( 0 ) ; } break ; case 27 : FREE_BN_( hold ) ; FREE_BN_( asc_in ) ; return ( - 1 ) ; case BACK_SP : if ( k ) { -- k ; -- q ; switch ( * q ) { case 'X' : case 'x' : digs = 1 ; gotx = 0 ; base2 = base ; break ; BN_FRAC( case '.' : p_got = 0 ; break ; ) BN_SIG( case '-' : ) case '+' : sigot = 0 ; break ; default : BN_FRAC( if ( p_got ) -- p_got ; else ) if ( digs ) -- digs ; /* digit */ } } /* end switch * q , if ( k ) */ ok_char = - 1 ; break ; /* - 1 to supress bell */ default : ok_char = 0 ; } } } /* else , switch , if */ /* actions */ if ( ok_char < 1 ) { #ifndef NO_BELL if ( ! ok_char ) putchar( '\a' ) ; #endif * q = 0 ; SET_C_POS_( ypos , 1 ) ; printf( "%s " , asc_in ) ; SET_C_POS_( ypos , 1 ) ; printf( "%s" , asc_in ) ; } else { BN_FRAC( if ( p_got ) ++ p_got ; else ) ++ digs ; ++ q ; ++ k ; } } } /* end of while ( 1 ) , fn */ #else { char asc_in [ 81 ] ; /* alternative fn */ printf ( "\t80 characters maximum\n" ) ; scanf( "%80s" , asc_in ) ; bnnum_here ( asc_in , base , dest BNA_1 ) ; return ( 1 ) ; } #endif /** num_here converts a decimal text string to a big number, terminates ok on any character that does not parse for the conversion num_here responds to overflow or no number as an error num_here calls bnnum_here setting base 10 */ R_D num_here ( char * sg , bele * x ) /* put a value into x */ { BN_ERR( if ) ( bnnum_here ( sg , ( ( sg [ 1 ] | 32 ) == 'x' ) || ( ( sg [ 2 ] | 32 ) == 'x' ) ? 12 : 10 , x BNA_1 ) ) BNE_FUN( "num_here " ) ; BN0 ; } /** to provide a routine that tests and converts a string number to binary it returns 0 if it finds a number or 1 if overflow or no number bnnum_here advances a pointer through : leading spaces - ignored if SIGNED , a sign - adopted spaces - ignored optional 0x - set base to 16 spaces - ignored leading zeros - noted as a number, otherwise ignored if base is 16 a direct hex conversion to base 16 is used is made the integer of the number is measured to find point or low end the hex digits are converted into their places below the point the hex digits are converted to their places if base is 10 if FRAC it : tests for a decimal point, if yes saves & x { S_FRAC ] runs to the end of the ascii steps back along ascii ch by ch repeatedly until decimal point puts value from ch in x [ S_FRAC ] divides the unit.fraction by base restores x [ S_FRAC ] tests if wanted and appropriate and increments number */ int bnnum_here ( char * sg , int base , bele * x #if ( BIG_DAJ == 1 ) && ( ! defined NO_DEC ) , int asc_inc #endif ) { int pos = 0 ; char * s2 ; bele * x2 ; BN_FRAC( BN_DEC( blong j = 0 ; ) unsigned int n ; ) /* characters ; digit value */ BN_SIG( int sig = 0 ; ) /* sign */ #if ( BIG_DAJ == 1 ) && ( ! defined NO_DEC ) int rem = 0 ; #endif #ifndef NO_DEC struct bn_in sc ; sc.x = x ; BN_FRAC( sc.h = NULL ; ) sc.ulbuff = L2( 0 ) ; sc.n = L2( 0 ) ; sc.m = 1 ; #endif bnflen ( x , S_LEN , ( bele ) 0 ) ; x2 = x ; while ( * sg == ' ' ) ++ sg ; /* tolerate leading spaces */ BN_SIG( if ( * sg == '-' ) { ++ sg ; sig = 1 ; } else ) if ( * sg == '+' ) ++ sg ; while ( * sg == ' ' ) ++ sg ; /* tolerate leading spaces */ if ( ( * sg == '0' ) && ( ( sg [ 1 ] | 32 ) == 'x' ) ) { base = 16 ; sg = sg + 2 ; while ( * sg == ' ' ) ++ sg ; } if ( ! base ) return ( 1 ) ; while ( * sg == '0' ) ++ sg ; /* leading zeroes */ #ifndef NO_DEC if ( base == 10 ) /* convert from decimal */ /* integer part */ { while ( ( bn_n_( * sg ) ) < 10 ) /* step down digits */ { if ( bn_dec_in_ip ( * sg , & sc ) ) /* insert digits */ return ( 1 ) ; ++ sg ; } if ( bn_decip_end ( & sc ) ) return ( 1 ) ; /* convert */ #if FRAC /* prepare fraction part */ if ( * sg == '.' ) /* if found frac */ { ++ sg ; while ( bn_n_( * sg ) < 10 ) { ++ j ; ++ sg ; } -- sg ; /* at end */ /* fraction part conversion */ while ( * sg != '.' ) { #if BIG_DAJ == 1 rem = rem | /* keep underflow */ #endif bndivul ( ( ublong ) * ( sg -- ) - '0' , L2( 10 ) , x , x , S_FRAC ) ; } #if BIG_DAJ == 1 bnadd_ul ( ( blong ) ( asc_inc && rem && ( j == FRAC_CHAR ) ) , x , 0 ) ; #endif } /* end '.' */ #endif } /* end decimal */ else #endif /* convert from hex */ { if ( ! ( * sg == '.' ) ) { s2 = sg ; while ( bn_n_( * s2 ) < 16 ) { ++ s2 ; ++ pos ; } /* digits in integer */ if ( pos > ( ( S_PREC - S_FRAC ) * E_SZ( 4 , 8 ) ) ) return ( 1 ) ; x2 = x2 + BN_FRAC( S_FRAC + ) ( ( pos - 1 ) >> E_SZ( 2 , 3 ) ) ; /* hex integer part */ while ( pos -- ) /* down integer */ { * x2 = * x2 | ( bn_n_( * sg ) << ( ( pos & E_SZ( 3 , 7 ) ) * 4 ) ) ; ++ sg ; if ( ! ( pos & E_SZ( 3 , 7 ) ) ) -- x2 ; } } #if FRAC if ( * sg == '.' ) /* maybe end */ /* hex fraction part */ { ++ sg ; x2 = x + S_FRAC - 1 ; pos = S_FRAC * E_SZ( 4 , 8 ) ; while ( ( ( n = bn_n_( * sg ) ) < 16 ) && ( ( pos >> E_SZ( 2 , 3 ) ) > - 1 ) ) { -- pos ; * x2 = * x2 | ( n << ( ( pos & E_SZ( 3 , 7 ) ) * 4 ) ) ; ++ sg ; if ( ! ( pos & E_SZ( 3 , 7 ) ) ) -- x2 ; } } #endif } BN_SIG( x [ S_PREC ] = sig ; mssb ( x ) ; ) return ( 0 ) ; } /* sc AT EM = 0 IS NOT USED */ /** output to a stream */ /** bn_out if hex / \ if decimal / \ bn_m_00 readyx these initialise as needed makes buffer | \ / bn_s_out does the work */ R_D big_out ( int name_len , char * sg , bele * x , FILE * sm , int mark , /* ^^^ ch length string big number stream begin mark */ int b_end , int group , unsigned line_len , blong chip , /* ^^^ end mark group line length integer-part characters */ #if FRAC int fmode , /* mode for chfp */ blong chfp , /* fraction-part characters */ #endif int leadz , int base ) /* ^^^ to replace leading 0 base */ { struct bnout ctrl ; ctrl.nam_len = name_len ; ctrl.sg = sg ; ctrl.mark = mark ; ctrl.x = x ; ctrl.b_end = b_end ; ctrl.group = ( blong ) group ; ctrl.line_len = ( blong ) line_len ; ctrl.base = base ; ctrl.sm = sm ; BN_DEC( ctrl.achip = ) ctrl.chip = chip ; ctrl.leadz = ctrl.lead1 = leadz ; #if FRAC ctrl.ofm = fmode & 1 ; ctrl.fpnl = fmode & 2 ; ctrl.frnd = ! ( fmode & 4 ) ; ctrl.chfp = chfp ; #endif #if ERROR_MODE if ( ( sm == NULL ) ? 1 : ( BN_DEC( base == 10 ? bn_m_00 ( & ctrl ) : ) bn_readyx ( & ctrl ) ) ) BNE_FUN( "writing ascii " ) ; BN0 ; } #else if ( sm != NULL ) BN_DEC( if ( base == 10 ) bn_m_00 ( & ctrl ) ; else ) bn_readyx ( & ctrl ) ; } #endif /** bn_readyx and bn_m_00 have to prepare the control values in the struct ctrl arrival use ctrl->chip i-p request i-p characters ctrl->ofm f-p mode 0 : ctrl->chfp as a dock 1 : ctrl->chfp as length ctrl-chfp f-p length request neg of f-p characters ctrl->n number of i-p n000 ctrl->achip dec i-p min places i-p places at arrival out of range values arriving produce the natural length has to set ctrl->n the top hex digit lead1 lead ch for o-f position */ BN_E bn_readyx ( struct bnout * ctrl ) { blong len ; BN_FRAC( blong add_8 ; int pl ; BN_ERR( int bnerr ; ) ) ctrl->fcall = bn2x ; /* set ctrl->achip */ ctrl->lead1 = ( int ) ( ( blong ) ctrl->chip == BNXICH ) ; /* horrible patch, elegance has competitors */ if ( ! ctrl->chip || ( ( ublong ) ctrl->chip >= BNXICH ) ) ctrl->achip = BNXICH ; /* set achip for integer-part natural length */ else if ( ctrl->chip < ( len = ( ntop ( ctrl->x ) / L2( 4 ) + L2( 1 ) ) ) ) /* characters in i-p , not counting o-f */ ctrl->achip = len ; #if FRAC /* set ctrl->chfp */ if ( ( ublong ) ctrl->chfp > ( S_FRAC * BNXPE ) ) { ctrl->ofm = 0 ; ctrl->chfp = L2( 0 ) ; } ctrl->chfp = ctrl->ofm ? - ctrl->chfp : ctrl->chfp - S_FRAC * BNXPE ; /* set chfp to minus length */ /* rounding and possible consequent o-f */ if ( ( ctrl->chfp + S_FRAC * BNXPE ) ) /* if chfp + cut */ { ctrl->ofm = bnadd_ul ( add_8 = ( blong ) ( L2( 8 ) << /* ofm is o-f */ ( ( ( S_FRAC * BNXPE + ctrl->chfp - L2( 1 ) ) & E_SZ( 3L , L2( 7 ) ) ) * L2( 4 ) ) ) * ctrl->frnd , /* add_8 is the 8 positioned in int */ ctrl->x , pl = ( unsigned int ) ( ( blong ) ( S_FRAC * BNXPE + ctrl->chfp - L2( 1 ) ) >> E_SZ( 2L , L2( 3 ) ) ) ) ; ctrl->lead1 = ctrl->lead1 ? ' ' : ctrl->leadz ; } else { ctrl->ofm = 0 ; add_8 = L2( 0 ) ; ctrl->lead1 = ctrl->leadz ; } /* ofm to bn_s_out, add_8 to below */ ctrl->achip += ( ( add_8 > 0 ) && ( ctrl->achip == BNXICH ) ) * ctrl->frnd ; /* 1 more if add_8 and full length i-p */ #endif ctrl->n = ctrl->achip #if FRAC + ( blong ) S_FRAC * E_SZ( 4L , L2( 8 ) ) ; BN_ERR( bnerr = ) bn_s_out ( ctrl ) ; if ( add_8 ) bns_lipos ( add_8 , ctrl->x , pl ) ; /* restore */ BN_ERR( return ( bnerr ) ) ; } #else ; /* not an accident */ BN_ERR( return ) ( bn_s_out ( ctrl ) ) ; } #endif #ifndef NO_DEC #define BNZ( A ) (int) ((ublong) BNASZ( A )/E_SZ(4L,L2(9))+L2(1)) #define BN00MX BNZ( BNHOP ) #if ( defined USE_HEAP && defined SOFT_SIZE ) || ( PREC > BNHOP ) #ifdef SOFT_SIZE #define BN_UP( A ) if( A ++ == ctrl->n00top && (S_PREC>BNHOP)) A = ctrl->n002 #define BN_DO( A ) if( A -- == ctrl->n002 && (S_PREC>BNHOP)) A = ctrl->n00top #else #define BN_UP( A ) if ( A ++ == ctrl->n00top ) A = ctrl->n002 #define BN_DO( A ) if ( A -- == ctrl->n002 ) A = ctrl->n00top #endif #else #define BN_UP( A ) ++ A #define BN_DO( A ) -- A #endif /** for decimal output makes a buffer and, if needed an overflow buffer load this with clusters of decimal places then call bn_s_out written as a number, least significant to the right : [ ] ... [ ] . [ ] ... [ ] ^ ^ numb n00 when the n00s have to be broken because there are too many numb pointing to the 0 int place may be in either array : [ ] ... [ ] [ ] ... [ ] ^ ^ n002 n00top n00 test pointer going up against n00top after incrementing down against n002 before decrementing */ BN_E bn_m_00 ( struct bnout * ctrl ) { BN_FRAC( bele * n00fp ; ) unsigned m ; blong len ; int bn2 ; #if FRAC bele * numb , noddy = 0 ; #endif BN_HEAP( BN_ERR( int bnerr = 1 ; ) ) /* set to zero by success */ #ifndef USE_HEAP /* take stack */ #ifndef SOFT_SIZE bele numb0 [ ( ( PREC - FRAC ) > FRAC ? PREC - FRAC : FRAC ) ] ; /* fraction-part , integer-part */ #else big_n numb0 ; #endif #if ( PREC > BNHOP ) bele n00 [ BNZ( BNHOP ) ] , n002 [ BNZ( PREC - BNHOP ) + 1 ] ; ctrl->n002 = n002 ; #else bele n00 [ BNZ( PREC ) + 1 ] ; /* + 1 for 2 roundings up */ #endif BN_FRAC( numb = numb0 ; ) #else bele * n00 , * numb0 ; #endif if ( ! ctrl->chip || ( ( ublong ) ctrl->chip > INT_CHAR ) ) len = ctrl->achip = INT_CHAR ; /* natural length */ else len = BNBSZ( bn_msx ( & ctrl->x [ S_FRAC ] , S_PREC - S_FRAC ) ) ; ctrl->n = ( len + E_SZ( 3L , L2( 8 ) ) ) / E_SZ( 4L , L2( 9 ) ) ; if ( len > ctrl->achip ) ctrl->achip = len ; #if FRAC /* ofm determines how chfp will be used, see above then when that is resolved, signals f-p to o/p shorter than naturally chfp of 0 or outside the natural length gives the natural length chfp is used as a negative */ #ifdef SOFT_SIZE if ( ! S_FRAC ) { ctrl->ofm = 1 ; ctrl->chfp = L2( 0 ) ; } #endif if ( ( ublong ) ctrl->chfp > FRAC_CHAR ) { ctrl->ofm = 0 ; ctrl->chfp = L2( 0 ) ; } /* natural length */ ctrl->chfp = ctrl->ofm ? - ctrl->chfp : ctrl->chfp - FRAC_CHAR ; /* control - given dok */ ctrl->ofm = ( ( - ctrl->chfp ) != FRAC_CHAR ) ; /* reuse */ #endif #ifdef USE_HEAP /* take heap memory */ BN_FRAC( numb = ) numb0 = ( bele * ) bn_h ( #if FRAC ( S_PREC - S_FRAC ) > S_FRAC ? S_PREC - S_FRAC : S_FRAC #else S_PREC #endif , BY_P_E ) ; n00 = ( bele * ) bn_h ( S_PREC > BNHOP ? BN00MX : BNZ( S_PREC ) + 1 , BY_P_E ) ; /* initialise n00ip, save point */ #if ( defined USE_HEAP && defined SOFT_SIZE ) || ( PREC > BNHOP ) ctrl->n00top = n00 + BNZ( S_PREC > BNHOP ? BNHOP : s_prec ) - 1 ; #endif #if defined USE_HEAP && ( ( defined SOFT_SIZE ) || ( PREC > BNHOP ) ) ctrl->n002 = ( bele * ) bn_h ( #ifdef SOFT_SIZE ( S_PREC <= BNHOP ) ? 1 : #endif BNZ( S_PREC - BNHOP ) + 1 , BY_P_E ) ; #endif #endif ctrl->n00ip = /* n00 place 0 */ #if FRAC n00fp = #if defined USE_HEAP && ( ( defined SOFT_SIZE ) || ( PREC > BNHOP ) ) ( S_FRAC > BNHOP ) ? ctrl->n002 + BNZ( S_FRAC - BNHOP ) : #endif BNZ( S_FRAC ) + /* n00fp start at the unit place */ #endif n00 ; /* these fills can be slightly accelerated, is it worth it ? */ /* fill n00s, integer-part */ bnclen ( & ctrl->x [ S_FRAC ] , numb0 , m = S_PREC - S_FRAC ) ; ctrl->n = ( ( blong ) ( ctrl->achip + E_SZ( 3L , L2( 8 ) ) ) / E_SZ( 4L , L2( 9 ) ) ) ; while ( ctrl->n -- ) { * ctrl->n00ip = bndivul ( L2( 0 ) , E_SZ( 10000UL , L2( 1000000000U ) ) , numb0 , numb0 , m ) ; m -= ( ! numb0 [ m - 1 ] ) && ( m > 0 ) ; /* shorten i-p */ BN_UP( ctrl->n00ip ) ; } #if FRAC /* fill n00s, fraction-part */ bnclen ( ctrl->x , numb , bn2 = S_FRAC ) ; /* big fraction-part */ ctrl->n = /* number of n00s to load in f-p */ ( - ctrl->chfp + E_SZ( 3L , L2( 8 ) ) + ctrl->ofm ) / E_SZ( 4L , L2( 9 ) ) ; /* number of f-p n00s to fill */ while ( ctrl->n -- ) { BN_DO( n00fp ) ; * n00fp = bnmulul ( E_SZ( 10000UL , L2( 1000000000U ) ) , numb , numb , bn2 ) ; if ( ( ! * numb ) && bn2 ) { -- bn2 ; ++ numb ; } } /* shorten f-p */ /* n00fp points to last n00 filled */ /* dock tail and round for dock or BIG_DAJ */ /* will hold 10 * 10 ^ N or 5 * 10 ^ N , to add */ m = ( ctrl->ofm ? E_SZ( 5000UL , L2( 500000000U ) ) : ( #if BIG_DAJ == 2 bn_msx ( numb , bn2 ) != - L2( 1 ) ? E_SZ( 10000UL , L2( 1000000000U ) ) : #endif L2( 0 ) ) ) * ctrl->frnd ; noddy = ( int ) ( ( blong ) ( - L2( 0 ) - ctrl->chfp ) % E_SZ( 4L , L2( 9 ) ) ) ; while ( noddy -- ) m /= 10 ; /* position the 5 */ /* add and test for excess + 5 or + 1 at required place */ if ( ( * n00fp += m ) > E_SZ( 9999U , 999999999U ) ) /* but cast 64 bit */ { * ( n00fp ++ ) = 0 ; while ( ++ * n00fp == E_SZ( 10000 , 1000000000 ) ) { * n00fp = 0 ; /* carry up the n000s */ BN_UP( n00fp ) ; } } /* will never o-f */ #else #undef bn2 /* V end if FRAC */ #endif /* prepare for function bn210 */ -- ctrl->n00ip ; ctrl->bebuff = * ctrl->n00ip ; if ( ( m = ( int ) ( ( ctrl->n = ctrl->achip ) % E_SZ( 4 , 9 ) ) ) != 0 ) { m = E_SZ( 4 , 9 ) - m ; while ( m -- ) ctrl->bebuff *= 10 ; } /* if needed by ctrl->chip , lose top 0 */ if ( ctrl->chip && ( ctrl->achip > ctrl->chip ) && ! ( ctrl->bebuff / E_SZ( ( bele ) 1000 , 100000000 ) ) ) { -- ctrl->achip ; bn210 ( ctrl ) ; } /* set call */ ctrl->fcall = bn210 ; /* send */ BN_ERR( BN_NHEAP( return ) BN_HEAP( bnerr = ) ) bn_s_out ( ctrl ) ; #ifdef USE_HEAP #if ( defined SOFT_SIZE ) || ( PREC > BNHOP ) FREE_BN_( ctrl->n002 ) ; #endif FREE_BN_( n00 ) ; FREE_BN_( numb0 ) ; BN_ERR( return ( bnerr ) ) ; #endif } #endif BN_E bn_s_out ( struct bnout * ctrl ) { BN_ERR( int bnerr = 0 ; ) unsigned u , program ; ublong lu , pos ; int i = 0 , activ = '0' , tokens ; char mark_sg [ 3 ] = " " ; #if SIGNED mssb ( ctrl->x ) ; /* mend -0 */ #endif if ( ctrl->mark == 10 ) mark_sg [ 1 ] = 0 ; /* equals one space */ else mark_sg [ 0 ] = ctrl->mark ; /* 0 or 10 give no string length */ /* line length and group */ ctrl->line_len = ctrl->line_len > L2( 2 ) ? ctrl->line_len - L2( 2 ) : ( unsigned ) ( - L2( 1 ) ) ; if ( ctrl->group >= ctrl->line_len ) ctrl->group = ctrl->line_len ; /* print label */ tokens = ( ( ( ctrl->mark && ( ctrl->mark != 10 ) ) ? 2 : 1 ) + ( ctrl->base ? 0 : 3 ) + SIGNED + SIGNED ) ; /* send label */ if ( ctrl->sg ) /* NULL gives no label */ { while ( * ctrl->sg ) /* step through sg */ { if ( ( * ctrl->sg > 31 ) BN_NERR ) /* ignore non printable */ { BN_ERR( bnerr = ) ( BNEEOF putc( * ctrl->sg , ctrl->sm ) ) ; /* o/p */ ++ i ; } ++ ctrl->sg ; } } /* position cursor and send tokens */ if ( ( ctrl->mark != 10 ) && ( i <= ctrl->nam_len ) ) { pos = ctrl->nam_len + ( ctrl->nam_len > 0 ) + tokens ; i += tokens ; program = 0451 + /* adjust , pad , tokens */ ! ctrl->group ; } /* set for group = 0 */ else { pos = ( i = tokens ) + 1 ; program = 04531 - ! ctrl->group ; } /* adjust , \n , pad , tokens */ while ( program ) { switch ( program & 7 ) { case 0 : /* group == 0 , mark == 10 */ program = 05437 ; /* >> , \n , tokens , */ break ; case 1 : /* calculate adjustment */ lu = ctrl->achip % ctrl->group ; if ( ! lu ) lu = ctrl->group ; if ( pos > ( u = ( int ) ( ( blong ) ctrl->line_len - ( ctrl->line_len + L2( 1 ) ) % ( ctrl->group + L2( 1 ) ) - lu ) ) ) { pos = i = tokens ; program = 04537 ; /* >> , \n , pad , tokens */ if ( pos > u ) { pos = i = 0 ; program = ( ctrl->mark == 10 ) ? 053437 : /* >> , \n , tokens , \n , pad */ 05347 ; } } /* >> , tokens , \n , pad */ if ( ( u = ( ctrl->group - ( int ) ( ( blong ) ctrl->achip % ctrl->group + pos ) % ( ctrl->group + 1 ) ) % ( ctrl->group + 1 ) ) != ctrl->group ) pos += u ; else { if ( pos ) -- pos ; else program = ( ctrl->mark == 10 ) ? 0437 : /* >> , \n , tokens */ 047 ; } /* >> , tokens */ break ; case 2 : /* group == 0 */ pos = ctrl->nam_len + tokens ; program = 0457 ; /* >> , pad , tokens */ break ; case 3 : /* newline */ #ifdef CLEOL if ( ctrl->sm == stdout ) CLEOL ; #endif BN_ERR( if ( ! bnerr ) bnerr = ) ( BNEEOF putc( '\n' , ctrl->sm ) ) ; #ifdef CLEOL if ( ctrl->sm == stdout ) CLEOL ; #endif break ; case 4 : /* put tokens */ BN_ERR( if ( ! bnerr ) bnerr = ) ( BNEEOF fprintf( ctrl->sm , "%s" /* mark */ #if SIGNED "%c " /* sign */ #endif "%s" , mark_sg /* 0x */ #if SIGNED , ctrl->x [ S_PREC ] ? '-' : '+' #endif , ctrl->base ? "" : X_x ) ) ; /* allow 0X */ #ifdef CLEOL if ( ctrl->sm == stdout ) CLEOL ; #endif break ; case 5 : /* pad before tokens */ i = pos - i + 1 ; while ( i -- BN_NERR ) BN_ERR( bnerr = ) ( BNEEOF putc( ' ' , ctrl->sm ) ) ; break ; } program >>= 3 ; } ; /* send the body */ while ( ( ctrl->achip BN_FRAC( > ctrl->chfp ) ) BN_NERR ) /* character due && ! error */ { ++ pos ; /* this is this character increment */ if ( ( ctrl->group && ( blong ) ! ( ctrl->achip % ctrl->group ) ) || ! ctrl->achip || ( pos > ctrl->line_len ) ) /* group break */ { ++ pos ; if ( ( ( pos >= ( ctrl->line_len - ctrl->group - ! ctrl->group ) ) && ctrl->line_len ) #if FRAC || ( ! ctrl->achip && ctrl->fpnl ) #endif ) /* line end */ { BN_ERR( if ( ! bnerr ) bnerr = ) ( BNEEOF putc( '\n' , ctrl->sm ) ) ; #ifdef CLEOL if ( ctrl->sm == stdout ) CLEOL ; #endif pos = 1 ; } /* turn & then space */ #if FRAC BN_ERR( if ( ! bnerr ) bnerr = ) ( BNEEOF putc( ctrl->achip ? ' ' : '.' , ctrl->sm ) ) ; #else BN_ERR( if ( ! bnerr ) bnerr = ) ( BNEEOF putc( ' ' , ctrl->sm ) ) ; #endif } /* end group break */ BN_ERR( if ( ! bnerr ) ) { -- ctrl->achip ; /* get the character from the function assigned to ctrl->fcall */ u = ( * ctrl->fcall ) ( ctrl ) ; /* 000 suppress */ activ |= ( u | ( ctrl->achip == 0 ) ) ; BN_ERR( bnerr = ) ( BNEEOF putc( activ == '0' ? ctrl->lead1 : u , ctrl->sm ) ) ; ctrl->lead1 = ctrl->leadz ; } } /* end of : while , if ! bnerr */ /* terminator, \n, error call, return */ if ( ctrl->b_end && ( ctrl->b_end != 13 ) BN_NERR ) BN_ERR( bnerr = ) ( BNEEOF putc( ( char ) ctrl->b_end , ctrl->sm ) ) ; #ifdef CLEOL if ( ctrl->sm == stdout ) CLEOL ; #endif /* final newline */ #ifndef BNNONL BN_ERR( if ( ! bnerr ) bnerr = ) ( BNEEOF ( putc( '\n' , ctrl->sm ) ) ) ; #endif return BN_ERR( ( bnerr ) ) ; } #ifndef NO_DEC int bn210 ( struct bnout * ctrl ) { int u ; u = ( int ) ( ( bele ) ctrl->bebuff / E_SZ( 1000 , 100000000 ) ) ; /* take */ ctrl->bebuff = ( ctrl->bebuff - E_SZ( 1000 , 100000000 ) * u ) * 10 ; if ( ! ( -- ctrl->n % E_SZ( 4L , L2( 9 ) ) ) ) { BN_DO( ctrl->n00ip ) ; ctrl->bebuff = * ctrl->n00ip ; } return ( u + '0' ) ; } #undef BN00MX #undef NSZ #undef BNHOP #undef BN_UP #undef BN_DO #endif /* bn2x decrements ctrl->n and returns the indicated ascii hex */ int bn2x ( struct bnout * ctrl ) { int ich ; -- ctrl->n ; #if FRAC if ( ctrl->n == ( ( blong ) ( S_PREC ) * E_SZ( 4 , 8 ) ) ) return ( ctrl->ofm ? '1' : ' ' ) ; #endif ich = ( ( unsigned ) ctrl->x [ ( int ) ( ( blong ) ctrl->n >> E_SZ( 2L , L2( 3 ) ) ) ] >> ( ( ctrl->n & E_SZ( 3L , L2( 7 ) ) ) * L2( 4 ) ) ) & L2( 15 ) ; return ( ich + ( ich > 9 ? ( X_ten - 10 ) : '0' ) ) ; } /** output a big number as bits bit_show outputs to the console | bits_out to any stream | bn_bits2sm one element to stream */ void bit_show ( bele * w ) /* display w as bits */ { bits_out ( w , S_LEN , stdout ) ; } R_D bits_out ( bele * w , int m , FILE * sm ) { BN_ERR( int bnerr = 0 ; ) int mm ; mm = m ; while ( m -- BN_ERR( && ! bnerr ) ) /* all elements */ { BN_ERR( bnerr = ) ( BNEEOF fprintf( sm , BN_FRAC( m == ( S_FRAC - 1 ) ? BIG_B_POINT : ) " " ) ) ; BN_ERR( if ( ! bnerr ) bnerr = ) bn_bits2sm ( w [ m ] , sm ) ; if ( ! m || ! ( ( mm - m ) % ( ( LINE_LEN - 2 ) / E_SZ( 19 , 35 ) ) ) ) /* if end or EOL */ { #ifdef CLEOL if ( sm == stdout ) CLEOL ; #endif BN_ERR( bnerr = ) ( BNEEOF putc( '\n' , sm ) ) ; } } /* end all loop */ BN_ERR( if ( bnerr ) ) BNE_FUN( "in bits_out" ) ; BN0 ; } BN_E bn_bits2sm ( bele be , FILE * sm ) { unsigned o = E_SZ( 0x8000 , 0x80000000 ) ; do { if ( putc( ( be & o ) ? '1' : BIG_B_0 , sm ) == EOF ) BNE1 ; } while ( ( o = o >> 1 ) != 0 ) ; BNE0 ; } /** error function */ #if ( ( ERROR_MODE > 1 ) && ( ERROR_MODE < 64 ) ) void error_function ( char * sg ) { #ifndef NO_BELL putchar( '\a' ) ; #endif fprintf( ERR_SM , "\nerror : %s\n" #if ! ( ERROR_MODE & 8 ) "press a key " #endif , sg ) ; #if ! ( ERROR_MODE & 8 ) #if ( ERROR_MODE & 63 ) == 2 fprintf( ERR_SM , #ifdef GET_CH "to continue\n" ) ; GET_CH ; #else "to continue, and then press cr or enter\n" ) ; fflush ( stdin ) ; getchar ( ) ; fflush ( stdin ) ; #endif #elif ( ERROR_MODE & 63 ) == 3 fprintf( ERR_SM , #ifdef GET_CHE "or press q to quit\n" ) ; if ( ( GET_CH | 32 ) != 'q' ) return ; #else "or enter q to quit\n" ) ; fflush ( stdin ) ; if ( ( getchar ( ) | 32 ) != 'q' ) return ; #endif #elif ( ERROR_MODE & 63 ) == 4 fprintf( ERR_SM , "to quit\n" ) ; #ifdef GET_CH GET_CH ; #else fflush ( stdin ) ; getchar ( ) ; fflush ( stdin ) ; #endif #endif #endif #if ( ERROR_MODE & 7 ) > 2 fprintf( ERR_SM , "process inactive\n" ) ; #ifdef ICLOSE ICLOSE ; #endif exit ERR_EX ; #endif } #endif #ifdef USE_HEAP #ifndef BN_TAKE_GOT #define BN_TAKE_GOT /** take heap argument i of j bytes, return to pointer */ void * bn_h ( int i , int j ) { void * z ; if ( ( z = ( void * ) calloc ( i , j ) ) == NULL ) { fprintf( ERR_SM , "\tno heap memory left\n" ) ; #ifdef ICLOSE ICLOSE ; #endif exit ERR_EX ; } return ( z ) ; } #endif #endif #endif