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

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