github.com/matrixorigin/matrixone@v0.7.0/cgo/external/decNumber/decimal32.c (about)

     1  /* ------------------------------------------------------------------ */
     2  /* Decimal 32-bit format module                                       */
     3  /* ------------------------------------------------------------------ */
     4  /* Copyright (c) IBM Corporation, 2000, 2008.  All rights reserved.   */
     5  /*                                                                    */
     6  /* This software is made available under the terms of the             */
     7  /* ICU License -- ICU 1.8.1 and later.                                */
     8  /*                                                                    */
     9  /* The description and User's Guide ("The decNumber C Library") for   */
    10  /* this software is called decNumber.pdf.  This document is           */
    11  /* available, together with arithmetic and format specifications,     */
    12  /* testcases, and Web links, on the General Decimal Arithmetic page.  */
    13  /*                                                                    */
    14  /* Please send comments, suggestions, and corrections to the author:  */
    15  /*   mfc@uk.ibm.com                                                   */
    16  /*   Mike Cowlishaw, IBM Fellow                                       */
    17  /*   IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK         */
    18  /* ------------------------------------------------------------------ */
    19  /* This module comprises the routines for decimal32 format numbers.   */
    20  /* Conversions are supplied to and from decNumber and String.         */
    21  /*                                                                    */
    22  /* This is used when decNumber provides operations, either for all    */
    23  /* operations or as a proxy between decNumber and decSingle.          */
    24  /*                                                                    */
    25  /* Error handling is the same as decNumber (qv.).                     */
    26  /* ------------------------------------------------------------------ */
    27  #include <string.h>           // [for memset/memcpy]
    28  #include <stdio.h>            // [for printf]
    29  
    30  #define  DECNUMDIGITS  7      // make decNumbers with space for 7
    31  #include "decNumber.h"        // base number library
    32  #include "decNumberLocal.h"   // decNumber local types, etc.
    33  #include "decimal32.h"        // our primary include
    34  
    35  /* Utility tables and routines [in decimal64.c] */
    36  // DPD2BIN and the reverse are renamed to prevent link-time conflict
    37  // if decQuad is also built in the same executable
    38  #define DPD2BIN DPD2BINx
    39  #define BIN2DPD BIN2DPDx
    40  extern const uInt   COMBEXP[32], COMBMSD[32];
    41  extern const uShort DPD2BIN[1024];
    42  extern const uShort BIN2DPD[1000];
    43  extern const uByte  BIN2CHAR[4001];
    44  
    45  extern void decDigitsToDPD(const decNumber *, uInt *, Int);
    46  extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
    47  
    48  #if DECTRACE || DECCHECK
    49  void decimal32Show(const decimal32 *);            // for debug
    50  extern void decNumberShow(const decNumber *);     // ..
    51  #endif
    52  
    53  /* Useful macro */
    54  // Clear a structure (e.g., a decNumber)
    55  #define DEC_clear(d) memset(d, 0, sizeof(*d))
    56  
    57  /* ------------------------------------------------------------------ */
    58  /* decimal32FromNumber -- convert decNumber to decimal32              */
    59  /*                                                                    */
    60  /*   ds is the target decimal32                                       */
    61  /*   dn is the source number (assumed valid)                          */
    62  /*   set is the context, used only for reporting errors               */
    63  /*                                                                    */
    64  /* The set argument is used only for status reporting and for the     */
    65  /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
    66  /* digits or an overflow is detected).  If the exponent is out of the */
    67  /* valid range then Overflow or Underflow will be raised.             */
    68  /* After Underflow a subnormal result is possible.                    */
    69  /*                                                                    */
    70  /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
    71  /* by reducing its exponent and multiplying the coefficient by a      */
    72  /* power of ten, or if the exponent on a zero had to be clamped.      */
    73  /* ------------------------------------------------------------------ */
    74  decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
    75                                decContext *set) {
    76    uInt status=0;                   // status accumulator
    77    Int ae;                          // adjusted exponent
    78    decNumber  dw;                   // work
    79    decContext dc;                   // ..
    80    uInt comb, exp;                  // ..
    81    uInt uiwork;                     // for macros
    82    uInt targ=0;                     // target 32-bit
    83  
    84    // If the number has too many digits, or the exponent could be
    85    // out of range then reduce the number under the appropriate
    86    // constraints.  This could push the number to Infinity or zero,
    87    // so this check and rounding must be done before generating the
    88    // decimal32]
    89    ae=dn->exponent+dn->digits-1;              // [0 if special]
    90    if (dn->digits>DECIMAL32_Pmax              // too many digits
    91     || ae>DECIMAL32_Emax                      // likely overflow
    92     || ae<DECIMAL32_Emin) {                   // likely underflow
    93      decContextDefault(&dc, DEC_INIT_DECIMAL32); // [no traps]
    94      dc.round=set->round;                     // use supplied rounding
    95      decNumberPlus(&dw, dn, &dc);             // (round and check)
    96      // [this changes -0 to 0, so enforce the sign...]
    97      dw.bits|=dn->bits&DECNEG;
    98      status=dc.status;                        // save status
    99      dn=&dw;                                  // use the work number
   100      } // maybe out of range
   101  
   102    if (dn->bits&DECSPECIAL) {                      // a special value
   103      if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
   104       else {                                       // sNaN or qNaN
   105        if ((*dn->lsu!=0 || dn->digits>1)           // non-zero coefficient
   106         && (dn->digits<DECIMAL32_Pmax)) {          // coefficient fits
   107          decDigitsToDPD(dn, &targ, 0);
   108          }
   109        if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
   110         else targ|=DECIMAL_sNaN<<24;
   111        } // a NaN
   112      } // special
   113  
   114     else { // is finite
   115      if (decNumberIsZero(dn)) {               // is a zero
   116        // set and clamp exponent
   117        if (dn->exponent<-DECIMAL32_Bias) {
   118          exp=0;                               // low clamp
   119          status|=DEC_Clamped;
   120          }
   121         else {
   122          exp=dn->exponent+DECIMAL32_Bias;     // bias exponent
   123          if (exp>DECIMAL32_Ehigh) {           // top clamp
   124            exp=DECIMAL32_Ehigh;
   125            status|=DEC_Clamped;
   126            }
   127          }
   128        comb=(exp>>3) & 0x18;             // msd=0, exp top 2 bits ..
   129        }
   130       else {                             // non-zero finite number
   131        uInt msd;                         // work
   132        Int pad=0;                        // coefficient pad digits
   133  
   134        // the dn is known to fit, but it may need to be padded
   135        exp=(uInt)(dn->exponent+DECIMAL32_Bias);    // bias exponent
   136        if (exp>DECIMAL32_Ehigh) {                  // fold-down case
   137          pad=exp-DECIMAL32_Ehigh;
   138          exp=DECIMAL32_Ehigh;                      // [to maximum]
   139          status|=DEC_Clamped;
   140          }
   141  
   142        // fastpath common case
   143        if (DECDPUN==3 && pad==0) {
   144          targ=BIN2DPD[dn->lsu[0]];
   145          if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
   146          msd=(dn->digits==7 ? dn->lsu[2] : 0);
   147          }
   148         else { // general case
   149          decDigitsToDPD(dn, &targ, pad);
   150          // save and clear the top digit
   151          msd=targ>>20;
   152          targ&=0x000fffff;
   153          }
   154  
   155        // create the combination field
   156        if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
   157               else comb=((exp>>3) & 0x18) | msd;
   158        }
   159      targ|=comb<<26;                // add combination field ..
   160      targ|=(exp&0x3f)<<20;          // .. and exponent continuation
   161      } // finite
   162  
   163    if (dn->bits&DECNEG) targ|=0x80000000;  // add sign bit
   164  
   165    // now write to storage; this is endian
   166    UBFROMUI(d32->bytes, targ);      // directly store the int
   167  
   168    if (status!=0) decContextSetStatus(set, status); // pass on status
   169    // decimal32Show(d32);
   170    return d32;
   171    } // decimal32FromNumber
   172  
   173  /* ------------------------------------------------------------------ */
   174  /* decimal32ToNumber -- convert decimal32 to decNumber                */
   175  /*   d32 is the source decimal32                                      */
   176  /*   dn is the target number, with appropriate space                  */
   177  /* No error is possible.                                              */
   178  /* ------------------------------------------------------------------ */
   179  decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
   180    uInt msd;                        // coefficient MSD
   181    uInt exp;                        // exponent top two bits
   182    uInt comb;                       // combination field
   183    uInt sour;                       // source 32-bit
   184    uInt uiwork;                     // for macros
   185  
   186    // load source from storage; this is endian
   187    sour=UBTOUI(d32->bytes);         // directly load the int
   188  
   189    comb=(sour>>26)&0x1f;            // combination field
   190  
   191    decNumberZero(dn);               // clean number
   192    if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative
   193  
   194    msd=COMBMSD[comb];               // decode the combination field
   195    exp=COMBEXP[comb];               // ..
   196  
   197    if (exp==3) {                    // is a special
   198      if (msd==0) {
   199        dn->bits|=DECINF;
   200        return dn;                   // no coefficient needed
   201        }
   202      else if (sour&0x02000000) dn->bits|=DECSNAN;
   203      else dn->bits|=DECNAN;
   204      msd=0;                         // no top digit
   205      }
   206     else {                          // is a finite number
   207      dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
   208      }
   209  
   210    // get the coefficient
   211    sour&=0x000fffff;                // clean coefficient continuation
   212    if (msd) {                       // non-zero msd
   213      sour|=msd<<20;                 // prefix to coefficient
   214      decDigitsFromDPD(dn, &sour, 3); // process 3 declets
   215      return dn;
   216      }
   217    // msd=0
   218    if (!sour) return dn;            // easy: coefficient is 0
   219    if (sour&0x000ffc00)             // need 2 declets?
   220      decDigitsFromDPD(dn, &sour, 2); // process 2 declets
   221     else
   222      decDigitsFromDPD(dn, &sour, 1); // process 1 declet
   223    return dn;
   224    } // decimal32ToNumber
   225  
   226  /* ------------------------------------------------------------------ */
   227  /* to-scientific-string -- conversion to numeric string               */
   228  /* to-engineering-string -- conversion to numeric string              */
   229  /*                                                                    */
   230  /*   decimal32ToString(d32, string);                                  */
   231  /*   decimal32ToEngString(d32, string);                               */
   232  /*                                                                    */
   233  /*  d32 is the decimal32 format number to convert                     */
   234  /*  string is the string where the result will be laid out            */
   235  /*                                                                    */
   236  /*  string must be at least 24 characters                             */
   237  /*                                                                    */
   238  /*  No error is possible, and no status can be set.                   */
   239  /* ------------------------------------------------------------------ */
   240  char * decimal32ToEngString(const decimal32 *d32, char *string){
   241    decNumber dn;                         // work
   242    decimal32ToNumber(d32, &dn);
   243    decNumberToEngString(&dn, string);
   244    return string;
   245    } // decimal32ToEngString
   246  
   247  char * decimal32ToString(const decimal32 *d32, char *string){
   248    uInt msd;                        // coefficient MSD
   249    Int  exp;                        // exponent top two bits or full
   250    uInt comb;                       // combination field
   251    char *cstart;                    // coefficient start
   252    char *c;                         // output pointer in string
   253    const uByte *u;                  // work
   254    char *s, *t;                     // .. (source, target)
   255    Int  dpd;                        // ..
   256    Int  pre, e;                     // ..
   257    uInt uiwork;                     // for macros
   258    uInt sour;                       // source 32-bit
   259  
   260    // load source from storage; this is endian
   261    sour=UBTOUI(d32->bytes);         // directly load the int
   262  
   263    c=string;                        // where result will go
   264    if (((Int)sour)<0) *c++='-';     // handle sign
   265  
   266    comb=(sour>>26)&0x1f;            // combination field
   267    msd=COMBMSD[comb];               // decode the combination field
   268    exp=COMBEXP[comb];               // ..
   269  
   270    if (exp==3) {
   271      if (msd==0) {                  // infinity
   272        strcpy(c,   "Inf");
   273        strcpy(c+3, "inity");
   274        return string;               // easy
   275        }
   276      if (sour&0x02000000) *c++='s'; // sNaN
   277      strcpy(c, "NaN");              // complete word
   278      c+=3;                          // step past
   279      if ((sour&0x000fffff)==0) return string; // zero payload
   280      // otherwise drop through to add integer; set correct exp
   281      exp=0; msd=0;                  // setup for following code
   282      }
   283     else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
   284  
   285    // convert 7 digits of significand to characters
   286    cstart=c;                        // save start of coefficient
   287    if (msd) *c++='0'+(char)msd;     // non-zero most significant digit
   288  
   289    // Now decode the declets.  After extracting each one, it is
   290    // decoded to binary and then to a 4-char sequence by table lookup;
   291    // the 4-chars are a 1-char length (significant digits, except 000
   292    // has length 0).  This allows us to left-align the first declet
   293    // with non-zero content, then remaining ones are full 3-char
   294    // length.  We use fixed-length memcpys because variable-length
   295    // causes a subroutine call in GCC.  (These are length 4 for speed
   296    // and are safe because the array has an extra terminator byte.)
   297    #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                   \
   298                     if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
   299                      else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
   300  
   301    dpd=(sour>>10)&0x3ff;            // declet 1
   302    dpd2char;
   303    dpd=(sour)&0x3ff;                // declet 2
   304    dpd2char;
   305  
   306    if (c==cstart) *c++='0';         // all zeros -- make 0
   307  
   308    if (exp==0) {                    // integer or NaN case -- easy
   309      *c='\0';                       // terminate
   310      return string;
   311      }
   312  
   313    /* non-0 exponent */
   314    e=0;                             // assume no E
   315    pre=c-cstart+exp;
   316    // [here, pre-exp is the digits count (==1 for zero)]
   317    if (exp>0 || pre<-5) {           // need exponential form
   318      e=pre-1;                       // calculate E value
   319      pre=1;                         // assume one digit before '.'
   320      } // exponential form
   321  
   322    /* modify the coefficient, adding 0s, '.', and E+nn as needed */
   323    s=c-1;                           // source (LSD)
   324    if (pre>0) {                     // ddd.ddd (plain), perhaps with E
   325      char *dotat=cstart+pre;
   326      if (dotat<c) {                 // if embedded dot needed...
   327        t=c;                              // target
   328        for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
   329        *t='.';                           // insert the dot
   330        c++;                              // length increased by one
   331        }
   332  
   333      // finally add the E-part, if needed; it will never be 0, and has
   334      // a maximum length of 3 digits (E-101 case)
   335      if (e!=0) {
   336        *c++='E';                    // starts with E
   337        *c++='+';                    // assume positive
   338        if (e<0) {
   339          *(c-1)='-';                // oops, need '-'
   340          e=-e;                      // uInt, please
   341          }
   342        u=&BIN2CHAR[e*4];            // -> length byte
   343        memcpy(c, u+4-*u, 4);        // copy fixed 4 characters [is safe]
   344        c+=*u;                       // bump pointer appropriately
   345        }
   346      *c='\0';                       // add terminator
   347      //printf("res %s\n", string);
   348      return string;
   349      } // pre>0
   350  
   351    /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
   352    t=c+1-pre;
   353    *(t+1)='\0';                          // can add terminator now
   354    for (; s>=cstart; s--, t--) *t=*s;    // shift whole coefficient right
   355    c=cstart;
   356    *c++='0';                             // always starts with 0.
   357    *c++='.';
   358    for (; pre<0; pre++) *c++='0';        // add any 0's after '.'
   359    //printf("res %s\n", string);
   360    return string;
   361    } // decimal32ToString
   362  
   363  /* ------------------------------------------------------------------ */
   364  /* to-number -- conversion from numeric string                        */
   365  /*                                                                    */
   366  /*   decimal32FromString(result, string, set);                        */
   367  /*                                                                    */
   368  /*  result  is the decimal32 format number which gets the result of   */
   369  /*          the conversion                                            */
   370  /*  *string is the character string which should contain a valid      */
   371  /*          number (which may be a special value)                     */
   372  /*  set     is the context                                            */
   373  /*                                                                    */
   374  /* The context is supplied to this routine is used for error handling */
   375  /* (setting of status and traps) and for the rounding mode, only.     */
   376  /* If an error occurs, the result will be a valid decimal32 NaN.      */
   377  /* ------------------------------------------------------------------ */
   378  decimal32 * decimal32FromString(decimal32 *result, const char *string,
   379                                  decContext *set) {
   380    decContext dc;                             // work
   381    decNumber dn;                              // ..
   382  
   383    decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please
   384    dc.round=set->round;                        // use supplied rounding
   385  
   386    decNumberFromString(&dn, string, &dc);     // will round if needed
   387    decimal32FromNumber(result, &dn, &dc);
   388    if (dc.status!=0) {                        // something happened
   389      decContextSetStatus(set, dc.status);     // .. pass it on
   390      }
   391    return result;
   392    } // decimal32FromString
   393  
   394  /* ------------------------------------------------------------------ */
   395  /* decimal32IsCanonical -- test whether encoding is canonical         */
   396  /*   d32 is the source decimal32                                      */
   397  /*   returns 1 if the encoding of d32 is canonical, 0 otherwise       */
   398  /* No error is possible.                                              */
   399  /* ------------------------------------------------------------------ */
   400  uInt decimal32IsCanonical(const decimal32 *d32) {
   401    decNumber dn;                         // work
   402    decimal32 canon;                      // ..
   403    decContext dc;                        // ..
   404    decContextDefault(&dc, DEC_INIT_DECIMAL32);
   405    decimal32ToNumber(d32, &dn);
   406    decimal32FromNumber(&canon, &dn, &dc);// canon will now be canonical
   407    return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
   408    } // decimal32IsCanonical
   409  
   410  /* ------------------------------------------------------------------ */
   411  /* decimal32Canonical -- copy an encoding, ensuring it is canonical   */
   412  /*   d32 is the source decimal32                                      */
   413  /*   result is the target (may be the same decimal32)                 */
   414  /*   returns result                                                   */
   415  /* No error is possible.                                              */
   416  /* ------------------------------------------------------------------ */
   417  decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
   418    decNumber dn;                         // work
   419    decContext dc;                        // ..
   420    decContextDefault(&dc, DEC_INIT_DECIMAL32);
   421    decimal32ToNumber(d32, &dn);
   422    decimal32FromNumber(result, &dn, &dc);// result will now be canonical
   423    return result;
   424    } // decimal32Canonical
   425  
   426  #if DECTRACE || DECCHECK
   427  /* Macros for accessing decimal32 fields.  These assume the argument
   428     is a reference (pointer) to the decimal32 structure, and the
   429     decimal32 is in network byte order (big-endian) */
   430  // Get sign
   431  #define decimal32Sign(d)       ((unsigned)(d)->bytes[0]>>7)
   432  
   433  // Get combination field
   434  #define decimal32Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
   435  
   436  // Get exponent continuation [does not remove bias]
   437  #define decimal32ExpCon(d)     ((((d)->bytes[0] & 0x03)<<4)           \
   438                               | ((unsigned)(d)->bytes[1]>>4))
   439  
   440  // Set sign [this assumes sign previously 0]
   441  #define decimal32SetSign(d, b) {                                      \
   442    (d)->bytes[0]|=((unsigned)(b)<<7);}
   443  
   444  // Set exponent continuation [does not apply bias]
   445  // This assumes range has been checked and exponent previously 0;
   446  // type of exponent must be unsigned
   447  #define decimal32SetExpCon(d, e) {                                    \
   448    (d)->bytes[0]|=(uByte)((e)>>4);                                     \
   449    (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
   450  
   451  /* ------------------------------------------------------------------ */
   452  /* decimal32Show -- display a decimal32 in hexadecimal [debug aid]    */
   453  /*   d32 -- the number to show                                        */
   454  /* ------------------------------------------------------------------ */
   455  // Also shows sign/cob/expconfields extracted - valid bigendian only
   456  void decimal32Show(const decimal32 *d32) {
   457    char buf[DECIMAL32_Bytes*2+1];
   458    Int i, j=0;
   459  
   460    if (DECLITEND) {
   461      for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
   462        sprintf(&buf[j], "%02x", d32->bytes[3-i]);
   463        }
   464      printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
   465             d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
   466             ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
   467      }
   468     else {
   469      for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
   470        sprintf(&buf[j], "%02x", d32->bytes[i]);
   471        }
   472      printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
   473             decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
   474      }
   475    } // decimal32Show
   476  #endif