Ignore:
Timestamp:
Apr 13, 2021, 5:48:41 PM (3 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
3ada8ae
Parents:
4c4e444
git-author:
Peter A. Buhr <pabuhr@…> (04/13/21 17:44:33)
git-committer:
Peter A. Buhr <pabuhr@…> (04/13/21 17:48:41)
Message:

fix incorrectly decimal-point printing, add engineering-notation manipulator

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/iostream.cfa

    r4c4e444 rfd4c009  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar  2 14:51:30 2021
    13 // Update Count     : 1151
     12// Last Modified On : Tue Apr 13 13:05:24 2021
     13// Update Count     : 1324
    1414//
    1515
     
    195195                        int len = snprintf( buf, size, format, ##__VA_ARGS__, val ); \
    196196                        fmt( os, "%s", buf ); \
    197                         if ( isfinite( val ) ) {                                        /* if number, always print decimal point */ \
     197                        if ( isfinite( val ) ) { /* if number, print decimal point when no fraction or exponent */ \
    198198                                for ( int i = 0;; i += 1 ) { \
    199199                                        if ( i == len ) { fmt( os, "." ); break; } \
    200                                         if ( buf[i] == '.' ) break; \
     200                                        if ( buf[i] == '.' || buf[i] == 'e' || buf[i] == 'E' ) break; /* decimal point or scientific ? */ \
    201201                                } /* for */ \
    202202                        } /* if */ \
     
    525525} // distribution
    526526
    527 IntegralFMTImpl( signed char, "%    *hh ", "%    *.*hh " )
    528 IntegralFMTImpl( unsigned char, "%    *hh ", "%    *.*hh " )
    529 IntegralFMTImpl( signed short int, "%    *h ", "%    *.*h " )
    530 IntegralFMTImpl( unsigned short int, "%    *h ", "%    *.*h " )
    531 IntegralFMTImpl( signed int, "%    * ", "%    *.* " )
    532 IntegralFMTImpl( unsigned int, "%    * ", "%    *.* " )
    533 IntegralFMTImpl( signed long int, "%    *l ", "%    *.*l " )
    534 IntegralFMTImpl( unsigned long int, "%    *l ", "%    *.*l " )
    535 IntegralFMTImpl( signed long long int, "%    *ll ", "%    *.*ll " )
    536 IntegralFMTImpl( unsigned long long int, "%    *ll ", "%    *.*ll " )
    537 
    538 #if 0
    539 #if defined( __SIZEOF_INT128__ )
    540 // Default prefix for non-decimal prints is 0b, 0, 0x.
    541 #define IntegralFMTImpl128( T, SIGNED, CODE, IFMTNP, IFMTP ) \
    542 forall( ostype & | ostream( ostype ) ) \
    543 static void base10_128( ostype & os, _Ostream_Manip(T) f ) { \
    544         if ( f.val > UINT64_MAX ) { \
    545                 unsigned long long int lsig = f.val % P10_UINT64; \
    546                 f.val /= P10_UINT64; /* msig */ \
    547                 base10_128( os, f ); /* recursion */ \
    548                 _Ostream_Manip(unsigned long long int) fmt @= { lsig, 0, 19, 'u', { .all : 0 } }; \
    549                 fmt.flags.nobsdp = true; \
    550                 /* printf( "fmt1 %c %lld %d\n", fmt.base, fmt.val, fmt.all ); */ \
    551                 sepOff( os ); \
    552                 (ostype &)(os | fmt); \
    553         } else { \
    554                 /* printf( "fmt2 %c %lld %d\n", f.base, (unsigned long long int)f.val, f.all ); */ \
    555                 _Ostream_Manip(SIGNED long long int) fmt @= { (SIGNED long long int)f.val, f.wd, f.pc, f.base, { .all : f.all } }; \
    556                 (ostype &)(os | fmt); \
    557         } /* if */ \
    558 } /* base10_128 */ \
    559 forall( ostype & | ostream( ostype ) ) { \
    560         ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    561                 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
    562 \
    563                 if ( f.base == 'b' | f.base == 'B' | f.base == 'o' | f.base == 'x' | f.base == 'X' ) { \
    564                         unsigned long long int msig = (unsigned long long int)(f.val >> 64); \
    565                         unsigned long long int lsig = (unsigned long long int)(f.val); \
    566                         _Ostream_Manip(SIGNED long long int) fmt @= { msig, f.wd, f.pc, f.base, { .all : f.all } }; \
    567                         _Ostream_Manip(unsigned long long int) fmt2 @= { lsig, 0, 0, f.base, { .all : 0 } }; \
    568                         if ( msig == 0 ) { \
    569                                 fmt.val = lsig; \
    570                                 (ostype &)(os | fmt); \
    571                         } else { \
    572                                 fmt2.flags.pad0 = fmt2.flags.nobsdp = true;     \
    573                                 if ( f.base == 'b' | f.base == 'B' ) { \
    574                                         if ( fmt.flags.pc && fmt.pc > 64 ) fmt.pc -= 64; else { fmt.flags.pc = false; fmt.pc = 0; } \
    575                                         if ( fmt.flags.left ) { \
    576                                                 fmt.flags.left = false; \
    577                                                 fmt.wd = 0; \
    578                                                 /* printf( "L %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    579                                                 fmt2.flags.left = true; \
    580                                                 int msigd = high1( msig ); \
    581                                                 fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
    582                                                 if ( ! fmt.flags.nobsdp ) fmt2.wd -= 2; /* compensate for 0b base specifier */ \
    583                                                 if ( (int)fmt2.wd < 64 ) fmt2.wd = 64; /* cast deals with negative value */ \
    584                                                 fmt2.flags.pc = true; fmt2.pc = 64; \
    585                                         } else { \
    586                                                 if ( fmt.wd > 64 ) fmt.wd -= 64; \
    587                                                 else fmt.wd = 1; \
    588                                                 /* printf( "R %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    589                                                 fmt2.wd = 64; \
    590                                         } /* if */ \
    591                                         /* printf( "C %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    592                                         (ostype &)(os | fmt | "" | fmt2); \
    593                                 } else if ( f.base == 'o' ) { \
    594                                         if ( fmt.flags.pc && fmt.pc > 22 ) fmt.pc -= 22; else { fmt.flags.pc = false; fmt.pc = 0; } \
    595                                         fmt.val = (unsigned long long int)fmt.val >> 2; \
    596                                         fmt2.val = ((msig & 0x3) << 1) + ((lsig & 0x8000000000000000U) != 0); \
    597                                         if ( fmt.flags.left ) { \
    598                                                 fmt.flags.left = false; \
    599                                                 fmt.wd = 0; \
    600                                                 /* printf( "L %llo %llo %llo %d %d '%c' %x %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all, fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    601                                                 (ostype &)(os | fmt | "" | fmt2); \
    602                                                 sepOff( os ); \
    603                                                 fmt2.flags.left = true; \
    604                                                 int msigd = ceiling_div( high1( fmt.val ), 3 ); \
    605                                                 fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
    606                                                 if ( ! fmt.flags.nobsdp ) fmt2.wd -= 1; /* compensate for 0 base specifier */ \
    607                                                 if ( (int)fmt2.wd < 21 ) fmt2.wd = 21; /* cast deals with negative value */ \
    608                                                 fmt2.flags.pc = true; fmt2.pc = 21; \
    609                                         } else { \
    610                                                 if ( fmt.wd > 22 ) fmt.wd -= 22; \
    611                                                 else fmt.wd = 1; \
    612                                                 /* printf( "R %llo %llo %llo %d %d '%c' %x %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all, fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    613                                                 (ostype &)(os | fmt | "" | fmt2); \
    614                                                 sepOff( os ); \
    615                                                 fmt2.wd = 21; \
    616                                         } /* if */ \
    617                                         fmt2.val = lsig & 0x7fffffffffffffffU; \
    618                                         /* printf( "\nC %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    619                                         (ostype &)(os | fmt2); \
    620                                 } else { /* f.base == 'x'  | f.base == 'X' */ \
    621                                         if ( fmt.flags.pc && fmt.pc > 16 ) fmt.pc -= 16; else { fmt.flags.pc = false; fmt.pc = 0; } \
    622                                         if ( fmt.flags.left ) { \
    623                                                 fmt.flags.left = false; \
    624                                                 fmt.wd = 0; \
    625                                                 /* printf( "L %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    626                                                 fmt2.flags.left = true; \
    627                                                 int msigd = high1( msig ); \
    628                                                 fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd); \
    629                                                 if ( ! fmt.flags.nobsdp ) fmt2.wd -= 2; /* compensate for 0x base specifier */ \
    630                                                 if ( (int)fmt2.wd < 16 ) fmt2.wd = 16; /* cast deals with negative value */ \
    631                                                 fmt2.flags.pc = true; fmt2.pc = 16; \
    632                                         } else { \
    633                                                 if ( fmt.wd > 16 ) fmt.wd -= 16; \
    634                                                 else fmt.wd = 1; \
    635                                                 /* printf( "R %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
    636                                                 fmt2.wd = 16; \
    637                                         } /* if */ \
    638                                         /* printf( "C %llo %d %d '%c' %x\n", fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
    639                                         (ostype &)(os | fmt | "" | fmt2); \
    640                                 } /* if */ \
    641                         } /* if */ \
    642                 } else { \
    643                         if ( CODE == 'd' ) { \
    644                                 if ( f.val < 0 )  { fmt( os, "-" ); sepOff( os ); f.val = -f.val; f.flags.sign = false; } \
    645                         } /* if */ \
    646                         base10_128( os, f ); \
    647                 } /* if */ \
    648                 return os; \
    649         } /* ?|? */ \
    650         void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \
    651 } // distribution
    652 
    653 IntegralFMTImpl128( int128, signed, 'd', "%    *ll ", "%    *.*ll " )
    654 IntegralFMTImpl128( unsigned int128, unsigned, 'u', "%    *ll ", "%    *.*ll " )
    655 #endif // __SIZEOF_INT128__
    656 #endif // 0
    657 
    658 #if 1
     527IntegralFMTImpl( signed char, "     *hh ", "     *.*hh " )
     528IntegralFMTImpl( unsigned char, "     *hh ", "     *.*hh " )
     529IntegralFMTImpl( signed short int, "     *h ", "     *.*h " )
     530IntegralFMTImpl( unsigned short int, "     *h ", "     *.*h " )
     531IntegralFMTImpl( signed int, "     * ", "     *.* " )
     532IntegralFMTImpl( unsigned int, "     * ", "     *.* " )
     533IntegralFMTImpl( signed long int, "     *l ", "     *.*l " )
     534IntegralFMTImpl( unsigned long int, "     *l ", "     *.*l " )
     535IntegralFMTImpl( signed long long int, "     *ll ", "     *.*ll " )
     536IntegralFMTImpl( unsigned long long int, "     *ll ", "     *.*ll " )
     537
     538
    659539#if defined( __SIZEOF_INT128__ )
    660540// Default prefix for non-decimal prints is 0b, 0, 0x.
     
    746626IntegralFMTImpl128( unsigned int128 )
    747627#endif // __SIZEOF_INT128__
    748 #endif // 0
    749628
    750629// *********************************** floating point ***********************************
    751630
    752 #define PrintWithDP2( os, format, val, ... ) \
     631static const char *suffixes[] = {
     632        "y", "z", "a", "f", "p", "n", "u", "m", "",
     633        "K", "M", "G", "T", "P", "E", "Z", "Y"
     634};
     635#define SUFFIXES_START (-24) /* Smallest power for which there is a suffix defined. */
     636#define SUFFIXES_END (SUFFIXES_START + (int)((sizeof(suffixes) / sizeof(char *) - 1) * 3))
     637
     638#define PrintWithDP2( os, format, ... ) \
    753639        { \
    754                 enum { size = 48 }; \
    755                 char buf[size]; \
    756                 int bufbeg = 0, i, len = snprintf( buf, size, format, ##__VA_ARGS__, val ); \
    757                 if ( isfinite( val ) && (f.base != 'g' || f.pc != 0) ) { /* if number, print decimal point */ \
    758                         for ( i = 0; i < len && buf[i] != '.' && buf[i] != 'e' && buf[i] != 'E'; i += 1 ); /* decimal point or scientific ? */ \
    759                         if ( i == len && ! f.flags.nobsdp ) { \
    760                                 if ( ! f.flags.left ) { \
    761                                         buf[i] = '.'; buf[i + 1] = '\0'; \
    762                                         if ( buf[0] == ' ' ) bufbeg = 1;        /* decimal point within width */ \
    763                                 } else { \
    764                                         for ( i = 0; i < len && buf[i] != ' '; i += 1 ); /* trailing blank ? */ \
    765                                         buf[i] = '.'; \
    766                                         if ( i == len ) buf[i + 1] = '\0'; \
     640                if ( ! f.flags.eng ) { \
     641                        len = snprintf( buf, size, format, ##__VA_ARGS__ ); \
     642                        if ( isfinite( f.val ) && ( f.pc != 0 || ! f.flags.nobsdp ) ) { /* if number, print decimal point when no fraction or exponent */ \
     643                                for ( i = 0; i < len && buf[i] != '.' && buf[i] != 'e' && buf[i] != 'E'; i += 1 ); /* decimal point or scientific ? */ \
     644                                if ( i == len ) { \
     645                                        if ( ! f.flags.left ) { \
     646                                                buf[i] = '.'; buf[i + 1] = '\0'; \
     647                                                if ( buf[0] == ' ' ) bufbeg = 1; /* decimal point within width */ \
     648                                        } else { \
     649                                                for ( i = 0; i < len && buf[i] != ' '; i += 1 ); /* trailing blank ? */ \
     650                                                buf[i] = '.'; \
     651                                                if ( i == len ) buf[i + 1] = '\0'; \
     652                                        } /* if */ \
    767653                                } /* if */ \
    768654                        } /* if */ \
     655                } else { \
     656                        int exp10, len2; \
     657                        eng( f.val, f.pc, exp10 );                                      /* changes arguments */ \
     658                        if ( ! f.flags.left && f.wd > 1 ) { \
     659                                /* Exponent size (number of digits, 'e', optional minus sign) */ \
     660                                f.wd -= lrint( floor( log10( abs( exp10 ) ) ) ) + 1 + 1 + (exp10 < 0 ? 1 : 0); \
     661                                if ( f.wd < 1 ) f.wd = 1; \
     662                        } /* if */ \
     663                        len = snprintf( buf, size, format, ##__VA_ARGS__ ); \
     664                        if ( f.flags.left ) { \
     665                                for ( len -= 1; len > 0 && buf[len] == ' '; len -= 1 ); \
     666                                len += 1; \
     667                        } /* if */ \
     668                        if ( ! f.flags.nobsdp || (exp10 < SUFFIXES_START) || (exp10 > SUFFIXES_END) ) { \
     669                                len2 = snprintf( &buf[len], size - len, "e%d", exp10 ); \
     670                        } else { \
     671                                len2 = snprintf( &buf[len], size - len, "%s", suffixes[(exp10 - SUFFIXES_START) / 3] ); \
     672                        } /* if */ \
     673                        if ( f.flags.left && len + len2 < f.wd ) buf[len + len2] = ' '; \
    769674                } /* if */ \
    770675                fmt( os, "%s", &buf[bufbeg] ); \
     
    773678#define FloatingPointFMTImpl( T, DFMTNP, DFMTP ) \
    774679forall( ostype & | ostream( ostype ) ) { \
     680        static void eng( T &value, int & pc, int & exp10 ) { \
     681                exp10 = lrint( floor( log10( abs( value ) ) ) ); /* round to desired precision */ \
     682                if ( exp10 < 0 ) exp10 -= 2; \
     683                exp10 = floor( exp10, 3 ); \
     684                value *= pow( 10.0, -exp10 ); \
     685                if ( pc <= 3 ) pc = 3; \
     686        } /* eng */ \
     687\
    775688        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     689                enum { size = 48 }; \
     690                char buf[size]; \
     691                int bufbeg = 0, i, len; \
     692\
    776693                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
    777                 char fmtstr[sizeof(DFMTP)];                                             /* sizeof includes '\0' */ \
     694                char fmtstr[sizeof(DFMTP) + 8];                                 /* sizeof includes '\0' */ \
    778695                if ( ! f.flags.pc ) memcpy( &fmtstr, DFMTNP, sizeof(DFMTNP) ); \
    779696                else memcpy( &fmtstr, DFMTP, sizeof(DFMTP) ); \
     
    789706                        fmtstr[sizeof(DFMTNP)-2] = f.base;                      /* sizeof includes '\0' */ \
    790707                        /* printf( "%g %d %s\n", f.val, f.wd, &fmtstr[star]); */ \
    791                         PrintWithDP2( os, &fmtstr[star], f.val, f.wd ) \
     708                        PrintWithDP2( os, &fmtstr[star], f.wd, f.val ) \
    792709                } else {                                                                                /* precision */ \
    793710                        fmtstr[sizeof(DFMTP)-2] = f.base;                       /* sizeof includes '\0' */ \
    794711                        /* printf( "%g %d %d %s\n", f.val, f.wd, f.pc, &fmtstr[star] ); */ \
    795                         PrintWithDP2( os, &fmtstr[star], f.val, f.wd, f.pc ) \
     712                        PrintWithDP2( os, &fmtstr[star], f.wd, f.pc, f.val ) \
    796713                } /* if */ \
    797714                return os; \
     
    801718} // distribution
    802719
    803 FloatingPointFMTImpl( double, "%    * ", "%    *.* " )
    804 FloatingPointFMTImpl( long double, "%    *L ", "%    *.*L " )
     720FloatingPointFMTImpl( double, "     * ", "     *.* " )
     721FloatingPointFMTImpl( long double, "     *L ", "     *.*L " )
    805722
    806723// *********************************** character ***********************************
Note: See TracChangeset for help on using the changeset viewer.