OSDN Git Service

* libdecnumber: Import decNumber sources from the dfp-branch.
[pf3gnuchains/gcc-fork.git] / libdecnumber / decContext.c
1 /* Decimal context module for the decNumber C Library.
2    Copyright (C) 2005 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    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING.  If not, write to the Free
19    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 /*  This module compirises the routines for handling the arithmetic
23     context structures. */
24
25 #include <string.h>             /* for strcmp */
26 #include "decContext.h"         /* context and base types */
27 #include "decNumberLocal.h"     /* decNumber local types, etc. */
28
29 /* ------------------------------------------------------------------ */
30 /* decContextDefault -- initialize a context structure                */
31 /*                                                                    */
32 /*  context is the structure to be initialized                        */
33 /*  kind selects the required set of default values, one of:          */
34 /*      DEC_INIT_BASE       -- select ANSI X3-274 defaults            */
35 /*      DEC_INIT_DECIMAL32  -- select IEEE 754r defaults, 32-bit      */
36 /*      DEC_INIT_DECIMAL64  -- select IEEE 754r defaults, 64-bit      */
37 /*      DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit     */
38 /*      For any other value a valid context is returned, but with     */
39 /*      Invalid_operation set in the status field.                    */
40 /*  returns a context structure with the appropriate initial values.  */
41 /* ------------------------------------------------------------------ */
42 decContext *
43 decContextDefault (decContext * context, Int kind)
44 {
45   /* set defaults... */
46   context->digits = 9;          /* 9 digits */
47   context->emax = DEC_MAX_EMAX; /* 9-digit exponents */
48   context->emin = DEC_MIN_EMIN; /* .. balanced */
49   context->round = DEC_ROUND_HALF_UP;   /* 0.5 rises */
50   context->traps = DEC_Errors;  /* all but informational */
51   context->status = 0;          /* cleared */
52   context->clamp = 0;           /* no clamping */
53 #if DECSUBSET
54   context->extended = 0;        /* cleared */
55 #endif
56   switch (kind)
57     {
58     case DEC_INIT_BASE:
59       /* [use defaults] */
60       break;
61     case DEC_INIT_DECIMAL32:
62       context->digits = 7;      /* digits */
63       context->emax = 96;       /* Emax */
64       context->emin = -95;      /* Emin */
65       context->round = DEC_ROUND_HALF_EVEN;     /* 0.5 to nearest even */
66       context->traps = 0;       /* no traps set */
67       context->clamp = 1;       /* clamp exponents */
68 #if DECSUBSET
69       context->extended = 1;    /* set */
70 #endif
71       break;
72     case DEC_INIT_DECIMAL64:
73       context->digits = 16;     /* digits */
74       context->emax = 384;      /* Emax */
75       context->emin = -383;     /* Emin */
76       context->round = DEC_ROUND_HALF_EVEN;     /* 0.5 to nearest even */
77       context->traps = 0;       /* no traps set */
78       context->clamp = 1;       /* clamp exponents */
79 #if DECSUBSET
80       context->extended = 1;    /* set */
81 #endif
82       break;
83     case DEC_INIT_DECIMAL128:
84       context->digits = 34;     /* digits */
85       context->emax = 6144;     /* Emax */
86       context->emin = -6143;    /* Emin */
87       context->round = DEC_ROUND_HALF_EVEN;     /* 0.5 to nearest even */
88       context->traps = 0;       /* no traps set */
89       context->clamp = 1;       /* clamp exponents */
90 #if DECSUBSET
91       context->extended = 1;    /* set */
92 #endif
93       break;
94
95     default:                    /* invalid Kind */
96       /* use defaults, and .. */
97       decContextSetStatus (context, DEC_Invalid_operation);     /* trap */
98     }
99   return context;
100 }                               /* decContextDefault */
101
102 /* ------------------------------------------------------------------ */
103 /* decContextStatusToString -- convert status flags to a string       */
104 /*                                                                    */
105 /*  context is a context with valid status field                      */
106 /*                                                                    */
107 /*  returns a constant string describing the condition.  If multiple  */
108 /*    (or no) flags are set, a generic constant message is returned.  */
109 /* ------------------------------------------------------------------ */
110 const char *
111 decContextStatusToString (decContext * context)
112 {
113   Int status = context->status;
114   if (status == DEC_Conversion_syntax)
115     return DEC_Condition_CS;
116   if (status == DEC_Division_by_zero)
117     return DEC_Condition_DZ;
118   if (status == DEC_Division_impossible)
119     return DEC_Condition_DI;
120   if (status == DEC_Division_undefined)
121     return DEC_Condition_DU;
122   if (status == DEC_Inexact)
123     return DEC_Condition_IE;
124   if (status == DEC_Insufficient_storage)
125     return DEC_Condition_IS;
126   if (status == DEC_Invalid_context)
127     return DEC_Condition_IC;
128   if (status == DEC_Invalid_operation)
129     return DEC_Condition_IO;
130 #if DECSUBSET
131   if (status == DEC_Lost_digits)
132     return DEC_Condition_LD;
133 #endif
134   if (status == DEC_Overflow)
135     return DEC_Condition_OV;
136   if (status == DEC_Clamped)
137     return DEC_Condition_PA;
138   if (status == DEC_Rounded)
139     return DEC_Condition_RO;
140   if (status == DEC_Subnormal)
141     return DEC_Condition_SU;
142   if (status == DEC_Underflow)
143     return DEC_Condition_UN;
144   if (status == 0)
145     return DEC_Condition_ZE;
146   return DEC_Condition_MU;      /* Multiple errors */
147 }                               /* decContextStatusToString */
148
149 /* ------------------------------------------------------------------ */
150 /* decContextSetStatusFromString -- set status from a string          */
151 /*                                                                    */
152 /*  context is the controlling context                                */
153 /*  string is a string exactly equal to one that might be returned    */
154 /*            by decContextStatusToString                             */
155 /*                                                                    */
156 /*  The status bit corresponding to the string is set, and a trap     */
157 /*  is raised if appropriate.                                         */
158 /*                                                                    */
159 /*  returns the context structure, unless the string is equal to      */
160 /*    DEC_Condition_MU or is not recognized.  In these cases NULL is  */
161 /*    returned.                                                       */
162 /* ------------------------------------------------------------------ */
163 decContext *
164 decContextSetStatusFromString (decContext * context, char *string)
165 {
166   if (strcmp (string, DEC_Condition_CS) == 0)
167     return decContextSetStatus (context, DEC_Conversion_syntax);
168   if (strcmp (string, DEC_Condition_DZ) == 0)
169     return decContextSetStatus (context, DEC_Division_by_zero);
170   if (strcmp (string, DEC_Condition_DI) == 0)
171     return decContextSetStatus (context, DEC_Division_impossible);
172   if (strcmp (string, DEC_Condition_DU) == 0)
173     return decContextSetStatus (context, DEC_Division_undefined);
174   if (strcmp (string, DEC_Condition_IE) == 0)
175     return decContextSetStatus (context, DEC_Inexact);
176   if (strcmp (string, DEC_Condition_IS) == 0)
177     return decContextSetStatus (context, DEC_Insufficient_storage);
178   if (strcmp (string, DEC_Condition_IC) == 0)
179     return decContextSetStatus (context, DEC_Invalid_context);
180   if (strcmp (string, DEC_Condition_IO) == 0)
181     return decContextSetStatus (context, DEC_Invalid_operation);
182 #if DECSUBSET
183   if (strcmp (string, DEC_Condition_LD) == 0)
184     return decContextSetStatus (context, DEC_Lost_digits);
185 #endif
186   if (strcmp (string, DEC_Condition_OV) == 0)
187     return decContextSetStatus (context, DEC_Overflow);
188   if (strcmp (string, DEC_Condition_PA) == 0)
189     return decContextSetStatus (context, DEC_Clamped);
190   if (strcmp (string, DEC_Condition_RO) == 0)
191     return decContextSetStatus (context, DEC_Rounded);
192   if (strcmp (string, DEC_Condition_SU) == 0)
193     return decContextSetStatus (context, DEC_Subnormal);
194   if (strcmp (string, DEC_Condition_UN) == 0)
195     return decContextSetStatus (context, DEC_Underflow);
196   if (strcmp (string, DEC_Condition_ZE) == 0)
197     return context;
198   return NULL;                  /* Multiple status, or unknown */
199 }                               /* decContextSetStatusFromString */
200
201 /* ------------------------------------------------------------------ */
202 /* decContextSetStatus -- set status and raise trap if appropriate    */
203 /*                                                                    */
204 /*  context is the controlling context                                */
205 /*  status  is the DEC_ exception code                                */
206 /*  returns the context structure                                     */
207 /*                                                                    */
208 /* Control may never return from this routine, if there is a signal   */
209 /* handler and it takes a long jump.                                  */
210 /* ------------------------------------------------------------------ */
211 decContext *
212 decContextSetStatus (decContext * context, uInt status)
213 {
214   context->status |= status;
215   if (status & context->traps)
216     raise (SIGFPE);
217   return context;
218 }                               /* decContextSetStatus */