xref: /openbsd-src/gnu/gcc/libdecnumber/decContext.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
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