*** empty log message ***
[libfirm] / ir / tv / IeeeCC754 / include / UCB.h
1 /*
2 ##########################################################################
3 #                                                                        #
4 # Program: IeeeCC754                                                     #
5 #                                                                        #
6 # Description:                                                           #
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            #
12 #                                                                        #
13 #         http://win-www.uia.ac.be/u/cant/ieeecc754.html                 #
14 #                                                                        #
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.                                 #
22 #                                                                        #
23 #  Usage: see readme.usage                                               #
24 #                                                                        #
25 #  Responsible authors:                                                  #
26 #         Brigitte Verdonk                                               #
27 #         Annie Cuyt                                                     #
28 #                                                                        #
29 #  Contributors:                                                         #
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)                           #
36 #                                                                        #
37 #  Copyright (C) 2000  University of Antwerp                             #
38 #                                                                        #
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.                                     #
42 #                                                                        #
43 #  Contact:                                                              #
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                                           #
49 #                                                                        #
50 ##########################################################################
51
52 Filename:
53        $RCSfile$
54
55 Last updated:
56        $Date$
57
58 */
59
60 #ifndef _UCB_H
61 #define _UCB_H
62
63 // ----
64 // Includes
65 // ----
66 #include <string.h>
67 #include <ctype.h>
68 #include <stdlib.h>
69 #include <fstream.h>
70 #include <Fp.h>
71
72 // ----
73 // Defines
74 // ----
75 #define BUF_LEN    1024
76 #define FP_STR      256
77
78 #define NO_FLAGS_INEXACT      16
79 #define NO_FLAGS_OVERFLOW     8
80 #define NO_FLAGS_UNDERFLOW    4
81 #define NO_FLAGS_INVALID      2
82 #define NO_FLAGS_DIV_BY_ZERO  1
83
84 extern int ieee;
85
86 template<class T> class UCB
87 {
88
89 protected:
90
91   fstream infile, outfile,logfile;
92   char dest[ BUF_LEN ];
93   strstream logstream;
94
95   int line,sizeE,sizeM,hidden,dsizeE,dsizeM,dhidden,noFlags,signedZero,ieeeVector;
96   char operation[ 10 ],prec,rounding,compare[ 5 ],exceptions[ 10 ];
97   T operand1,operand2,result;
98   int pre, post; // to accomodate '?'
99   unsigned int errors,warnings,skipped;
100
101   void PrintError( T &res );
102
103 public:
104
105   int signalu,notsignalu,signalv,signalw,notsignalv,notsignalw,nou,nov,now,allops;
106
107   UCB( );
108   ~UCB( );
109
110   void SetFPRound ( );
111
112   int OpenInput( char* filename );
113   int OpenOutput( char* filename );
114   int OpenLogFile( char* filename,int argc,char **argv );
115   int ReadLine( char* str=NULL,int sZero=1, int nflags=0,int *lines=NULL );
116
117   char* GetOperation( );
118   char  GetPrecision( );
119   char  GetRounding( );
120   char* GetCompare( );
121   char* GetExceptions( );
122   T &  GetOperand1( );
123   T &  GetOperand2( );
124   T &  GetResult( );
125
126   char* DoLine( int tiny,int inf, int nan);
127   void Compare ( T &reslt );
128   void Close( int tiny );
129 };
130
131
132 template <class T>
133 UCB<T>::UCB( )
134 {
135   line = 0;
136   //  result.SetEnvironment(); change BV
137   signalu = 0;
138   signalv = 0;
139   signalw = 0;
140   notsignalu = 0;
141   notsignalv = 0;
142   notsignalw = 0;
143   nou= 1;
144   nov = 1;
145   now = 1;
146   pre = post = 0;
147   errors = 0;
148   warnings = 0;
149   skipped = 0;
150   allops = 0;
151 }
152
153 template <class T>
154 UCB<T>::~UCB( )
155 {}
156
157
158 template <class T>
159 int UCB<T>::OpenInput( char* filename )
160 {
161   infile.open( filename,ios::in );
162   if ( infile.good( ) )
163     return 1;
164
165   return 0;
166 }
167
168 template <class T>
169 void UCB<T>::Close( int tiny )
170 {
171   logfile << "Summary:  " << endl;
172   logfile << "--------  " << endl;
173
174   if ( tiny )   { // conclusion underflow
175     if ( ucb.nou )  {
176       if ( ucb.nov )  {
177         if ( !( ucb.now ) )
178           logfile << "Warning: only 'w' underflow cases in the testset" << endl;
179       } else
180         if ( ucb.now )
181           logfile << "Warning: only 'v' underflow cases in the testset" << endl;
182         else
183           logfile << "Warning: only 'v' and 'w' underflow cases in the testset" << endl;
184     } // if
185     else {
186       if ( ucb.nov )  {
187         if ( ucb.now )  {
188           logfile << "Warning: no special 'v' or 'w' underflow cases in the testset" << endl;
189           if ( ucb.signalu && !ucb.notsignalu )
190             logfile << "Implementation signals underflow in case the result" << endl << "(1) is tiny after rounding and" << endl << "(2) suffers denormalization loss" << endl << "('u' -  underflow)" << endl;
191         } else
192           logfile << "Warning: no special 'v' underflow cases in the testset" << endl;
193       } else {
194         if ( ucb.now )  {
195           logfile << "Warning: no special 'w' underflow cases in the testset" << endl;
196           if ( ( ucb.signalu && !ucb.notsignalu )  && ( ucb.signalv && !ucb.notsignalv ) )
197             logfile << "Implementation signals underflow in case the result" << endl << "(1) is tiny after rounding and" << endl << "(2) raises the inexact exception" << endl << "('v' - underflow)" << endl;
198         } else if ( ucb.signalu && !ucb.notsignalu )  {
199           if ( ucb.signalw && !ucb.notsignalw )
200             logfile << "Implementation signals underflow in case the result" << endl << "(1) is tiny before rounding and" << endl << "(2) raises the inexact exception" << endl << "('w' - underflow)" << endl;
201           else if ( ucb.signalv && !ucb.notsignalv )
202             logfile << "Implementation signals underflow in case the result" << endl << "(1) is tiny after rounding and" << endl << "(2) raises the inexact exception"<< endl << "('v' - underflow)" << endl;
203           else
204             logfile << "Implementation signals underflow in case the result" << endl << "(1) is tiny after rounding and" << endl << "(2) suffers denormalization loss" << endl << "('u' -  underflow)" << endl;
205         } // else
206       } // else
207     } // else
208   } // if tiny
209
210   logfile << "Errors:   " << errors << "/" << allops << endl;
211   logfile << "Warnings: " << warnings << "/" << allops << endl;
212   logfile << "Skipped:  " << skipped << "/" << allops << endl;
213 }
214
215 template <class T>
216 int UCB<T>::OpenOutput( char* filename )
217 {
218   outfile.open( filename,ios::out );
219   if ( outfile.good( ) )
220     return 1;
221
222   return 0;
223 }
224
225 template <class T>
226 int UCB<T>::OpenLogFile( char* filename,int argc, char **argv )
227 {
228   logfile.open( filename,ios::out );
229   if ( logfile.good( ) )  {
230     logfile << "Testrun: ";
231     for ( int i = 0; i < argc;i++ )
232       logfile << argv[ i ]  << " ";
233     logfile << endl << endl << flush;
234     return 1;
235   }
236
237   return 0;
238 }
239
240 template <class T>
241 int UCB<T>::ReadLine( char* str,int sZero,int nflags,int *lines )
242 {
243   int i,j,k,gotInput=0,count;
244   Hex tmphex,tmphex2;
245   Bitstring tmpbitstring,tmpbitstring2;
246   char buf[ BUF_LEN ],tmp[ FP_STR ];
247   line++;
248   signedZero=sZero;
249
250   pre = post = 0;
251   if( !str ) {
252     if ( !infile.eof( ) ) {
253       infile.getline( buf,BUF_LEN );
254       if( strlen( buf )  !=0 )
255         gotInput=1;
256     }
257
258     if( nflags )
259       noFlags = nflags;
260   } else {
261     strncpy( buf,str,strlen( str ) );
262     gotInput=1;
263     line=*lines;
264     noFlags=nflags;
265   }
266
267
268   if( gotInput ) {
269     i=0;
270     while ( buf[ i ] != ' ' ) {
271       operation[ i ] =buf[ i ];
272       i++;
273     }
274
275     operation[ i ] ='\0';
276
277     if ( !isdigit( operation[ strlen( operation ) -1 ] ) ) {
278       prec= operation[ strlen( operation ) -1 ];
279       operation[ strlen( operation ) -1 ] ='\0';
280       switch ( prec ) {
281         case 's':
282           sizeE=8;
283           sizeM=23+1;
284           hidden=1;
285           ieeeVector=0;
286           break;
287         case 'S':
288           sizeE=8;
289           sizeM=23+1;
290           hidden=1;
291           ieeeVector=1;
292           break;
293         case 'd':
294           sizeE=11;
295           sizeM=52+1;
296           hidden=1;
297           ieeeVector=0;
298           break;
299         case 'D':
300           sizeE=11;
301           sizeM=52+1;
302           hidden=1;
303           ieeeVector=1;
304           break;
305         case 'l':
306           sizeE=15;
307           sizeM=64 + 1;
308           hidden=0;
309           ieeeVector=0;
310           break;
311         case 'L':
312           sizeE=15;
313           sizeM=64 + 1;
314           hidden=0;
315           ieeeVector=1;
316           break;
317         case 'q':
318           sizeE=15;
319           sizeM=112+1;
320           hidden=1;
321           ieeeVector=0;
322           break;
323         case 'Q':
324           sizeE=15;
325           sizeM=112+1;
326           hidden=1;
327           ieeeVector=1;
328           break;
329         case 'm':
330           sizeE=15;
331           sizeM=240 + 1;
332           hidden = 0;
333           ieeeVector=0;
334           break;
335         case 'M':
336           sizeE=15;
337           sizeM=240 + 1;
338           hidden = 0;
339           ieeeVector=1;
340           break;
341       }
342     } else {
343
344       ieeeVector=0; // Cannot be ieeeVector!
345
346       i--;
347
348       while ( isdigit( buf[ i ] ) )  i--; // rewind
349
350       i++;
351       operation[ i ]  = '\0'; // ignore digit after operation
352       j = 0;
353
354       while ( buf[ i ] != ' ' )
355         tmp[ j++ ] =buf[ i++ ];
356
357       tmp[ j ] ='\0';
358       sizeE = atoi( tmp );
359
360       while ( buf[ ++i ] == ' ' );
361
362       j = 0;
363
364       while ( buf[ i ] != ' ' )
365         tmp[ j++ ] =buf[ i++ ];
366
367       tmp[ j ] ='\0';
368       hidden = atoi( tmp );
369
370       while ( buf[ ++i ] == ' ' );
371
372       j = 0;
373
374       while ( buf[ i ]  != ' ' )
375       tmp[ j++ ] =buf[ i++ ];
376
377       tmp[ j ] ='\0';
378       sizeM = atoi( tmp );
379       sizeM++ ;  // +1 for the sign
380     }
381
382     while ( buf[ i ]  == ' ' )  i++;
383
384     // read destination format
385     if ( ( strncmp( operation,"rt",2 )  == 0 )  || ( strncmp( operation,"ct",2 )  == 0 ) )  {
386       if ( !isdigit( buf[ i ] ) )  {
387         prec = buf[ i ];
388         switch ( prec )  {
389           case 's':
390             dsizeE=8;
391             dsizeM=23+1;
392             dhidden=1;
393             break;
394           case 'd':
395             dsizeE=11;
396             dsizeM=52+1;
397             dhidden=1;
398             break;
399           case 'l':
400             dsizeE=15;
401             dsizeM=64 + 1;
402             dhidden=0;
403             // cout << 'l' << endl;
404             break;
405           case 'q':
406             dsizeE=15;
407             dsizeM=112+1;
408             dhidden=1;
409             break;
410           case 'm':
411             dsizeE=15;
412             dsizeM=240 + 1;
413             dhidden = 0;
414             break;
415         } // switch
416
417         i++;
418         while ( buf[ i ]  == ' ' )  i++;
419       } // if
420       else {
421         j = 0;
422
423         while ( buf[ i ]  != ' ' )
424           tmp[ j++ ] =buf[ i++ ];
425         tmp[ j ] ='\0';
426         dsizeE = atoi( tmp );
427
428         while ( buf[ ++i ] == ' ' );
429
430         j = 0;
431         while ( buf[ i ]  != ' ' )
432          tmp[ j++ ]  = buf[ i++ ];
433         tmp[ j ] ='\0';
434         dhidden = atoi( tmp );
435
436         while ( buf[ ++i ] == ' ' );
437         j = 0;
438
439         while ( buf[ i ]  != ' ' )
440           tmp[ j++ ] =buf[ i++ ];
441         tmp[ j ] ='\0';
442         dsizeM = atoi( tmp );
443         dsizeM++;
444
445       } // else
446
447       while ( buf[ i ]  == ' ' )  i++;
448     } // if
449     else {
450       dsizeE = sizeE;
451       dhidden = hidden;
452       dsizeM = sizeM;
453     } // else
454
455     rounding=buf[ i ];
456
457     while ( buf[ ++i ] == ' ' );
458
459     j=0;
460
461     while ( buf[ i ]  != ' ' )
462        compare[ j++ ] =buf[ i++ ];
463
464     compare[ j ] ='\0';
465
466     while ( buf[ ++i ] == ' ' );
467
468     j=0;
469     while ( buf[ i ]  != ' ' )  {
470       exceptions[ j++ ] =buf[ i++ ];
471       exceptions[ j++ ] =' ';
472     }
473     exceptions[ j ] ='\0';
474
475     while ( buf[ ++i ] == ' ' );
476
477     if ( ( strncmp( operation,"ci",2 ) ==0 )  ||
478          ( strncmp( operation,"cu",2 ) ==0 ) )  {
479       count = 32; // 32 bit integer
480       i += 2; // avoid 0x
481
482       for ( j=0; j<count;j++ )  {
483       if ( isdigit( buf[ i ] )  || ( ( buf[ i ]  >= 'a' )  && ( buf[ i ]  <= 'f' ) ) )
484           tmp[ j ]  = buf[ i++ ];
485         else {
486           tmp[ j ]  = 0;
487           break;
488         }
489       } // for
490
491     for ( ; j<count;j++ )
492         tmp[ j ]  = 0;
493
494     } else if ( ( strncmp( operation,"cI",2 ) ==0 )  ||
495                 ( strncmp( operation,"cU",2 ) ==0 ) )  {
496       count = 64; // 64 bit integer
497       i += 2; // avoid 0x
498       for ( j=0; j<count;j++ )  {
499       if ( isdigit( buf[ i ] )  || ( ( buf[ i ]  >= 'a' )  && ( buf[ i ]  <= 'f' ) ) )
500           tmp[ j ]  = buf[ i++ ];
501         else {
502           tmp[ j ]  = 0;
503           break;
504         }
505       }
506       for ( ; j<count;j++ )
507         tmp[ j ]  = 0;
508
509     } else if ( strncmp( operation,"d2b",3 )  == 0 )  {
510       j = 0;
511       while ( buf[ i ]  != ' ' )  {
512         tmp[ j++ ]  = buf[ i++ ];
513       }
514
515     } else {
516       count =( int )  ceil( ( double ) ( sizeM+sizeE ) /32.0 ) *8;
517       for ( j=0; j<count ;j++ ) {
518         if ( buf[ i ] ==' ' )
519           i++;
520         tmp[ j ]  = buf[ i++ ];
521       }
522     }
523     tmp[ j ] ='\0';
524
525     if ( strncmp( operation,"d2b",3 )  == 0 )  {
526       operand1 = T( sizeM-1, sizeE, hidden ); // sets Mantissa and exp right
527       operand1.decimal = new char[ maxstr ];
528       for ( k = 0; k <= j; k++ )
529         operand1.decimal[ k ]  = tmp[ k ];
530       operand1.decimal[ k ]  = '\n';
531     } else if ( strncmp( operation,"ci",2 ) ==0 )  {
532       tmphex.StringToBitstr( tmp );
533       operand1 = T( tmphex,32,0,0 );
534     } else if ( strncmp( operation,"cu",2 ) ==0 )  {
535       tmphex.StringToBitstr( tmp );
536       operand1 = T( tmphex,32,0,0 );
537     } else if ( strncmp( operation,"cI",2 ) ==0 )  {
538       tmphex.StringToBitstr( tmp );
539       operand1 = T( tmphex,64,0,0 );
540     } else if ( strncmp( operation,"cU",2 ) ==0 )  {
541       tmphex.StringToBitstr( tmp );
542       operand1 = T( tmphex,64,0,0 );
543     } else {
544       tmphex.StringToBitstr( tmp );
545       operand1 = T( tmphex,sizeM-1,sizeE,hidden );
546     }
547
548     i++;
549     count =( int )  ceil( ( double ) ( sizeM+sizeE ) /32.0 ) *8; // reset count!
550
551     for ( j=0; j<count ;j++ ) {
552       if ( buf[ i ] ==' ' )
553         i++;
554       tmp[ j ]  = buf[ i++ ];
555     }
556
557     tmp[ j ] ='\0';
558     tmphex.StringToBitstr( tmp );
559     operand2 = T( tmphex,sizeM-1,sizeE,hidden );
560
561     if ( buf[ i+1 ]  == '?' )  {
562       pre = 1;
563     } else {
564       if ( ( strncmp( operation,"ri",2 ) ==0 )  ||
565            ( strncmp( operation,"ru",2 ) ==0 ) )  {
566         count = 32; // 32 bit integer
567         i += 3; // avoid 0x
568         for ( j=0; j<count;j++ )  {
569           if ( isdigit( buf[ i ] )  || ( ( buf[ i ]  >= 'a' )  && ( buf[ i ]  <= 'f' ) ) )
570             tmp[ j ]  = buf[ i++ ];
571           else {
572             tmp[ j ]  = 0;
573             break;
574           }
575         } // for
576         for ( ; j<count;j++ )
577           tmp[ j ]  = 0;
578       }
579       else if ( ( strncmp( operation,"rI",2 ) ==0 )  ||
580                 ( strncmp( operation,"rU",2 ) ==0 ) )  {
581         count = 64; // 64 bit integer
582         i += 3; // avoid 0x
583         for ( j=0; j<count;j++ )  {
584           if ( isdigit( buf[ i ] )  || ( ( buf[ i ]  >= 'a' )  && ( buf[ i ]  <= 'f' ) ) )
585             tmp[ j ]  = buf[ i++ ];
586           else {
587             tmp[ j ]  = 0;
588             break;
589           }
590         } // for
591         for ( ; j<count;j++ )
592           tmp[ j ]  = 0;
593       } else if ( strncmp( operation,"b2d",3 )  == 0 )  {
594         i++;
595         j = 0;
596         while ( buf[ i ]  != '\n' )  {
597           tmp[ j++ ]  = buf[ i++ ];
598         }
599       } else {
600         count =( int )  ceil( ( double ) ( dsizeM+dsizeE ) /32.0 ) *8;
601         i++;
602         for ( j=0; j<count ;j++ ) {
603           if ( buf[ i ] ==' ' )
604             i++;
605           tmp[ j ]  = buf[ i++ ];
606         }
607       }
608
609       tmp[ j ] ='\0';
610
611       if ( strncmp( operation,"b2d",3 )  == 0 )  {
612         result.decimal = new char[ maxstr ];
613         for ( k = 0; k <= j; k++ )
614           result.decimal[ k ]  = tmp[ k ];
615         result.decimal[ k ]  = '\0';
616       }
617
618       else if ( strncmp( operation,"ri",2 ) ==0 )  {
619         tmphex.StringToBitstr( tmp );
620         result = T( tmphex,32,0,0 );
621       } else if ( strncmp( operation,"ru",2 ) ==0 )  {
622         tmphex.StringToBitstr( tmp );
623         result = T( tmphex,32,0,0 );
624       } else if ( strncmp( operation,"rI",2 ) ==0 )  {
625         tmphex.StringToBitstr( tmp );
626         result = T( tmphex,64,0,0 );
627       } else if ( strncmp( operation,"rU",2 ) ==0 )  {
628         tmphex.StringToBitstr( tmp );
629         result = T( tmphex,64,0,0 );
630       } else {
631         tmphex.StringToBitstr( tmp );
632         result = T( tmphex,dsizeM-1,dsizeE,dhidden );
633       }
634
635       return 1;
636     }
637   }
638   return 0;
639 }
640
641 template <class T>
642 char* UCB<T>::GetOperation( )
643 {
644   return operation;
645 }
646
647 template <class T>
648 char  UCB<T>::GetPrecision( )
649 {
650   return prec;
651 }
652
653 template <class T>
654 char  UCB<T>::GetRounding( )
655 {
656   return rounding;
657 }
658
659 template <class T>
660 char* UCB<T>::GetCompare( )
661 {
662   return compare;
663 }
664
665 template <class T>
666 char* UCB<T>::GetExceptions( )
667 {
668   return exceptions;
669 }
670
671 template <class T>
672 T &  UCB<T>::GetOperand1( )
673 {
674   return operand1;
675 }
676
677 template <class T>
678 T &  UCB<T>::GetOperand2( )
679 {
680   return operand2;
681 }
682
683 template <class T>
684 T &  UCB<T>::GetResult( )
685 {
686   return result;
687 }
688
689 template <class T>
690 char* UCB<T>::DoLine( int tiny,int inf, int nan)
691 {
692   T res;
693   int i = 0;
694
695   if ( !( tiny )  && ( operand1.istiny( )  || operand2.istiny( )  || result.istiny( ) ) )
696     return NULL; // do not test tiny denormalized numbers
697   else if ( !( inf )  && ( operand1.isInf( )  || operand2.isInf( )  || result.isInf( ) ) )
698     return NULL; // do not test infinities
699   else if ( !( nan )  && ( operand1.isNan( )  || operand2.isNan( )  || result.isNan( ) ) )
700     return NULL; // do not test NaNs
701   // logstream.seekp(0,ios::beg);
702
703   allops++;
704   SetFPRound( );
705   result.ClearFPEnvironment( );
706
707 #ifdef BasicOperations
708   if ( strncmp( operation,"add",3 ) ==0 )
709     res = operand1 + operand2;
710   else if( strncmp( operation,"sub",3 ) ==0 )
711     res = operand1 - operand2;
712   else if( strncmp( operation,"mul",3 ) ==0 )
713     res = operand1 * operand2;
714   else if( strncmp( operation,"div",3 ) ==0 )
715     res = operand1 / operand2; // debug
716   else if( strncmp( operation,"rem",3 ) ==0 )
717     res = operand1 % operand2;
718   else if( strncmp( operation,"sqrt",4 ) ==0 )
719     res = operand1.sqrt( );
720 #endif
721
722 #ifdef Conversions
723   if ( strncmp( operation,"rt",2 ) ==0 )
724     res = operand1.roundto( dsizeE,dsizeM-1,dhidden );
725   else if ( strncmp( operation,"ct",2 ) ==0 )
726     res = operand1.copyto( dsizeE,dsizeM-1,dhidden );
727   else if ( strncmp( operation,"i",1 ) ==0 )
728     res = operand1.rint( );
729   else if ( strncmp( operation,"ri",2 ) ==0 )
730     res = operand1.ri( );
731   else if ( strncmp( operation,"ru",2 ) ==0 )
732     res = operand1.ru( );
733   else if ( strncmp( operation,"rI",2 ) ==0 )
734     res = operand1.rI( );
735   else if ( strncmp( operation,"rU",2 ) ==0 )
736     res = operand1.rU( );
737   else if ( strncmp( operation,"ci",2 ) ==0 )
738     res = operand1.ci( dsizeE,dsizeM-1,dhidden );
739   else if ( strncmp( operation,"cu",2 ) ==0 )
740     res = operand1.cu( dsizeE,dsizeM-1,dhidden );
741   else if ( strncmp( operation,"cI",2 ) ==0 )
742     res = operand1.cI( dsizeE,dsizeM-1,dhidden );
743   else if ( strncmp( operation,"cU",2 ) ==0 )
744     res = operand1.cU( dsizeE,dsizeM-1,dhidden );
745   else if ( strncmp( operation,"b2d",3 ) ==0 )  {
746     i = 0;
747     while ( result.decimal[ i ]  != 'E' )  {
748       i++;
749     }
750     if ( result.decimal[ 0 ]  == '+' || result.decimal[ 0 ]  == '-' )
751       i--;
752
753     res = operand1.b2d( i );
754   }
755   else if ( strncmp( operation,"d2b",3 ) ==0 )  {
756     res = operand1.d2b( );
757   }
758 #if defined(IntelPentium) && defined(NONE_TEST) && defined(Conversions)
759   else if( strncmp( operation,"rem",3 ) ==0 )
760     res = operand1 % operand2;
761   else if( strncmp( operation,"sqrt",4 ) ==0 )
762     res = operand1.sqrt( );
763 #endif
764
765 #endif
766
767   Compare( res );
768   return dest;
769 }
770
771 template <class T>
772 void UCB<T>::PrintError( T &res )
773 {
774   unsigned int i;
775   if ( (!ieeeVector) || (ieee) )
776     errors++; // total number of errors encountered
777   else
778     warnings++;
779   logfile<<"Operation: " << operation << endl;
780   switch ( rounding )  {
781     case 'n':
782       logfile<<"Round to nearest" << endl;
783       break;
784     case 'z':
785       logfile<<"Round to zero" << endl;
786       break;
787     case 'p':
788       logfile<<"Round up" << endl;
789       break;
790     case 'm':
791       logfile<<"Round down" << endl;
792       break;
793   } // switch
794   logfile<<"Operand 1: " << operand1 << endl;
795   logfile<<"Operand 2: " << operand2 << endl;
796   logfile<< "Flags expected: ";
797   for( i=0 ; i < strlen( exceptions );i++ )
798     switch ( exceptions[ i ] ) {
799       case 'x':
800         logfile<<"x ";
801         break;
802       case 'o':
803         logfile<<"o ";
804         break;
805       case 'u':
806         logfile<<"u ";
807         break;
808       case 'a':
809         logfile<<"v ";
810         break;
811       case 'b':
812         logfile<<"w ";
813         break;
814       case 'v':
815         logfile<<"i ";
816         break;
817       case 'd':
818         logfile<<"z ";
819         break;
820     } // switch
821   logfile << endl;
822   logfile <<"Flags returned: ";
823   if ( res.GetFPDivByZero( ) )
824     logfile << "z " ;
825   if ( res.GetFPInvalid( ) )
826     logfile << "i " ;
827   if ( res.GetFPInexact( ) )
828     logfile << "x " ;
829   if ( res.GetFPOverflow( ) )
830     logfile << "o " ;
831   if ( res.GetFPUnderflow( ) )  {
832     logfile << "u " ;
833   }
834   logfile << endl;
835   logfile << "Correct result:  " << result << endl;
836   logfile << "Returned result: " << res << endl<< endl;
837 }
838
839
840 template <class T>
841 void UCB<T>::Compare ( T &reslt )
842 {
843   unsigned int i,check=1;
844   if ( ( noFlags &  NO_FLAGS_DIV_BY_ZERO )  == 0 ) {
845     if( reslt.GetFPDivByZero( ) )
846       if( !strchr( exceptions,'d' ) ) {
847         logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") << "Line "<<line<< ": divide by zero not expected"<<endl;
848         check = 0;
849       }
850   }
851
852   if ( ( noFlags &  NO_FLAGS_INVALID )  == 0 ) {
853     if( reslt.GetFPInvalid( ) )
854       if( !strchr( exceptions,'v' ) ) {
855         logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": invalid not expected "<<endl;
856         check = 0;
857       }
858   }
859
860   if ( ( noFlags &  NO_FLAGS_INEXACT )  == 0 ) {
861     if( reslt.GetFPInexact( ) )
862       if( !strchr( exceptions,'x' ) ) {
863         logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": inexact not expected"<<endl;
864         check = 0;
865       }
866   }
867
868   if ( ( noFlags &  NO_FLAGS_OVERFLOW )  == 0 ) {
869     if( reslt.GetFPOverflow( ) )
870       if( !strchr( exceptions,'o' ) ) {
871         logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": overflow not expected"<<endl;
872         check = 0;
873       }
874   }
875
876   if ( ( noFlags &  NO_FLAGS_UNDERFLOW )  == 0 ) {
877     if( reslt.GetFPUnderflow( ) )
878       if( !strchr( exceptions,'u' ) ) {
879         if( strchr( exceptions,'a' ) )  {
880           signalv = 1;
881           if ( notsignalv )  {
882             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": underflow without denormalization loss previously not detected"<< endl;
883             check = 0;
884           } // end if
885         }
886         else if ( strchr( exceptions,'b' ) )  {
887           signalw = 1;
888           if ( notsignalv )  {
889             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": underflow without denormalization loss previously not detected" << endl;
890           }
891           if ( notsignalw )  {
892             logfile <<((ieeeVector) && !(ieee) ? "Warning " : "Error ")<<"Line "<<line<< ": underflow before rounding previously not detected"<< endl;
893             check = 0;
894           } // end if
895         }
896         else {
897           logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": underflow not expected"<<endl;
898           check = 0;
899         } // end if
900       }
901       else
902         signalu = 1;
903   } // end if
904
905   for( i=0 ; i < strlen( exceptions );i++ ) {
906     switch ( exceptions[ i ] ) {
907       case 'x':
908         if ( ( noFlags &  NO_FLAGS_INEXACT )  == 0 ) {
909           if( !reslt.GetFPInexact( ) ) {
910             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": inexact flag not returned"<<endl;
911             check = 0;
912           }
913         }
914         break;
915       case 'o':
916         if ( ( noFlags &  NO_FLAGS_OVERFLOW )  == 0 ) {
917           if( !reslt.GetFPOverflow( ) ) {
918             logfile <<((ieeeVector) && !(ieee) ? "Warning " : "Error ")<<"Line "<<line<< ": overflow flag not returned"<<endl;
919             check = 0;
920           }
921         }
922         break;
923       case 'u':
924         nou = 0;
925         if ( ( noFlags &  NO_FLAGS_UNDERFLOW )  == 0 ) {
926           if( !reslt.GetFPUnderflow( ) ) {
927             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": underflow not returned"<<endl;
928             notsignalu = 1;
929             check = 0;
930           }
931         }
932         break;
933       case 'a':
934         nov = 0;
935         if ( ( noFlags &  NO_FLAGS_UNDERFLOW )  == 0 ) {
936           if( !reslt.GetFPUnderflow( ) )  {
937             notsignalv = 1;
938             //PrintError(reslt);
939             if ( signalv )  {
940               check = 0;
941             } // end if
942           } // end if
943         } // end if
944
945         break;
946       case 'b':
947         now = 0;
948         if ( ( noFlags &  NO_FLAGS_UNDERFLOW )  == 0 ) {
949           if( !reslt.GetFPUnderflow( ) ) {
950             notsignalw = 1;
951             if ( signalw )  {
952               logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": underflow before rounding previously detected"<< endl;
953               check = 0;
954             } // end if
955           } // end if
956         } // end if
957
958         break;
959       case 'v':
960         if ( ( noFlags &  NO_FLAGS_INVALID )  == 0 ) {
961           if( !reslt.GetFPInvalid( ) ) {
962             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": invalid flag not returned"<<endl;
963             check = 0;
964           }
965         }
966         break;
967       case 'd':
968         if ( ( noFlags &  NO_FLAGS_DIV_BY_ZERO )  == 0 ) {
969           if( !reslt.GetFPDivByZero( ) ) {
970             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ")  <<"Line "<<line<< ": divide flag not returned"<<endl;
971             check = 0;
972           }
973         }
974         break;
975     }
976   }
977   if ( !pre )  { // no '?'
978     if ( result.decimal != NULL )  {
979       if ( strcmp( result.decimal,reslt.decimal )  != 0 )  {
980               int rd=0, rdd=0, epos=-100;
981               char *resultdummy=new char[maxstr];
982               while (result.decimal[rd] != '\0')
983               {
984                       if ((rd==epos+1) && result.decimal[rd]!='-')
985                          resultdummy[rdd++]='+';
986
987                  resultdummy[rdd] = result.decimal[rd];
988
989                  if (result.decimal[rd] == 'E')
990                     epos=rd;
991                  rd++;
992                  rdd++;
993               }
994               resultdummy[rdd] = '\0';
995
996               if (strcmp(resultdummy, reslt.decimal) != 0)
997                  {
998                    logfile <<((ieeeVector) && !(ieee) ? "Warning " : "Error ") << "Line "<<line<< ": different decimal representation"<< endl;
999                    check =0;
1000                  }
1001               delete[] resultdummy;
1002       }
1003     } else if ( result.IsNaN( ) ) {
1004       if( !reslt.IsNaN( ) ) {
1005         check=0;
1006         logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line : "<< line << ": result is not a NaN"<<endl;
1007       }
1008     } else {
1009       if ( reslt.sizeExp > 0 )  {
1010         if  ( result.Sign( )  != reslt.Sign( ) ) {
1011           if (!result.IsZero( )  ) {
1012             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": Different sign"<< endl;
1013             check =0;
1014           }
1015           else if ( signedZero ) {
1016             // In this case result is a zero and there is signedzero
1017             logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") <<"Line "<<line<< ": Different sign"<< endl;
1018             check =0;
1019           }
1020         }
1021         if ( result.GetExponent( )  != reslt.GetExponent( ) ) {
1022           logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") << "Line "<<line<< ": exponent different" << endl;
1023           check =0;
1024         }
1025       }
1026       if( result.GetMantissa( )  != reslt.GetMantissa( ) ) {
1027         logfile<<((ieeeVector) && !(ieee) ? "Warning " : "Error ") << "Line "<<line<< ": mantissa different" << endl;
1028         check =0;
1029       }
1030     }
1031   }
1032   if ( !check )
1033     PrintError( reslt );
1034 }
1035
1036 template <class T>
1037 void UCB<T>::SetFPRound( )
1038 {
1039   switch ( rounding ) {
1040     case 'n':
1041       result.SetFPRound( RM_NEAR );
1042       break;
1043     case 'z':
1044       result.SetFPRound( RM_ZERO );
1045       break;
1046     case 'p':
1047       result.SetFPRound( RM_UP );
1048       break;
1049     case 'm':
1050       result.SetFPRound( RM_DOWN );
1051       break;
1052   }
1053 }
1054
1055 #endif