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