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