]>
git.proxmox.com Git - mirror_qemu.git/blob - 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.
5 This file is part of GCC.
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
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.)
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
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
31 /* ------------------------------------------------------------------ */
32 /* Decimal Context module */
33 /* ------------------------------------------------------------------ */
34 /* This module comprises the routines for handling arithmetic */
35 /* context structures. */
36 /* ------------------------------------------------------------------ */
38 #include <string.h> /* for strcmp */
39 #include <stdio.h> /* for printf if DECCHECK */
40 #include "libdecnumber/dconfig.h"
41 #include "libdecnumber/decContext.h"
42 #include "libdecnumber/decNumberLocal.h"
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 */
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 */
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};
62 /* ------------------------------------------------------------------ */
63 /* decContextClearStatus -- clear bits in current status */
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) */
70 /* No error is possible. */
71 /* ------------------------------------------------------------------ */
72 decContext
*decContextClearStatus(decContext
*context
, uInt mask
) {
73 context
->status
&=~mask
;
75 } /* decContextClearStatus */
77 /* ------------------------------------------------------------------ */
78 /* decContextDefault -- initialize a context structure */
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
) {
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 */
100 context
->extended
=0; /* cleared */
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 */
114 context
->extended
=1; /* set */
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 */
125 context
->extended
=1; /* set */
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 */
136 context
->extended
=1; /* set */
140 default: /* invalid Kind */
141 /* use defaults, and .. */
142 decContextSetStatus(context
, DEC_Invalid_operation
); /* trap */
146 if (LITEND
!=DECLITEND
) {
148 if (LITEND
) adj
="little";
150 printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
154 return context
;} /* decContextDefault */
156 /* ------------------------------------------------------------------ */
157 /* decContextGetRounding -- return current rounding mode */
159 /* context is the context structure to be queried */
160 /* returns the rounding mode */
162 /* No error is possible. */
163 /* ------------------------------------------------------------------ */
164 enum rounding
decContextGetRounding(decContext
*context
) {
165 return context
->round
;
166 } /* decContextGetRounding */
168 /* ------------------------------------------------------------------ */
169 /* decContextGetStatus -- return current status */
171 /* context is the context structure to be queried */
174 /* No error is possible. */
175 /* ------------------------------------------------------------------ */
176 uInt
decContextGetStatus(decContext
*context
) {
177 return context
->status
;
178 } /* decContextGetStatus */
180 /* ------------------------------------------------------------------ */
181 /* decContextRestoreStatus -- restore bits in current status */
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 */
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 */
197 } /* decContextRestoreStatus */
199 /* ------------------------------------------------------------------ */
200 /* decContextSaveStatus -- save bits in current status */
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 */
207 /* No error is possible. */
208 /* ------------------------------------------------------------------ */
209 uInt
decContextSaveStatus(decContext
*context
, uInt mask
) {
210 return context
->status
&mask
;
211 } /* decContextSaveStatus */
213 /* ------------------------------------------------------------------ */
214 /* decContextSetRounding -- set current rounding mode */
216 /* context is the context structure to be updated */
217 /* newround is the value which will replace the current mode */
218 /* returns context */
220 /* No error is possible. */
221 /* ------------------------------------------------------------------ */
222 decContext
*decContextSetRounding(decContext
*context
,
223 enum rounding newround
) {
224 context
->round
=newround
;
226 } /* decContextSetRounding */
228 /* ------------------------------------------------------------------ */
229 /* decContextSetStatus -- set status and raise trap if appropriate */
231 /* context is the context structure to be updated */
232 /* status is the DEC_ exception code */
233 /* returns the context structure */
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 */
243 /* ------------------------------------------------------------------ */
244 /* decContextSetStatusFromString -- set status from a string + trap */
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 */
250 /* The status bit corresponding to the string is set, and a trap */
251 /* is raised if appropriate. */
253 /* returns the context structure, unless the string is equal to */
254 /* DEC_Condition_MU or is not recognized. In these cases NULL is */
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
);
276 if (strcmp(string
, DEC_Condition_LD
)==0)
277 return decContextSetStatus(context
, DEC_Lost_digits
);
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)
291 return NULL
; /* Multiple status, or unknown */
292 } /* decContextSetStatusFromString */
294 /* ------------------------------------------------------------------ */
295 /* decContextSetStatusFromStringQuiet -- set status from a string */
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 */
301 /* The status bit corresponding to the string is set; no trap is */
304 /* returns the context structure, unless the string is equal to */
305 /* DEC_Condition_MU or is not recognized. In these cases NULL is */
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
);
327 if (strcmp(string
, DEC_Condition_LD
)==0)
328 return decContextSetStatusQuiet(context
, DEC_Lost_digits
);
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)
342 return NULL
; /* Multiple status, or unknown */
343 } /* decContextSetStatusFromStringQuiet */
345 /* ------------------------------------------------------------------ */
346 /* decContextSetStatusQuiet -- set status without trap */
348 /* context is the context structure to be updated */
349 /* status is the DEC_ exception code */
350 /* returns the context structure */
352 /* No error is possible. */
353 /* ------------------------------------------------------------------ */
354 decContext
* decContextSetStatusQuiet(decContext
*context
, uInt status
) {
355 context
->status
|=status
;
356 return context
;} /* decContextSetStatusQuiet */
358 /* ------------------------------------------------------------------ */
359 /* decContextStatusToString -- convert status flags to a string */
361 /* context is a context with valid status field */
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
;
369 /* test the five IEEE first, as some of the others are ambiguous when */
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
;
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
;
386 if (status
==DEC_Lost_digits
) return DEC_Condition_LD
;
388 if (status
==0 ) return DEC_Condition_ZE
;
389 return DEC_Condition_MU
; /* Multiple errors */
390 } /* decContextStatusToString */
392 /* ------------------------------------------------------------------ */
393 /* decContextTestSavedStatus -- test bits in saved status */
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 */
400 /* No error is possible. */
401 /* ------------------------------------------------------------------ */
402 uInt
decContextTestSavedStatus(uInt oldstatus
, uInt mask
) {
403 return (oldstatus
&mask
)!=0;
404 } /* decContextTestSavedStatus */
406 /* ------------------------------------------------------------------ */
407 /* decContextTestStatus -- test bits in current status */
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 */
414 /* No error is possible. */
415 /* ------------------------------------------------------------------ */
416 uInt
decContextTestStatus(decContext
*context
, uInt mask
) {
417 return (context
->status
&mask
)!=0;
418 } /* decContextTestStatus */
420 /* ------------------------------------------------------------------ */
421 /* decContextZeroStatus -- clear all status bits */
423 /* context is the context structure to be updated */
424 /* returns context */
426 /* No error is possible. */
427 /* ------------------------------------------------------------------ */
428 decContext
*decContextZeroStatus(decContext
*context
) {
431 } /* decContextZeroStatus */