@ 261102.1

250206.1 · 972772153f3d6905c7e6a2bad7b7e3b4706185a1

Move oniguruma and decNumber to vendor directory (#3234)

reading declarations

Changes to vendor/decNumber/decimal32.c. All files

vendor/decNumber/decimal32.c

new file mode 100644@@ -0,0 +1,476 @@+/* ------------------------------------------------------------------ */
+/* Decimal 32-bit format module                                       */
+/* ------------------------------------------------------------------ */
+/* Copyright (c) IBM Corporation, 2000, 2008.  All rights reserved.   */
+/*                                                                    */
+/* This software is made available under the terms of the             */
+/* ICU License -- ICU 1.8.1 and later.                                */
+/*                                                                    */
+/* The description and User's Guide ("The decNumber C Library") for   */
+/* this software is called decNumber.pdf.  This document is           */
+/* available, together with arithmetic and format specifications,     */
+/* testcases, and Web links, on the General Decimal Arithmetic page.  */
+/*                                                                    */
+/* Please send comments, suggestions, and corrections to the author:  */
+/*   mfc@uk.ibm.com                                                   */
+/*   Mike Cowlishaw, IBM Fellow                                       */
+/*   IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK         */
+/* ------------------------------------------------------------------ */
+/* This module comprises the routines for decimal32 format numbers.   */
+/* Conversions are supplied to and from decNumber and String.         */
+/*                                                                    */
+/* This is used when decNumber provides operations, either for all    */
+/* operations or as a proxy between decNumber and decSingle.          */
+/*                                                                    */
+/* Error handling is the same as decNumber (qv.).                     */
+/* ------------------------------------------------------------------ */
+#include <string.h>           // [for memset/memcpy]
+#include <stdio.h>            // [for printf]
+
+#define  DECNUMDIGITS  7      // make decNumbers with space for 7
+#include "decNumber.h"        // base number library
+#include "decNumberLocal.h"   // decNumber local types, etc.
+#include "decimal32.h"        // our primary include
+
+/* Utility tables and routines [in decimal64.c] */
+// DPD2BIN and the reverse are renamed to prevent link-time conflict
+// if decQuad is also built in the same executable
+#define DPD2BIN DPD2BINx
+#define BIN2DPD BIN2DPDx
+extern const uInt   COMBEXP[32], COMBMSD[32];
+extern const uShort DPD2BIN[1024];
+extern const uShort BIN2DPD[1000];
+extern const uByte  BIN2CHAR[4001];
+
+extern void decDigitsToDPD(const decNumber *, uInt *, Int);
+extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
+
+#if DECTRACE || DECCHECK
+void decimal32Show(const decimal32 *);            // for debug
+extern void decNumberShow(const decNumber *);     // ..
+#endif
+
+/* Useful macro */
+// Clear a structure (e.g., a decNumber)
+#define DEC_clear(d) memset(d, 0, sizeof(*d))
+
+/* ------------------------------------------------------------------ */
+/* decimal32FromNumber -- convert decNumber to decimal32              */
+/*                                                                    */
+/*   ds is the target decimal32                                       */
+/*   dn is the source number (assumed valid)                          */
+/*   set is the context, used only for reporting errors               */
+/*                                                                    */
+/* The set argument is used only for status reporting and for the     */
+/* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
+/* digits or an overflow is detected).  If the exponent is out of the */
+/* valid range then Overflow or Underflow will be raised.             */
+/* After Underflow a subnormal result is possible.                    */
+/*                                                                    */
+/* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
+/* by reducing its exponent and multiplying the coefficient by a      */
+/* power of ten, or if the exponent on a zero had to be clamped.      */
+/* ------------------------------------------------------------------ */
+decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
+                              decContext *set) {
+  uInt status=0;                   // status accumulator
+  Int ae;                          // adjusted exponent
+  decNumber  dw;                   // work
+  decContext dc;                   // ..
+  uInt comb, exp;                  // ..
+  uInt uiwork;                     // for macros
+  uInt targ=0;                     // target 32-bit
+
+  // If the number has too many digits, or the exponent could be
+  // out of range then reduce the number under the appropriate
+  // constraints.  This could push the number to Infinity or zero,
+  // so this check and rounding must be done before generating the
+  // decimal32]
+  ae=dn->exponent+dn->digits-1;              // [0 if special]
+  if (dn->digits>DECIMAL32_Pmax              // too many digits
+   || ae>DECIMAL32_Emax                      // likely overflow
+   || ae<DECIMAL32_Emin) {                   // likely underflow
+    decContextDefault(&dc, DEC_INIT_DECIMAL32); // [no traps]
+    dc.round=set->round;                     // use supplied rounding
+    decNumberPlus(&dw, dn, &dc);             // (round and check)
+    // [this changes -0 to 0, so enforce the sign...]
+    dw.bits|=dn->bits&DECNEG;
+    status=dc.status;                        // save status
+    dn=&dw;                                  // use the work number
+    } // maybe out of range
+
+  if (dn->bits&DECSPECIAL) {                      // a special value
+    if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
+     else {                                       // sNaN or qNaN
+      if ((*dn->lsu!=0 || dn->digits>1)           // non-zero coefficient
+       && (dn->digits<DECIMAL32_Pmax)) {          // coefficient fits
+        decDigitsToDPD(dn, &targ, 0);
+        }
+      if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
+       else targ|=DECIMAL_sNaN<<24;
+      } // a NaN
+    } // special
+
+   else { // is finite
+    if (decNumberIsZero(dn)) {               // is a zero
+      // set and clamp exponent
+      if (dn->exponent<-DECIMAL32_Bias) {
+        exp=0;                               // low clamp
+        status|=DEC_Clamped;
+        }
+       else {
+        exp=dn->exponent+DECIMAL32_Bias;     // bias exponent
+        if (exp>DECIMAL32_Ehigh) {           // top clamp
+          exp=DECIMAL32_Ehigh;
+          status|=DEC_Clamped;
+          }
+        }
+      comb=(exp>>3) & 0x18;             // msd=0, exp top 2 bits ..
+      }
+     else {                             // non-zero finite number
+      uInt msd;                         // work
+      Int pad=0;                        // coefficient pad digits
+
+      // the dn is known to fit, but it may need to be padded
+      exp=(uInt)(dn->exponent+DECIMAL32_Bias);    // bias exponent
+      if (exp>DECIMAL32_Ehigh) {                  // fold-down case
+        pad=exp-DECIMAL32_Ehigh;
+        exp=DECIMAL32_Ehigh;                      // [to maximum]
+        status|=DEC_Clamped;
+        }
+
+      // fastpath common case
+      if (DECDPUN==3 && pad==0) {
+        targ=BIN2DPD[dn->lsu[0]];
+        if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
+        msd=(dn->digits==7 ? dn->lsu[2] : 0);
+        }
+       else { // general case
+        decDigitsToDPD(dn, &targ, pad);
+        // save and clear the top digit
+        msd=targ>>20;
+        targ&=0x000fffff;
+        }
+
+      // create the combination field
+      if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
+             else comb=((exp>>3) & 0x18) | msd;
+      }
+    targ|=comb<<26;                // add combination field ..
+    targ|=(exp&0x3f)<<20;          // .. and exponent continuation
+    } // finite
+
+  if (dn->bits&DECNEG) targ|=0x80000000;  // add sign bit
+
+  // now write to storage; this is endian
+  UBFROMUI(d32->bytes, targ);      // directly store the int
+
+  if (status!=0) decContextSetStatus(set, status); // pass on status
+  // decimal32Show(d32);
+  return d32;
+  } // decimal32FromNumber
+
+/* ------------------------------------------------------------------ */
+/* decimal32ToNumber -- convert decimal32 to decNumber                */
+/*   d32 is the source decimal32                                      */
+/*   dn is the target number, with appropriate space                  */
+/* No error is possible.                                              */
+/* ------------------------------------------------------------------ */
+decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
+  uInt msd;                        // coefficient MSD
+  uInt exp;                        // exponent top two bits
+  uInt comb;                       // combination field
+  uInt sour;                       // source 32-bit
+  uInt uiwork;                     // for macros
+
+  // load source from storage; this is endian
+  sour=UBTOUI(d32->bytes);         // directly load the int
+
+  comb=(sour>>26)&0x1f;            // combination field
+
+  decNumberZero(dn);               // clean number
+  if (sour&0x80000000) dn->bits=DECNEG; // set sign if negative
+
+  msd=COMBMSD[comb];               // decode the combination field
+  exp=COMBEXP[comb];               // ..
+
+  if (exp==3) {                    // is a special
+    if (msd==0) {
+      dn->bits|=DECINF;
+      return dn;                   // no coefficient needed
+      }
+    else if (sour&0x02000000) dn->bits|=DECSNAN;
+    else dn->bits|=DECNAN;
+    msd=0;                         // no top digit
+    }
+   else {                          // is a finite number
+    dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
+    }
+
+  // get the coefficient
+  sour&=0x000fffff;                // clean coefficient continuation
+  if (msd) {                       // non-zero msd
+    sour|=msd<<20;                 // prefix to coefficient
+    decDigitsFromDPD(dn, &sour, 3); // process 3 declets
+    return dn;
+    }
+  // msd=0
+  if (!sour) return dn;            // easy: coefficient is 0
+  if (sour&0x000ffc00)             // need 2 declets?
+    decDigitsFromDPD(dn, &sour, 2); // process 2 declets
+   else
+    decDigitsFromDPD(dn, &sour, 1); // process 1 declet
+  return dn;
+  } // decimal32ToNumber
+
+/* ------------------------------------------------------------------ */
+/* to-scientific-string -- conversion to numeric string               */
+/* to-engineering-string -- conversion to numeric string              */
+/*                                                                    */
+/*   decimal32ToString(d32, string);                                  */
+/*   decimal32ToEngString(d32, string);                               */
+/*                                                                    */
+/*  d32 is the decimal32 format number to convert                     */
+/*  string is the string where the result will be laid out            */
+/*                                                                    */
+/*  string must be at least 24 characters                             */
+/*                                                                    */
+/*  No error is possible, and no status can be set.                   */
+/* ------------------------------------------------------------------ */
+char * decimal32ToEngString(const decimal32 *d32, char *string){
+  decNumber dn;                         // work
+  decimal32ToNumber(d32, &dn);
+  decNumberToEngString(&dn, string);
+  return string;
+  } // decimal32ToEngString
+
+char * decimal32ToString(const decimal32 *d32, char *string){
+  uInt msd;                        // coefficient MSD
+  Int  exp;                        // exponent top two bits or full
+  uInt comb;                       // combination field
+  char *cstart;                    // coefficient start
+  char *c;                         // output pointer in string
+  const uByte *u;                  // work
+  char *s, *t;                     // .. (source, target)
+  Int  dpd;                        // ..
+  Int  pre, e;                     // ..
+  uInt uiwork;                     // for macros
+  uInt sour;                       // source 32-bit
+
+  // load source from storage; this is endian
+  sour=UBTOUI(d32->bytes);         // directly load the int
+
+  c=string;                        // where result will go
+  if (((Int)sour)<0) *c++='-';     // handle sign
+
+  comb=(sour>>26)&0x1f;            // combination field
+  msd=COMBMSD[comb];               // decode the combination field
+  exp=COMBEXP[comb];               // ..
+
+  if (exp==3) {
+    if (msd==0) {                  // infinity
+      strcpy(c,   "Inf");
+      strcpy(c+3, "inity");
+      return string;               // easy
+      }
+    if (sour&0x02000000) *c++='s'; // sNaN
+    strcpy(c, "NaN");              // complete word
+    c+=3;                          // step past
+    if ((sour&0x000fffff)==0) return string; // zero payload
+    // otherwise drop through to add integer; set correct exp
+    exp=0; msd=0;                  // setup for following code
+    }
+   else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; // unbiased
+
+  // convert 7 digits of significand to characters
+  cstart=c;                        // save start of coefficient
+  if (msd) *c++='0'+(char)msd;     // non-zero most significant digit
+
+  // Now decode the declets.  After extracting each one, it is
+  // decoded to binary and then to a 4-char sequence by table lookup;
+  // the 4-chars are a 1-char length (significant digits, except 000
+  // has length 0).  This allows us to left-align the first declet
+  // with non-zero content, then remaining ones are full 3-char
+  // length.  We use fixed-length memcpys because variable-length
+  // causes a subroutine call in GCC.  (These are length 4 for speed
+  // and are safe because the array has an extra terminator byte.)
+  #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                   \
+                   if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
+                    else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
+
+  dpd=(sour>>10)&0x3ff;            // declet 1
+  dpd2char;
+  dpd=(sour)&0x3ff;                // declet 2
+  dpd2char;
+
+  if (c==cstart) *c++='0';         // all zeros -- make 0
+
+  if (exp==0) {                    // integer or NaN case -- easy
+    *c='\0';                       // terminate
+    return string;
+    }
+
+  /* non-0 exponent */
+  e=0;                             // assume no E
+  pre=c-cstart+exp;
+  // [here, pre-exp is the digits count (==1 for zero)]
+  if (exp>0 || pre<-5) {           // need exponential form
+    e=pre-1;                       // calculate E value
+    pre=1;                         // assume one digit before '.'
+    } // exponential form
+
+  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
+  s=c-1;                           // source (LSD)
+  if (pre>0) {                     // ddd.ddd (plain), perhaps with E
+    char *dotat=cstart+pre;
+    if (dotat<c) {                 // if embedded dot needed...
+      t=c;                              // target
+      for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
+      *t='.';                           // insert the dot
+      c++;                              // length increased by one
+      }
+
+    // finally add the E-part, if needed; it will never be 0, and has
+    // a maximum length of 3 digits (E-101 case)
+    if (e!=0) {
+      *c++='E';                    // starts with E
+      *c++='+';                    // assume positive
+      if (e<0) {
+        *(c-1)='-';                // oops, need '-'
+        e=-e;                      // uInt, please
+        }
+      u=&BIN2CHAR[e*4];            // -> length byte
+      memcpy(c, u+4-*u, 4);        // copy fixed 4 characters [is safe]
+      c+=*u;                       // bump pointer appropriately
+      }
+    *c='\0';                       // add terminator
+    //printf("res %s\n", string);
+    return string;
+    } // pre>0
+
+  /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
+  t=c+1-pre;
+  *(t+1)='\0';                          // can add terminator now
+  for (; s>=cstart; s--, t--) *t=*s;    // shift whole coefficient right
+  c=cstart;
+  *c++='0';                             // always starts with 0.
+  *c++='.';
+  for (; pre<0; pre++) *c++='0';        // add any 0's after '.'
+  //printf("res %s\n", string);
+  return string;
+  } // decimal32ToString
+
+/* ------------------------------------------------------------------ */
+/* to-number -- conversion from numeric string                        */
+/*                                                                    */
+/*   decimal32FromString(result, string, set);                        */
+/*                                                                    */
+/*  result  is the decimal32 format number which gets the result of   */
+/*          the conversion                                            */
+/*  *string is the character string which should contain a valid      */
+/*          number (which may be a special value)                     */
+/*  set     is the context                                            */
+/*                                                                    */
+/* The context is supplied to this routine is used for error handling */
+/* (setting of status and traps) and for the rounding mode, only.     */
+/* If an error occurs, the result will be a valid decimal32 NaN.      */
+/* ------------------------------------------------------------------ */
+decimal32 * decimal32FromString(decimal32 *result, const char *string,
+                                decContext *set) {
+  decContext dc;                             // work
+  decNumber dn;                              // ..
+
+  decContextDefault(&dc, DEC_INIT_DECIMAL32); // no traps, please
+  dc.round=set->round;                        // use supplied rounding
+
+  decNumberFromString(&dn, string, &dc);     // will round if needed
+  decimal32FromNumber(result, &dn, &dc);
+  if (dc.status!=0) {                        // something happened
+    decContextSetStatus(set, dc.status);     // .. pass it on
+    }
+  return result;
+  } // decimal32FromString
+
+/* ------------------------------------------------------------------ */
+/* decimal32IsCanonical -- test whether encoding is canonical         */
+/*   d32 is the source decimal32                                      */
+/*   returns 1 if the encoding of d32 is canonical, 0 otherwise       */
+/* No error is possible.                                              */
+/* ------------------------------------------------------------------ */
+uInt decimal32IsCanonical(const decimal32 *d32) {
+  decNumber dn;                         // work
+  decimal32 canon;                      // ..
+  decContext dc;                        // ..
+  decContextDefault(&dc, DEC_INIT_DECIMAL32);
+  decimal32ToNumber(d32, &dn);
+  decimal32FromNumber(&canon, &dn, &dc);// canon will now be canonical
+  return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
+  } // decimal32IsCanonical
+
+/* ------------------------------------------------------------------ */
+/* decimal32Canonical -- copy an encoding, ensuring it is canonical   */
+/*   d32 is the source decimal32                                      */
+/*   result is the target (may be the same decimal32)                 */
+/*   returns result                                                   */
+/* No error is possible.                                              */
+/* ------------------------------------------------------------------ */
+decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
+  decNumber dn;                         // work
+  decContext dc;                        // ..
+  decContextDefault(&dc, DEC_INIT_DECIMAL32);
+  decimal32ToNumber(d32, &dn);
+  decimal32FromNumber(result, &dn, &dc);// result will now be canonical
+  return result;
+  } // decimal32Canonical
+
+#if DECTRACE || DECCHECK
+/* Macros for accessing decimal32 fields.  These assume the argument
+   is a reference (pointer) to the decimal32 structure, and the
+   decimal32 is in network byte order (big-endian) */
+// Get sign
+#define decimal32Sign(d)       ((unsigned)(d)->bytes[0]>>7)
+
+// Get combination field
+#define decimal32Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
+
+// Get exponent continuation [does not remove bias]
+#define decimal32ExpCon(d)     ((((d)->bytes[0] & 0x03)<<4)           \
+                             | ((unsigned)(d)->bytes[1]>>4))
+
+// Set sign [this assumes sign previously 0]
+#define decimal32SetSign(d, b) {                                      \
+  (d)->bytes[0]|=((unsigned)(b)<<7);}
+
+// Set exponent continuation [does not apply bias]
+// This assumes range has been checked and exponent previously 0;
+// type of exponent must be unsigned
+#define decimal32SetExpCon(d, e) {                                    \
+  (d)->bytes[0]|=(uByte)((e)>>4);                                     \
+  (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
+
+/* ------------------------------------------------------------------ */
+/* decimal32Show -- display a decimal32 in hexadecimal [debug aid]    */
+/*   d32 -- the number to show                                        */
+/* ------------------------------------------------------------------ */
+// Also shows sign/cob/expconfields extracted - valid bigendian only
+void decimal32Show(const decimal32 *d32) {
+  char buf[DECIMAL32_Bytes*2+1];
+  Int i, j=0;
+
+  if (DECLITEND) {
+    for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d32->bytes[3-i]);
+      }
+    printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
+           d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
+           ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
+    }
+   else {
+    for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d32->bytes[i]);
+      }
+    printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
+           decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
+    }
+  } // decimal32Show
+#endif