2037 lines
66 KiB
C
2037 lines
66 KiB
C
|
#include "big.h"
|
||
|
#include <string.h>
|
||
|
|
||
|
#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
|
||
|
|