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