diff options
author | Robert Nagy <robert@cvs.openbsd.org> | 2009-10-15 17:11:34 +0000 |
---|---|---|
committer | Robert Nagy <robert@cvs.openbsd.org> | 2009-10-15 17:11:34 +0000 |
commit | 2faa5c93c1cb8fe9a551a57cbe7ccee57638b318 (patch) | |
tree | ae87020fe63f170fb407b2fb81db6bd3b2494657 /gnu/gcc/libdecnumber/decContext.c | |
parent | 53e92725352eac1e8b50d3ebb549af601e383850 (diff) |
import of gcc-4.2.1, the last gcc release under GPLv2
Diffstat (limited to 'gnu/gcc/libdecnumber/decContext.c')
-rw-r--r-- | gnu/gcc/libdecnumber/decContext.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/gnu/gcc/libdecnumber/decContext.c b/gnu/gcc/libdecnumber/decContext.c new file mode 100644 index 00000000000..66da2ae7956 --- /dev/null +++ b/gnu/gcc/libdecnumber/decContext.c @@ -0,0 +1,228 @@ +/* Decimal context module for the decNumber C Library. + Copyright (C) 2005 Free Software Foundation, Inc. + Contributed by IBM Corporation. Author Mike Cowlishaw. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + In addition to the permissions in the GNU General Public License, + the Free Software Foundation gives you unlimited permission to link + the compiled version of this file into combinations with other + programs, and to distribute those combinations without any + restriction coming from the use of this file. (The General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into a combine executable.) + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* This module compirises the routines for handling the arithmetic + context structures. */ + +#include <string.h> /* for strcmp */ +#include "config.h" +#include "decContext.h" /* context and base types */ +#include "decNumberLocal.h" /* decNumber local types, etc. */ + +/* ------------------------------------------------------------------ */ +/* decContextDefault -- initialize a context structure */ +/* */ +/* context is the structure to be initialized */ +/* kind selects the required set of default values, one of: */ +/* DEC_INIT_BASE -- select ANSI X3-274 defaults */ +/* DEC_INIT_DECIMAL32 -- select IEEE 754r defaults, 32-bit */ +/* DEC_INIT_DECIMAL64 -- select IEEE 754r defaults, 64-bit */ +/* DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit */ +/* For any other value a valid context is returned, but with */ +/* Invalid_operation set in the status field. */ +/* returns a context structure with the appropriate initial values. */ +/* ------------------------------------------------------------------ */ +decContext * +decContextDefault (decContext * context, Int kind) +{ + /* set defaults... */ + context->digits = 9; /* 9 digits */ + context->emax = DEC_MAX_EMAX; /* 9-digit exponents */ + context->emin = DEC_MIN_EMIN; /* .. balanced */ + context->round = DEC_ROUND_HALF_UP; /* 0.5 rises */ + context->traps = DEC_Errors; /* all but informational */ + context->status = 0; /* cleared */ + context->clamp = 0; /* no clamping */ +#if DECSUBSET + context->extended = 0; /* cleared */ +#endif + switch (kind) + { + case DEC_INIT_BASE: + /* [use defaults] */ + break; + case DEC_INIT_DECIMAL32: + context->digits = 7; /* digits */ + context->emax = 96; /* Emax */ + context->emin = -95; /* Emin */ + context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ + context->traps = 0; /* no traps set */ + context->clamp = 1; /* clamp exponents */ +#if DECSUBSET + context->extended = 1; /* set */ +#endif + break; + case DEC_INIT_DECIMAL64: + context->digits = 16; /* digits */ + context->emax = 384; /* Emax */ + context->emin = -383; /* Emin */ + context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ + context->traps = 0; /* no traps set */ + context->clamp = 1; /* clamp exponents */ +#if DECSUBSET + context->extended = 1; /* set */ +#endif + break; + case DEC_INIT_DECIMAL128: + context->digits = 34; /* digits */ + context->emax = 6144; /* Emax */ + context->emin = -6143; /* Emin */ + context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ + context->traps = 0; /* no traps set */ + context->clamp = 1; /* clamp exponents */ +#if DECSUBSET + context->extended = 1; /* set */ +#endif + break; + + default: /* invalid Kind */ + /* use defaults, and .. */ + decContextSetStatus (context, DEC_Invalid_operation); /* trap */ + } + return context; +} /* decContextDefault */ + +/* ------------------------------------------------------------------ */ +/* decContextStatusToString -- convert status flags to a string */ +/* */ +/* context is a context with valid status field */ +/* */ +/* returns a constant string describing the condition. If multiple */ +/* (or no) flags are set, a generic constant message is returned. */ +/* ------------------------------------------------------------------ */ +const char * +decContextStatusToString (const decContext * context) +{ + Int status = context->status; + if (status == DEC_Conversion_syntax) + return DEC_Condition_CS; + if (status == DEC_Division_by_zero) + return DEC_Condition_DZ; + if (status == DEC_Division_impossible) + return DEC_Condition_DI; + if (status == DEC_Division_undefined) + return DEC_Condition_DU; + if (status == DEC_Inexact) + return DEC_Condition_IE; + if (status == DEC_Insufficient_storage) + return DEC_Condition_IS; + if (status == DEC_Invalid_context) + return DEC_Condition_IC; + if (status == DEC_Invalid_operation) + return DEC_Condition_IO; +#if DECSUBSET + if (status == DEC_Lost_digits) + return DEC_Condition_LD; +#endif + if (status == DEC_Overflow) + return DEC_Condition_OV; + if (status == DEC_Clamped) + return DEC_Condition_PA; + if (status == DEC_Rounded) + return DEC_Condition_RO; + if (status == DEC_Subnormal) + return DEC_Condition_SU; + if (status == DEC_Underflow) + return DEC_Condition_UN; + if (status == 0) + return DEC_Condition_ZE; + return DEC_Condition_MU; /* Multiple errors */ +} /* decContextStatusToString */ + +/* ------------------------------------------------------------------ */ +/* decContextSetStatusFromString -- set status from a string */ +/* */ +/* context is the controlling context */ +/* string is a string exactly equal to one that might be returned */ +/* by decContextStatusToString */ +/* */ +/* The status bit corresponding to the string is set, and a trap */ +/* is raised if appropriate. */ +/* */ +/* returns the context structure, unless the string is equal to */ +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ +/* returned. */ +/* ------------------------------------------------------------------ */ +decContext * +decContextSetStatusFromString (decContext * context, const char *string) +{ + if (strcmp (string, DEC_Condition_CS) == 0) + return decContextSetStatus (context, DEC_Conversion_syntax); + if (strcmp (string, DEC_Condition_DZ) == 0) + return decContextSetStatus (context, DEC_Division_by_zero); + if (strcmp (string, DEC_Condition_DI) == 0) + return decContextSetStatus (context, DEC_Division_impossible); + if (strcmp (string, DEC_Condition_DU) == 0) + return decContextSetStatus (context, DEC_Division_undefined); + if (strcmp (string, DEC_Condition_IE) == 0) + return decContextSetStatus (context, DEC_Inexact); + if (strcmp (string, DEC_Condition_IS) == 0) + return decContextSetStatus (context, DEC_Insufficient_storage); + if (strcmp (string, DEC_Condition_IC) == 0) + return decContextSetStatus (context, DEC_Invalid_context); + if (strcmp (string, DEC_Condition_IO) == 0) + return decContextSetStatus (context, DEC_Invalid_operation); +#if DECSUBSET + if (strcmp (string, DEC_Condition_LD) == 0) + return decContextSetStatus (context, DEC_Lost_digits); +#endif + if (strcmp (string, DEC_Condition_OV) == 0) + return decContextSetStatus (context, DEC_Overflow); + if (strcmp (string, DEC_Condition_PA) == 0) + return decContextSetStatus (context, DEC_Clamped); + if (strcmp (string, DEC_Condition_RO) == 0) + return decContextSetStatus (context, DEC_Rounded); + if (strcmp (string, DEC_Condition_SU) == 0) + return decContextSetStatus (context, DEC_Subnormal); + if (strcmp (string, DEC_Condition_UN) == 0) + return decContextSetStatus (context, DEC_Underflow); + if (strcmp (string, DEC_Condition_ZE) == 0) + return context; + return NULL; /* Multiple status, or unknown */ +} /* decContextSetStatusFromString */ + +/* ------------------------------------------------------------------ */ +/* decContextSetStatus -- set status and raise trap if appropriate */ +/* */ +/* context is the controlling context */ +/* status is the DEC_ exception code */ +/* returns the context structure */ +/* */ +/* Control may never return from this routine, if there is a signal */ +/* handler and it takes a long jump. */ +/* ------------------------------------------------------------------ */ +decContext * +decContextSetStatus (decContext * context, uInt status) +{ + context->status |= status; + if (status & context->traps) + raise (SIGFPE); + return context; +} /* decContextSetStatus */ |