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