Home | History | Annotate | Download | only in i18n
      1 /* ------------------------------------------------------------------ */
      2 /* Decimal Context module                                             */
      3 /* ------------------------------------------------------------------ */
      4 /* Copyright (c) IBM Corporation, 2000-2010.  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 (at) 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 handling arithmetic         */
     20 /* context structures.                                                */
     21 /* ------------------------------------------------------------------ */
     22 
     23 #include <string.h>           /* for strcmp  */
     24 #include <stdio.h>            /* for printf if DECCHECK  */
     25 #include "decContext.h"       /* context and base types  */
     26 #include "decNumberLocal.h"   /* decNumber local types, etc.  */
     27 
     28 /* compile-time endian tester [assumes sizeof(Int)>1] */
     29 static  const  Int mfcone=1;                 /* constant 1  */
     30 static  const  Flag *mfctop=(Flag *)&mfcone; /* -> top byte  */
     31 #define LITEND *mfctop             /* named flag; 1=little-endian  */
     32 
     33 /* ------------------------------------------------------------------ */
     34 /* round-for-reround digits                                           */
     35 /* ------------------------------------------------------------------ */
     36 const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
     37 
     38 /* ------------------------------------------------------------------ */
     39 /* Powers of ten (powers[n]==10**n, 0<=n<=9)                          */
     40 /* ------------------------------------------------------------------ */
     41 const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
     42                           10000000, 100000000, 1000000000};
     43 
     44 /* ------------------------------------------------------------------ */
     45 /* decContextClearStatus -- clear bits in current status              */
     46 /*                                                                    */
     47 /*  context is the context structure to be queried                    */
     48 /*  mask indicates the bits to be cleared (the status bit that        */
     49 /*    corresponds to each 1 bit in the mask is cleared)               */
     50 /*  returns context                                                   */
     51 /*                                                                    */
     52 /* No error is possible.                                              */
     53 /* ------------------------------------------------------------------ */
     54 U_CAPI decContext * U_EXPORT2 uprv_decContextClearStatus(decContext *context, uInt mask) {
     55   context->status&=~mask;
     56   return context;
     57   } /* decContextClearStatus  */
     58 
     59 /* ------------------------------------------------------------------ */
     60 /* decContextDefault -- initialize a context structure                */
     61 /*                                                                    */
     62 /*  context is the structure to be initialized                        */
     63 /*  kind selects the required set of default values, one of:          */
     64 /*      DEC_INIT_BASE       -- select ANSI X3-274 defaults            */
     65 /*      DEC_INIT_DECIMAL32  -- select IEEE 754 defaults, 32-bit       */
     66 /*      DEC_INIT_DECIMAL64  -- select IEEE 754 defaults, 64-bit       */
     67 /*      DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit      */
     68 /*      For any other value a valid context is returned, but with     */
     69 /*      Invalid_operation set in the status field.                    */
     70 /*  returns a context structure with the appropriate initial values.  */
     71 /* ------------------------------------------------------------------ */
     72 U_CAPI decContext *  U_EXPORT2 uprv_decContextDefault(decContext *context, Int kind) {
     73   /* set defaults...  */
     74   context->digits=9;                         /* 9 digits  */
     75   context->emax=DEC_MAX_EMAX;                /* 9-digit exponents  */
     76   context->emin=DEC_MIN_EMIN;                /* .. balanced  */
     77   context->round=DEC_ROUND_HALF_UP;          /* 0.5 rises  */
     78   context->traps=DEC_Errors;                 /* all but informational  */
     79   context->status=0;                         /* cleared  */
     80   context->clamp=0;                          /* no clamping  */
     81   #if DECSUBSET
     82   context->extended=0;                       /* cleared  */
     83   #endif
     84   switch (kind) {
     85     case DEC_INIT_BASE:
     86       /* [use defaults]  */
     87       break;
     88     case DEC_INIT_DECIMAL32:
     89       context->digits=7;                     /* digits  */
     90       context->emax=96;                      /* Emax  */
     91       context->emin=-95;                     /* Emin  */
     92       context->round=DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even  */
     93       context->traps=0;                      /* no traps set  */
     94       context->clamp=1;                      /* clamp exponents  */
     95       #if DECSUBSET
     96       context->extended=1;                   /* set  */
     97       #endif
     98       break;
     99     case DEC_INIT_DECIMAL64:
    100       context->digits=16;                    /* digits  */
    101       context->emax=384;                     /* Emax  */
    102       context->emin=-383;                    /* Emin  */
    103       context->round=DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even  */
    104       context->traps=0;                      /* no traps set  */
    105       context->clamp=1;                      /* clamp exponents  */
    106       #if DECSUBSET
    107       context->extended=1;                   /* set  */
    108       #endif
    109       break;
    110     case DEC_INIT_DECIMAL128:
    111       context->digits=34;                    /* digits  */
    112       context->emax=6144;                    /* Emax  */
    113       context->emin=-6143;                   /* Emin  */
    114       context->round=DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even  */
    115       context->traps=0;                      /* no traps set  */
    116       context->clamp=1;                      /* clamp exponents  */
    117       #if DECSUBSET
    118       context->extended=1;                   /* set  */
    119       #endif
    120       break;
    121 
    122     default:                                 /* invalid Kind  */
    123       /* use defaults, and ..  */
    124       uprv_decContextSetStatus(context, DEC_Invalid_operation); /* trap  */
    125     }
    126 
    127   return context;} /* decContextDefault  */
    128 
    129 /* ------------------------------------------------------------------ */
    130 /* decContextGetRounding -- return current rounding mode              */
    131 /*                                                                    */
    132 /*  context is the context structure to be queried                    */
    133 /*  returns the rounding mode                                         */
    134 /*                                                                    */
    135 /* No error is possible.                                              */
    136 /* ------------------------------------------------------------------ */
    137 U_CAPI enum rounding  U_EXPORT2 uprv_decContextGetRounding(decContext *context) {
    138   return context->round;
    139   } /* decContextGetRounding  */
    140 
    141 /* ------------------------------------------------------------------ */
    142 /* decContextGetStatus -- return current status                       */
    143 /*                                                                    */
    144 /*  context is the context structure to be queried                    */
    145 /*  returns status                                                    */
    146 /*                                                                    */
    147 /* No error is possible.                                              */
    148 /* ------------------------------------------------------------------ */
    149 U_CAPI uInt  U_EXPORT2 uprv_decContextGetStatus(decContext *context) {
    150   return context->status;
    151   } /* decContextGetStatus  */
    152 
    153 /* ------------------------------------------------------------------ */
    154 /* decContextRestoreStatus -- restore bits in current status          */
    155 /*                                                                    */
    156 /*  context is the context structure to be updated                    */
    157 /*  newstatus is the source for the bits to be restored               */
    158 /*  mask indicates the bits to be restored (the status bit that       */
    159 /*    corresponds to each 1 bit in the mask is set to the value of    */
    160 /*    the correspnding bit in newstatus)                              */
    161 /*  returns context                                                   */
    162 /*                                                                    */
    163 /* No error is possible.                                              */
    164 /* ------------------------------------------------------------------ */
    165 U_CAPI decContext * U_EXPORT2 uprv_decContextRestoreStatus(decContext *context,
    166                                     uInt newstatus, uInt mask) {
    167   context->status&=~mask;               /* clear the selected bits  */
    168   context->status|=(mask&newstatus);    /* or in the new bits  */
    169   return context;
    170   } /* decContextRestoreStatus  */
    171 
    172 /* ------------------------------------------------------------------ */
    173 /* decContextSaveStatus -- save bits in current status                */
    174 /*                                                                    */
    175 /*  context is the context structure to be queried                    */
    176 /*  mask indicates the bits to be saved (the status bits that         */
    177 /*    correspond to each 1 bit in the mask are saved)                 */
    178 /*  returns the AND of the mask and the current status                */
    179 /*                                                                    */
    180 /* No error is possible.                                              */
    181 /* ------------------------------------------------------------------ */
    182 U_CAPI uInt  U_EXPORT2 uprv_decContextSaveStatus(decContext *context, uInt mask) {
    183   return context->status&mask;
    184   } /* decContextSaveStatus  */
    185 
    186 /* ------------------------------------------------------------------ */
    187 /* decContextSetRounding -- set current rounding mode                 */
    188 /*                                                                    */
    189 /*  context is the context structure to be updated                    */
    190 /*  newround is the value which will replace the current mode         */
    191 /*  returns context                                                   */
    192 /*                                                                    */
    193 /* No error is possible.                                              */
    194 /* ------------------------------------------------------------------ */
    195 U_CAPI decContext * U_EXPORT2 uprv_decContextSetRounding(decContext *context,
    196                                   enum rounding newround) {
    197   context->round=newround;
    198   return context;
    199   } /* decContextSetRounding  */
    200 
    201 /* ------------------------------------------------------------------ */
    202 /* decContextSetStatus -- set status and raise trap if appropriate    */
    203 /*                                                                    */
    204 /*  context is the context structure to be updated                    */
    205 /*  status  is the DEC_ exception code                                */
    206 /*  returns the context structure                                     */
    207 /*                                                                    */
    208 /* Control may never return from this routine, if there is a signal   */
    209 /* handler and it takes a long jump.                                  */
    210 /* ------------------------------------------------------------------ */
    211 U_CAPI decContext *  U_EXPORT2 uprv_decContextSetStatus(decContext *context, uInt status) {
    212   context->status|=status;
    213   if (status & context->traps) raise(SIGFPE);
    214   return context;} /* decContextSetStatus  */
    215 
    216 /* ------------------------------------------------------------------ */
    217 /* decContextSetStatusFromString -- set status from a string + trap   */
    218 /*                                                                    */
    219 /*  context is the context structure to be updated                    */
    220 /*  string is a string exactly equal to one that might be returned    */
    221 /*            by decContextStatusToString                             */
    222 /*                                                                    */
    223 /*  The status bit corresponding to the string is set, and a trap     */
    224 /*  is raised if appropriate.                                         */
    225 /*                                                                    */
    226 /*  returns the context structure, unless the string is equal to      */
    227 /*    DEC_Condition_MU or is not recognized.  In these cases NULL is  */
    228 /*    returned.                                                       */
    229 /* ------------------------------------------------------------------ */
    230 U_CAPI decContext *  U_EXPORT2 uprv_decContextSetStatusFromString(decContext *context,
    231                                            const char *string) {
    232   if (strcmp(string, DEC_Condition_CS)==0)
    233     return uprv_decContextSetStatus(context, DEC_Conversion_syntax);
    234   if (strcmp(string, DEC_Condition_DZ)==0)
    235     return uprv_decContextSetStatus(context, DEC_Division_by_zero);
    236   if (strcmp(string, DEC_Condition_DI)==0)
    237     return uprv_decContextSetStatus(context, DEC_Division_impossible);
    238   if (strcmp(string, DEC_Condition_DU)==0)
    239     return uprv_decContextSetStatus(context, DEC_Division_undefined);
    240   if (strcmp(string, DEC_Condition_IE)==0)
    241     return uprv_decContextSetStatus(context, DEC_Inexact);
    242   if (strcmp(string, DEC_Condition_IS)==0)
    243     return uprv_decContextSetStatus(context, DEC_Insufficient_storage);
    244   if (strcmp(string, DEC_Condition_IC)==0)
    245     return uprv_decContextSetStatus(context, DEC_Invalid_context);
    246   if (strcmp(string, DEC_Condition_IO)==0)
    247     return uprv_decContextSetStatus(context, DEC_Invalid_operation);
    248   #if DECSUBSET
    249   if (strcmp(string, DEC_Condition_LD)==0)
    250     return uprv_decContextSetStatus(context, DEC_Lost_digits);
    251   #endif
    252   if (strcmp(string, DEC_Condition_OV)==0)
    253     return uprv_decContextSetStatus(context, DEC_Overflow);
    254   if (strcmp(string, DEC_Condition_PA)==0)
    255     return uprv_decContextSetStatus(context, DEC_Clamped);
    256   if (strcmp(string, DEC_Condition_RO)==0)
    257     return uprv_decContextSetStatus(context, DEC_Rounded);
    258   if (strcmp(string, DEC_Condition_SU)==0)
    259     return uprv_decContextSetStatus(context, DEC_Subnormal);
    260   if (strcmp(string, DEC_Condition_UN)==0)
    261     return uprv_decContextSetStatus(context, DEC_Underflow);
    262   if (strcmp(string, DEC_Condition_ZE)==0)
    263     return context;
    264   return NULL;  /* Multiple status, or unknown  */
    265   } /* decContextSetStatusFromString  */
    266 
    267 /* ------------------------------------------------------------------ */
    268 /* decContextSetStatusFromStringQuiet -- set status from a string     */
    269 /*                                                                    */
    270 /*  context is the context structure to be updated                    */
    271 /*  string is a string exactly equal to one that might be returned    */
    272 /*            by decContextStatusToString                             */
    273 /*                                                                    */
    274 /*  The status bit corresponding to the string is set; no trap is     */
    275 /*  raised.                                                           */
    276 /*                                                                    */
    277 /*  returns the context structure, unless the string is equal to      */
    278 /*    DEC_Condition_MU or is not recognized.  In these cases NULL is  */
    279 /*    returned.                                                       */
    280 /* ------------------------------------------------------------------ */
    281 U_CAPI decContext *  U_EXPORT2 uprv_decContextSetStatusFromStringQuiet(decContext *context,
    282                                                 const char *string) {
    283   if (strcmp(string, DEC_Condition_CS)==0)
    284     return uprv_decContextSetStatusQuiet(context, DEC_Conversion_syntax);
    285   if (strcmp(string, DEC_Condition_DZ)==0)
    286     return uprv_decContextSetStatusQuiet(context, DEC_Division_by_zero);
    287   if (strcmp(string, DEC_Condition_DI)==0)
    288     return uprv_decContextSetStatusQuiet(context, DEC_Division_impossible);
    289   if (strcmp(string, DEC_Condition_DU)==0)
    290     return uprv_decContextSetStatusQuiet(context, DEC_Division_undefined);
    291   if (strcmp(string, DEC_Condition_IE)==0)
    292     return uprv_decContextSetStatusQuiet(context, DEC_Inexact);
    293   if (strcmp(string, DEC_Condition_IS)==0)
    294     return uprv_decContextSetStatusQuiet(context, DEC_Insufficient_storage);
    295   if (strcmp(string, DEC_Condition_IC)==0)
    296     return uprv_decContextSetStatusQuiet(context, DEC_Invalid_context);
    297   if (strcmp(string, DEC_Condition_IO)==0)
    298     return uprv_decContextSetStatusQuiet(context, DEC_Invalid_operation);
    299   #if DECSUBSET
    300   if (strcmp(string, DEC_Condition_LD)==0)
    301     return uprv_decContextSetStatusQuiet(context, DEC_Lost_digits);
    302   #endif
    303   if (strcmp(string, DEC_Condition_OV)==0)
    304     return uprv_decContextSetStatusQuiet(context, DEC_Overflow);
    305   if (strcmp(string, DEC_Condition_PA)==0)
    306     return uprv_decContextSetStatusQuiet(context, DEC_Clamped);
    307   if (strcmp(string, DEC_Condition_RO)==0)
    308     return uprv_decContextSetStatusQuiet(context, DEC_Rounded);
    309   if (strcmp(string, DEC_Condition_SU)==0)
    310     return uprv_decContextSetStatusQuiet(context, DEC_Subnormal);
    311   if (strcmp(string, DEC_Condition_UN)==0)
    312     return uprv_decContextSetStatusQuiet(context, DEC_Underflow);
    313   if (strcmp(string, DEC_Condition_ZE)==0)
    314     return context;
    315   return NULL;  /* Multiple status, or unknown  */
    316   } /* decContextSetStatusFromStringQuiet  */
    317 
    318 /* ------------------------------------------------------------------ */
    319 /* decContextSetStatusQuiet -- set status without trap                */
    320 /*                                                                    */
    321 /*  context is the context structure to be updated                    */
    322 /*  status  is the DEC_ exception code                                */
    323 /*  returns the context structure                                     */
    324 /*                                                                    */
    325 /* No error is possible.                                              */
    326 /* ------------------------------------------------------------------ */
    327 U_CAPI decContext *  U_EXPORT2 uprv_decContextSetStatusQuiet(decContext *context, uInt status) {
    328   context->status|=status;
    329   return context;} /* decContextSetStatusQuiet  */
    330 
    331 /* ------------------------------------------------------------------ */
    332 /* decContextStatusToString -- convert status flags to a string       */
    333 /*                                                                    */
    334 /*  context is a context with valid status field                      */
    335 /*                                                                    */
    336 /*  returns a constant string describing the condition.  If multiple  */
    337 /*    (or no) flags are set, a generic constant message is returned.  */
    338 /* ------------------------------------------------------------------ */
    339 U_CAPI const char * U_EXPORT2 uprv_decContextStatusToString(const decContext *context) {
    340   Int status=context->status;
    341 
    342   /* test the five IEEE first, as some of the others are ambiguous when  */
    343   /* DECEXTFLAG=0  */
    344   if (status==DEC_Invalid_operation    ) return DEC_Condition_IO;
    345   if (status==DEC_Division_by_zero     ) return DEC_Condition_DZ;
    346   if (status==DEC_Overflow             ) return DEC_Condition_OV;
    347   if (status==DEC_Underflow            ) return DEC_Condition_UN;
    348   if (status==DEC_Inexact              ) return DEC_Condition_IE;
    349 
    350   if (status==DEC_Division_impossible  ) return DEC_Condition_DI;
    351   if (status==DEC_Division_undefined   ) return DEC_Condition_DU;
    352   if (status==DEC_Rounded              ) return DEC_Condition_RO;
    353   if (status==DEC_Clamped              ) return DEC_Condition_PA;
    354   if (status==DEC_Subnormal            ) return DEC_Condition_SU;
    355   if (status==DEC_Conversion_syntax    ) return DEC_Condition_CS;
    356   if (status==DEC_Insufficient_storage ) return DEC_Condition_IS;
    357   if (status==DEC_Invalid_context      ) return DEC_Condition_IC;
    358   #if DECSUBSET
    359   if (status==DEC_Lost_digits          ) return DEC_Condition_LD;
    360   #endif
    361   if (status==0                        ) return DEC_Condition_ZE;
    362   return DEC_Condition_MU;  /* Multiple errors  */
    363   } /* decContextStatusToString  */
    364 
    365 /* ------------------------------------------------------------------ */
    366 /* decContextTestEndian -- test whether DECLITEND is set correctly    */
    367 /*                                                                    */
    368 /*  quiet is 1 to suppress message; 0 otherwise                       */
    369 /*  returns 0 if DECLITEND is correct                                 */
    370 /*          1 if DECLITEND is incorrect and should be 1               */
    371 /*         -1 if DECLITEND is incorrect and should be 0               */
    372 /*                                                                    */
    373 /* A message is displayed if the return value is not 0 and quiet==0.  */
    374 /*                                                                    */
    375 /* No error is possible.                                              */
    376 /* ------------------------------------------------------------------ */
    377 U_CAPI Int  U_EXPORT2 uprv_decContextTestEndian(Flag quiet) {
    378   Int res=0;                  /* optimist  */
    379   uInt dle=(uInt)DECLITEND;   /* unsign  */
    380   if (dle>1) dle=1;           /* ensure 0 or 1  */
    381 
    382   if (LITEND!=DECLITEND) {
    383     const char *adj;
    384     if (!quiet) {
    385       if (LITEND) adj="little";
    386              else adj="big";
    387       printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
    388              DECLITEND, adj);
    389       }
    390     res=(Int)LITEND-dle;
    391     }
    392   return res;
    393   } /* decContextTestEndian  */
    394 
    395 /* ------------------------------------------------------------------ */
    396 /* decContextTestSavedStatus -- test bits in saved status             */
    397 /*                                                                    */
    398 /*  oldstatus is the status word to be tested                         */
    399 /*  mask indicates the bits to be tested (the oldstatus bits that     */
    400 /*    correspond to each 1 bit in the mask are tested)                */
    401 /*  returns 1 if any of the tested bits are 1, or 0 otherwise         */
    402 /*                                                                    */
    403 /* No error is possible.                                              */
    404 /* ------------------------------------------------------------------ */
    405 U_CAPI  uInt U_EXPORT2 uprv_decContextTestSavedStatus(uInt oldstatus, uInt mask) {
    406   return (oldstatus&mask)!=0;
    407   } /* decContextTestSavedStatus  */
    408 
    409 /* ------------------------------------------------------------------ */
    410 /* decContextTestStatus -- test bits in current status                */
    411 /*                                                                    */
    412 /*  context is the context structure to be updated                    */
    413 /*  mask indicates the bits to be tested (the status bits that        */
    414 /*    correspond to each 1 bit in the mask are tested)                */
    415 /*  returns 1 if any of the tested bits are 1, or 0 otherwise         */
    416 /*                                                                    */
    417 /* No error is possible.                                              */
    418 /* ------------------------------------------------------------------ */
    419 U_CAPI uInt  U_EXPORT2 uprv_decContextTestStatus(decContext *context, uInt mask) {
    420   return (context->status&mask)!=0;
    421   } /* decContextTestStatus  */
    422 
    423 /* ------------------------------------------------------------------ */
    424 /* decContextZeroStatus -- clear all status bits                      */
    425 /*                                                                    */
    426 /*  context is the context structure to be updated                    */
    427 /*  returns context                                                   */
    428 /*                                                                    */
    429 /* No error is possible.                                              */
    430 /* ------------------------------------------------------------------ */
    431 U_CAPI decContext * U_EXPORT2 uprv_decContextZeroStatus(decContext *context) {
    432   context->status=0;
    433   return context;
    434   } /* decContextZeroStatus  */
    435 
    436