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