Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / i18n / decNumber.c
index 0461e9b..0848540 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------ */
 /* Decimal Number arithmetic module                                   */
 /* ------------------------------------------------------------------ */
-/* Copyright (c) IBM Corporation, 2000-2010.  All rights reserved.    */
+/* Copyright (c) IBM Corporation, 2000-2012.  All rights reserved.    */
 /*                                                                    */
 /* This software is made available under the terms of the             */
 /* ICU License -- ICU 1.8.1 and later.                                */
 #include "cmemory.h"               /* for uprv_malloc, etc., in ICU */
 #include "decNumber.h"             /* base number library  */
 #include "decNumberLocal.h"        /* decNumber local types, etc.  */
+#include "uassert.h"
 
 /* Constants */
 /* Public lookup table used by the D2U macro  */
-const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
+static const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
 
 #define DECVERB     1              /* set to 1 for verbose DECCHECK  */
 #define powers      DECPOWERS      /* old internal name  */
@@ -209,7 +210,19 @@ const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
 #define BIGEVEN (Int)0x80000002
 #define BIGODD  (Int)0x80000003
 
-static Unit uarrone[1]={1};   /* Unit array of 1, used for incrementing  */
+static const Unit uarrone[1]={1};   /* Unit array of 1, used for incrementing  */
+
+/* ------------------------------------------------------------------ */
+/* round-for-reround digits                                           */
+/* ------------------------------------------------------------------ */
+static const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
+
+/* ------------------------------------------------------------------ */
+/* Powers of ten (powers[n]==10**n, 0<=n<=9)                          */
+/* ------------------------------------------------------------------ */
+static const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
+                          10000000, 100000000, 1000000000};
+
 
 /* Granularity-dependent code */
 #if DECDPUN<=4
@@ -1392,8 +1405,10 @@ U_CAPI decNumber * U_EXPORT2 uprv_decNumberLogB(decNumber *res, const decNumber
 /* fastpath in decLnOp.  The final division is done to the requested  */
 /* precision.                                                         */
 /* ------------------------------------------------------------------ */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warray-bounds"
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
 U_CAPI decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *res, const decNumber *rhs,
                           decContext *set) {
   uInt status=0, ignore=0;         /* status accumulators  */
@@ -1529,7 +1544,9 @@ U_CAPI decNumber * U_EXPORT2 uprv_decNumberLog10(decNumber *res, const decNumber
   #endif
   return res;
   } /* decNumberLog10  */
-#pragma clang diagnostic pop
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
+#pragma GCC diagnostic pop
+#endif
 
 /* ------------------------------------------------------------------ */
 /* decNumberMax -- compare two Numbers and return the maximum         */
@@ -2803,8 +2820,10 @@ U_CAPI decNumber * U_EXPORT2 uprv_decNumberShift(decNumber *res, const decNumber
 /* result setexp(approx, e div 2)  % fix exponent                     */
 /* end sqrt                                                           */
 /* ------------------------------------------------------------------ */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warray-bounds"
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
 U_CAPI decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *res, const decNumber *rhs,
                                 decContext *set) {
   decContext workset, approxset;   /* work contexts  */
@@ -3134,7 +3153,9 @@ U_CAPI decNumber * U_EXPORT2 uprv_decNumberSquareRoot(decNumber *res, const decN
   #endif
   return res;
   } /* decNumberSquareRoot  */
-#pragma clang diagnostic pop
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
+#pragma GCC diagnostic pop
+#endif
 
 /* ------------------------------------------------------------------ */
 /* decNumberSubtract -- subtract two Numbers                          */
@@ -4065,6 +4086,8 @@ static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
     #endif
 
     /* add [A+B*m] or subtract [A+B*(-m)]  */
+    U_ASSERT(rhs->digits > 0);
+    U_ASSERT(lhs->digits > 0);
     res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
                               rhs->lsu, D2U(rhs->digits),
                               rhsshift, acc, mult)
@@ -4977,6 +5000,10 @@ static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
       /* (rounded up to a multiple of 8 bytes), and the uLong  */
       /* accumulator starts offset the appropriate number of units  */
       /* to the right to avoid overwrite during the unchunking.  */
+
+      /* Make sure no signed int overflow below. This is always true */
+      /* if the given numbers have less digits than DEC_MAX_DIGITS. */
+      U_ASSERT(iacc <= INT32_MAX/sizeof(uLong));
       needbytes=iacc*sizeof(uLong);
       #if DECDPUN==1
       zoff=(iacc+7)/8;        /* items to offset by  */
@@ -5518,7 +5545,7 @@ decNumber * decExpOp(decNumber *res, const decNumber *rhs,
 /*           where x is truncated (NB) into the range 10 through 99,  */
 /*           and then c = k>>2 and e = k&3.                           */
 /* ------------------------------------------------------------------ */
-const uShort LNnn[90]={9016,  8652,  8316,  8008,  7724,  7456,  7208,
+static const uShort LNnn[90]={9016,  8652,  8316,  8008,  7724,  7456,  7208,
   6972,  6748,  6540,  6340,  6148,  5968,  5792,  5628,  5464,  5312,
   5164,  5020,  4884,  4748,  4620,  4496,  4376,  4256,  4144,  4032,
  39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
@@ -5590,8 +5617,10 @@ const uShort LNnn[90]={9016,  8652,  8316,  8008,  7724,  7456,  7208,
 /* 5. The static buffers are larger than might be expected to allow   */
 /*    for calls from decNumberPower.                                  */
 /* ------------------------------------------------------------------ */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warray-bounds"
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
 decNumber * decLnOp(decNumber *res, const decNumber *rhs,
                     decContext *set, uInt *status) {
   uInt ignore=0;                   /* working status accumulator  */
@@ -5813,7 +5842,9 @@ decNumber * decLnOp(decNumber *res, const decNumber *rhs,
   /* [status is handled by caller]  */
   return res;
   } /* decLnOp  */
-#pragma clang diagnostic pop
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 406
+#pragma GCC diagnostic pop
+#endif
 
 /* ------------------------------------------------------------------ */
 /* decQuantizeOp  -- force exponent to requested value                */
@@ -6044,11 +6075,11 @@ static decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
 
     /* If total ordering then handle differing signs 'up front'  */
     if (op==COMPTOTAL) {                /* total ordering  */
-      if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) {
+      if (decNumberIsNegative(lhs) && !decNumberIsNegative(rhs)) {
         result=-1;
         break;
         }
-      if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) {
+      if (!decNumberIsNegative(lhs) && decNumberIsNegative(rhs)) {
         result=+1;
         break;
         }
@@ -6987,6 +7018,7 @@ static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
     if (cut==0) quot=*up;          /* is at bottom of unit  */
      else /* cut>0 */ {            /* it's not at bottom of unit  */
       #if DECDPUN<=4
+        U_ASSERT(/* cut >= 0 &&*/ cut <= 4);
         quot=QUOT10(*up, cut);
         rem=*up-quot*powers[cut];
       #else