root/src/decNumber/decContext.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. decContextClearStatus
  2. decContextDefault
  3. decContextGetRounding
  4. decContextGetStatus
  5. decContextRestoreStatus
  6. decContextSaveStatus
  7. decContextSetRounding
  8. decContextSetStatus
  9. decContextSetStatusFromString
  10. decContextSetStatusFromStringQuiet
  11. decContextSetStatusQuiet
  12. decContextStatusToString
  13. decContextTestEndian
  14. decContextTestSavedStatus
  15. decContextTestStatus
  16. decContextZeroStatus

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

/* [previous][next][first][last][top][bottom][index][help] */