xref: /openbmc/qemu/libdecnumber/decContext.c (revision f10e7b9f6fc18be390b3bc189e04b5147eb8dbf8)
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