OSDN Git Service

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