15796c8dcSSimon Schubert /* Decimal context module for the decNumber C Library.
2*ef5ccd6cSJohn Marino Copyright (C) 2005-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert Contributed by IBM Corporation. Author Mike Cowlishaw.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GCC.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert GCC is free software; you can redistribute it and/or modify it under
85796c8dcSSimon Schubert the terms of the GNU General Public License as published by the Free
95796c8dcSSimon Schubert Software Foundation; either version 3, or (at your option) any later
105796c8dcSSimon Schubert version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
135796c8dcSSimon Schubert WARRANTY; without even the implied warranty of MERCHANTABILITY or
145796c8dcSSimon Schubert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
155796c8dcSSimon Schubert for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert Under Section 7 of GPL version 3, you are granted additional
185796c8dcSSimon Schubert permissions described in the GCC Runtime Library Exception, version
195796c8dcSSimon Schubert 3.1, as published by the Free Software Foundation.
205796c8dcSSimon Schubert
215796c8dcSSimon Schubert You should have received a copy of the GNU General Public License and
225796c8dcSSimon Schubert a copy of the GCC Runtime Library Exception along with this program;
235796c8dcSSimon Schubert see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
245796c8dcSSimon Schubert <http://www.gnu.org/licenses/>. */
255796c8dcSSimon Schubert
265796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
275796c8dcSSimon Schubert /* Decimal Context module */
285796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
295796c8dcSSimon Schubert /* This module comprises the routines for handling arithmetic */
305796c8dcSSimon Schubert /* context structures. */
315796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
325796c8dcSSimon Schubert
335796c8dcSSimon Schubert #include <string.h> /* for strcmp */
345796c8dcSSimon Schubert #ifdef DECCHECK
355796c8dcSSimon Schubert #include <stdio.h> /* for printf if DECCHECK */
365796c8dcSSimon Schubert #endif
375796c8dcSSimon Schubert #include "dconfig.h" /* for GCC definitions */
385796c8dcSSimon Schubert #include "decContext.h" /* context and base types */
395796c8dcSSimon Schubert #include "decNumberLocal.h" /* decNumber local types, etc. */
405796c8dcSSimon Schubert
415796c8dcSSimon Schubert /* compile-time endian tester [assumes sizeof(Int)>1] */
425796c8dcSSimon Schubert static const Int mfcone=1; /* constant 1 */
435796c8dcSSimon Schubert static const Flag *mfctop=(const Flag *)&mfcone; /* -> top byte */
445796c8dcSSimon Schubert #define LITEND *mfctop /* named flag; 1=little-endian */
455796c8dcSSimon Schubert
465796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
475796c8dcSSimon Schubert /* round-for-reround digits */
485796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
495796c8dcSSimon Schubert const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
505796c8dcSSimon Schubert
515796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
525796c8dcSSimon Schubert /* Powers of ten (powers[n]==10**n, 0<=n<=9) */
535796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
545796c8dcSSimon Schubert const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
555796c8dcSSimon Schubert 10000000, 100000000, 1000000000};
565796c8dcSSimon Schubert
575796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
585796c8dcSSimon Schubert /* decContextClearStatus -- clear bits in current status */
595796c8dcSSimon Schubert /* */
605796c8dcSSimon Schubert /* context is the context structure to be queried */
615796c8dcSSimon Schubert /* mask indicates the bits to be cleared (the status bit that */
625796c8dcSSimon Schubert /* corresponds to each 1 bit in the mask is cleared) */
635796c8dcSSimon Schubert /* returns context */
645796c8dcSSimon Schubert /* */
655796c8dcSSimon Schubert /* No error is possible. */
665796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextClearStatus(decContext * context,uInt mask)675796c8dcSSimon Schubert decContext *decContextClearStatus(decContext *context, uInt mask) {
685796c8dcSSimon Schubert context->status&=~mask;
695796c8dcSSimon Schubert return context;
705796c8dcSSimon Schubert } /* decContextClearStatus */
715796c8dcSSimon Schubert
725796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
735796c8dcSSimon Schubert /* decContextDefault -- initialize a context structure */
745796c8dcSSimon Schubert /* */
755796c8dcSSimon Schubert /* context is the structure to be initialized */
765796c8dcSSimon Schubert /* kind selects the required set of default values, one of: */
775796c8dcSSimon Schubert /* DEC_INIT_BASE -- select ANSI X3-274 defaults */
785796c8dcSSimon Schubert /* DEC_INIT_DECIMAL32 -- select IEEE 754 defaults, 32-bit */
795796c8dcSSimon Schubert /* DEC_INIT_DECIMAL64 -- select IEEE 754 defaults, 64-bit */
805796c8dcSSimon Schubert /* DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit */
815796c8dcSSimon Schubert /* For any other value a valid context is returned, but with */
825796c8dcSSimon Schubert /* Invalid_operation set in the status field. */
835796c8dcSSimon Schubert /* returns a context structure with the appropriate initial values. */
845796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextDefault(decContext * context,Int kind)855796c8dcSSimon Schubert decContext * decContextDefault(decContext *context, Int kind) {
865796c8dcSSimon Schubert /* set defaults... */
875796c8dcSSimon Schubert context->digits=9; /* 9 digits */
885796c8dcSSimon Schubert context->emax=DEC_MAX_EMAX; /* 9-digit exponents */
895796c8dcSSimon Schubert context->emin=DEC_MIN_EMIN; /* .. balanced */
905796c8dcSSimon Schubert context->round=DEC_ROUND_HALF_UP; /* 0.5 rises */
915796c8dcSSimon Schubert context->traps=DEC_Errors; /* all but informational */
925796c8dcSSimon Schubert context->status=0; /* cleared */
935796c8dcSSimon Schubert context->clamp=0; /* no clamping */
945796c8dcSSimon Schubert #if DECSUBSET
955796c8dcSSimon Schubert context->extended=0; /* cleared */
965796c8dcSSimon Schubert #endif
975796c8dcSSimon Schubert switch (kind) {
985796c8dcSSimon Schubert case DEC_INIT_BASE:
995796c8dcSSimon Schubert /* [use defaults] */
1005796c8dcSSimon Schubert break;
1015796c8dcSSimon Schubert case DEC_INIT_DECIMAL32:
1025796c8dcSSimon Schubert context->digits=7; /* digits */
1035796c8dcSSimon Schubert context->emax=96; /* Emax */
1045796c8dcSSimon Schubert context->emin=-95; /* Emin */
1055796c8dcSSimon Schubert context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
1065796c8dcSSimon Schubert context->traps=0; /* no traps set */
1075796c8dcSSimon Schubert context->clamp=1; /* clamp exponents */
1085796c8dcSSimon Schubert #if DECSUBSET
1095796c8dcSSimon Schubert context->extended=1; /* set */
1105796c8dcSSimon Schubert #endif
1115796c8dcSSimon Schubert break;
1125796c8dcSSimon Schubert case DEC_INIT_DECIMAL64:
1135796c8dcSSimon Schubert context->digits=16; /* digits */
1145796c8dcSSimon Schubert context->emax=384; /* Emax */
1155796c8dcSSimon Schubert context->emin=-383; /* Emin */
1165796c8dcSSimon Schubert context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
1175796c8dcSSimon Schubert context->traps=0; /* no traps set */
1185796c8dcSSimon Schubert context->clamp=1; /* clamp exponents */
1195796c8dcSSimon Schubert #if DECSUBSET
1205796c8dcSSimon Schubert context->extended=1; /* set */
1215796c8dcSSimon Schubert #endif
1225796c8dcSSimon Schubert break;
1235796c8dcSSimon Schubert case DEC_INIT_DECIMAL128:
1245796c8dcSSimon Schubert context->digits=34; /* digits */
1255796c8dcSSimon Schubert context->emax=6144; /* Emax */
1265796c8dcSSimon Schubert context->emin=-6143; /* Emin */
1275796c8dcSSimon Schubert context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */
1285796c8dcSSimon Schubert context->traps=0; /* no traps set */
1295796c8dcSSimon Schubert context->clamp=1; /* clamp exponents */
1305796c8dcSSimon Schubert #if DECSUBSET
1315796c8dcSSimon Schubert context->extended=1; /* set */
1325796c8dcSSimon Schubert #endif
1335796c8dcSSimon Schubert break;
1345796c8dcSSimon Schubert
1355796c8dcSSimon Schubert default: /* invalid Kind */
1365796c8dcSSimon Schubert /* use defaults, and .. */
1375796c8dcSSimon Schubert decContextSetStatus(context, DEC_Invalid_operation); /* trap */
1385796c8dcSSimon Schubert }
1395796c8dcSSimon Schubert
1405796c8dcSSimon Schubert return context;} /* decContextDefault */
1415796c8dcSSimon Schubert
1425796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1435796c8dcSSimon Schubert /* decContextGetRounding -- return current rounding mode */
1445796c8dcSSimon Schubert /* */
1455796c8dcSSimon Schubert /* context is the context structure to be queried */
1465796c8dcSSimon Schubert /* returns the rounding mode */
1475796c8dcSSimon Schubert /* */
1485796c8dcSSimon Schubert /* No error is possible. */
1495796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextGetRounding(decContext * context)1505796c8dcSSimon Schubert enum rounding decContextGetRounding(decContext *context) {
1515796c8dcSSimon Schubert return context->round;
1525796c8dcSSimon Schubert } /* decContextGetRounding */
1535796c8dcSSimon Schubert
1545796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1555796c8dcSSimon Schubert /* decContextGetStatus -- return current status */
1565796c8dcSSimon Schubert /* */
1575796c8dcSSimon Schubert /* context is the context structure to be queried */
1585796c8dcSSimon Schubert /* returns status */
1595796c8dcSSimon Schubert /* */
1605796c8dcSSimon Schubert /* No error is possible. */
1615796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextGetStatus(decContext * context)1625796c8dcSSimon Schubert uInt decContextGetStatus(decContext *context) {
1635796c8dcSSimon Schubert return context->status;
1645796c8dcSSimon Schubert } /* decContextGetStatus */
1655796c8dcSSimon Schubert
1665796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1675796c8dcSSimon Schubert /* decContextRestoreStatus -- restore bits in current status */
1685796c8dcSSimon Schubert /* */
1695796c8dcSSimon Schubert /* context is the context structure to be updated */
1705796c8dcSSimon Schubert /* newstatus is the source for the bits to be restored */
1715796c8dcSSimon Schubert /* mask indicates the bits to be restored (the status bit that */
1725796c8dcSSimon Schubert /* corresponds to each 1 bit in the mask is set to the value of */
1735796c8dcSSimon Schubert /* the correspnding bit in newstatus) */
1745796c8dcSSimon Schubert /* returns context */
1755796c8dcSSimon Schubert /* */
1765796c8dcSSimon Schubert /* No error is possible. */
1775796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextRestoreStatus(decContext * context,uInt newstatus,uInt mask)1785796c8dcSSimon Schubert decContext *decContextRestoreStatus(decContext *context,
1795796c8dcSSimon Schubert uInt newstatus, uInt mask) {
1805796c8dcSSimon Schubert context->status&=~mask; /* clear the selected bits */
1815796c8dcSSimon Schubert context->status|=(mask&newstatus); /* or in the new bits */
1825796c8dcSSimon Schubert return context;
1835796c8dcSSimon Schubert } /* decContextRestoreStatus */
1845796c8dcSSimon Schubert
1855796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1865796c8dcSSimon Schubert /* decContextSaveStatus -- save bits in current status */
1875796c8dcSSimon Schubert /* */
1885796c8dcSSimon Schubert /* context is the context structure to be queried */
1895796c8dcSSimon Schubert /* mask indicates the bits to be saved (the status bits that */
1905796c8dcSSimon Schubert /* correspond to each 1 bit in the mask are saved) */
1915796c8dcSSimon Schubert /* returns the AND of the mask and the current status */
1925796c8dcSSimon Schubert /* */
1935796c8dcSSimon Schubert /* No error is possible. */
1945796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextSaveStatus(decContext * context,uInt mask)1955796c8dcSSimon Schubert uInt decContextSaveStatus(decContext *context, uInt mask) {
1965796c8dcSSimon Schubert return context->status&mask;
1975796c8dcSSimon Schubert } /* decContextSaveStatus */
1985796c8dcSSimon Schubert
1995796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
2005796c8dcSSimon Schubert /* decContextSetRounding -- set current rounding mode */
2015796c8dcSSimon Schubert /* */
2025796c8dcSSimon Schubert /* context is the context structure to be updated */
2035796c8dcSSimon Schubert /* newround is the value which will replace the current mode */
2045796c8dcSSimon Schubert /* returns context */
2055796c8dcSSimon Schubert /* */
2065796c8dcSSimon Schubert /* No error is possible. */
2075796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextSetRounding(decContext * context,enum rounding newround)2085796c8dcSSimon Schubert decContext *decContextSetRounding(decContext *context,
2095796c8dcSSimon Schubert enum rounding newround) {
2105796c8dcSSimon Schubert context->round=newround;
2115796c8dcSSimon Schubert return context;
2125796c8dcSSimon Schubert } /* decContextSetRounding */
2135796c8dcSSimon Schubert
2145796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
2155796c8dcSSimon Schubert /* decContextSetStatus -- set status and raise trap if appropriate */
2165796c8dcSSimon Schubert /* */
2175796c8dcSSimon Schubert /* context is the context structure to be updated */
2185796c8dcSSimon Schubert /* status is the DEC_ exception code */
2195796c8dcSSimon Schubert /* returns the context structure */
2205796c8dcSSimon Schubert /* */
2215796c8dcSSimon Schubert /* Control may never return from this routine, if there is a signal */
2225796c8dcSSimon Schubert /* handler and it takes a long jump. */
2235796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextSetStatus(decContext * context,uInt status)2245796c8dcSSimon Schubert decContext * decContextSetStatus(decContext *context, uInt status) {
2255796c8dcSSimon Schubert context->status|=status;
2265796c8dcSSimon Schubert if (status & context->traps) raise(SIGFPE);
2275796c8dcSSimon Schubert return context;} /* decContextSetStatus */
2285796c8dcSSimon Schubert
2295796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
2305796c8dcSSimon Schubert /* decContextSetStatusFromString -- set status from a string + trap */
2315796c8dcSSimon Schubert /* */
2325796c8dcSSimon Schubert /* context is the context structure to be updated */
2335796c8dcSSimon Schubert /* string is a string exactly equal to one that might be returned */
2345796c8dcSSimon Schubert /* by decContextStatusToString */
2355796c8dcSSimon Schubert /* */
2365796c8dcSSimon Schubert /* The status bit corresponding to the string is set, and a trap */
2375796c8dcSSimon Schubert /* is raised if appropriate. */
2385796c8dcSSimon Schubert /* */
2395796c8dcSSimon Schubert /* returns the context structure, unless the string is equal to */
2405796c8dcSSimon Schubert /* DEC_Condition_MU or is not recognized. In these cases NULL is */
2415796c8dcSSimon Schubert /* returned. */
2425796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextSetStatusFromString(decContext * context,const char * string)2435796c8dcSSimon Schubert decContext * decContextSetStatusFromString(decContext *context,
2445796c8dcSSimon Schubert const char *string) {
2455796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_CS)==0)
2465796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Conversion_syntax);
2475796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_DZ)==0)
2485796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Division_by_zero);
2495796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_DI)==0)
2505796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Division_impossible);
2515796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_DU)==0)
2525796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Division_undefined);
2535796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IE)==0)
2545796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Inexact);
2555796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IS)==0)
2565796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Insufficient_storage);
2575796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IC)==0)
2585796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Invalid_context);
2595796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IO)==0)
2605796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Invalid_operation);
2615796c8dcSSimon Schubert #if DECSUBSET
2625796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_LD)==0)
2635796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Lost_digits);
2645796c8dcSSimon Schubert #endif
2655796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_OV)==0)
2665796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Overflow);
2675796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_PA)==0)
2685796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Clamped);
2695796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_RO)==0)
2705796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Rounded);
2715796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_SU)==0)
2725796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Subnormal);
2735796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_UN)==0)
2745796c8dcSSimon Schubert return decContextSetStatus(context, DEC_Underflow);
2755796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_ZE)==0)
2765796c8dcSSimon Schubert return context;
2775796c8dcSSimon Schubert return NULL; /* Multiple status, or unknown */
2785796c8dcSSimon Schubert } /* decContextSetStatusFromString */
2795796c8dcSSimon Schubert
2805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
2815796c8dcSSimon Schubert /* decContextSetStatusFromStringQuiet -- set status from a string */
2825796c8dcSSimon Schubert /* */
2835796c8dcSSimon Schubert /* context is the context structure to be updated */
2845796c8dcSSimon Schubert /* string is a string exactly equal to one that might be returned */
2855796c8dcSSimon Schubert /* by decContextStatusToString */
2865796c8dcSSimon Schubert /* */
2875796c8dcSSimon Schubert /* The status bit corresponding to the string is set; no trap is */
2885796c8dcSSimon Schubert /* raised. */
2895796c8dcSSimon Schubert /* */
2905796c8dcSSimon Schubert /* returns the context structure, unless the string is equal to */
2915796c8dcSSimon Schubert /* DEC_Condition_MU or is not recognized. In these cases NULL is */
2925796c8dcSSimon Schubert /* returned. */
2935796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextSetStatusFromStringQuiet(decContext * context,const char * string)2945796c8dcSSimon Schubert decContext * decContextSetStatusFromStringQuiet(decContext *context,
2955796c8dcSSimon Schubert const char *string) {
2965796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_CS)==0)
2975796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Conversion_syntax);
2985796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_DZ)==0)
2995796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Division_by_zero);
3005796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_DI)==0)
3015796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Division_impossible);
3025796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_DU)==0)
3035796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Division_undefined);
3045796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IE)==0)
3055796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Inexact);
3065796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IS)==0)
3075796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Insufficient_storage);
3085796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IC)==0)
3095796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Invalid_context);
3105796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_IO)==0)
3115796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Invalid_operation);
3125796c8dcSSimon Schubert #if DECSUBSET
3135796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_LD)==0)
3145796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Lost_digits);
3155796c8dcSSimon Schubert #endif
3165796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_OV)==0)
3175796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Overflow);
3185796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_PA)==0)
3195796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Clamped);
3205796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_RO)==0)
3215796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Rounded);
3225796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_SU)==0)
3235796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Subnormal);
3245796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_UN)==0)
3255796c8dcSSimon Schubert return decContextSetStatusQuiet(context, DEC_Underflow);
3265796c8dcSSimon Schubert if (strcmp(string, DEC_Condition_ZE)==0)
3275796c8dcSSimon Schubert return context;
3285796c8dcSSimon Schubert return NULL; /* Multiple status, or unknown */
3295796c8dcSSimon Schubert } /* decContextSetStatusFromStringQuiet */
3305796c8dcSSimon Schubert
3315796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
3325796c8dcSSimon Schubert /* decContextSetStatusQuiet -- set status without trap */
3335796c8dcSSimon Schubert /* */
3345796c8dcSSimon Schubert /* context is the context structure to be updated */
3355796c8dcSSimon Schubert /* status is the DEC_ exception code */
3365796c8dcSSimon Schubert /* returns the context structure */
3375796c8dcSSimon Schubert /* */
3385796c8dcSSimon Schubert /* No error is possible. */
3395796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextSetStatusQuiet(decContext * context,uInt status)3405796c8dcSSimon Schubert decContext * decContextSetStatusQuiet(decContext *context, uInt status) {
3415796c8dcSSimon Schubert context->status|=status;
3425796c8dcSSimon Schubert return context;} /* decContextSetStatusQuiet */
3435796c8dcSSimon Schubert
3445796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
3455796c8dcSSimon Schubert /* decContextStatusToString -- convert status flags to a string */
3465796c8dcSSimon Schubert /* */
3475796c8dcSSimon Schubert /* context is a context with valid status field */
3485796c8dcSSimon Schubert /* */
3495796c8dcSSimon Schubert /* returns a constant string describing the condition. If multiple */
3505796c8dcSSimon Schubert /* (or no) flags are set, a generic constant message is returned. */
3515796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextStatusToString(const decContext * context)3525796c8dcSSimon Schubert const char *decContextStatusToString(const decContext *context) {
3535796c8dcSSimon Schubert Int status=context->status;
3545796c8dcSSimon Schubert
3555796c8dcSSimon Schubert /* test the five IEEE first, as some of the others are ambiguous when */
3565796c8dcSSimon Schubert /* DECEXTFLAG=0 */
3575796c8dcSSimon Schubert if (status==DEC_Invalid_operation ) return DEC_Condition_IO;
3585796c8dcSSimon Schubert if (status==DEC_Division_by_zero ) return DEC_Condition_DZ;
3595796c8dcSSimon Schubert if (status==DEC_Overflow ) return DEC_Condition_OV;
3605796c8dcSSimon Schubert if (status==DEC_Underflow ) return DEC_Condition_UN;
3615796c8dcSSimon Schubert if (status==DEC_Inexact ) return DEC_Condition_IE;
3625796c8dcSSimon Schubert
3635796c8dcSSimon Schubert if (status==DEC_Division_impossible ) return DEC_Condition_DI;
3645796c8dcSSimon Schubert if (status==DEC_Division_undefined ) return DEC_Condition_DU;
3655796c8dcSSimon Schubert if (status==DEC_Rounded ) return DEC_Condition_RO;
3665796c8dcSSimon Schubert if (status==DEC_Clamped ) return DEC_Condition_PA;
3675796c8dcSSimon Schubert if (status==DEC_Subnormal ) return DEC_Condition_SU;
3685796c8dcSSimon Schubert if (status==DEC_Conversion_syntax ) return DEC_Condition_CS;
3695796c8dcSSimon Schubert if (status==DEC_Insufficient_storage ) return DEC_Condition_IS;
3705796c8dcSSimon Schubert if (status==DEC_Invalid_context ) return DEC_Condition_IC;
3715796c8dcSSimon Schubert #if DECSUBSET
3725796c8dcSSimon Schubert if (status==DEC_Lost_digits ) return DEC_Condition_LD;
3735796c8dcSSimon Schubert #endif
3745796c8dcSSimon Schubert if (status==0 ) return DEC_Condition_ZE;
3755796c8dcSSimon Schubert return DEC_Condition_MU; /* Multiple errors */
3765796c8dcSSimon Schubert } /* decContextStatusToString */
3775796c8dcSSimon Schubert
3785796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
3795796c8dcSSimon Schubert /* decContextTestEndian -- test whether DECLITEND is set correctly */
3805796c8dcSSimon Schubert /* */
3815796c8dcSSimon Schubert /* quiet is 1 to suppress message; 0 otherwise */
3825796c8dcSSimon Schubert /* returns 0 if DECLITEND is correct */
3835796c8dcSSimon Schubert /* 1 if DECLITEND is incorrect and should be 1 */
3845796c8dcSSimon Schubert /* -1 if DECLITEND is incorrect and should be 0 */
3855796c8dcSSimon Schubert /* */
3865796c8dcSSimon Schubert /* A message is displayed if the return value is not 0 and quiet==0. */
3875796c8dcSSimon Schubert /* */
3885796c8dcSSimon Schubert /* No error is possible. */
3895796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextTestEndian(Flag quiet)3905796c8dcSSimon Schubert Int decContextTestEndian(Flag quiet) {
3915796c8dcSSimon Schubert Int res=0; /* optimist */
3925796c8dcSSimon Schubert uInt dle=(uInt)DECLITEND; /* unsign */
3935796c8dcSSimon Schubert if (dle>1) dle=1; /* ensure 0 or 1 */
3945796c8dcSSimon Schubert
3955796c8dcSSimon Schubert if (LITEND!=DECLITEND) {
3965796c8dcSSimon Schubert if (!quiet) {
397cf7f2e2dSJohn Marino #if DECCHECK
398cf7f2e2dSJohn Marino const char *adj;
3995796c8dcSSimon Schubert if (LITEND) adj="little";
4005796c8dcSSimon Schubert else adj="big";
4015796c8dcSSimon Schubert printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
4025796c8dcSSimon Schubert DECLITEND, adj);
4035796c8dcSSimon Schubert #endif
4045796c8dcSSimon Schubert }
4055796c8dcSSimon Schubert res=(Int)LITEND-dle;
4065796c8dcSSimon Schubert }
4075796c8dcSSimon Schubert return res;
4085796c8dcSSimon Schubert } /* decContextTestEndian */
4095796c8dcSSimon Schubert
4105796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4115796c8dcSSimon Schubert /* decContextTestSavedStatus -- test bits in saved status */
4125796c8dcSSimon Schubert /* */
4135796c8dcSSimon Schubert /* oldstatus is the status word to be tested */
4145796c8dcSSimon Schubert /* mask indicates the bits to be tested (the oldstatus bits that */
4155796c8dcSSimon Schubert /* correspond to each 1 bit in the mask are tested) */
4165796c8dcSSimon Schubert /* returns 1 if any of the tested bits are 1, or 0 otherwise */
4175796c8dcSSimon Schubert /* */
4185796c8dcSSimon Schubert /* No error is possible. */
4195796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextTestSavedStatus(uInt oldstatus,uInt mask)4205796c8dcSSimon Schubert uInt decContextTestSavedStatus(uInt oldstatus, uInt mask) {
4215796c8dcSSimon Schubert return (oldstatus&mask)!=0;
4225796c8dcSSimon Schubert } /* decContextTestSavedStatus */
4235796c8dcSSimon Schubert
4245796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4255796c8dcSSimon Schubert /* decContextTestStatus -- test bits in current status */
4265796c8dcSSimon Schubert /* */
4275796c8dcSSimon Schubert /* context is the context structure to be updated */
4285796c8dcSSimon Schubert /* mask indicates the bits to be tested (the status bits that */
4295796c8dcSSimon Schubert /* correspond to each 1 bit in the mask are tested) */
4305796c8dcSSimon Schubert /* returns 1 if any of the tested bits are 1, or 0 otherwise */
4315796c8dcSSimon Schubert /* */
4325796c8dcSSimon Schubert /* No error is possible. */
4335796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextTestStatus(decContext * context,uInt mask)4345796c8dcSSimon Schubert uInt decContextTestStatus(decContext *context, uInt mask) {
4355796c8dcSSimon Schubert return (context->status&mask)!=0;
4365796c8dcSSimon Schubert } /* decContextTestStatus */
4375796c8dcSSimon Schubert
4385796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4395796c8dcSSimon Schubert /* decContextZeroStatus -- clear all status bits */
4405796c8dcSSimon Schubert /* */
4415796c8dcSSimon Schubert /* context is the context structure to be updated */
4425796c8dcSSimon Schubert /* returns context */
4435796c8dcSSimon Schubert /* */
4445796c8dcSSimon Schubert /* No error is possible. */
4455796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decContextZeroStatus(decContext * context)4465796c8dcSSimon Schubert decContext *decContextZeroStatus(decContext *context) {
4475796c8dcSSimon Schubert context->status=0;
4485796c8dcSSimon Schubert return context;
4495796c8dcSSimon Schubert } /* decContextZeroStatus */
4505796c8dcSSimon Schubert
451