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