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