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