1169695Skan/* Decimal context module for the decNumber C Library. 2169695Skan Copyright (C) 2005 Free Software Foundation, Inc. 3169695Skan Contributed by IBM Corporation. Author Mike Cowlishaw. 4169695Skan 5169695Skan This file is part of GCC. 6169695Skan 7169695Skan GCC is free software; you can redistribute it and/or modify it under 8169695Skan the terms of the GNU General Public License as published by the Free 9169695Skan Software Foundation; either version 2, or (at your option) any later 10169695Skan version. 11169695Skan 12169695Skan In addition to the permissions in the GNU General Public License, 13169695Skan the Free Software Foundation gives you unlimited permission to link 14169695Skan the compiled version of this file into combinations with other 15169695Skan programs, and to distribute those combinations without any 16169695Skan restriction coming from the use of this file. (The General Public 17169695Skan License restrictions do apply in other respects; for example, they 18169695Skan cover modification of the file, and distribution when not linked 19169695Skan into a combine executable.) 20169695Skan 21169695Skan GCC is distributed in the hope that it will be useful, but WITHOUT ANY 22169695Skan WARRANTY; without even the implied warranty of MERCHANTABILITY or 23169695Skan FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 24169695Skan for more details. 25169695Skan 26169695Skan You should have received a copy of the GNU General Public License 27169695Skan along with GCC; see the file COPYING. If not, write to the Free 28169695Skan Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 29169695Skan 02110-1301, USA. */ 30169695Skan 31169695Skan/* This module compirises the routines for handling the arithmetic 32169695Skan context structures. */ 33169695Skan 34169695Skan#include <string.h> /* for strcmp */ 35169695Skan#include "config.h" 36169695Skan#include "decContext.h" /* context and base types */ 37169695Skan#include "decNumberLocal.h" /* decNumber local types, etc. */ 38169695Skan 39169695Skan/* ------------------------------------------------------------------ */ 40169695Skan/* decContextDefault -- initialize a context structure */ 41169695Skan/* */ 42169695Skan/* context is the structure to be initialized */ 43169695Skan/* kind selects the required set of default values, one of: */ 44169695Skan/* DEC_INIT_BASE -- select ANSI X3-274 defaults */ 45169695Skan/* DEC_INIT_DECIMAL32 -- select IEEE 754r defaults, 32-bit */ 46169695Skan/* DEC_INIT_DECIMAL64 -- select IEEE 754r defaults, 64-bit */ 47169695Skan/* DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit */ 48169695Skan/* For any other value a valid context is returned, but with */ 49169695Skan/* Invalid_operation set in the status field. */ 50169695Skan/* returns a context structure with the appropriate initial values. */ 51169695Skan/* ------------------------------------------------------------------ */ 52169695SkandecContext * 53169695SkandecContextDefault (decContext * context, Int kind) 54169695Skan{ 55169695Skan /* set defaults... */ 56169695Skan context->digits = 9; /* 9 digits */ 57169695Skan context->emax = DEC_MAX_EMAX; /* 9-digit exponents */ 58169695Skan context->emin = DEC_MIN_EMIN; /* .. balanced */ 59169695Skan context->round = DEC_ROUND_HALF_UP; /* 0.5 rises */ 60169695Skan context->traps = DEC_Errors; /* all but informational */ 61169695Skan context->status = 0; /* cleared */ 62169695Skan context->clamp = 0; /* no clamping */ 63169695Skan#if DECSUBSET 64169695Skan context->extended = 0; /* cleared */ 65169695Skan#endif 66169695Skan switch (kind) 67169695Skan { 68169695Skan case DEC_INIT_BASE: 69169695Skan /* [use defaults] */ 70169695Skan break; 71169695Skan case DEC_INIT_DECIMAL32: 72169695Skan context->digits = 7; /* digits */ 73169695Skan context->emax = 96; /* Emax */ 74169695Skan context->emin = -95; /* Emin */ 75169695Skan context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ 76169695Skan context->traps = 0; /* no traps set */ 77169695Skan context->clamp = 1; /* clamp exponents */ 78169695Skan#if DECSUBSET 79169695Skan context->extended = 1; /* set */ 80169695Skan#endif 81169695Skan break; 82169695Skan case DEC_INIT_DECIMAL64: 83169695Skan context->digits = 16; /* digits */ 84169695Skan context->emax = 384; /* Emax */ 85169695Skan context->emin = -383; /* Emin */ 86169695Skan context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ 87169695Skan context->traps = 0; /* no traps set */ 88169695Skan context->clamp = 1; /* clamp exponents */ 89169695Skan#if DECSUBSET 90169695Skan context->extended = 1; /* set */ 91169695Skan#endif 92169695Skan break; 93169695Skan case DEC_INIT_DECIMAL128: 94169695Skan context->digits = 34; /* digits */ 95169695Skan context->emax = 6144; /* Emax */ 96169695Skan context->emin = -6143; /* Emin */ 97169695Skan context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ 98169695Skan context->traps = 0; /* no traps set */ 99169695Skan context->clamp = 1; /* clamp exponents */ 100169695Skan#if DECSUBSET 101169695Skan context->extended = 1; /* set */ 102169695Skan#endif 103169695Skan break; 104169695Skan 105169695Skan default: /* invalid Kind */ 106169695Skan /* use defaults, and .. */ 107169695Skan decContextSetStatus (context, DEC_Invalid_operation); /* trap */ 108169695Skan } 109169695Skan return context; 110169695Skan} /* decContextDefault */ 111169695Skan 112169695Skan/* ------------------------------------------------------------------ */ 113169695Skan/* decContextStatusToString -- convert status flags to a string */ 114169695Skan/* */ 115169695Skan/* context is a context with valid status field */ 116169695Skan/* */ 117169695Skan/* returns a constant string describing the condition. If multiple */ 118169695Skan/* (or no) flags are set, a generic constant message is returned. */ 119169695Skan/* ------------------------------------------------------------------ */ 120169695Skanconst char * 121169695SkandecContextStatusToString (const decContext * context) 122169695Skan{ 123169695Skan Int status = context->status; 124169695Skan if (status == DEC_Conversion_syntax) 125169695Skan return DEC_Condition_CS; 126169695Skan if (status == DEC_Division_by_zero) 127169695Skan return DEC_Condition_DZ; 128169695Skan if (status == DEC_Division_impossible) 129169695Skan return DEC_Condition_DI; 130169695Skan if (status == DEC_Division_undefined) 131169695Skan return DEC_Condition_DU; 132169695Skan if (status == DEC_Inexact) 133169695Skan return DEC_Condition_IE; 134169695Skan if (status == DEC_Insufficient_storage) 135169695Skan return DEC_Condition_IS; 136169695Skan if (status == DEC_Invalid_context) 137169695Skan return DEC_Condition_IC; 138169695Skan if (status == DEC_Invalid_operation) 139169695Skan return DEC_Condition_IO; 140169695Skan#if DECSUBSET 141169695Skan if (status == DEC_Lost_digits) 142169695Skan return DEC_Condition_LD; 143169695Skan#endif 144169695Skan if (status == DEC_Overflow) 145169695Skan return DEC_Condition_OV; 146169695Skan if (status == DEC_Clamped) 147169695Skan return DEC_Condition_PA; 148169695Skan if (status == DEC_Rounded) 149169695Skan return DEC_Condition_RO; 150169695Skan if (status == DEC_Subnormal) 151169695Skan return DEC_Condition_SU; 152169695Skan if (status == DEC_Underflow) 153169695Skan return DEC_Condition_UN; 154169695Skan if (status == 0) 155169695Skan return DEC_Condition_ZE; 156169695Skan return DEC_Condition_MU; /* Multiple errors */ 157169695Skan} /* decContextStatusToString */ 158169695Skan 159169695Skan/* ------------------------------------------------------------------ */ 160169695Skan/* decContextSetStatusFromString -- set status from a string */ 161169695Skan/* */ 162169695Skan/* context is the controlling context */ 163169695Skan/* string is a string exactly equal to one that might be returned */ 164169695Skan/* by decContextStatusToString */ 165169695Skan/* */ 166169695Skan/* The status bit corresponding to the string is set, and a trap */ 167169695Skan/* is raised if appropriate. */ 168169695Skan/* */ 169169695Skan/* returns the context structure, unless the string is equal to */ 170169695Skan/* DEC_Condition_MU or is not recognized. In these cases NULL is */ 171169695Skan/* returned. */ 172169695Skan/* ------------------------------------------------------------------ */ 173169695SkandecContext * 174169695SkandecContextSetStatusFromString (decContext * context, const char *string) 175169695Skan{ 176169695Skan if (strcmp (string, DEC_Condition_CS) == 0) 177169695Skan return decContextSetStatus (context, DEC_Conversion_syntax); 178169695Skan if (strcmp (string, DEC_Condition_DZ) == 0) 179169695Skan return decContextSetStatus (context, DEC_Division_by_zero); 180169695Skan if (strcmp (string, DEC_Condition_DI) == 0) 181169695Skan return decContextSetStatus (context, DEC_Division_impossible); 182169695Skan if (strcmp (string, DEC_Condition_DU) == 0) 183169695Skan return decContextSetStatus (context, DEC_Division_undefined); 184169695Skan if (strcmp (string, DEC_Condition_IE) == 0) 185169695Skan return decContextSetStatus (context, DEC_Inexact); 186169695Skan if (strcmp (string, DEC_Condition_IS) == 0) 187169695Skan return decContextSetStatus (context, DEC_Insufficient_storage); 188169695Skan if (strcmp (string, DEC_Condition_IC) == 0) 189169695Skan return decContextSetStatus (context, DEC_Invalid_context); 190169695Skan if (strcmp (string, DEC_Condition_IO) == 0) 191169695Skan return decContextSetStatus (context, DEC_Invalid_operation); 192169695Skan#if DECSUBSET 193169695Skan if (strcmp (string, DEC_Condition_LD) == 0) 194169695Skan return decContextSetStatus (context, DEC_Lost_digits); 195169695Skan#endif 196169695Skan if (strcmp (string, DEC_Condition_OV) == 0) 197169695Skan return decContextSetStatus (context, DEC_Overflow); 198169695Skan if (strcmp (string, DEC_Condition_PA) == 0) 199169695Skan return decContextSetStatus (context, DEC_Clamped); 200169695Skan if (strcmp (string, DEC_Condition_RO) == 0) 201169695Skan return decContextSetStatus (context, DEC_Rounded); 202169695Skan if (strcmp (string, DEC_Condition_SU) == 0) 203169695Skan return decContextSetStatus (context, DEC_Subnormal); 204169695Skan if (strcmp (string, DEC_Condition_UN) == 0) 205169695Skan return decContextSetStatus (context, DEC_Underflow); 206169695Skan if (strcmp (string, DEC_Condition_ZE) == 0) 207169695Skan return context; 208169695Skan return NULL; /* Multiple status, or unknown */ 209169695Skan} /* decContextSetStatusFromString */ 210169695Skan 211169695Skan/* ------------------------------------------------------------------ */ 212169695Skan/* decContextSetStatus -- set status and raise trap if appropriate */ 213169695Skan/* */ 214169695Skan/* context is the controlling context */ 215169695Skan/* status is the DEC_ exception code */ 216169695Skan/* returns the context structure */ 217169695Skan/* */ 218169695Skan/* Control may never return from this routine, if there is a signal */ 219169695Skan/* handler and it takes a long jump. */ 220169695Skan/* ------------------------------------------------------------------ */ 221169695SkandecContext * 222169695SkandecContextSetStatus (decContext * context, uInt status) 223169695Skan{ 224169695Skan context->status |= status; 225169695Skan if (status & context->traps) 226169695Skan raise (SIGFPE); 227169695Skan return context; 228169695Skan} /* decContextSetStatus */ 229