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