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