1*404b540aSrobert /* Decimal context module for the decNumber C Library.
2*404b540aSrobert Copyright (C) 2005 Free Software Foundation, Inc.
3*404b540aSrobert Contributed by IBM Corporation. Author Mike Cowlishaw.
4*404b540aSrobert
5*404b540aSrobert This file is part of GCC.
6*404b540aSrobert
7*404b540aSrobert GCC is free software; you can redistribute it and/or modify it under
8*404b540aSrobert the terms of the GNU General Public License as published by the Free
9*404b540aSrobert Software Foundation; either version 2, or (at your option) any later
10*404b540aSrobert version.
11*404b540aSrobert
12*404b540aSrobert In addition to the permissions in the GNU General Public License,
13*404b540aSrobert the Free Software Foundation gives you unlimited permission to link
14*404b540aSrobert the compiled version of this file into combinations with other
15*404b540aSrobert programs, and to distribute those combinations without any
16*404b540aSrobert restriction coming from the use of this file. (The General Public
17*404b540aSrobert License restrictions do apply in other respects; for example, they
18*404b540aSrobert cover modification of the file, and distribution when not linked
19*404b540aSrobert into a combine executable.)
20*404b540aSrobert
21*404b540aSrobert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
22*404b540aSrobert WARRANTY; without even the implied warranty of MERCHANTABILITY or
23*404b540aSrobert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24*404b540aSrobert for more details.
25*404b540aSrobert
26*404b540aSrobert You should have received a copy of the GNU General Public License
27*404b540aSrobert along with GCC; see the file COPYING. If not, write to the Free
28*404b540aSrobert Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29*404b540aSrobert 02110-1301, USA. */
30*404b540aSrobert
31*404b540aSrobert /* This module compirises the routines for handling the arithmetic
32*404b540aSrobert context structures. */
33*404b540aSrobert
34*404b540aSrobert #include <string.h> /* for strcmp */
35*404b540aSrobert #include "config.h"
36*404b540aSrobert #include "decContext.h" /* context and base types */
37*404b540aSrobert #include "decNumberLocal.h" /* decNumber local types, etc. */
38*404b540aSrobert
39*404b540aSrobert /* ------------------------------------------------------------------ */
40*404b540aSrobert /* decContextDefault -- initialize a context structure */
41*404b540aSrobert /* */
42*404b540aSrobert /* context is the structure to be initialized */
43*404b540aSrobert /* kind selects the required set of default values, one of: */
44*404b540aSrobert /* DEC_INIT_BASE -- select ANSI X3-274 defaults */
45*404b540aSrobert /* DEC_INIT_DECIMAL32 -- select IEEE 754r defaults, 32-bit */
46*404b540aSrobert /* DEC_INIT_DECIMAL64 -- select IEEE 754r defaults, 64-bit */
47*404b540aSrobert /* DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit */
48*404b540aSrobert /* For any other value a valid context is returned, but with */
49*404b540aSrobert /* Invalid_operation set in the status field. */
50*404b540aSrobert /* returns a context structure with the appropriate initial values. */
51*404b540aSrobert /* ------------------------------------------------------------------ */
52*404b540aSrobert decContext *
decContextDefault(decContext * context,Int kind)53*404b540aSrobert decContextDefault (decContext * context, Int kind)
54*404b540aSrobert {
55*404b540aSrobert /* set defaults... */
56*404b540aSrobert context->digits = 9; /* 9 digits */
57*404b540aSrobert context->emax = DEC_MAX_EMAX; /* 9-digit exponents */
58*404b540aSrobert context->emin = DEC_MIN_EMIN; /* .. balanced */
59*404b540aSrobert context->round = DEC_ROUND_HALF_UP; /* 0.5 rises */
60*404b540aSrobert context->traps = DEC_Errors; /* all but informational */
61*404b540aSrobert context->status = 0; /* cleared */
62*404b540aSrobert context->clamp = 0; /* no clamping */
63*404b540aSrobert #if DECSUBSET
64*404b540aSrobert context->extended = 0; /* cleared */
65*404b540aSrobert #endif
66*404b540aSrobert switch (kind)
67*404b540aSrobert {
68*404b540aSrobert case DEC_INIT_BASE:
69*404b540aSrobert /* [use defaults] */
70*404b540aSrobert break;
71*404b540aSrobert case DEC_INIT_DECIMAL32:
72*404b540aSrobert context->digits = 7; /* digits */
73*404b540aSrobert context->emax = 96; /* Emax */
74*404b540aSrobert context->emin = -95; /* Emin */
75*404b540aSrobert context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
76*404b540aSrobert context->traps = 0; /* no traps set */
77*404b540aSrobert context->clamp = 1; /* clamp exponents */
78*404b540aSrobert #if DECSUBSET
79*404b540aSrobert context->extended = 1; /* set */
80*404b540aSrobert #endif
81*404b540aSrobert break;
82*404b540aSrobert case DEC_INIT_DECIMAL64:
83*404b540aSrobert context->digits = 16; /* digits */
84*404b540aSrobert context->emax = 384; /* Emax */
85*404b540aSrobert context->emin = -383; /* Emin */
86*404b540aSrobert context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
87*404b540aSrobert context->traps = 0; /* no traps set */
88*404b540aSrobert context->clamp = 1; /* clamp exponents */
89*404b540aSrobert #if DECSUBSET
90*404b540aSrobert context->extended = 1; /* set */
91*404b540aSrobert #endif
92*404b540aSrobert break;
93*404b540aSrobert case DEC_INIT_DECIMAL128:
94*404b540aSrobert context->digits = 34; /* digits */
95*404b540aSrobert context->emax = 6144; /* Emax */
96*404b540aSrobert context->emin = -6143; /* Emin */
97*404b540aSrobert context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
98*404b540aSrobert context->traps = 0; /* no traps set */
99*404b540aSrobert context->clamp = 1; /* clamp exponents */
100*404b540aSrobert #if DECSUBSET
101*404b540aSrobert context->extended = 1; /* set */
102*404b540aSrobert #endif
103*404b540aSrobert break;
104*404b540aSrobert
105*404b540aSrobert default: /* invalid Kind */
106*404b540aSrobert /* use defaults, and .. */
107*404b540aSrobert decContextSetStatus (context, DEC_Invalid_operation); /* trap */
108*404b540aSrobert }
109*404b540aSrobert return context;
110*404b540aSrobert } /* decContextDefault */
111*404b540aSrobert
112*404b540aSrobert /* ------------------------------------------------------------------ */
113*404b540aSrobert /* decContextStatusToString -- convert status flags to a string */
114*404b540aSrobert /* */
115*404b540aSrobert /* context is a context with valid status field */
116*404b540aSrobert /* */
117*404b540aSrobert /* returns a constant string describing the condition. If multiple */
118*404b540aSrobert /* (or no) flags are set, a generic constant message is returned. */
119*404b540aSrobert /* ------------------------------------------------------------------ */
120*404b540aSrobert const char *
decContextStatusToString(const decContext * context)121*404b540aSrobert decContextStatusToString (const decContext * context)
122*404b540aSrobert {
123*404b540aSrobert Int status = context->status;
124*404b540aSrobert if (status == DEC_Conversion_syntax)
125*404b540aSrobert return DEC_Condition_CS;
126*404b540aSrobert if (status == DEC_Division_by_zero)
127*404b540aSrobert return DEC_Condition_DZ;
128*404b540aSrobert if (status == DEC_Division_impossible)
129*404b540aSrobert return DEC_Condition_DI;
130*404b540aSrobert if (status == DEC_Division_undefined)
131*404b540aSrobert return DEC_Condition_DU;
132*404b540aSrobert if (status == DEC_Inexact)
133*404b540aSrobert return DEC_Condition_IE;
134*404b540aSrobert if (status == DEC_Insufficient_storage)
135*404b540aSrobert return DEC_Condition_IS;
136*404b540aSrobert if (status == DEC_Invalid_context)
137*404b540aSrobert return DEC_Condition_IC;
138*404b540aSrobert if (status == DEC_Invalid_operation)
139*404b540aSrobert return DEC_Condition_IO;
140*404b540aSrobert #if DECSUBSET
141*404b540aSrobert if (status == DEC_Lost_digits)
142*404b540aSrobert return DEC_Condition_LD;
143*404b540aSrobert #endif
144*404b540aSrobert if (status == DEC_Overflow)
145*404b540aSrobert return DEC_Condition_OV;
146*404b540aSrobert if (status == DEC_Clamped)
147*404b540aSrobert return DEC_Condition_PA;
148*404b540aSrobert if (status == DEC_Rounded)
149*404b540aSrobert return DEC_Condition_RO;
150*404b540aSrobert if (status == DEC_Subnormal)
151*404b540aSrobert return DEC_Condition_SU;
152*404b540aSrobert if (status == DEC_Underflow)
153*404b540aSrobert return DEC_Condition_UN;
154*404b540aSrobert if (status == 0)
155*404b540aSrobert return DEC_Condition_ZE;
156*404b540aSrobert return DEC_Condition_MU; /* Multiple errors */
157*404b540aSrobert } /* decContextStatusToString */
158*404b540aSrobert
159*404b540aSrobert /* ------------------------------------------------------------------ */
160*404b540aSrobert /* decContextSetStatusFromString -- set status from a string */
161*404b540aSrobert /* */
162*404b540aSrobert /* context is the controlling context */
163*404b540aSrobert /* string is a string exactly equal to one that might be returned */
164*404b540aSrobert /* by decContextStatusToString */
165*404b540aSrobert /* */
166*404b540aSrobert /* The status bit corresponding to the string is set, and a trap */
167*404b540aSrobert /* is raised if appropriate. */
168*404b540aSrobert /* */
169*404b540aSrobert /* returns the context structure, unless the string is equal to */
170*404b540aSrobert /* DEC_Condition_MU or is not recognized. In these cases NULL is */
171*404b540aSrobert /* returned. */
172*404b540aSrobert /* ------------------------------------------------------------------ */
173*404b540aSrobert decContext *
decContextSetStatusFromString(decContext * context,const char * string)174*404b540aSrobert decContextSetStatusFromString (decContext * context, const char *string)
175*404b540aSrobert {
176*404b540aSrobert if (strcmp (string, DEC_Condition_CS) == 0)
177*404b540aSrobert return decContextSetStatus (context, DEC_Conversion_syntax);
178*404b540aSrobert if (strcmp (string, DEC_Condition_DZ) == 0)
179*404b540aSrobert return decContextSetStatus (context, DEC_Division_by_zero);
180*404b540aSrobert if (strcmp (string, DEC_Condition_DI) == 0)
181*404b540aSrobert return decContextSetStatus (context, DEC_Division_impossible);
182*404b540aSrobert if (strcmp (string, DEC_Condition_DU) == 0)
183*404b540aSrobert return decContextSetStatus (context, DEC_Division_undefined);
184*404b540aSrobert if (strcmp (string, DEC_Condition_IE) == 0)
185*404b540aSrobert return decContextSetStatus (context, DEC_Inexact);
186*404b540aSrobert if (strcmp (string, DEC_Condition_IS) == 0)
187*404b540aSrobert return decContextSetStatus (context, DEC_Insufficient_storage);
188*404b540aSrobert if (strcmp (string, DEC_Condition_IC) == 0)
189*404b540aSrobert return decContextSetStatus (context, DEC_Invalid_context);
190*404b540aSrobert if (strcmp (string, DEC_Condition_IO) == 0)
191*404b540aSrobert return decContextSetStatus (context, DEC_Invalid_operation);
192*404b540aSrobert #if DECSUBSET
193*404b540aSrobert if (strcmp (string, DEC_Condition_LD) == 0)
194*404b540aSrobert return decContextSetStatus (context, DEC_Lost_digits);
195*404b540aSrobert #endif
196*404b540aSrobert if (strcmp (string, DEC_Condition_OV) == 0)
197*404b540aSrobert return decContextSetStatus (context, DEC_Overflow);
198*404b540aSrobert if (strcmp (string, DEC_Condition_PA) == 0)
199*404b540aSrobert return decContextSetStatus (context, DEC_Clamped);
200*404b540aSrobert if (strcmp (string, DEC_Condition_RO) == 0)
201*404b540aSrobert return decContextSetStatus (context, DEC_Rounded);
202*404b540aSrobert if (strcmp (string, DEC_Condition_SU) == 0)
203*404b540aSrobert return decContextSetStatus (context, DEC_Subnormal);
204*404b540aSrobert if (strcmp (string, DEC_Condition_UN) == 0)
205*404b540aSrobert return decContextSetStatus (context, DEC_Underflow);
206*404b540aSrobert if (strcmp (string, DEC_Condition_ZE) == 0)
207*404b540aSrobert return context;
208*404b540aSrobert return NULL; /* Multiple status, or unknown */
209*404b540aSrobert } /* decContextSetStatusFromString */
210*404b540aSrobert
211*404b540aSrobert /* ------------------------------------------------------------------ */
212*404b540aSrobert /* decContextSetStatus -- set status and raise trap if appropriate */
213*404b540aSrobert /* */
214*404b540aSrobert /* context is the controlling context */
215*404b540aSrobert /* status is the DEC_ exception code */
216*404b540aSrobert /* returns the context structure */
217*404b540aSrobert /* */
218*404b540aSrobert /* Control may never return from this routine, if there is a signal */
219*404b540aSrobert /* handler and it takes a long jump. */
220*404b540aSrobert /* ------------------------------------------------------------------ */
221*404b540aSrobert decContext *
decContextSetStatus(decContext * context,uInt status)222*404b540aSrobert decContextSetStatus (decContext * context, uInt status)
223*404b540aSrobert {
224*404b540aSrobert context->status |= status;
225*404b540aSrobert if (status & context->traps)
226*404b540aSrobert raise (SIGFPE);
227*404b540aSrobert return context;
228*404b540aSrobert } /* decContextSetStatus */
229