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