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