2 ##########################################################################
7 # IeeeCC754 or IEEE 754 Compliance Checker is a precision and range #
8 # independent tool to test whether an implementation of #
9 # floating-point arithmetic (in hardware or software) is compliant #
10 # with the principles of the IEEE 754-854 floating-point standards. #
11 # You can find out more about the testing tool IeeeCC754 at #
13 # http://win-www.uia.ac.be/u/cant/ieeecc754.html #
15 # This tool is in parts based on and greatly benefited from the #
16 # the program FPTEST developed by Jerome Coonen. For a full #
17 # description of the extensions to FPTEST and a reference to #
18 # the original Coonen program, please refer to the URL given above. #
19 # For the options available with the program IeeeCC754 and its #
20 # compatibility with David Hough's hexadecimal UCB format, we #
21 # also refer to the file readme.usage. #
23 # Usage: see readme.usage #
25 # Responsible authors: #
30 # Tarun Agarwal(05-07/2002) #
31 # Johan Bogo (1998-1999) #
32 # Tim Gevers (10-12/2000) #
33 # Debby Ooms (1996-1997) #
34 # Geert Vermuyten (1996-1997) #
35 # Dennis Verschaeren (09/1996-06/2000) #
37 # Copyright (C) 2000 University of Antwerp #
39 # This program can be obtained from the authors, free, but WITHOUT ANY #
40 # WARRANTY; without even the implied warranty of MERCHANTABILITY or #
41 # FITNESS FOR A PARTICULAR PURPOSE. #
44 # Brigitte.Verdonk@uia.ua.ac.be #
45 # Department of Mathematics and Computer Science #
46 # University of Antwerp (UIA) #
47 # Universiteitsplein 1 #
48 # B2610 Antwerp, BELGIUM #
50 ##########################################################################
66 #include <strstream.h>
69 #include <Bitstring.h>
80 #include <DriverFloatRepr.h>
81 template<class M> class UCB;
82 UCB<DriverFloatRepr> ucb;
84 #define TD_OVERFLOW 0x08
85 #define TD_UNDERFLOW 0x10
86 #define TD_UNDERFLOWV 0x40 // inexactness, no denormalization loss
87 #define TD_UNDERFLOWW 0x80 // tininess before rounding
89 #define TD_INVALID 0x01
90 #define TD_INEXACT 0x20
91 #define TD_DIVBYZERO 0x04
92 #define IEEEDEFAULTENV 0
94 #define TD_TONEAREST 0 // deze numberlen worden gebruikt // FP_RN
95 #define TD_UPWARD 2 // ipv de originele roundingnumberlen // FP_RP
96 #define TD_DOWNWARD 3 // zoals die voorkomen in "ieeefp.h" // FP_RM
97 #define TD_TOWARDZERO 1 // voor compatibiliteit met de UCB // FP_RZ
98 // outputfile qua volgorde van
100 #define ALL_FORMATS 3
104 #define NO_FLAGS_INEXACT 16
105 #define NO_FLAGS_OVERFLOW 8
106 #define NO_FLAGS_UNDERFLOW 4
107 #define NO_FLAGS_INVALID 2
108 #define NO_FLAGS_DIV_BY_ZERO 1
110 #define ROUND_NEAREST 8
114 #define ALL_MODES ((1<<TD_TONEAREST) | (1<<TD_DOWNWARD) | (1<<TD_UPWARD) | (1<<TD_TOWARDZERO))
115 #define NO_OF_BITS 32
116 #define USAGE "Error in calling " << argv[0] <<endl<<\
117 "For instructions on calling the program, see the readme.usage file."<<endl\
120 int cant_infinity=0 , small_norm=0;
129 unsigned long hidden;
131 unsigned long length;
133 unsigned long sign_exp_length;
134 unsigned long kl_biased_exp;
135 unsigned long sign_exp_rest ;
136 FILE *input=NULL, *output=NULL;
137 unsigned long readings;
138 unsigned long sexpon;
139 unsigned long dexpon;
140 unsigned long smant=0;
141 unsigned long dmant=0;
142 unsigned long shidden;
143 unsigned long dhidden;
144 unsigned long slength;
146 unsigned long dlength;
148 unsigned long ssign_exp_length; // sign+exponent length(in multiples of NO_OF_BITS)
149 unsigned long ssign_exp_rest;
150 unsigned long dsign_exp_length;
151 unsigned long dsign_exp_rest;
152 unsigned long skl_biased_exp;
153 unsigned long dkl_biased_exp;
154 unsigned long testFormats;
155 unsigned long testModes;
156 unsigned long flushVector;
157 unsigned long killerVector;
158 unsigned long *operand1, *operand2, *result;
159 long xcp, dots, wrong_input, lines_in, err_form;
160 char dot, opcode, op2code, op3code, op4code;
162 int CmndLinePos=1, def=0, defe = 0,deft=0,falt =0;
166 int Round =ROUND_ALL;
174 int skipVector=0,jumpOverflow=0,jumpUnderflow=0,jumpInvalid=0,jumpDivZero=0;
175 int pre = 0, post = 0; // to accomodate '?' before or after a result
181 char *decimal = new char[ maxstr ];
182 char *updecimal = new char[ maxstr ];
183 char *logfilename = "ieee.log";
186 void ParseArgs( int, char** );
187 void ParsecaseO( int argc, char** argv);
189 void ParsecaseD( int argc, char** argv);
193 void ParsecaseE( int argc, char** argv);
194 void ParsecaseT( int argc, char** argv);
195 void ParsecaseR( int argc, char** argv);
196 void ParsecaseN( int argc, char** argv);
197 void ParsecaseJ( int argc, char** argv);
199 void PostParseAction( int argc, char** argv );
200 void readParam( unsigned long & );
202 void Calc_General_Stuff( );
205 void getExceptions( );
206 unsigned long getinteger();
207 unsigned long getHex();
208 void getNumber( unsigned long *number);
209 void getbinary( unsigned long *number);
211 void getFPsig(unsigned long *number);
212 void getFPexp(unsigned long *number);
213 void getBbias(unsigned long *number);
214 void getBsignificant(unsigned long *number);
215 long int getBexpon();
216 void getDsignificand();
219 int FindNextSpace( string pstring , int beginpos, int occurance );
221 void writeUCBopcode(ostrstream &stream);
222 void writeUCBprecision(ostrstream &stream);
223 void writeUCBround(int m,ostrstream &stream);
224 void writeUCBexcep(ostrstream &stream);
225 void writeUCBoperand(ostrstream &stream);
226 void writeUCBresult(int m,ostrstream &stream);
227 void writeUCBcomutative(ostrstream &stream);
228 void writeUCBresultBin (int m, ostrstream &stream);
229 void writeUCBresultDec (int m, ostrstream &stream);
230 void writeUCBresultNum (ostrstream &stream);
231 void getFPInteger( unsigned long *number);
232 void Infinity( unsigned long *number);
233 void Quiet_NaN( unsigned long *number);
234 void Signaling_NaN( unsigned long *number);
235 void Smallest_Norm( unsigned long *number);
236 void ModifierPorM(unsigned long *number,int McasePorM);
237 void getModifier(unsigned long *number);
238 void ModifierIorD(unsigned long *number,int McaseIorD);
239 void getFPRootNumber( unsigned long *number);
242 void initialize_values(int source);
243 unsigned long null_exp( const unsigned long *number);
244 unsigned long one_exp( const unsigned long *number);
245 void Plus( unsigned long *number, unsigned long k);
246 void PlusBias( unsigned long *number);
247 void Minus( unsigned long *number, unsigned long k);
248 void MinusBias( unsigned long *number);
249 void PlusBk( unsigned long *number, unsigned long k );
250 void MinusBk( unsigned long *number, unsigned long k);
251 void Incr_at_pos( unsigned long *number, unsigned long pos, unsigned long k);
252 void Incr( unsigned long *number, unsigned long k);
253 void Decr_at_pos (long unsigned int *, long unsigned int, long unsigned int);
254 void Decr( unsigned long *number, unsigned long k);
255 void ModifierU( unsigned long *number, unsigned long ulps);
256 char* WriteNumber( const unsigned long *, unsigned long, unsigned long,unsigned long, unsigned long, const int );
259 void myungetc( int, FILE* );
263 /*-----------------------------------------------------------------------------
265 description :this is the Ieee compliance checker for floating point
266 implementation according to IEEE754-854 specifications.
268 call fns :ParseArgs(),Calc_General_Stuff(),readAline(),putdot(),ucb.close()
272 -----------------------------------------------------------------------------*/
275 int main( int argc,char * argv[ ] )
278 readings=dots=wrong_input=lines_in=err_form=0;
281 ParseArgs( argc, argv ); /* to parse arguments in the executing statement*/
290 Calc_General_Stuff( );
292 operand1 = new unsigned long[ slength ];
293 if ( operand1 == NULL )
295 printf( "\nNot enough memory!\n" );
296 printf( "Program aborted.\n" );
299 exit( EXIT_SUCCESS );
302 operand2 = new unsigned long[ slength ];
303 if ( operand2 == NULL )
305 printf( "\nNot enough memory\n" );
306 printf( "Program aborted.\n" );
310 exit( EXIT_SUCCESS );
313 result = new unsigned long[ dlength ];
315 if ( result == NULL )
317 printf( "\nNot enough memory\n" );
318 printf( "Program aborted.\n" );
323 exit( EXIT_SUCCESS );
328 while ( readAline( ) )
335 printf( "\n\nCounting %ld lines.\n", readings );
350 /*-----------------------------------------------------------------------------
352 description :parse the command line arguments to get the precision and
355 call fns :ParsecaseO/S/D/L/Q/M/E/T/R/N/J/H , PostParseAction
356 Global var. used :check, def,defe,deft,flat,ucbInput
357 -----------------------------------------------------------------------------*/
358 void ParseArgs( int argc, char** argv )
365 while ( CmndLinePos < argc )
367 if ( ( strlen( argv[ CmndLinePos ] ) <= 3 ) && ( argv[CmndLinePos][ 0 ] == '-' ) )
369 switch ( argv[CmndLinePos][ 1 ] )
371 case 'c': //coonen format
378 case 'u': //ucb format (precisely one of
379 // -c | -u |-o should be there)
386 case 'o': //change coonen to ucb format
387 ParsecaseO(argc,argv);
391 case 's': //single precision
394 case 'd': //if -d then double presion
395 ParsecaseD(argc,argv); // else specifications for destination
397 case 'l': //long double precision
400 case 'q': //quadruple precision
403 case 'm': //multi precision
406 case 'e': //specify no. of bits for exponent
407 ParsecaseE(argc,argv);
409 case 't': //specify <int> bits precision
410 ParsecaseT(argc,argv);
413 case 'r': //specify rounding modes
414 ParsecaseR(argc,argv);
417 case 'i': //test conversions within range specified by ieee
421 case 'n': //do not test specified exceptions, infinity,...
422 ParsecaseN(argc,argv);
425 case 'j': //jump/skip test vectors raising overflow, ...
426 ParsecaseJ(argc,argv);
429 case 'h': //specify if hidden bit
433 case 'f': // name of log file
435 logfilename = argv[CmndLinePos];
444 if ( CmndLinePos == argc-1 ) //check if test vector file exists
446 input = fopen( argv[CmndLinePos], "r" );
449 printf( "ERROR: can't open %s.\n",argv[CmndLinePos] );
452 printf( "Taking input from %s.\n",argv[CmndLinePos] );
467 if ( ( dmant == 0 ) || ( dexpon == 0 ) ) //if destination precision still has initial
468 { //values then equate them to that of source.
469 dmant = smant; //(could be changed only for conversions)
475 PostParseAction(argc,argv);
482 /*-----------------------------------------------------------------------------
484 description :change coonen to ucb format
485 called from :ParseArgs()
487 Global var. used :check,CmndLinePos,falt
488 -----------------------------------------------------------------------------*/
489 void ParsecaseO( int argc, char** argv)
493 if ( ++CmndLinePos != argc )
495 if ( argv[CmndLinePos][ 0 ] != '-' )
497 output = fopen( argv[CmndLinePos], "w" );
498 if ( output == NULL )
500 printf( "ERROR: can't create %s.\n",argv[CmndLinePos] );
503 printf( "Output sent to %s.\n",argv[CmndLinePos] );
514 /*-----------------------------------------------------------------------------
516 description :specify single precision
517 called from :ParseArgs()
519 Global var. used :sexpon,smant,shidden,def,falt
520 -----------------------------------------------------------------------------*/
534 /*-----------------------------------------------------------------------------
536 description :default is for double precision else it gets precision
537 specifications for the destination (only used in conversions)
538 called from :ParseArgs()
540 Global var. used :CmndLinePos,falt
541 -----------------------------------------------------------------------------*/
542 void ParsecaseD( int argc, char** argv)
544 switch ( argv[CmndLinePos][ 2 ] )
551 if ( ++CmndLinePos != argc )
553 dexpon = atoi( argv[CmndLinePos] );
556 cout << "Error: not a number or zero" << endl;
562 if ( ++CmndLinePos != argc )
564 dmant = dmant + atoi( argv[CmndLinePos] );
566 cout << "Error: not a number or zero" << endl;
608 /*-----------------------------------------------------------------------------
610 description :long doulbe precision
611 called from :ParseArgs()
614 -----------------------------------------------------------------------------*/
628 /*-----------------------------------------------------------------------------
630 description :quadruple precision
631 called from :ParseArgs()
634 -----------------------------------------------------------------------------*/
648 /*-----------------------------------------------------------------------------
650 description :Multi precision
651 called from :ParseArgs()
654 -----------------------------------------------------------------------------*/
668 /*-----------------------------------------------------------------------------
670 description :specify no. of bits for exponent
671 called from :ParseArgs()
673 Global var. used :CmndLinePos,falt
674 -----------------------------------------------------------------------------*/
675 void ParsecaseE( int argc, char** argv)
679 if ( ++CmndLinePos != argc )
681 sexpon = atoi( argv[CmndLinePos] );
684 cout << "Error: not a number or zero" << endl;
695 /*-----------------------------------------------------------------------------
697 description :specify <int> bits precision
698 called from :ParseArgs()
700 Global var. used :CmndLinePos,falt
701 -----------------------------------------------------------------------------*/
702 void ParsecaseT( int argc, char** argv)
706 if ( ++CmndLinePos != argc )
708 smant = smant + atoi( argv[CmndLinePos] );
711 cout << "Error: not a number or zero" << endl;
722 /*-----------------------------------------------------------------------------
724 description :specify rounding modes
725 called from :ParseArgs()
728 -----------------------------------------------------------------------------*/
729 void ParsecaseR( int argc, char** argv)
733 if ( ++CmndLinePos != argc )
735 if ( ( argv[CmndLinePos][ 0 ] != '-' ) && ( CmndLinePos != argc -1 ) )
738 while ( argv[CmndLinePos][ j ] != '\0' )
740 switch( argv[CmndLinePos][ j ] )
743 Round |= ROUND_NEAREST;
760 Round = ROUND_ALL; // Test all
768 /*-----------------------------------------------------------------------------
770 description :do not test specified exceptions, denormalized nos., NaNs,
771 signed infinty, signed zeros
772 called from :ParseArgs()
775 -----------------------------------------------------------------------------*/
776 void ParsecaseN( int argc, char** argv)
779 if ( ++CmndLinePos != argc )
781 if ( ( argv[CmndLinePos][ 0 ] != '-' ) && ( CmndLinePos != argc -1 ) )
784 while ( argv[CmndLinePos][ j ] != '\0' )
786 switch( argv[CmndLinePos][ j ] )
790 noFlags |= NO_FLAGS_INVALID;
794 noFlags |= NO_FLAGS_OVERFLOW ;
797 noFlags |= NO_FLAGS_INEXACT;
800 noFlags |= NO_FLAGS_DIV_BY_ZERO;
803 noFlags |= NO_FLAGS_UNDERFLOW;
806 if ( ( argv[CmndLinePos][ j+1 ] == 'i' ) &&
807 ( argv[CmndLinePos][ j+2 ] == 'n' ) &&
808 ( argv[CmndLinePos][ j+3 ] == 'y' ) )
816 if ( ( argv[CmndLinePos][ j+1 ] == 'n' ) &&
817 ( argv[CmndLinePos][ j+2 ] == 'f' ) ) {
822 noFlags |= NO_FLAGS_INVALID;
826 if ( ( argv[CmndLinePos][ j+1 ] == 'a' ) &&
827 ( argv[CmndLinePos][ j+2 ] == 'n' ) )
835 if ( ( argv[CmndLinePos][ j+1 ] == 'n' ) &&
836 ( argv[CmndLinePos][ j+2 ] == 'z' ) )
849 noFlags = NO_FLAGS; //Test no flags (all values selected)
857 /*-----------------------------------------------------------------------------
859 description :jump/skip test vectors raising overflow, underflow, invalid or
860 divide by zero exception
861 called from :ParseArgs()
864 -----------------------------------------------------------------------------*/
865 void ParsecaseJ( int argc, char** argv)
868 if ( ++CmndLinePos != argc )
870 if ( ( argv[CmndLinePos][ 0 ] != '-' ) && ( CmndLinePos != argc -1 ) )
873 while ( argv[CmndLinePos][ j ] != '\0' )
875 switch( argv[CmndLinePos][ j ] ) {
900 /*-----------------------------------------------------------------------------
902 description :specify if hidden bit
903 called from :ParseArgs()
906 -----------------------------------------------------------------------------*/
919 /*-----------------------------------------------------------------------------
920 name :PostParseAction()
921 description :if change to ucb then calls required fns,
922 else check for errors and opens log file.
923 called from :ParseArgs()
924 call fns :ucb.OpenLogFile(),ucb.ReadLine(),ucb.DoLine(),ucb.Close
925 Global var. used :check, def,defe,deft,flat,ucbInput
926 -----------------------------------------------------------------------------*/
927 void PostParseAction( int argc, char** argv )
931 { // check float formats
932 if ( ( sexpon > 32 ) || ( dexpon> 32 ) )
934 cout << "Exit: exponent size too big (> 32)" << endl;
936 } else if ( ( smant+shidden <24 ) || ( dmant+dhidden <24 ) || ( sexpon < 8 ) || ( dexpon < 8 ) )
938 cout << "Exit: floating-point format too small" << endl;
940 } else if ( ( smant + shidden < sexpon ) || ( dmant + dhidden < dexpon ) )
942 cout << "Exit: Precision t must at least equal exponent size" << endl;
944 } else if ( ( smant + shidden > ((unsigned long)1 << (sexpon-1))) || ( dmant + dhidden > ((unsigned long)1 << (dexpon-1)) ) )
946 cout << "Exit: Precision t > Bias + 1 = 2^(e-1)" << endl;
951 if ( ( !def ) & ( !deft | !defe ) )
959 ucb.OpenLogFile( logfilename,argc,argv );
966 ucb.OpenInput( argv[ argc-1 ] );
967 while ( ucb.ReadLine( NULL,signedZero, noFlags ) )
969 ucb.DoLine( tiny,inf,NaN );
977 if ( ( input == NULL ) | ( ( output == NULL ) & ( check == -1 ) ) )
980 cout << "Error: No input \n";
982 cout << "Error: No output\n";
991 /*-----------------------------------------------------------------------------
992 name :Calc_General_Stuff()
993 description :calculates the sizes of arrays to store numbers according to the
994 precision specifications in the command line
999 Global var. used :slength,srest,sexpon,smant,delength,drest,dexpon,dmant,
1000 ssign_exp_length,ssign_exp_rest,skl_biased_exp,dkl_biased_exp,
1001 dsign_exp_length,dsign_exp_rest.
1002 -----------------------------------------------------------------------------*/
1004 void Calc_General_Stuff( )
1006 //to calculate length of arrays used
1007 // change BV 17/01/01
1009 /* comments regarding the calculated variables
1010 s for source , d for destination.
1011 slength ---- length of FP format in multiples of <no. of bits>
1012 srest ---- no. of bits required for FP format in
1013 the last of these allocated array elemnt
1014 ssign_exp_length ---number of array elements to
1015 represent all the bits in exponent + sign bit
1016 ssign_exp_rest --- no. of bits required for sign + exponent in
1017 the last of these allocated array elemnt - 1
1018 NO_OF_BITS--- number of bits in array element
1021 slength = ( unsigned long ) ceil( ( sexpon+smant+1 ) /float(NO_OF_BITS));
1022 srest = ( sexpon+smant+1 ) % NO_OF_BITS;
1024 dlength = ( unsigned long ) ceil( ( dexpon+dmant+1 ) /float(NO_OF_BITS));
1025 drest = ( dexpon+dmant+1 ) % NO_OF_BITS;
1027 ssign_exp_length = ( sexpon/NO_OF_BITS ) + 1;
1028 ssign_exp_rest = sexpon % NO_OF_BITS;
1030 dsign_exp_length = ( dexpon/NO_OF_BITS ) + 1;
1031 dsign_exp_rest = dexpon % NO_OF_BITS;
1033 skl_biased_exp = 1L << ( NO_OF_BITS-ssign_exp_rest-1 );
1034 dkl_biased_exp = 1L << ( NO_OF_BITS-dsign_exp_rest-1 );
1042 /*-----------------------------------------------------------------------------
1044 description :reads a test vector from the file and checks if the test
1045 software/hardware is compatible with IEEE spcifications
1047 call fns :getbinary(),getNumber(),getdecimal()isspace(),mygetc(),myungetc(),
1048 getModes(),getException(),skipSpace(),WriteNumber(),
1049 initialize_values(),writeUCB().
1052 Global var. used :lots
1053 -----------------------------------------------------------------------------*/
1058 err1=0,err2=0,err3=0, isIeeeVector=0;
1062 int NaN1, NaN2, NaN3;
1068 NaN1 = NaN2 = NaN3 = 0;
1070 while ( ( ( c = mygetc( input ) ) == '!' ) || ( c == '\n' ) || ( c == ' ' ) )
1073 /* Skip rest of comment line. */
1074 while ( ( c = mygetc( input ) ) != '\n' )
1083 opcode = mygetc( input ); // 2nd character is the first character of the opcode
1084 op2code=op3code = op4code = ' ';
1086 c = mygetc( input );
1088 if ( !isspace( c ) )
1092 // seek further opcode bytes
1093 while ( !isspace( c ) ) c = mygetc( input ); // and throw them away because we only need first char
1096 // Get the precision specifications
1097 while ( isspace( c ) ) c= mygetc( input );
1115 testFormats= TESTEVEN;
1118 testFormats= TESTODD;
1121 op3code='z'; // op3code z-> no precisions specification
1122 myungetc( c, input); // put the current char back because it does not belong to precision specs
1125 // check if test-vector precision specs correspond with command-line provided precision specs
1126 if ( op3code !='z' && op3code !='e' && op3code!='o' )
1128 if ( ( (sexpon==8) && ( (shidden+smant) ==24 ) && (op3code != 's') ) ||
1129 ( ( ( (sexpon!=8) || (shidden+smant)!=24 ) ) && (op3code == 's') ) ||
1130 ( ( sexpon==11 ) && ( (shidden+smant)==53) && (op3code != 'd') ) ||
1131 ( ( (sexpon!=11) || ( (shidden+smant)!=53) ) && (op3code == 'd') ) ||
1132 ( ( sexpon==15 ) && ((shidden+smant)==64 ) && ( op3code != 'l' ) ) ||
1133 ( ( ( sexpon!=15 ) || ((shidden+smant)!=64 ) ) && ( op3code == 'l' ) ) ||
1134 ( ( sexpon==15 ) && ((shidden+smant)==113 ) && ( op3code != 'q' ) ) ||
1135 ( ( ( sexpon!=15 ) || ((shidden+smant)!=113 ) ) && ( op3code == 'q' ) ) ||
1136 ( ( sexpon==15 ) && ((shidden+smant)==240 ) && ( op3code != 'm' ) ) ||
1137 ( ( ( sexpon!=15 ) || ((shidden+smant)!=240 ) ) && ( op3code == 'm' ) ) ) {
1138 while ( ( c = mygetc( input ) ) != '\n' ) /* Skip rest of line. */
1140 return 1; // precision dependent test vectors
1143 c = mygetc( input );
1144 if ( op3code !='z' && op3code !='e' && op3code!='o' )
1150 while ( !isspace( c ) ) c= mygetc( input ); // read the eee and throw it away!
1155 myungetc( c, input);
1160 if ( opcode == 'b' )
1162 source=1; //for source
1163 initialize_values(source);
1164 getbinary(operand1);
1165 for ( long i=0; i<slength;i++ ) // init operand2
1167 } else if ( opcode == 'd' ) {
1169 for ( long i=0; i<slength;i++ ) // init operand2
1173 source=1; //for source
1174 initialize_values(source);
1175 getNumber(operand1);
1184 source=1; //for source
1185 initialize_values(source);
1186 getNumber(operand2);
1199 if ( opcode == 'b' )
1203 else if ( opcode == 'd' )
1205 source=1; //for source
1206 initialize_values(source);
1211 source=0; //for destination
1212 initialize_values(source);
1219 if ( opcode != 'C' )
1224 printf( "\nWrong input on line %ld\n",lines_in+readings+1 );
1226 c = mygetc( input );
1231 /*-----------------------------------------------------------------------------
1233 description :writes the test vector in UCB fromat
1234 called from :readAline()
1235 calls fns :writeUCBopcode(),writeUCBprecision(),writeUCBround(),
1236 writeUCBexcep(),writeUCBoperand,writeUCBresult()
1237 writeUCBcomutaitive()
1239 -----------------------------------------------------------------------------*/
1243 if ( ( ( ( smant + shidden ) % 2 == 0 ) && ( testFormats == TESTEVEN ) ) |
1244 ( ( ( smant + shidden ) % 2 != 0 ) && ( testFormats == TESTODD ) ) |
1245 ( testFormats == ALL_FORMATS ) )
1251 if ( ( testModes >> m ) & 0x1 )
1253 writeUCBopcode(stream);
1254 writeUCBprecision(stream);
1255 writeUCBround(m,stream);
1256 writeUCBexcep(stream);
1257 writeUCBoperand(stream);
1258 writeUCBresult(m,stream);
1260 writeUCBcomutative(stream);
1263 if ( intstr != NULL )
1273 /*-----------------------------------------------------------------------------
1274 name :writeUCBopcode()
1275 description :writes opcode of testvector in the UCB format
1276 called from :writeUCB
1279 -----------------------------------------------------------------------------*/
1280 void writeUCBopcode(ostrstream &stream)
1306 switch ( op2code ) {
1325 switch ( op2code ) {
1353 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
1354 printf( "\nERROR: unrecognizable operation: %c\n", opcode );
1355 printf( "\n\nDone with %ld readings.\n", readings );
1356 exit( EXIT_SUCCESS );
1361 /*-----------------------------------------------------------------------------
1362 name :writeUCBprecision()
1363 description :writes precision of testvector in the UCB format
1364 called from :writeUCB
1367 -----------------------------------------------------------------------------*/
1368 void writeUCBprecision(ostrstream &stream)
1370 if ( ( shidden ) && ( sexpon==8 ) && ( smant==23 ) )
1371 if ( !isIeeeVector )
1375 else if ( ( shidden ) && ( sexpon==11 ) && ( smant==52 ) )
1376 if ( !isIeeeVector )
1380 else if ( !( shidden ) && ( sexpon==15 ) && ( smant==64 ) )
1381 if ( !isIeeeVector )
1385 else if ( ( shidden ) && ( sexpon==15 ) && ( smant==112 ) )
1386 if ( !isIeeeVector )
1390 else if ( !( shidden ) && ( sexpon==15 ) && ( smant==240 ) )
1391 if ( !isIeeeVector )
1396 stream << sexpon << " "<< shidden <<" "<< smant <<" " ;
1399 if ( ( ( opcode == 'r' ) || ( opcode == 'c' ) ) && ( op2code == ' ' ) )
1400 if ( ( dhidden ) && ( dexpon==8 ) && ( dmant==23 ) )
1402 else if ( ( dhidden ) && ( dexpon==11 ) && ( dmant==52 ) )
1404 else if ( !( dhidden ) && ( dexpon==15 ) && ( dmant==64 ) )
1406 else if ( ( dhidden ) && ( dexpon==15 ) && ( dmant==112 ) )
1408 else if ( !( dhidden ) && ( dexpon==15 ) && ( dmant==240 ) )
1411 stream << dexpon << " "<< dhidden <<" "<< dmant <<" " ;
1416 /*-----------------------------------------------------------------------------
1418 description :writes rounding mode of the test vector in the UCB format
1419 called from :writeUCB
1422 -----------------------------------------------------------------------------*/
1423 void writeUCBround(int m,ostrstream &stream)
1442 /*-----------------------------------------------------------------------------
1443 name :writeUCBexcep()
1444 description :writes exceptions of the testvector in the UCB format
1448 -----------------------------------------------------------------------------*/
1449 void writeUCBexcep(ostrstream &stream)
1451 if ( !killerVector )
1458 if ( xcp & long( TD_INVALID ) )
1460 if ( xcp & long( TD_INEXACT ) )
1462 if ( xcp & long( TD_OVERFLOW ) )
1464 if ( xcp & long( TD_UNDERFLOW ) )
1466 if ( xcp & long( TD_UNDERFLOWV ) )
1468 if ( xcp & long( TD_UNDERFLOWW ) )
1470 if ( xcp & long( TD_DIVBYZERO ) )
1475 /*-----------------------------------------------------------------------------
1476 name :writeUCBoperand()
1477 description :writes operannds or source for the operation in UCB format
1478 called from :writeUCB
1481 -----------------------------------------------------------------------------*/
1482 void writeUCBoperand(ostrstream &stream)
1485 if ( ( intstr != NULL ) && ( opcode == 'c' ) )
1493 tmp = WriteNumber( operand2,sexpon,shidden,smant,slength,err1 );
1505 if ( opcode == 'd' )
1511 tmp = WriteNumber( operand1,sexpon,shidden,smant,slength,err1 );
1520 tmp = WriteNumber( operand2,sexpon,shidden,smant,slength,err1 );
1527 /*-----------------------------------------------------------------------------
1528 name :writeUCBresult()
1529 description :writes result or destination of the operation in UCB format
1530 called from :writeUCB
1531 calls fns :writeUCBresultBin(),writeUCBresultDec(),writeUCBresultNum()
1533 -----------------------------------------------------------------------------*/
1534 void writeUCBresult(int m,ostrstream &stream)
1536 if ( ( intstr != NULL ) && ( opcode == 'r' ) )
1544 } else if ( opcode == 'b' )
1546 writeUCBresultBin(m,stream);
1547 }else if ( opcode == 'd' )
1549 writeUCBresultDec(m,stream);
1552 writeUCBresultNum(stream);
1557 /*-----------------------------------------------------------------------------
1558 name :writeUCBresultBin()
1559 description :round and write the destination for binary to decimal conversion
1560 called from :writeUCBresult()
1563 -----------------------------------------------------------------------------*/
1564 void writeUCBresultBin(int m,ostrstream &stream)
1566 // check rounding mode
1570 switch ( nextdig ) {
1579 stream << updecimal;
1587 if ( mysignbit ) // negative
1590 stream << updecimal;
1594 stream << updecimal;
1603 /*-----------------------------------------------------------------------------
1604 name :writeUCBresultDec()
1605 description :writes deatination for decimal to binary conversion
1606 called from :writeUCBresult()
1609 -----------------------------------------------------------------------------*/
1610 void writeUCBresultDec(int m,ostrstream &stream)
1614 // check rounding mode
1623 for ( long i = 0; i < dlength; i++ )
1624 operand1[ i ] = result[ i ];
1628 source=0; //for destination
1629 initialize_values(source);
1634 switch ( nextdig ) {
1637 tmp = WriteNumber( result,dexpon,dhidden,dmant,dlength,err3 );
1642 tmp = WriteNumber( operand1,dexpon,dhidden,dmant,dlength,err3 );
1649 tmp = WriteNumber( result,dexpon,dhidden,dmant,dlength,err3 );
1656 tmp = WriteNumber( result,dexpon,dhidden,dmant,dlength,err3 );
1661 tmp = WriteNumber( operand1,dexpon,dhidden,dmant,dlength,err3 );
1669 tmp = WriteNumber( operand1,dexpon,dhidden,dmant,dlength,err3 );
1674 tmp = WriteNumber( result,dexpon,dhidden,dmant,dlength,err3 );
1686 /*-----------------------------------------------------------------------------
1687 name :writeUCBresultNum()
1688 description :writes desination for operations other than b2d and d2b
1689 called from :writeUCBresult()
1692 -----------------------------------------------------------------------------*/
1693 void writeUCBresultNum(ostrstream &stream)
1702 tmp = WriteNumber( result,dexpon,dhidden,dmant,dlength,err3 );
1710 /*-----------------------------------------------------------------------------
1711 name :writeUCBcomutative()
1712 description :if + or * then writes test vector to check comutativity and
1713 calls functions to check the test vectors generated
1714 called from :writeUCB
1715 calls fns :ucb.ReadLine(),ucb.DoLine()
1717 -----------------------------------------------------------------------------*/
1718 void writeUCBcomutative(ostrstream &stream)
1720 char* outputStream = stream.str( );
1721 string outputStream2;
1724 if ( opcode=='+' || opcode=='*' )
1726 // if the operation is add or mult we have to
1727 // generate second line with operands switched places
1728 // in order to check correctness with concern to
1729 // commutativity law.
1732 outputStream2 = string( stream.str( ) );
1734 switch (outputStream2[3])
1737 i= FindNextSpace( outputStream2,10,1 );
1738 j= FindNextSpace( outputStream2,i+1,1 );
1739 op1= outputStream2.substr( i+1,j-i );
1740 k= FindNextSpace( outputStream2, j+1,1 );
1741 op2= outputStream2.substr( j+1,k-j );
1742 outputStream2.replace( i+1,op2.length( ),op2 );
1743 outputStream2.replace( i+1+op2.length( ),op1.length( ),op1 );
1747 i= FindNextSpace( outputStream2,10,1 );
1748 j= FindNextSpace( outputStream2,i+1,2 );
1749 op1= outputStream2.substr( i+1,j-i );
1750 k= FindNextSpace( outputStream2, j+1,2 );
1751 op2= outputStream2.substr( j+1,k-j );
1752 outputStream2.replace( i+1,op2.length( ),op2 );
1753 outputStream2.replace( i+1+op2.length( ),op1.length( ),op1 );
1757 i= FindNextSpace( outputStream2,10,1 );
1758 j= FindNextSpace( outputStream2,i+1,4 );
1759 op1= outputStream2.substr( i+1,j-i );
1760 k= FindNextSpace( outputStream2, j+1,4 );
1761 op2= outputStream2.substr( j+1,k-j );
1762 outputStream2.replace( i+1,op2.length( ),op2 );
1763 outputStream2.replace( i+1+op2.length( ),op1.length( ),op1 );
1767 i= FindNextSpace( outputStream2,10,1 );
1768 j= FindNextSpace( outputStream2,i+1,3 );
1769 op1= outputStream2.substr( i+1,j-i );
1770 k= FindNextSpace( outputStream2, j+1,3 );
1771 op2= outputStream2.substr( j+1,k-j );
1772 outputStream2.replace( i+1,op2.length( ),op2 );
1773 outputStream2.replace( i+1+op2.length( ),op1.length( ),op1 );
1777 i= FindNextSpace( outputStream2,10,1 );
1778 j= FindNextSpace( outputStream2,i+1,8 );
1779 op1= outputStream2.substr( i+1,j-i );
1780 k= FindNextSpace( outputStream2, j+1,8 );
1781 op2= outputStream2.substr( j+1,k-j );
1782 outputStream2.replace( i+1,op2.length( ),op2 );
1783 outputStream2.replace( i+1+op2.length( ),op1.length( ),op1 );
1786 // mantsize and expsize were given explicitly
1788 int opLength=smant+sexpon+1;
1791 // Calculate operand length as multiple of 32
1792 opLength= ( opLength/32 ) *32 + ( !( !( opLength%32 ) ) ) * 32;
1794 // Calculate nr of 32 bit blocks for operand
1797 // grep operand 1 out of the outputstream
1798 i= FindNextSpace( outputStream2,0,6 ); // find 6th space
1799 j= FindNextSpace( outputStream2,i+1,blocks );
1800 op1= outputStream2.substr( i+1,j-i );
1802 // grep operand 2 out of the outputstream
1803 k= FindNextSpace( outputStream2, j+1, blocks );
1804 op2= outputStream2.substr( j+1,k-j );
1806 // switch operand1 and operand2
1807 outputStream2.replace( i+1,op2.length( ),op2 );
1808 outputStream2.replace( i+1+op2.length( ),op1.length( ),op1 );
1813 if ( check == 0 && !skipVector )
1815 fprintf( output,outputStream );
1816 if ( opcode=='+' || opcode=='*' )
1818 if ( !( op1==op2 ) )
1820 // generate line with operands switched to test commutivity
1821 fprintf( output,outputStream2.c_str( ) );
1828 int tempLines=( int ) lines_in+readings+1;
1830 ucb.ReadLine( outputStream,signedZero,noFlags,&tempLines );
1831 ucb.DoLine( tiny,inf,NaN );
1833 if ( opcode=='+' || opcode=='*' )
1835 if ( !( op1==op2 ) )
1837 // generate line with operands switched to test commutivity
1838 ucb.ReadLine( ( char* ) outputStream2.c_str( ), signedZero, noFlags, &tempLines );
1839 ucb.DoLine( tiny,inf,NaN);
1844 delete [ ] outputStream;
1851 /*-----------------------------------------------------------------------------
1853 description :Slam a dot out to show some life
1854 called from :readAline()
1859 -----------------------------------------------------------------------------*/
1864 cout << '.' << flush;
1877 /*-----------------------------------------------------------------------------
1878 name :FindNextSpace()
1879 description :to find location to stream with proper spaces
1880 called from :readAline()
1885 -----------------------------------------------------------------------------*/
1887 int FindNextSpace( string pstring , int beginpos, int occurance )
1891 while ( i<pstring.length( ) )
1893 if ( pstring[ i ] ==' ' )
1906 /*-----------------------------------------------------------------------------
1908 description :avoid spaces while reading a vector
1909 called from :readAline()
1910 call fns :mygetc(),myungetc()
1914 -----------------------------------------------------------------------------*/
1918 while ( isspace( c = mygetc( input ) ) ) {
1923 myungetc( c, input );
1930 /*-----------------------------------------------------------------------------
1932 description :get rounding modes from the test vector
1933 called from :readAline()
1934 call fns :mygetc(),myungetc()
1937 Global var. used :round,testmodes,flushVector
1938 -----------------------------------------------------------------------------*/
1943 testModes = flushVector = 0;
1944 while ( !isspace( c = mygetc( input ) ) )
1946 case 'A': // all rounding modes
1947 c = mygetc( input ); /* skip 'LL' */
1949 if ( Round & ROUND_ZERO )
1950 testModes |= ( 1 << TD_TOWARDZERO );
1951 if ( Round & ROUND_NEAREST )
1952 testModes |= ( 1 << TD_TONEAREST );
1953 if ( Round & ROUND_DOWN )
1954 testModes |= ( 1 << TD_DOWNWARD );
1955 if ( Round & ROUND_UP )
1956 testModes |= ( 1 << TD_UPWARD );
1957 c = mygetc( input );
1960 if ( Round & ROUND_ZERO )
1961 testModes |= ( 1 << TD_TOWARDZERO );
1964 if ( Round & ROUND_NEAREST )
1965 testModes |= ( 1 << TD_TONEAREST );
1968 if ( Round & ROUND_DOWN )
1969 testModes |= ( 1 << TD_DOWNWARD );
1972 if ( Round & ROUND_UP )
1973 testModes |= ( 1 << TD_UPWARD );
1976 testFormats = TESTODD;
1979 testFormats = TESTEVEN;
1982 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
1983 printf( "\nERROR: unrecognizable mode character: %c\n", c );
1984 printf( "\n\nDone with %ld readings.\n", readings );
1985 exit( EXIT_SUCCESS );
1988 myungetc( c, input );
1989 if ( testFormats == 0 )
1990 testFormats = ALL_FORMATS;
1994 /*-----------------------------------------------------------------------------
1995 name :initialize_values()
1996 description :assigns values to global variables for precision parsed
1997 from the command line.
1998 called from :readAline()
2002 Global var. used :expon,hidden,mant,length,rest,sign_exp_length,
2003 kl_biased_exp,exp_rest.
2004 -----------------------------------------------------------------------------*/
2005 void initialize_values( int source)
2014 sign_exp_length = ssign_exp_length;
2015 kl_biased_exp = skl_biased_exp;
2016 sign_exp_rest = ssign_exp_rest ;
2026 sign_exp_length = dsign_exp_length;
2027 kl_biased_exp = dkl_biased_exp;
2028 sign_exp_rest = dsign_exp_rest ;
2036 /*-----------------------------------------------------------------------------
2037 name :getExceptions()
2038 description :gets exceptions raised for the test vector
2039 called from :readAline()
2043 Global var. used :skipVector,jumpOverflow,jumpUnderflow,jumpInvalid,jumpDivZero
2044 -----------------------------------------------------------------------------*/
2045 void getExceptions( )
2050 while ( !isspace( c = mygetc( input ) ) ) {
2053 xcp |= ( long ) TD_INEXACT;
2056 * In the Metro case, checking tininess before rounding to detect
2057 * underflow means that all possible cases of underflow apply.
2058 * (By contrast, checking AFTER rounding lets some boundary cases
2059 * slip by, and checking for EXTRAORDINARY error due to subnormalization
2060 * lets some tiny cases through that happen to round the same in
2061 * spite of subnormalization.
2065 xcp |= ( long ) TD_UNDERFLOW;
2070 xcp |= ( long ) TD_UNDERFLOWV;
2075 xcp |= ( long ) TD_UNDERFLOWW;
2080 xcp |= ( long ) TD_OVERFLOW;
2085 xcp |= ( long ) TD_INVALID;
2090 xcp |= ( long ) TD_DIVBYZERO;
2095 c = mygetc( input );
2099 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2100 printf( "\nERROR: unrecognizable exception character: %c\n", c );
2101 printf( "\n\nDone with %ld readings.\n", readings );
2102 exit( EXIT_SUCCESS );
2106 myungetc( c, input );
2110 /*-----------------------------------------------------------------------------
2112 description :reads the binary coded number form the test set //ONLY FOR CONVERSIONS
2113 called from :readAline()
2114 call fns :mygetc(),myungetc(),skipSpaces()
2117 Global var. used :length,rest,sign_exp_length,exp_rest,pre,binary,upbinary,nextdig
2118 -----------------------------------------------------------------------------*/
2119 void getbinary( unsigned long *number)
2124 for ( i=0; i<length;i++ ) // init number
2127 mysignbit=getSign();
2129 getBsignificant(number);
2133 /* Stuff the sign nonarithmetically, to protect signaling NaNs. */
2135 number[ 0 ] |= 0x80000000L;
2139 /*-----------------------------------------------------------------------------
2140 name :getBsignificant()
2141 description :get significant of the binary number
2142 called from :getbinary()
2147 -----------------------------------------------------------------------------*/
2148 void getBsignificant(unsigned long *number)
2151 char c=mygetc(input);
2152 binary = new char[ maxstr ];
2155 while ( !isspace( c ) && ( c != '_' ) )
2158 c = mygetc( input );
2160 nextdig = 0; // exact
2163 if ( mygetc( input ) == '1' )
2166 if ( mygetc( input ) == '1' )
2171 while ( !isspace( c ) ) c = mygetc( input ); // skip tail
2174 // copy binary per 4 bits for each hex input character
2175 i--; // binary length (times 4 bits)
2178 while ( i - 7 >= 0 )
2180 if ( isdigit( binary[ i-7 ] ) )
2181 val = binary[ i-7 ] - '0';
2183 val = 0xa + ( binary[ i-7 ] - 'a' );
2185 for ( k = 6;k >= 0;k-- )
2188 if ( isdigit( binary[ i-k ] ) )
2189 val = binary[ i-k ] - '0';
2191 val = 0xa + ( binary[ i-k ] - 'a' );
2200 for ( k = 0;k < i;k++ )
2202 if ( isdigit( binary[ k ] ) )
2203 val = binary[ k ] - '0';
2205 val = 0xa + ( binary[ k ] - 'a' );
2210 if ( isdigit( binary[ k ] ) )
2211 val = binary[ k ] - '0';
2213 val = 0xa + ( binary[ k ] - 'a' );
2218 i = sign_exp_length - 1;
2219 for ( ; i<length-1;i++ )
2220 for ( j = 0;j < NO_OF_BITS - rest;j++ )
2223 if ( number[ i+1 ] & ( 1L << ( (NO_OF_BITS-1) - j ) ) )
2226 for ( j = 0;j < NO_OF_BITS - rest;j++ )
2230 if ( ( hidden ) && ( number[ 0 ] != 0 ) ) // remove leading bit, if not zero!
2232 if ( sign_exp_rest==(NO_OF_BITS-1) )
2233 number[ sign_exp_length ] -= ( 1L<<(NO_OF_BITS-1) );
2235 number[ sign_exp_length-1 ] -= ( 1L<<( NO_OF_BITS-sign_exp_rest-1 ) );
2240 /*-----------------------------------------------------------------------------
2242 description :gets bias for the binary number
2243 called from :getbinary()
2244 calls fns :getBexpon()
2248 -----------------------------------------------------------------------------*/
2249 void getBbias(unsigned long *number)
2256 unsigned long * bias = new unsigned long[ sign_exp_length ];
2259 for ( i=1; i<sign_exp_length;i++ )
2260 bias[ i ] =0xFFFFFFFFL;
2261 bias[ 0 ] =0x3FFFFFFFL;
2262 if ( sign_exp_length > 1 )
2263 bias[ sign_exp_length-1 ] <<= ( NO_OF_BITS-sign_exp_rest-1 );
2265 bias[ 0 ] =( unsigned long ) ( ((unsigned long)1 << (expon-1)) -1 ) << ( NO_OF_BITS-sign_exp_rest-1 );
2269 bias[ sign_exp_length-1 ] += ( 1L << ( NO_OF_BITS-sign_exp_rest-1 ) );
2270 k=sign_exp_length-1;
2271 while ( bias[ k ] ==0 )
2276 k=sign_exp_length-1;
2281 k=sign_exp_length-1;
2282 while ( bias[ k ] ==0 )
2287 bias[ sign_exp_length-1 ] -= ( 1L << ( NO_OF_BITS-sign_exp_rest-1 ) );
2291 // copy bias into number
2292 for ( i=0;i<sign_exp_length-1;i++ )
2293 number[ i ] = bias[ i ];
2295 if (kl_biased_exp > 0) // change kl_biased_exp
2296 number[sign_exp_length-1] &= kl_biased_exp-1;
2298 number[ sign_exp_length-1 ] |= bias[ sign_exp_length-1 ];
2304 /*-----------------------------------------------------------------------------
2306 description :gets exponent for the binary number
2307 called from :getBbias()
2312 -----------------------------------------------------------------------------*/
2313 long int getBexpon()
2316 unsigned long signexp = 0;
2318 c=mygetc( input ); // skip 'E' character
2323 c = mygetc( input );
2324 } else if ( c == '+' )
2326 c = mygetc( input );
2329 while ( isdigit( c ) )
2331 u = ( u * 10 ) + ( c - '0' );
2332 c = mygetc( input );
2334 myungetc( c, input ); // for EOL
2344 /*-----------------------------------------------------------------------------
2346 description :get decimal coded number form testset // ONLY FOR CONVERSION
2347 called from :readAline()
2348 call fns :getDsignificand(),getDexpon
2351 Global var. used :decimal,updecimal,nextdig
2352 -----------------------------------------------------------------------------*/
2356 getDsignificand(); //i is the position till which
2357 //significant has occupied decimal[]
2363 /*-----------------------------------------------------------------------------
2364 name :getDsignificand()
2365 description :get significand of decimal coded number
2366 called from :getdecimal()
2367 call fns :mygetc(),myungetc()
2370 Global var. used :decimal,updecimal,nextdig,incexp
2371 -----------------------------------------------------------------------------*/
2373 void getDsignificand()
2374 { // get significand
2375 posDec = 0,posUpDec = 0;
2378 c = mygetc( input );
2380 while ( !isspace( c ) && ( c != '_' ) )
2382 decimal[ posDec ] = c;
2383 updecimal[ posDec++ ] = c;
2384 c = mygetc( input );
2386 if ( c == '_' ) //find next number for case of 9's in end
2388 posUpDec = posDec-1; // or all 9's .
2389 while ( ( posUpDec > 1 ) && ( updecimal[ posUpDec ] == '9' ) )
2390 updecimal[ posUpDec-- ] = '0';
2391 if ( updecimal[ posUpDec ] == '9' )
2393 updecimal[ 1 ] = '1';
2394 for ( posUpDec = 2; posUpDec <= posDec; posUpDec++ )
2395 updecimal[ posUpDec ] = '0';
2398 updecimal[ posUpDec ] = ( int ) updecimal[ posUpDec ] + 1;
2399 nextdig = mygetc( input ) - '0';
2400 c = mygetc( input );
2401 while ( !isspace( c ) ) c = mygetc( input ); // skip tail
2408 /*-----------------------------------------------------------------------------
2410 description :get exponent of decimal coded number
2411 called from :getdecimal()
2412 call fns :mygetc(),myungetc(),exceptions :/
2414 Global var. used :decimal,updecimal,nextdig,incexp
2415 -----------------------------------------------------------------------------*/
2419 c = mygetc( input );
2421 if ( c == 'E' ) // get exponent
2423 decimal[ posDec ] = c;
2424 updecimal[ posDec++ ] = c;
2425 c = mygetc( input );
2427 while ( !isspace( c ) )
2429 decimal[ posDec ] = c;
2430 updecimal[ posDec++ ] = c;
2431 c = mygetc( input );
2433 decimal[ posDec ] = '\0';
2438 if ( signexp != '-' ) // inc exponent
2441 while ( updecimal[ posDec ] == '9' )
2443 updecimal[ posDec ] = 0;
2446 if ( updecimal[ posDec ] == 'E' )
2448 updecimal[ posDec+1 ] = '1';
2449 updecimal[ posUpDec++ ] = '0';
2452 updecimal[ posDec ] = ( int ) updecimal[ posDec ] + 1;
2454 } else // dec exponent
2457 while ( updecimal[ posDec ] == '0' )
2459 updecimal[ posDec ] = 9;
2462 updecimal[ posDec ] = ( int ) updecimal[ posDec ] - 1;
2467 myungetc( c,input );
2469 updecimal[ posUpDec ] = '\0';
2470 myungetc( c, input );
2474 /*-----------------------------------------------------------------------------
2476 description :takes the coded number and precsion to get the number
2477 called from :readAline()
2478 call fns :getSign(), getFPRootNumber(),getModifier()
2481 Global var. used :HexNoIsGiven,cant_infinity,small_norm,NaNresult
2482 -----------------------------------------------------------------------------*/
2485 void getNumber( unsigned long *number)
2488 unsigned long i, k, pos;
2492 HexNoIsGiven=0; //initialize global variable
2493 cant_infinity=0, small_norm=0; //initialize global variable
2494 NaNresult = 0; // change DV
2496 for ( i=0; i<length;i++ ) // number initialized to 0
2501 getFPRootNumber(number);
2503 if (HexNoIsGiven) return ;
2504 /* if hexadecimal number is given as operand then save
2505 the number to the global char *intstr and exit this function */
2507 getModifier(number);
2509 /* Stuff the sign nonarithmetically, to protect signaling NaNs. */
2510 if (signbit) // checksign() is to get the sign of sign of number
2511 number[ 0 ] |= 0x80000000L;
2516 /*-----------------------------------------------------------------------------
2518 description :Inserts correct number of zeros at most significant posiotion.
2519 called from :readAline()
2521 Global var. used :length,nanresult
2522 -----------------------------------------------------------------------------*/
2525 char* WriteNumber( const unsigned long *number, unsigned long expon,
2526 unsigned long hidden, unsigned long mant, unsigned long length,const int err )
2532 for ( i=0; i<length;i++ )
2533 // stream << " "<< setw(8) << setfill('0') << hex << number[i];
2534 if ( number[ i ] >= 0x10000000 )
2535 stream << " " << hex << number[ i ];
2536 else if ( number[ i ] >= 0x01000000 ) {
2537 stream << " 0" << hex << number[ i ];
2538 } else if ( number[ i ] >= 0x00100000 ) {
2539 stream << " 00" << hex << number[ i ];
2540 } else if ( number[ i ] >= 0x00010000 ) {
2541 stream << " 000" << hex << number[ i ];
2542 } else if ( number[ i ] >= 0x00001000 ) {
2543 stream << " 0000" << hex << number[ i ];
2544 } else if ( number[ i ] >= 0x00000100 ) {
2545 stream << " 00000" << hex << number[ i ];
2546 } else if ( number[ i ] >= 0x00000010 ) {
2547 stream << " 000000" << hex << number[ i ];
2549 stream << " 0000000" << hex << number[ i ];
2552 stream<< " Fout invoernumber";
2559 return stream.str( );
2564 /*-----------------------------------------------------------------------------
2566 description :checks if the sign of a number is + or negative ... by default it returns + .
2567 called from :getNumber()
2568 call fns :/ //mygetc()
2571 Global var. used :pre
2572 -----------------------------------------------------------------------------*/
2575 int signBit=0; //default takes positive
2576 c = mygetc( input );
2597 /*-----------------------------------------------------------------------------
2598 name :getFPRootNumber
2599 description :extracts the rootnumber from the coded number
2600 called from :getNumber()
2601 calls fns :Infinity(),Quiet_NaN(),Signaling_NaN(),smallest_Norm(),getFPHexNo(),getFPInteger()
2604 Global var. used :cant_infinity,killerVector,small_norm,NaNresult,HexNoIsGiven
2605 -----------------------------------------------------------------------------*/
2606 void getFPRootNumber( unsigned long *number)
2609 c = mygetc( input );
2618 killerVector = 1; /* change BV */
2619 NaNresult = 1; // change DV
2622 Signaling_NaN( number);
2623 killerVector = 1; /* change BV */
2626 case 'E': // this 'E' is given for compatibility with Coonen vectors
2628 Smallest_Norm( number);
2629 small_norm=1; // indien er een number volgt op T, dan kan via deze
2630 // variabele gezien worden of er een plus (voor T)
2631 // of een minus (voor H, zie aldaar) moet gebeuren
2634 d = mygetc( input );
2635 if ( d == 'x' ) //hexadecimal number
2637 getFPHexNo(); //save Hexadecimal no. in intstr[]
2644 getFPInteger( number);
2651 getFPInteger( number);
2654 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2655 printf( "\ngetNumber() ERROR: %c is an unknown number specifier in getNumber\n", c );
2656 printf( "\n\nDone with %ld readings.\n", readings );
2657 exit( EXIT_SUCCESS );
2663 /*-----------------------------------------------------------------------------
2665 description :Modifies the rootnumber
2666 called from :getNumber()
2667 calls fns :ModifierPorM(),ModifierIorD(),ModifierU()
2671 -----------------------------------------------------------------------------*/
2675 void getModifier(unsigned long *number)
2678 int McasePorM,McaseIorD;
2681 while ( !isspace( c = mygetc( input ) ) )
2686 ModifierPorM(number,McasePorM);
2690 ModifierPorM(number,McasePorM);
2694 ModifierIorD(number,McaseIorD);
2698 ModifierIorD(number,McaseIorD);
2702 ModifierU( number,k);
2709 case '3': // indien er hier een cijfer wordt ingelezen, dan
2711 case '4': // kan dat enkel voorafgegaan zijn door een
2713 case '5': // H (infinity) of een T (smallest normalized)
2715 case '6': // if here a figure is read in , then that can
2716 // can only be preceded by H(infinty )
2717 //or T (smallest normalised)
2724 if ( ( c != 't' ) && ( c != 'u' ) && ( c!='B' ) && ( c != 'C' ) )
2725 k=( long ) atoi( &c );
2726 else if ( c == 't' )
2728 else if ( c == 'B' )
2730 // k = (unsigned long) (((unsigned long)1 << (expon-1)) - 1);
2732 cout << "ULONG_MAX :" << ULONG_MAX << endl;
2733 } else if ( c == 'u' )
2734 k = dmant + dhidden;
2735 else if ( c == 'C' )
2736 // k = (unsigned long) (((unsigned long)1 << (dexpon-1)) - 1);
2738 if ( cant_infinity ) // if H
2740 // PlusBk( number,k);
2741 if ( small_norm ) // if T
2747 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2748 printf( "\ngetNumber() ERROR: unrecognizable modifier character: %c\n", c );
2749 printf( "\n\nDone with %ld readings.\n", readings );
2750 exit( EXIT_SUCCESS );
2753 myungetc( c, input );
2760 /*-----------------------------------------------------------------------------
2762 description :this is called if the coded number is hexadecimal . This stores hexadecimal number in intstr[] and quits getNumber().
2763 called from :getFPRootNumber()
2767 Global var. used : intstr[]
2768 -----------------------------------------------------------------------------*/
2772 intstr = new char[ 64 ];
2776 for ( capc = toupper( c = mygetc( input ) );
2777 ( '0' <= capc && capc <= '9' ) || ( 'A' <= capc && capc <= 'F' );
2778 capc = toupper( c = mygetc( input ) ) )
2789 /*-----------------------------------------------------------------------------
2791 description :Modifies the rootnumber for case 'i'-increment or case 'd'-decrement
2792 called from :getModifier()
2793 calls fns :Incr_at_pos(), Incr(),Decr_at_pos(),Decr(),getInteger()
2797 -----------------------------------------------------------------------------*/
2799 void ModifierIorD(unsigned long *number,int McaseIorD) {
2802 unsigned long pos,k;
2803 c = mygetc( input );
2807 pos = getinteger( );
2808 c = mygetc( input );
2812 pos += getinteger( );
2813 c = mygetc( input );
2818 Decr_at_pos( number,pos,k);
2820 Incr_at_pos( number,pos,k);
2823 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2824 printf( "\ngetNumber() ERROR: unexpected character: %c\n", c );
2825 printf( "\n\nDone with %ld readings.\n", readings );
2826 exit( EXIT_SUCCESS );
2831 pos -= getinteger( );
2832 c = mygetc( input );
2837 Decr_at_pos( number,pos,k);
2839 Incr_at_pos( number,pos,k);
2842 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2843 printf( "\ngetNumber() ERROR: unexpected character: %c\n", c );
2844 printf( "\n\nDone with %ld readings.\n", readings );
2845 exit( EXIT_SUCCESS );
2852 Decr_at_pos( number,pos,k);
2854 Incr_at_pos( number,pos,k);
2858 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2859 printf( "\ngetNumber() ERROR: unexpected character: %c\n", c );
2860 printf( "\n\nDone with %ld readings.\n", readings );
2861 exit( EXIT_SUCCESS );
2866 myungetc( c, input );
2873 } // switch case 'i'
2879 /*-----------------------------------------------------------------------------
2881 description :Modifies the rootnumber for case 'p'-plus or case 'm'-minus
2882 called from :getModifier()
2883 calls fns :Plus(),PLusBk(),Minus(),MinusBk()
2887 -----------------------------------------------------------------------------*/
2888 void ModifierPorM(unsigned long *number,int McasePorM)
2893 c = mygetc( input );
2894 if (c== 'B' || c== 'C' ) //Bias (C is only for conversions)
2898 if ((c - '0')>0 && (c - '0')<10)
2906 } else if ((c - '0') != 0 ) //makes B0 as B
2910 myungetc( c,input );
2921 /*-----------------------------------------------------------------------------
2923 description :operates u<digit>
2924 called from :getModifier()
2925 call fns :null_exp(),one_exp()
2928 Global var. used :sign_exp_length,exp_rest,length,rest,hidden,kl_biased_exp,mant
2929 -----------------------------------------------------------------------------*/
2931 void ModifierU( unsigned long *number, unsigned long ulps)
2933 unsigned long *e, i, exp_all_null, bits_ulps, k, shift_part;
2936 e = new unsigned long[ sign_exp_length ];
2939 printf( "\nNot enough memory in procedure ModifierU!!!\n" );
2940 printf( "Program aborted.\n" );
2946 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
2947 printf( "\n\nDone with %ld readings.\n", readings );
2948 exit( EXIT_SUCCESS );
2951 for ( i=0;i<sign_exp_length-1;i++ )
2952 e[ i ] =number[ i ];
2953 e[ sign_exp_length-1 ] = ( number[ sign_exp_length-1 ] >> ( (NO_OF_BITS-1)-sign_exp_rest ) );
2954 e[ sign_exp_length-1 ] <<= ( (NO_OF_BITS-1)-sign_exp_rest );
2958 if ( null_exp( e) ||
2961 for ( i=0;i<length;i++ )
2965 bits_ulps = ( unsigned long ) floor( ::log10( ulps ) / ::log10( 2 ) ) +1;
2966 if ( bits_ulps > mant )
2972 number[ length-1 ] =ulps;
2976 if ( ( ( bits_ulps > rest ) && hidden ) || ( ( bits_ulps+1 > rest ) && ( !hidden ) ) )
2977 number[ length-2 ] = ( ulps >> rest );
2978 number[ length-1 ] <<= ( NO_OF_BITS-rest );
2984 for ( i=0;i<length;i++ )
2988 bits_ulps = ( unsigned long ) floor( ::log10( ulps ) / ::log10( 2 ) ) +1;
2989 if ( bits_ulps > mant )
2995 number[ length-1 ] =ulps;
2999 if ( ( ( bits_ulps > rest ) && hidden ) || ( ( bits_ulps+1 > rest ) && ( !hidden ) ) )
3000 number[ length-2 ] = ( ulps >> rest );
3001 number[ length-1 ] <<= ( NO_OF_BITS-rest );
3004 k=sign_exp_length-1;
3005 shift_part=length-1;
3007 while ( ( hidden && !( number[ sign_exp_length-1 ] & kl_biased_exp ) ) ||
3008 ( !hidden && ( ( ( !( number[ sign_exp_length ] & ( 1L<<(NO_OF_BITS-1) ) ) ) &&
3009 ( sign_exp_rest == (NO_OF_BITS-1) ) ) ||
3010 ( !( number[ sign_exp_length-1 ] & ( kl_biased_exp>>1 ) ) &&
3011 ( sign_exp_rest != (NO_OF_BITS-1) ) ) ) )
3013 e[ sign_exp_length-1 ] -= ( 1L << ( (NO_OF_BITS-1)-sign_exp_rest ) );
3014 k=sign_exp_length-1;
3015 while ( k==sign_exp_length-1 ? e[ k ] ==( 0xFFFFFFFFL << ( NO_OF_BITS-sign_exp_rest-1 ) ) : e[ k ] ==0xFFFFFFFFL )
3021 if ( shift_part!=0 )
3022 number[ shift_part-1 ] = ( number[ shift_part-1 ] << 1 ) | ( ( number[ shift_part ] >> (NO_OF_BITS-1) ) & 0x01L );
3023 number[ shift_part ] <<= 1;
3024 if ( number[ shift_part ] ==0 )
3029 for ( i=0; i<sign_exp_length-1; i++ )
3030 number[ i ] = e[ i ];
3031 number[ i ] &= kl_biased_exp-1;
3032 number[ i ] |= e[ sign_exp_length-1 ];
3042 /*-----------------------------------------------------------------------------
3044 description :gets integer value from the string (also checks for hex no.)
3045 called from :Modifier(),ModifierIorD(),ModifierPorM()
3046 call fns :mygetc(),myungetc()
3050 -----------------------------------------------------------------------------*/
3051 /* Peruse the input stream for an unsigned integer.
3052 * Allow the 0xddddd syntax of C integers, and also decimals.
3055 unsigned long getinteger()
3058 unsigned long u = 0;
3060 u=getHex(); //returns integer value if Hex
3061 if (u != 0) return u; // hex no. is given
3063 //Now the input character c is either a decimal
3064 //digit or a terminal. A null number returns as zero.
3069 u = smant + shidden;
3074 u = ( unsigned long ) ( ((unsigned long)1 << (sexpon-1)) - 1 );
3078 u = dmant + dhidden;
3083 u = ( unsigned long ) ( ((unsigned long)1 << (dexpon-1)) - 1 );
3088 u = ( mant + hidden + 1 ) / 2 - 1;
3092 while ( isdigit( c ) ) {
3093 u = ( u * 10 ) + ( c - '0' );
3094 c = mygetc( input );
3096 myungetc( c, input );
3102 /*-----------------------------------------------------------------------------
3104 description :gets integer value of Hex no.
3105 called from :getinteger()
3106 call fns :mygetc(),myungetc()
3108 -----------------------------------------------------------------------------*/
3109 unsigned long getHex()
3113 c = mygetc( input );
3115 c = mygetc( input );
3117 for ( capc = toupper( c = mygetc( input ) );
3118 ( '0' <= capc && capc <= '9' ) || ( 'A' <= capc && capc <= 'F' ); capc = toupper( c = mygetc( input ) ) ) {
3120 if ( isdigit( capc ) )
3123 u |= 0xa + ( capc - 'A' );
3125 myungetc( c, input );
3135 /*-----------------------------------------------------------------------------
3136 name :getFPInteger()
3137 description :get floating ponit integer in IEEE format
3138 called from :getFPRootNumber()
3139 call fns :mygetc(),myungetc()
3142 Global var. used :wrong_input
3143 -----------------------------------------------------------------------------*/
3145 void getFPInteger( unsigned long *number)
3148 unsigned long bits_u, ex, *bias, u=0;
3153 while ( isdigit( c ) )
3155 u = ( u * 10 ) + ( c - '0' );
3156 c = mygetc( input );
3159 myungetc( c, input );
3162 { // determine no. of bits for u
3163 bits_u = ( unsigned long ) floor( ::log10( u ) / ::log10( 2 ) ) + 1;
3164 if ( bits_u> mant+hidden )
3167 wrong_input=1; // u greater than maximal value of significand
3171 u &= 0x00FFFFFFL; // limited to 24-bit integer
3174 //determine no. of bits for u (now less than 24)
3175 bits_u = ( unsigned long ) floor( ::log10( u ) / ::log10( 2 ) ) + 1;
3178 u |= ( 1L << bits_u ); // put hidden bit in front
3180 number[ length-1 ] =u;
3184 if ( ( ( bits_u > rest ) && hidden ) || ( ( bits_u+1 > rest ) && ( !hidden ) ) )
3185 number[ length-2 ] =( u >> rest ); // if the 2 parts overlap
3186 // then the (bits_u-rest) bits that
3187 //follow will be added to the previous part
3188 number[ length-1 ] <<= ( NO_OF_BITS-rest );
3198 while ( ( number[ sign_exp_length-1 ] & kl_biased_exp ) ==0 )
3201 number[ k-1 ] = ( number[ k-1 ] << 1 ) | ( ( number[ k ] >> (NO_OF_BITS-1) ) & 0x01L );
3206 if ( number[ k ] ==0 )
3210 bias = new unsigned long[ sign_exp_length ];
3214 printf( "\nNot enough memory in procedure getFPInteger!!!\n" );
3215 printf( "Program aborted.\n" );
3221 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
3222 printf( "\n\nDone with %ld readings.\n", readings );
3223 exit( EXIT_SUCCESS );
3226 for ( i=0; i<sign_exp_length;i++ )
3229 for ( i=1; i<sign_exp_length;i++ )
3230 bias[ i ] =0xFFFFFFFFL;
3231 bias[ 0 ] =0x3FFFFFFFL;
3233 if ( sign_exp_length > 1 )
3234 bias[ sign_exp_length-1 ] <<= ( NO_OF_BITS-sign_exp_rest-1 );
3236 bias[ 0 ] =( unsigned long ) ( ((unsigned long)1 << (expon-1)) -1 ) << ( NO_OF_BITS-sign_exp_rest-1 );
3238 //add rest of exponent to bias
3239 k=sign_exp_length-1;
3241 for ( i=0;i<ex;i++ )
3243 bias[ sign_exp_length-1 ] += ( 1L << ( NO_OF_BITS-sign_exp_rest-1 ) );
3244 while ( bias[ k ] ==0 )
3249 k=sign_exp_length-1;
3252 // determine Exponent of number[] by assigning number[] =bias[]
3253 for ( i=0;i<sign_exp_length-1;i++ )
3254 number[ i ] =bias[ i ];
3256 if ( kl_biased_exp > 0 ) // change kl_biased_exp
3257 number[ sign_exp_length-1 ] &= kl_biased_exp-1;
3259 number[ sign_exp_length-1 ] |= bias[ sign_exp_length-1 ];
3267 /*-----------------------------------------------------------------------------
3269 description :Sets a number to infinty according to precision
3270 called from :getFPRootNumber()
3274 Global var. used :sign_exp_length,exp_rest,hidden
3275 -----------------------------------------------------------------------------*/
3278 void Infinity( unsigned long *number)
3282 if ( sign_exp_length==1 )
3283 number[ 0 ] =0x7FFFFFFFL<<( NO_OF_BITS-sign_exp_rest-1 ) ;
3285 number[ 0 ] =0x7FFFFFFFL;
3287 if ( ( sign_exp_length==1 ) && ( sign_exp_rest!=(NO_OF_BITS-1) ) )
3288 number[ 0 ] -= ( 1L << (NO_OF_BITS-1) );
3290 for ( j=sign_exp_length-2;j>0;j-- )
3291 number[ j ] += 0xFFFFFFFFL;
3293 if ( sign_exp_length != 1 )
3294 number[ sign_exp_length-1 ] = ( 0xFFFFFFFFL<<( NO_OF_BITS-sign_exp_rest-1 ) );
3297 if ( sign_exp_rest==(NO_OF_BITS-1) )
3298 number[ sign_exp_length ] += ( 1L<<(NO_OF_BITS-1) );
3300 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) );
3306 /*-----------------------------------------------------------------------------
3308 description :sets a number to Q
3309 called from :getFPRootNumber()
3313 Global var. used :sign_exp_length,exp_rest,hidden
3314 -----------------------------------------------------------------------------*/
3317 void Quiet_NaN( unsigned long *number)
3320 if ( sign_exp_length==1 )
3321 number[ 0 ] =0x7FFFFFFFL<<( NO_OF_BITS-sign_exp_rest-1 );
3323 number[ 0 ] =0x7FFFFFFFL;
3325 if ( ( sign_exp_length==1 ) && ( sign_exp_rest!=(NO_OF_BITS-1) ) )
3326 number[ 0 ] -= ( 1L << (NO_OF_BITS-1) );
3328 for ( j=sign_exp_length-2;j>0;j-- )
3329 number[ j ] += 0xFFFFFFFFL;
3330 if ( sign_exp_length != 1 )
3331 number[ sign_exp_length-1 ] = ( 0xFFFFFFFFL<<( NO_OF_BITS-sign_exp_rest-1 ) );
3334 if ( sign_exp_rest==(NO_OF_BITS-1) )
3335 number[ sign_exp_length ] += ( 1L<<30 );
3336 else if ( sign_exp_rest==30 )
3337 number[ sign_exp_length ] += ( 1L<<(NO_OF_BITS-1) );
3339 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-3 ) );
3341 if ( sign_exp_rest==(NO_OF_BITS-1) )
3342 number[ sign_exp_length ] += ( 1L<<(NO_OF_BITS-1) );
3344 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) );
3347 if ( sign_exp_rest==(NO_OF_BITS-1) )
3348 number[ sign_exp_length ] += ( 1L<<(NO_OF_BITS-1) );
3350 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) );
3354 /*-----------------------------------------------------------------------------
3355 name :Signaling_NaN()
3356 description :sets number to S
3357 called from :getFPRootNumber()
3361 Global var. used :sign_exp_length,exp_rest,hidden
3362 -----------------------------------------------------------------------------*/
3364 void Signaling_NaN( unsigned long *number)
3367 if ( sign_exp_length==1 )
3368 number[ 0 ] =0x7FFFFFFFL<<( NO_OF_BITS-sign_exp_rest-1 );
3370 number[ 0 ] =0x7FFFFFFFL;
3372 if ( ( sign_exp_length==1 ) && ( sign_exp_rest!=(NO_OF_BITS-1) ) )
3373 number[ 0 ] -= ( 1L << (NO_OF_BITS-1) );
3374 for ( j=sign_exp_length-2;j>0;j-- )
3375 number[ j ] += 0xFFFFFFFFL;
3376 if ( sign_exp_length != 1 )
3377 number[ sign_exp_length-1 ] = ( 0xFFFFFFFFL<<( NO_OF_BITS-sign_exp_rest-1 ) );
3380 number[ length-1 ] += ( 1L<<( NO_OF_BITS-rest ) );
3382 number[ length-1 ] += 1;
3385 if ( sign_exp_rest==(NO_OF_BITS-1) )
3386 number[ sign_exp_length ] += ( 1L<<(NO_OF_BITS-1) );
3388 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) );
3393 /*-----------------------------------------------------------------------------
3394 name :Smallest_Norm()
3395 description :sets number to samllest normal (or tiny T)
3396 called from :getFPRootNumber()
3400 Global var. used :sign_exp_length,exp_rest,hidden
3401 -----------------------------------------------------------------------------*/
3403 void Smallest_Norm( unsigned long *number)
3405 // if (hidden) // change DV
3406 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-1 ) );
3407 if ( ( !hidden ) && ( sign_exp_rest==(NO_OF_BITS-1) ) )
3408 number[ sign_exp_length ] += ( 1L<<(NO_OF_BITS-1) );
3410 number[ sign_exp_length-1 ] += ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) );
3415 /*-----------------------------------------------------------------------------
3417 description :operates p<digit> operation in the coded number
3418 called from :ModifierPorM()
3419 call fns :null_exp()
3422 Global var. used :sign_exp_length,exp_rest
3423 -----------------------------------------------------------------------------*/
3425 void Plus( unsigned long *number, unsigned long k)
3427 unsigned long pre_zero, j, i;
3428 pre_zero = null_exp( number);
3430 //bij de exponent 1'tje optellen en dit k keer
3431 for ( i=0;i<k;i++ ) {
3432 j = sign_exp_length-1;
3433 number[ j ] += ( 1L<<( (NO_OF_BITS-1)-sign_exp_rest ) );
3434 if ( ( ( number[ j ] >>( NO_OF_BITS-sign_exp_rest-1 ) ) == 0 ) && ( j!=0 ) ) //enkel exponent_stuk
3440 if ( number[ j ] ==0 ) {
3447 /*-----------------------------------------------------------------------------
3449 description :operates m<digits> operation in coded number
3450 called from :ModifierPorM
3451 call fns :null_exp()
3454 Global var. used :sign_exp_length,exp_rest
3455 -----------------------------------------------------------------------------*/
3457 void Minus( unsigned long *number, unsigned long k)
3459 unsigned long pre_zero, j, i;
3461 pre_zero = null_exp( number);
3462 //bij de exponent 1'tje aftrekken en dit k keer
3463 // Only works for e<=31
3464 for ( i=0;i<k;i++ ) {
3465 j = sign_exp_length-1;
3466 number[ j ] -= ( 1L<<( NO_OF_BITS-sign_exp_rest-1 ) );
3467 if ( ( number[ j ] >>( NO_OF_BITS-sign_exp_rest-1 ) ) == ( 0xFFFFFFFFL>>( NO_OF_BITS-sign_exp_rest-1 ) ) && ( j!=0 ) ) {
3471 while ( ( j>0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3478 /*-----------------------------------------------------------------------------
3480 description :divide Bias by 2^k ... operation mB<digits>
3481 called from :ModifierPorM
3486 -----------------------------------------------------------------------------*/
3489 void MinusBk( unsigned long *number, unsigned long k)
3491 // incorrect, only for e <= 31 // for exp <= 2^31
3492 unsigned long Bk = 0;
3497 /* Divide (Bias + 1) by k */
3498 for ( i=1;i<=k;i++ ) // shift exponent k places to the right
3506 /*-----------------------------------------------------------------------------
3508 description :multiply B by 2^k ... operation pB<digits>
3509 called from :ModifierPorM()
3514 -----------------------------------------------------------------------------*/
3517 void PlusBk( unsigned long *number, unsigned long k)
3519 // incorrect only works for e<=31 // for exp <= 2^31
3520 unsigned long Bk = 0;
3525 /* Divide (Bias + 1) by k */
3526 for ( i=1;i<=k;i++ ) // shift exponent k places to the right
3535 /*-----------------------------------------------------------------------------
3537 description :operates i(<pos>)<digit>
3538 called from :ModifierIorD()
3539 call fns :null_exp()
3542 Global var. used :sign_exp_length,exp_rest,hidden,expon
3543 -----------------------------------------------------------------------------*/
3546 void Incr_at_pos( unsigned long *number, unsigned long pos, unsigned long k)
3548 unsigned long leading, j, i,position,pos_part,pos_rest;
3550 // determine leading bit if not hidden
3551 if ( ( sign_exp_rest!=(NO_OF_BITS-1) ) && ( !hidden ) )
3552 leading = ( number[ sign_exp_length-1 ] >>( NO_OF_BITS-sign_exp_rest-2 ) ) & 1L;
3554 leading = ( number[ sign_exp_length ] >>(NO_OF_BITS-1) ) & 1L;
3556 // calculate position
3557 position = expon + pos + 1 - hidden;
3558 pos_part = position / NO_OF_BITS + 1;
3559 pos_rest = position % NO_OF_BITS + 1;
3561 //Increment significand by 1, k times
3562 for ( i=0;i<k;i++ ) {
3563 if ( pos_rest==0 ) {
3564 number[ pos_part-2 ] += 1;
3566 while ( ( j>0 ) && ( number[ j ] ==0 ) ) {
3572 number[ pos_part-1 ] += ( 1L<<( NO_OF_BITS-pos_rest ) );
3574 if ( ( number[ j ] >>( NO_OF_BITS-pos_rest ) ) == 0 ) {
3577 while ( ( j>0 ) && ( number[ j ] ==0 ) ) {
3585 // replace hidden bit
3587 if ( ( !hidden ) && ( j<sign_exp_length ) ) {
3588 if ( ( sign_exp_rest==(NO_OF_BITS-1) ) && ( ( number[ sign_exp_length ] ) ==0 ) ) {
3590 number[ sign_exp_length-1 ] += 1; //exp+1
3591 else if ( !null_exp( number) )
3592 number[ sign_exp_length ] |= ( 1L<<(NO_OF_BITS-1) ); //leading 1
3594 else if ( ( number[ sign_exp_length-1 ] << ( sign_exp_rest+2 ) ) ==0 ) {
3596 number[ sign_exp_length-1 ] += 1L<<( NO_OF_BITS-sign_exp_rest-1 ); //exp+1
3597 else if ( !null_exp( number) )
3598 number[ sign_exp_length-1 ] |= ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) ); //leading 1
3601 } else if ( ( !hidden ) && ( j==sign_exp_length ) ) {
3602 if ( ( sign_exp_rest==(NO_OF_BITS-1) ) && ( ( number[ sign_exp_length ] ) ==0 ) ) {
3604 number[ sign_exp_length-1 ] += 1;
3605 else if ( !null_exp( number) )
3606 number[ sign_exp_length-1 ] |= ( 1L << (NO_OF_BITS-1) );
3612 /*-----------------------------------------------------------------------------
3614 description :operates i<digit> on the coded number
3615 called from :ModifierIorD()
3616 call fns :null_exp()
3619 Global var. used :length,hidden,sign_exp_length,exp_rest,rest
3620 -----------------------------------------------------------------------------*/
3622 void Incr( unsigned long *number, unsigned long k)
3624 unsigned long leidende, j, i;
3626 //bepalen van leidende bit als deze niet hidden is
3627 if ( ( sign_exp_rest!=(NO_OF_BITS-1) ) && ( !hidden ) )
3628 leidende = ( number[ sign_exp_length-1 ] >>( NO_OF_BITS-sign_exp_rest-2 ) ) & 1L;
3630 leidende = ( number[ sign_exp_length ] >>(NO_OF_BITS-1) ) & 1L;
3632 //1 optellen bij de significand en dit k keer
3633 for ( i=0;i<k;i++ ) {
3635 number[ length-1 ] += 1;
3637 number[ length-1 ] += ( 1L<<( NO_OF_BITS-rest ) );
3639 while ( ( j>0 ) && ( number[ j ] ==0 ) ) // carry propagation
3646 if ( ( !hidden ) && ( j<sign_exp_length ) ) {
3647 if ( ( sign_exp_rest==(NO_OF_BITS-1) ) && ( ( number[ sign_exp_length ] ) ==0 ) ) {
3649 number[ sign_exp_length-1 ] += 1; //exp+1
3650 else if ( !null_exp( number) )
3651 number[ sign_exp_length ] |= ( 1L<<(NO_OF_BITS-1) ); //leidende 1
3653 else if ( ( number[ sign_exp_length-1 ] << ( sign_exp_rest+2 ) ) ==0 ) {
3655 number[ sign_exp_length-1 ] += 1L<<( NO_OF_BITS-sign_exp_rest-1 ); //exp+1
3656 else if ( !null_exp( number ) )
3657 number[ sign_exp_length-1 ] |= ( 1L<<( NO_OF_BITS-sign_exp_rest-2 ) ); //leidende 1
3660 } else if ( ( !hidden ) && ( j==sign_exp_length ) ) {
3661 if ( ( sign_exp_rest==(NO_OF_BITS-1) ) && ( ( number[ sign_exp_length ] ) ==0 ) ) {
3663 number[ sign_exp_length-1 ] += 1;
3664 else if ( !null_exp( number) )
3665 number[ sign_exp_length-1 ] |= ( 1L << (NO_OF_BITS-1) );
3671 /*-----------------------------------------------------------------------------
3673 description :operates d(<pos>)<digit> on the coded number
3674 called from :ModifierIorD()
3675 call fns :null_exp()
3678 Global var. used :hidden,sign_exp_length,exp_rest,expon
3679 -----------------------------------------------------------------------------*/
3682 void Decr_at_pos( unsigned long *number, unsigned long pos, unsigned long k)
3684 unsigned long leading, j, i,position,pos_part,pos_rest;
3686 // determine leading bit if not hidden
3687 if ( ( sign_exp_rest!=(NO_OF_BITS-1) ) && ( !hidden ) )
3688 leading = ( number[ sign_exp_length-1 ] >>( NO_OF_BITS-sign_exp_rest-2 ) ) & 1L;
3690 leading = ( number[ sign_exp_length ] >>(NO_OF_BITS-1) ) & 1L;
3692 // calculate position
3693 position = expon + pos + 1 - hidden;
3694 pos_part = position / NO_OF_BITS + 1;
3695 pos_rest = position % NO_OF_BITS + 1;
3697 for ( i=0;i<k;i++ ) {
3698 if ( pos_rest==0 ) {
3699 number[ pos_part-2 ] -= 1;
3701 while ( ( j>0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3707 number[ pos_part-1 ] -= ( 1L<<( NO_OF_BITS-pos_rest ) );
3709 if ( ( number[ j ] >>( NO_OF_BITS-pos_rest ) ) == ( 0xFFFFFFFFL>>( NO_OF_BITS-pos_rest ) ) ) {
3712 while ( ( j>0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3720 // bepalen van leidende bit als deze niet hidden is
3723 if ( ( !hidden ) && ( !null_exp( number) ) ) {
3724 j = sign_exp_length-1;
3726 if ( ( number[ j ] >> ( 30-sign_exp_rest ) ) % 2 == 0 ) {
3727 j = sign_exp_length-1;
3728 number[ j ] -= ( 1L<<( (NO_OF_BITS-1) - sign_exp_rest ) );
3729 if ( number[ j ] >>( (NO_OF_BITS-1)-sign_exp_rest ) == 0xFFFFFFFFL>>( (NO_OF_BITS-1)-sign_exp_rest ) ) {
3733 while ( ( j>0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3737 // replace leading bit if necessary
3738 if ( sign_exp_rest==(NO_OF_BITS-1) )
3739 number[ sign_exp_length ] |= 1L<<(NO_OF_BITS-1);
3741 number[ sign_exp_length-1 ] |= 1L<<( 30-sign_exp_rest );
3746 /*-----------------------------------------------------------------------------
3748 description :operates d<digit> on the coded number
3749 called from :ModifierIorD()
3750 call fns :null_exp()
3753 Global var. used :length,hidden,sign_exp_length,exp_rest,rest
3754 -----------------------------------------------------------------------------*/
3757 void Decr( unsigned long *number, unsigned long k)
3762 //decrement significand k times
3763 for ( i=0;i<k;i++ ) {
3768 number[ j ] -= ( 1L<<( NO_OF_BITS-rest ) );
3769 if ( ( number[ j ] >>( NO_OF_BITS-rest ) ) == ( 0xFFFFFFFFL>>( NO_OF_BITS-rest ) ) && ( j!=0 ) ) {
3774 while ( ( j>0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3782 ( !null_exp( number) ) ) {
3783 // leading bit = zero ?
3784 j = sign_exp_length-1;
3786 if ( ( ( sign_exp_rest < (NO_OF_BITS-1) ) && !( number[ j ] & ( 1L << 30 - sign_exp_rest ) ) ) ||
3787 ( ( sign_exp_rest == (NO_OF_BITS-1) ) && !( number[ j ] & ( 1L << (NO_OF_BITS-1) ) ) ) ) {
3790 if ( sign_exp_rest == (NO_OF_BITS-1) ) {
3793 if ( ( j > 0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3798 /// change DV 28/01/2000
3800 if ( hidden && ( !( ( number[ j ] >> ( (NO_OF_BITS-1) - sign_exp_rest ) ) & 1L ) ) ) {
3801 // trailing exp bit == 0
3802 number[ j ] += 1L << ( (NO_OF_BITS-1) - sign_exp_rest );
3806 while ( ( j>0 ) && ( number[ j ] == 0xFFFFFFFFL ) ) {
3810 } else if ( sign_exp_rest == 0 ) { // change DV 8/3/2000
3811 if ( !( number[ j ] & ( 1L << ( (NO_OF_BITS-1) - sign_exp_rest ) ) ) ) { // leading exp. bit = 0
3812 number[ j-1 ] -= 1; // borrow carry
3813 number[ j ] += ( 1L << ( (NO_OF_BITS-1) - sign_exp_rest ) );
3815 number[ j ] -= ( 1L << ( (NO_OF_BITS-1) - sign_exp_rest ) );
3819 number[ j ] -= ( 1L << ( (NO_OF_BITS-1) - sign_exp_rest ) );
3826 // replace leading bit if necessary
3827 if ( ( !hidden ) && ( !null_exp( number) ) ) {
3828 if ( sign_exp_rest==(NO_OF_BITS-1) )
3829 number[ sign_exp_length ] |= 1L<<(NO_OF_BITS-1);
3831 number[ sign_exp_length-1 ] |= 1L<<( 30-sign_exp_rest );
3836 /*-----------------------------------------------------------------------------
3838 description :exit if less memory to store number
3839 //but why only getbinary() (have to figure out)
3840 called from :getbinary()
3843 -----------------------------------------------------------------------------*/
3848 printf( "\nNot enough memory\n" );
3849 printf( "Program aborted.\n" );
3855 printf( "\n\nError on line %ld of inputfile.",lines_in+readings+1 );
3856 printf( "\n\nDone with %ld readings.\n", readings );
3862 /*-----------------------------------------------------------------------------
3864 description :checks if exponent is zero
3865 called from :Plus(),Minus(),Incr_at_pos(),Incr(),Decr_at_pos(),
3870 Global var. used :sign_exp_length,exp_rest,length
3871 -----------------------------------------------------------------------------*/
3873 unsigned long null_exp( const unsigned long *number)
3875 unsigned long m, null=1;
3877 for ( m=1;m<sign_exp_length-1;m++ ) {
3878 if ( number[ m ] !=0 )
3881 if ( ( sign_exp_rest==0 ) && ( ( ( number[ 0 ] & 0x7FFFFFFFL ) << 1 ) != 0 ) )
3883 if ( ( ( number[ 0 ] & 0x7FFFFFFFL ) >> ( NO_OF_BITS-sign_exp_rest-1 ) ) != 0 )
3885 if ( ( length != 1 ) && ( sign_exp_length !=1 ) && ( ( number[ sign_exp_length-1 ] >> ( NO_OF_BITS-sign_exp_rest-1 ) ) != 0 ) )
3891 /*-----------------------------------------------------------------------------
3893 description :checks if exponent is one
3894 called from :ModifierU()
3898 Global var. used :sign_exp_length,exp_rest
3899 -----------------------------------------------------------------------------*/
3902 unsigned long one_exp( const unsigned long *number)
3904 unsigned long m, one=0;
3906 if ( ( ( number[ sign_exp_length-1 ] >> ( NO_OF_BITS - sign_exp_rest - 1 ) ) | 1L ) == 1L )
3909 for ( m=0;m<sign_exp_length-1;m++ ) {
3910 if ( number[ m ] != 0 )
3913 if ( ( sign_exp_length > 1 ) && ( ( number[ 0 ] & 0x7FFFFFFFL ) != 0 ) )
3922 /*-----------------------------------------------------------------------------
3924 description :apply getc() of <stdio.h> to the present location of file in use
3925 called from :whole program
3930 -----------------------------------------------------------------------------*/
3932 int mygetc( FILE *f )
3940 /*-----------------------------------------------------------------------------
3942 description :apply ungetc() of <stdio.h> to the present location of file in use
3943 called from :whole program
3948 -----------------------------------------------------------------------------*/
3950 void myungetc( int c, FILE *f )
3957 /* ============================ END OF FILE ============================*/