1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/decContext.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,430 @@ 1.4 +/* ------------------------------------------------------------------ */ 1.5 +/* Decimal Context module */ 1.6 +/* ------------------------------------------------------------------ */ 1.7 +/* Copyright (c) IBM Corporation, 2000-2012. All rights reserved. */ 1.8 +/* */ 1.9 +/* This software is made available under the terms of the */ 1.10 +/* ICU License -- ICU 1.8.1 and later. */ 1.11 +/* */ 1.12 +/* The description and User's Guide ("The decNumber C Library") for */ 1.13 +/* this software is called decNumber.pdf. This document is */ 1.14 +/* available, together with arithmetic and format specifications, */ 1.15 +/* testcases, and Web links, on the General Decimal Arithmetic page. */ 1.16 +/* */ 1.17 +/* Please send comments, suggestions, and corrections to the author: */ 1.18 +/* mfc@uk.ibm.com */ 1.19 +/* Mike Cowlishaw, IBM Fellow */ 1.20 +/* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 1.21 +/* ------------------------------------------------------------------ */ 1.22 +/* This module comprises the routines for handling arithmetic */ 1.23 +/* context structures. */ 1.24 +/* ------------------------------------------------------------------ */ 1.25 + 1.26 +#include <string.h> /* for strcmp */ 1.27 +#include <stdio.h> /* for printf if DECCHECK */ 1.28 +#include "decContext.h" /* context and base types */ 1.29 +#include "decNumberLocal.h" /* decNumber local types, etc. */ 1.30 + 1.31 +#if 0 /* ICU: No need to test endianness at runtime. */ 1.32 +/* compile-time endian tester [assumes sizeof(Int)>1] */ 1.33 +static const Int mfcone=1; /* constant 1 */ 1.34 +static const Flag *mfctop=(Flag *)&mfcone; /* -> top byte */ 1.35 +#define LITEND *mfctop /* named flag; 1=little-endian */ 1.36 +#endif 1.37 + 1.38 +/* ------------------------------------------------------------------ */ 1.39 +/* decContextClearStatus -- clear bits in current status */ 1.40 +/* */ 1.41 +/* context is the context structure to be queried */ 1.42 +/* mask indicates the bits to be cleared (the status bit that */ 1.43 +/* corresponds to each 1 bit in the mask is cleared) */ 1.44 +/* returns context */ 1.45 +/* */ 1.46 +/* No error is possible. */ 1.47 +/* ------------------------------------------------------------------ */ 1.48 +U_CAPI decContext * U_EXPORT2 uprv_decContextClearStatus(decContext *context, uInt mask) { 1.49 + context->status&=~mask; 1.50 + return context; 1.51 + } /* decContextClearStatus */ 1.52 + 1.53 +/* ------------------------------------------------------------------ */ 1.54 +/* decContextDefault -- initialize a context structure */ 1.55 +/* */ 1.56 +/* context is the structure to be initialized */ 1.57 +/* kind selects the required set of default values, one of: */ 1.58 +/* DEC_INIT_BASE -- select ANSI X3-274 defaults */ 1.59 +/* DEC_INIT_DECIMAL32 -- select IEEE 754 defaults, 32-bit */ 1.60 +/* DEC_INIT_DECIMAL64 -- select IEEE 754 defaults, 64-bit */ 1.61 +/* DEC_INIT_DECIMAL128 -- select IEEE 754 defaults, 128-bit */ 1.62 +/* For any other value a valid context is returned, but with */ 1.63 +/* Invalid_operation set in the status field. */ 1.64 +/* returns a context structure with the appropriate initial values. */ 1.65 +/* ------------------------------------------------------------------ */ 1.66 +U_CAPI decContext * U_EXPORT2 uprv_decContextDefault(decContext *context, Int kind) { 1.67 + /* set defaults... */ 1.68 + context->digits=9; /* 9 digits */ 1.69 + context->emax=DEC_MAX_EMAX; /* 9-digit exponents */ 1.70 + context->emin=DEC_MIN_EMIN; /* .. balanced */ 1.71 + context->round=DEC_ROUND_HALF_UP; /* 0.5 rises */ 1.72 + context->traps=DEC_Errors; /* all but informational */ 1.73 + context->status=0; /* cleared */ 1.74 + context->clamp=0; /* no clamping */ 1.75 + #if DECSUBSET 1.76 + context->extended=0; /* cleared */ 1.77 + #endif 1.78 + switch (kind) { 1.79 + case DEC_INIT_BASE: 1.80 + /* [use defaults] */ 1.81 + break; 1.82 + case DEC_INIT_DECIMAL32: 1.83 + context->digits=7; /* digits */ 1.84 + context->emax=96; /* Emax */ 1.85 + context->emin=-95; /* Emin */ 1.86 + context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ 1.87 + context->traps=0; /* no traps set */ 1.88 + context->clamp=1; /* clamp exponents */ 1.89 + #if DECSUBSET 1.90 + context->extended=1; /* set */ 1.91 + #endif 1.92 + break; 1.93 + case DEC_INIT_DECIMAL64: 1.94 + context->digits=16; /* digits */ 1.95 + context->emax=384; /* Emax */ 1.96 + context->emin=-383; /* Emin */ 1.97 + context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ 1.98 + context->traps=0; /* no traps set */ 1.99 + context->clamp=1; /* clamp exponents */ 1.100 + #if DECSUBSET 1.101 + context->extended=1; /* set */ 1.102 + #endif 1.103 + break; 1.104 + case DEC_INIT_DECIMAL128: 1.105 + context->digits=34; /* digits */ 1.106 + context->emax=6144; /* Emax */ 1.107 + context->emin=-6143; /* Emin */ 1.108 + context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ 1.109 + context->traps=0; /* no traps set */ 1.110 + context->clamp=1; /* clamp exponents */ 1.111 + #if DECSUBSET 1.112 + context->extended=1; /* set */ 1.113 + #endif 1.114 + break; 1.115 + 1.116 + default: /* invalid Kind */ 1.117 + /* use defaults, and .. */ 1.118 + uprv_decContextSetStatus(context, DEC_Invalid_operation); /* trap */ 1.119 + } 1.120 + 1.121 + return context;} /* decContextDefault */ 1.122 + 1.123 +/* ------------------------------------------------------------------ */ 1.124 +/* decContextGetRounding -- return current rounding mode */ 1.125 +/* */ 1.126 +/* context is the context structure to be queried */ 1.127 +/* returns the rounding mode */ 1.128 +/* */ 1.129 +/* No error is possible. */ 1.130 +/* ------------------------------------------------------------------ */ 1.131 +U_CAPI enum rounding U_EXPORT2 uprv_decContextGetRounding(decContext *context) { 1.132 + return context->round; 1.133 + } /* decContextGetRounding */ 1.134 + 1.135 +/* ------------------------------------------------------------------ */ 1.136 +/* decContextGetStatus -- return current status */ 1.137 +/* */ 1.138 +/* context is the context structure to be queried */ 1.139 +/* returns status */ 1.140 +/* */ 1.141 +/* No error is possible. */ 1.142 +/* ------------------------------------------------------------------ */ 1.143 +U_CAPI uInt U_EXPORT2 uprv_decContextGetStatus(decContext *context) { 1.144 + return context->status; 1.145 + } /* decContextGetStatus */ 1.146 + 1.147 +/* ------------------------------------------------------------------ */ 1.148 +/* decContextRestoreStatus -- restore bits in current status */ 1.149 +/* */ 1.150 +/* context is the context structure to be updated */ 1.151 +/* newstatus is the source for the bits to be restored */ 1.152 +/* mask indicates the bits to be restored (the status bit that */ 1.153 +/* corresponds to each 1 bit in the mask is set to the value of */ 1.154 +/* the correspnding bit in newstatus) */ 1.155 +/* returns context */ 1.156 +/* */ 1.157 +/* No error is possible. */ 1.158 +/* ------------------------------------------------------------------ */ 1.159 +U_CAPI decContext * U_EXPORT2 uprv_decContextRestoreStatus(decContext *context, 1.160 + uInt newstatus, uInt mask) { 1.161 + context->status&=~mask; /* clear the selected bits */ 1.162 + context->status|=(mask&newstatus); /* or in the new bits */ 1.163 + return context; 1.164 + } /* decContextRestoreStatus */ 1.165 + 1.166 +/* ------------------------------------------------------------------ */ 1.167 +/* decContextSaveStatus -- save bits in current status */ 1.168 +/* */ 1.169 +/* context is the context structure to be queried */ 1.170 +/* mask indicates the bits to be saved (the status bits that */ 1.171 +/* correspond to each 1 bit in the mask are saved) */ 1.172 +/* returns the AND of the mask and the current status */ 1.173 +/* */ 1.174 +/* No error is possible. */ 1.175 +/* ------------------------------------------------------------------ */ 1.176 +U_CAPI uInt U_EXPORT2 uprv_decContextSaveStatus(decContext *context, uInt mask) { 1.177 + return context->status&mask; 1.178 + } /* decContextSaveStatus */ 1.179 + 1.180 +/* ------------------------------------------------------------------ */ 1.181 +/* decContextSetRounding -- set current rounding mode */ 1.182 +/* */ 1.183 +/* context is the context structure to be updated */ 1.184 +/* newround is the value which will replace the current mode */ 1.185 +/* returns context */ 1.186 +/* */ 1.187 +/* No error is possible. */ 1.188 +/* ------------------------------------------------------------------ */ 1.189 +U_CAPI decContext * U_EXPORT2 uprv_decContextSetRounding(decContext *context, 1.190 + enum rounding newround) { 1.191 + context->round=newround; 1.192 + return context; 1.193 + } /* decContextSetRounding */ 1.194 + 1.195 +/* ------------------------------------------------------------------ */ 1.196 +/* decContextSetStatus -- set status and raise trap if appropriate */ 1.197 +/* */ 1.198 +/* context is the context structure to be updated */ 1.199 +/* status is the DEC_ exception code */ 1.200 +/* returns the context structure */ 1.201 +/* */ 1.202 +/* Control may never return from this routine, if there is a signal */ 1.203 +/* handler and it takes a long jump. */ 1.204 +/* ------------------------------------------------------------------ */ 1.205 +U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatus(decContext *context, uInt status) { 1.206 + context->status|=status; 1.207 +#if 0 /* ICU: Do not raise signals. */ 1.208 + if (status & context->traps) raise(SIGFPE); 1.209 +#endif 1.210 + return context;} /* decContextSetStatus */ 1.211 + 1.212 +/* ------------------------------------------------------------------ */ 1.213 +/* decContextSetStatusFromString -- set status from a string + trap */ 1.214 +/* */ 1.215 +/* context is the context structure to be updated */ 1.216 +/* string is a string exactly equal to one that might be returned */ 1.217 +/* by decContextStatusToString */ 1.218 +/* */ 1.219 +/* The status bit corresponding to the string is set, and a trap */ 1.220 +/* is raised if appropriate. */ 1.221 +/* */ 1.222 +/* returns the context structure, unless the string is equal to */ 1.223 +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ 1.224 +/* returned. */ 1.225 +/* ------------------------------------------------------------------ */ 1.226 +U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatusFromString(decContext *context, 1.227 + const char *string) { 1.228 + if (strcmp(string, DEC_Condition_CS)==0) 1.229 + return uprv_decContextSetStatus(context, DEC_Conversion_syntax); 1.230 + if (strcmp(string, DEC_Condition_DZ)==0) 1.231 + return uprv_decContextSetStatus(context, DEC_Division_by_zero); 1.232 + if (strcmp(string, DEC_Condition_DI)==0) 1.233 + return uprv_decContextSetStatus(context, DEC_Division_impossible); 1.234 + if (strcmp(string, DEC_Condition_DU)==0) 1.235 + return uprv_decContextSetStatus(context, DEC_Division_undefined); 1.236 + if (strcmp(string, DEC_Condition_IE)==0) 1.237 + return uprv_decContextSetStatus(context, DEC_Inexact); 1.238 + if (strcmp(string, DEC_Condition_IS)==0) 1.239 + return uprv_decContextSetStatus(context, DEC_Insufficient_storage); 1.240 + if (strcmp(string, DEC_Condition_IC)==0) 1.241 + return uprv_decContextSetStatus(context, DEC_Invalid_context); 1.242 + if (strcmp(string, DEC_Condition_IO)==0) 1.243 + return uprv_decContextSetStatus(context, DEC_Invalid_operation); 1.244 + #if DECSUBSET 1.245 + if (strcmp(string, DEC_Condition_LD)==0) 1.246 + return uprv_decContextSetStatus(context, DEC_Lost_digits); 1.247 + #endif 1.248 + if (strcmp(string, DEC_Condition_OV)==0) 1.249 + return uprv_decContextSetStatus(context, DEC_Overflow); 1.250 + if (strcmp(string, DEC_Condition_PA)==0) 1.251 + return uprv_decContextSetStatus(context, DEC_Clamped); 1.252 + if (strcmp(string, DEC_Condition_RO)==0) 1.253 + return uprv_decContextSetStatus(context, DEC_Rounded); 1.254 + if (strcmp(string, DEC_Condition_SU)==0) 1.255 + return uprv_decContextSetStatus(context, DEC_Subnormal); 1.256 + if (strcmp(string, DEC_Condition_UN)==0) 1.257 + return uprv_decContextSetStatus(context, DEC_Underflow); 1.258 + if (strcmp(string, DEC_Condition_ZE)==0) 1.259 + return context; 1.260 + return NULL; /* Multiple status, or unknown */ 1.261 + } /* decContextSetStatusFromString */ 1.262 + 1.263 +/* ------------------------------------------------------------------ */ 1.264 +/* decContextSetStatusFromStringQuiet -- set status from a string */ 1.265 +/* */ 1.266 +/* context is the context structure to be updated */ 1.267 +/* string is a string exactly equal to one that might be returned */ 1.268 +/* by decContextStatusToString */ 1.269 +/* */ 1.270 +/* The status bit corresponding to the string is set; no trap is */ 1.271 +/* raised. */ 1.272 +/* */ 1.273 +/* returns the context structure, unless the string is equal to */ 1.274 +/* DEC_Condition_MU or is not recognized. In these cases NULL is */ 1.275 +/* returned. */ 1.276 +/* ------------------------------------------------------------------ */ 1.277 +U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatusFromStringQuiet(decContext *context, 1.278 + const char *string) { 1.279 + if (strcmp(string, DEC_Condition_CS)==0) 1.280 + return uprv_decContextSetStatusQuiet(context, DEC_Conversion_syntax); 1.281 + if (strcmp(string, DEC_Condition_DZ)==0) 1.282 + return uprv_decContextSetStatusQuiet(context, DEC_Division_by_zero); 1.283 + if (strcmp(string, DEC_Condition_DI)==0) 1.284 + return uprv_decContextSetStatusQuiet(context, DEC_Division_impossible); 1.285 + if (strcmp(string, DEC_Condition_DU)==0) 1.286 + return uprv_decContextSetStatusQuiet(context, DEC_Division_undefined); 1.287 + if (strcmp(string, DEC_Condition_IE)==0) 1.288 + return uprv_decContextSetStatusQuiet(context, DEC_Inexact); 1.289 + if (strcmp(string, DEC_Condition_IS)==0) 1.290 + return uprv_decContextSetStatusQuiet(context, DEC_Insufficient_storage); 1.291 + if (strcmp(string, DEC_Condition_IC)==0) 1.292 + return uprv_decContextSetStatusQuiet(context, DEC_Invalid_context); 1.293 + if (strcmp(string, DEC_Condition_IO)==0) 1.294 + return uprv_decContextSetStatusQuiet(context, DEC_Invalid_operation); 1.295 + #if DECSUBSET 1.296 + if (strcmp(string, DEC_Condition_LD)==0) 1.297 + return uprv_decContextSetStatusQuiet(context, DEC_Lost_digits); 1.298 + #endif 1.299 + if (strcmp(string, DEC_Condition_OV)==0) 1.300 + return uprv_decContextSetStatusQuiet(context, DEC_Overflow); 1.301 + if (strcmp(string, DEC_Condition_PA)==0) 1.302 + return uprv_decContextSetStatusQuiet(context, DEC_Clamped); 1.303 + if (strcmp(string, DEC_Condition_RO)==0) 1.304 + return uprv_decContextSetStatusQuiet(context, DEC_Rounded); 1.305 + if (strcmp(string, DEC_Condition_SU)==0) 1.306 + return uprv_decContextSetStatusQuiet(context, DEC_Subnormal); 1.307 + if (strcmp(string, DEC_Condition_UN)==0) 1.308 + return uprv_decContextSetStatusQuiet(context, DEC_Underflow); 1.309 + if (strcmp(string, DEC_Condition_ZE)==0) 1.310 + return context; 1.311 + return NULL; /* Multiple status, or unknown */ 1.312 + } /* decContextSetStatusFromStringQuiet */ 1.313 + 1.314 +/* ------------------------------------------------------------------ */ 1.315 +/* decContextSetStatusQuiet -- set status without trap */ 1.316 +/* */ 1.317 +/* context is the context structure to be updated */ 1.318 +/* status is the DEC_ exception code */ 1.319 +/* returns the context structure */ 1.320 +/* */ 1.321 +/* No error is possible. */ 1.322 +/* ------------------------------------------------------------------ */ 1.323 +U_CAPI decContext * U_EXPORT2 uprv_decContextSetStatusQuiet(decContext *context, uInt status) { 1.324 + context->status|=status; 1.325 + return context;} /* decContextSetStatusQuiet */ 1.326 + 1.327 +/* ------------------------------------------------------------------ */ 1.328 +/* decContextStatusToString -- convert status flags to a string */ 1.329 +/* */ 1.330 +/* context is a context with valid status field */ 1.331 +/* */ 1.332 +/* returns a constant string describing the condition. If multiple */ 1.333 +/* (or no) flags are set, a generic constant message is returned. */ 1.334 +/* ------------------------------------------------------------------ */ 1.335 +U_CAPI const char * U_EXPORT2 uprv_decContextStatusToString(const decContext *context) { 1.336 + Int status=context->status; 1.337 + 1.338 + /* test the five IEEE first, as some of the others are ambiguous when */ 1.339 + /* DECEXTFLAG=0 */ 1.340 + if (status==DEC_Invalid_operation ) return DEC_Condition_IO; 1.341 + if (status==DEC_Division_by_zero ) return DEC_Condition_DZ; 1.342 + if (status==DEC_Overflow ) return DEC_Condition_OV; 1.343 + if (status==DEC_Underflow ) return DEC_Condition_UN; 1.344 + if (status==DEC_Inexact ) return DEC_Condition_IE; 1.345 + 1.346 + if (status==DEC_Division_impossible ) return DEC_Condition_DI; 1.347 + if (status==DEC_Division_undefined ) return DEC_Condition_DU; 1.348 + if (status==DEC_Rounded ) return DEC_Condition_RO; 1.349 + if (status==DEC_Clamped ) return DEC_Condition_PA; 1.350 + if (status==DEC_Subnormal ) return DEC_Condition_SU; 1.351 + if (status==DEC_Conversion_syntax ) return DEC_Condition_CS; 1.352 + if (status==DEC_Insufficient_storage ) return DEC_Condition_IS; 1.353 + if (status==DEC_Invalid_context ) return DEC_Condition_IC; 1.354 + #if DECSUBSET 1.355 + if (status==DEC_Lost_digits ) return DEC_Condition_LD; 1.356 + #endif 1.357 + if (status==0 ) return DEC_Condition_ZE; 1.358 + return DEC_Condition_MU; /* Multiple errors */ 1.359 + } /* decContextStatusToString */ 1.360 + 1.361 +/* ------------------------------------------------------------------ */ 1.362 +/* decContextTestEndian -- test whether DECLITEND is set correctly */ 1.363 +/* */ 1.364 +/* quiet is 1 to suppress message; 0 otherwise */ 1.365 +/* returns 0 if DECLITEND is correct */ 1.366 +/* 1 if DECLITEND is incorrect and should be 1 */ 1.367 +/* -1 if DECLITEND is incorrect and should be 0 */ 1.368 +/* */ 1.369 +/* A message is displayed if the return value is not 0 and quiet==0. */ 1.370 +/* */ 1.371 +/* No error is possible. */ 1.372 +/* ------------------------------------------------------------------ */ 1.373 +#if 0 /* ICU: Unused function. Anyway, do not call printf(). */ 1.374 +U_CAPI Int U_EXPORT2 uprv_decContextTestEndian(Flag quiet) { 1.375 + Int res=0; /* optimist */ 1.376 + uInt dle=(uInt)DECLITEND; /* unsign */ 1.377 + if (dle>1) dle=1; /* ensure 0 or 1 */ 1.378 + 1.379 + if (LITEND!=DECLITEND) { 1.380 + const char *adj; 1.381 + if (!quiet) { 1.382 + if (LITEND) adj="little"; 1.383 + else adj="big"; 1.384 + printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n", 1.385 + DECLITEND, adj); 1.386 + } 1.387 + res=(Int)LITEND-dle; 1.388 + } 1.389 + return res; 1.390 + } /* decContextTestEndian */ 1.391 +#endif 1.392 + 1.393 +/* ------------------------------------------------------------------ */ 1.394 +/* decContextTestSavedStatus -- test bits in saved status */ 1.395 +/* */ 1.396 +/* oldstatus is the status word to be tested */ 1.397 +/* mask indicates the bits to be tested (the oldstatus bits that */ 1.398 +/* correspond to each 1 bit in the mask are tested) */ 1.399 +/* returns 1 if any of the tested bits are 1, or 0 otherwise */ 1.400 +/* */ 1.401 +/* No error is possible. */ 1.402 +/* ------------------------------------------------------------------ */ 1.403 +U_CAPI uInt U_EXPORT2 uprv_decContextTestSavedStatus(uInt oldstatus, uInt mask) { 1.404 + return (oldstatus&mask)!=0; 1.405 + } /* decContextTestSavedStatus */ 1.406 + 1.407 +/* ------------------------------------------------------------------ */ 1.408 +/* decContextTestStatus -- test bits in current status */ 1.409 +/* */ 1.410 +/* context is the context structure to be updated */ 1.411 +/* mask indicates the bits to be tested (the status bits that */ 1.412 +/* correspond to each 1 bit in the mask are tested) */ 1.413 +/* returns 1 if any of the tested bits are 1, or 0 otherwise */ 1.414 +/* */ 1.415 +/* No error is possible. */ 1.416 +/* ------------------------------------------------------------------ */ 1.417 +U_CAPI uInt U_EXPORT2 uprv_decContextTestStatus(decContext *context, uInt mask) { 1.418 + return (context->status&mask)!=0; 1.419 + } /* decContextTestStatus */ 1.420 + 1.421 +/* ------------------------------------------------------------------ */ 1.422 +/* decContextZeroStatus -- clear all status bits */ 1.423 +/* */ 1.424 +/* context is the context structure to be updated */ 1.425 +/* returns context */ 1.426 +/* */ 1.427 +/* No error is possible. */ 1.428 +/* ------------------------------------------------------------------ */ 1.429 +U_CAPI decContext * U_EXPORT2 uprv_decContextZeroStatus(decContext *context) { 1.430 + context->status=0; 1.431 + return context; 1.432 + } /* decContextZeroStatus */ 1.433 +