138032Speter/* Decimal context module for the decNumber C Library.
238032Speter   Copyright (C) 2005 Free Software Foundation, Inc.
338032Speter   Contributed by IBM Corporation.  Author Mike Cowlishaw.
464562Sgshapiro
564562Sgshapiro   This file is part of GCC.
638032Speter
738032Speter   GCC is free software; you can redistribute it and/or modify it under
838032Speter   the terms of the GNU General Public License as published by the Free
938032Speter   Software Foundation; either version 2, or (at your option) any later
1038032Speter   version.
1138032Speter
1238032Speter   In addition to the permissions in the GNU General Public License,
1338032Speter   the Free Software Foundation gives you unlimited permission to link
1438032Speter   the compiled version of this file into combinations with other
1538032Speter   programs, and to distribute those combinations without any
1638032Speter   restriction coming from the use of this file.  (The General Public
1738032Speter   License restrictions do apply in other respects; for example, they
1838032Speter   cover modification of the file, and distribution when not linked
1938032Speter   into a combine executable.)
2038032Speter
2138032Speter   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
2238032Speter   WARRANTY; without even the implied warranty of MERCHANTABILITY or
2338032Speter   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
2464562Sgshapiro   for more details.
2564562Sgshapiro
2638032Speter   You should have received a copy of the GNU General Public License
2738032Speter   along with GCC; see the file COPYING.  If not, write to the Free
2838032Speter   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2938032Speter   02110-1301, USA.  */
3038032Speter
3138032Speter/*  This module compirises the routines for handling the arithmetic
3238032Speter    context structures. */
3338032Speter
3438032Speter#include <string.h>		/* for strcmp */
3538032Speter#include "config.h"
3664562Sgshapiro#include "decContext.h"		/* context and base types */
3738032Speter#include "decNumberLocal.h"	/* decNumber local types, etc. */
3838032Speter
3938032Speter/* ------------------------------------------------------------------ */
4038032Speter/* decContextDefault -- initialize a context structure                */
4138032Speter/*                                                                    */
4238032Speter/*  context is the structure to be initialized                        */
4338032Speter/*  kind selects the required set of default values, one of:          */
4438032Speter/*      DEC_INIT_BASE       -- select ANSI X3-274 defaults            */
4538032Speter/*      DEC_INIT_DECIMAL32  -- select IEEE 754r defaults, 32-bit      */
4638032Speter/*      DEC_INIT_DECIMAL64  -- select IEEE 754r defaults, 64-bit      */
4738032Speter/*      DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit     */
4838032Speter/*      For any other value a valid context is returned, but with     */
4938032Speter/*      Invalid_operation set in the status field.                    */
5038032Speter/*  returns a context structure with the appropriate initial values.  */
5138032Speter/* ------------------------------------------------------------------ */
5238032SpeterdecContext *
5338032SpeterdecContextDefault (decContext * context, Int kind)
5438032Speter{
5538032Speter  /* set defaults... */
5638032Speter  context->digits = 9;		/* 9 digits */
5738032Speter  context->emax = DEC_MAX_EMAX;	/* 9-digit exponents */
5838032Speter  context->emin = DEC_MIN_EMIN;	/* .. balanced */
5938032Speter  context->round = DEC_ROUND_HALF_UP;	/* 0.5 rises */
6038032Speter  context->traps = DEC_Errors;	/* all but informational */
6138032Speter  context->status = 0;		/* cleared */
6264562Sgshapiro  context->clamp = 0;		/* no clamping */
6338032Speter#if DECSUBSET
6438032Speter  context->extended = 0;	/* cleared */
6538032Speter#endif
6638032Speter  switch (kind)
6738032Speter    {
6838032Speter    case DEC_INIT_BASE:
6938032Speter      /* [use defaults] */
7038032Speter      break;
7138032Speter    case DEC_INIT_DECIMAL32:
7238032Speter      context->digits = 7;	/* digits */
7338032Speter      context->emax = 96;	/* Emax */
7438032Speter      context->emin = -95;	/* Emin */
7538032Speter      context->round = DEC_ROUND_HALF_EVEN;	/* 0.5 to nearest even */
7638032Speter      context->traps = 0;	/* no traps set */
7738032Speter      context->clamp = 1;	/* clamp exponents */
7838032Speter#if DECSUBSET
7964562Sgshapiro      context->extended = 1;	/* set */
80#endif
81      break;
82    case DEC_INIT_DECIMAL64:
83      context->digits = 16;	/* digits */
84      context->emax = 384;	/* Emax */
85      context->emin = -383;	/* Emin */
86      context->round = DEC_ROUND_HALF_EVEN;	/* 0.5 to nearest even */
87      context->traps = 0;	/* no traps set */
88      context->clamp = 1;	/* clamp exponents */
89#if DECSUBSET
90      context->extended = 1;	/* set */
91#endif
92      break;
93    case DEC_INIT_DECIMAL128:
94      context->digits = 34;	/* digits */
95      context->emax = 6144;	/* Emax */
96      context->emin = -6143;	/* Emin */
97      context->round = DEC_ROUND_HALF_EVEN;	/* 0.5 to nearest even */
98      context->traps = 0;	/* no traps set */
99      context->clamp = 1;	/* clamp exponents */
100#if DECSUBSET
101      context->extended = 1;	/* set */
102#endif
103      break;
104
105    default:			/* invalid Kind */
106      /* use defaults, and .. */
107      decContextSetStatus (context, DEC_Invalid_operation);	/* trap */
108    }
109  return context;
110}				/* decContextDefault */
111
112/* ------------------------------------------------------------------ */
113/* decContextStatusToString -- convert status flags to a string       */
114/*                                                                    */
115/*  context is a context with valid status field                      */
116/*                                                                    */
117/*  returns a constant string describing the condition.  If multiple  */
118/*    (or no) flags are set, a generic constant message is returned.  */
119/* ------------------------------------------------------------------ */
120const char *
121decContextStatusToString (const decContext * context)
122{
123  Int status = context->status;
124  if (status == DEC_Conversion_syntax)
125    return DEC_Condition_CS;
126  if (status == DEC_Division_by_zero)
127    return DEC_Condition_DZ;
128  if (status == DEC_Division_impossible)
129    return DEC_Condition_DI;
130  if (status == DEC_Division_undefined)
131    return DEC_Condition_DU;
132  if (status == DEC_Inexact)
133    return DEC_Condition_IE;
134  if (status == DEC_Insufficient_storage)
135    return DEC_Condition_IS;
136  if (status == DEC_Invalid_context)
137    return DEC_Condition_IC;
138  if (status == DEC_Invalid_operation)
139    return DEC_Condition_IO;
140#if DECSUBSET
141  if (status == DEC_Lost_digits)
142    return DEC_Condition_LD;
143#endif
144  if (status == DEC_Overflow)
145    return DEC_Condition_OV;
146  if (status == DEC_Clamped)
147    return DEC_Condition_PA;
148  if (status == DEC_Rounded)
149    return DEC_Condition_RO;
150  if (status == DEC_Subnormal)
151    return DEC_Condition_SU;
152  if (status == DEC_Underflow)
153    return DEC_Condition_UN;
154  if (status == 0)
155    return DEC_Condition_ZE;
156  return DEC_Condition_MU;	/* Multiple errors */
157}				/* decContextStatusToString */
158
159/* ------------------------------------------------------------------ */
160/* decContextSetStatusFromString -- set status from a string          */
161/*                                                                    */
162/*  context is the controlling context                                */
163/*  string is a string exactly equal to one that might be returned    */
164/*            by decContextStatusToString                             */
165/*                                                                    */
166/*  The status bit corresponding to the string is set, and a trap     */
167/*  is raised if appropriate.                                         */
168/*                                                                    */
169/*  returns the context structure, unless the string is equal to      */
170/*    DEC_Condition_MU or is not recognized.  In these cases NULL is  */
171/*    returned.                                                       */
172/* ------------------------------------------------------------------ */
173decContext *
174decContextSetStatusFromString (decContext * context, const char *string)
175{
176  if (strcmp (string, DEC_Condition_CS) == 0)
177    return decContextSetStatus (context, DEC_Conversion_syntax);
178  if (strcmp (string, DEC_Condition_DZ) == 0)
179    return decContextSetStatus (context, DEC_Division_by_zero);
180  if (strcmp (string, DEC_Condition_DI) == 0)
181    return decContextSetStatus (context, DEC_Division_impossible);
182  if (strcmp (string, DEC_Condition_DU) == 0)
183    return decContextSetStatus (context, DEC_Division_undefined);
184  if (strcmp (string, DEC_Condition_IE) == 0)
185    return decContextSetStatus (context, DEC_Inexact);
186  if (strcmp (string, DEC_Condition_IS) == 0)
187    return decContextSetStatus (context, DEC_Insufficient_storage);
188  if (strcmp (string, DEC_Condition_IC) == 0)
189    return decContextSetStatus (context, DEC_Invalid_context);
190  if (strcmp (string, DEC_Condition_IO) == 0)
191    return decContextSetStatus (context, DEC_Invalid_operation);
192#if DECSUBSET
193  if (strcmp (string, DEC_Condition_LD) == 0)
194    return decContextSetStatus (context, DEC_Lost_digits);
195#endif
196  if (strcmp (string, DEC_Condition_OV) == 0)
197    return decContextSetStatus (context, DEC_Overflow);
198  if (strcmp (string, DEC_Condition_PA) == 0)
199    return decContextSetStatus (context, DEC_Clamped);
200  if (strcmp (string, DEC_Condition_RO) == 0)
201    return decContextSetStatus (context, DEC_Rounded);
202  if (strcmp (string, DEC_Condition_SU) == 0)
203    return decContextSetStatus (context, DEC_Subnormal);
204  if (strcmp (string, DEC_Condition_UN) == 0)
205    return decContextSetStatus (context, DEC_Underflow);
206  if (strcmp (string, DEC_Condition_ZE) == 0)
207    return context;
208  return NULL;			/* Multiple status, or unknown */
209}				/* decContextSetStatusFromString */
210
211/* ------------------------------------------------------------------ */
212/* decContextSetStatus -- set status and raise trap if appropriate    */
213/*                                                                    */
214/*  context is the controlling context                                */
215/*  status  is the DEC_ exception code                                */
216/*  returns the context structure                                     */
217/*                                                                    */
218/* Control may never return from this routine, if there is a signal   */
219/* handler and it takes a long jump.                                  */
220/* ------------------------------------------------------------------ */
221decContext *
222decContextSetStatus (decContext * context, uInt status)
223{
224  context->status |= status;
225  if (status & context->traps)
226    raise (SIGFPE);
227  return context;
228}				/* decContextSetStatus */
229