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