| 1 |
# Copyright (c) 2004 Python Software Foundation. |
|---|
| 2 |
# All rights reserved. |
|---|
| 3 |
|
|---|
| 4 |
# Written by Eric Price <eprice at tjhsst.edu> |
|---|
| 5 |
# and Facundo Batista <facundo at taniquetil.com.ar> |
|---|
| 6 |
# and Raymond Hettinger <python at rcn.com> |
|---|
| 7 |
# and Aahz <aahz at pobox.com> |
|---|
| 8 |
# and Tim Peters |
|---|
| 9 |
|
|---|
| 10 |
# This module is currently Py2.3 compatible and should be kept that way |
|---|
| 11 |
# unless a major compelling advantage arises. IOW, 2.3 compatibility is |
|---|
| 12 |
# strongly preferred, but not guaranteed. |
|---|
| 13 |
|
|---|
| 14 |
# Also, this module should be kept in sync with the latest updates of |
|---|
| 15 |
# the IBM specification as it evolves. Those updates will be treated |
|---|
| 16 |
# as bug fixes (deviation from the spec is a compatibility, usability |
|---|
| 17 |
# bug) and will be backported. At this point the spec is stabilizing |
|---|
| 18 |
# and the updates are becoming fewer, smaller, and less significant. |
|---|
| 19 |
|
|---|
| 20 |
""" |
|---|
| 21 |
This is a Py2.3 implementation of decimal floating point arithmetic based on |
|---|
| 22 |
the General Decimal Arithmetic Specification: |
|---|
| 23 |
|
|---|
| 24 |
www2.hursley.ibm.com/decimal/decarith.html |
|---|
| 25 |
|
|---|
| 26 |
and IEEE standard 854-1987: |
|---|
| 27 |
|
|---|
| 28 |
www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html |
|---|
| 29 |
|
|---|
| 30 |
Decimal floating point has finite precision with arbitrarily large bounds. |
|---|
| 31 |
|
|---|
| 32 |
The purpose of the module is to support arithmetic using familiar |
|---|
| 33 |
"schoolhouse" rules and to avoid the some of tricky representation |
|---|
| 34 |
issues associated with binary floating point. The package is especially |
|---|
| 35 |
useful for financial applications or for contexts where users have |
|---|
| 36 |
expectations that are at odds with binary floating point (for instance, |
|---|
| 37 |
in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead |
|---|
| 38 |
of the expected Decimal("0.00") returned by decimal floating point). |
|---|
| 39 |
|
|---|
| 40 |
Here are some examples of using the decimal module: |
|---|
| 41 |
|
|---|
| 42 |
>>> from decimal import * |
|---|
| 43 |
>>> setcontext(ExtendedContext) |
|---|
| 44 |
>>> Decimal(0) |
|---|
| 45 |
Decimal("0") |
|---|
| 46 |
>>> Decimal("1") |
|---|
| 47 |
Decimal("1") |
|---|
| 48 |
>>> Decimal("-.0123") |
|---|
| 49 |
Decimal("-0.0123") |
|---|
| 50 |
>>> Decimal(123456) |
|---|
| 51 |
Decimal("123456") |
|---|
| 52 |
>>> Decimal("123.45e12345678901234567890") |
|---|
| 53 |
Decimal("1.2345E+12345678901234567892") |
|---|
| 54 |
>>> Decimal("1.33") + Decimal("1.27") |
|---|
| 55 |
Decimal("2.60") |
|---|
| 56 |
>>> Decimal("12.34") + Decimal("3.87") - Decimal("18.41") |
|---|
| 57 |
Decimal("-2.20") |
|---|
| 58 |
>>> dig = Decimal(1) |
|---|
| 59 |
>>> print dig / Decimal(3) |
|---|
| 60 |
0.333333333 |
|---|
| 61 |
>>> getcontext().prec = 18 |
|---|
| 62 |
>>> print dig / Decimal(3) |
|---|
| 63 |
0.333333333333333333 |
|---|
| 64 |
>>> print dig.sqrt() |
|---|
| 65 |
1 |
|---|
| 66 |
>>> print Decimal(3).sqrt() |
|---|
| 67 |
1.73205080756887729 |
|---|
| 68 |
>>> print Decimal(3) ** 123 |
|---|
| 69 |
4.85192780976896427E+58 |
|---|
| 70 |
>>> inf = Decimal(1) / Decimal(0) |
|---|
| 71 |
>>> print inf |
|---|
| 72 |
Infinity |
|---|
| 73 |
>>> neginf = Decimal(-1) / Decimal(0) |
|---|
| 74 |
>>> print neginf |
|---|
| 75 |
-Infinity |
|---|
| 76 |
>>> print neginf + inf |
|---|
| 77 |
NaN |
|---|
| 78 |
>>> print neginf * inf |
|---|
| 79 |
-Infinity |
|---|
| 80 |
>>> print dig / 0 |
|---|
| 81 |
Infinity |
|---|
| 82 |
>>> getcontext().traps[DivisionByZero] = 1 |
|---|
| 83 |
>>> print dig / 0 |
|---|
| 84 |
Traceback (most recent call last): |
|---|
| 85 |
... |
|---|
| 86 |
... |
|---|
| 87 |
... |
|---|
| 88 |
DivisionByZero: x / 0 |
|---|
| 89 |
>>> c = Context() |
|---|
| 90 |
>>> c.traps[InvalidOperation] = 0 |
|---|
| 91 |
>>> print c.flags[InvalidOperation] |
|---|
| 92 |
0 |
|---|
| 93 |
>>> c.divide(Decimal(0), Decimal(0)) |
|---|
| 94 |
Decimal("NaN") |
|---|
| 95 |
>>> c.traps[InvalidOperation] = 1 |
|---|
| 96 |
>>> print c.flags[InvalidOperation] |
|---|
| 97 |
1 |
|---|
| 98 |
>>> c.flags[InvalidOperation] = 0 |
|---|
| 99 |
>>> print c.flags[InvalidOperation] |
|---|
| 100 |
0 |
|---|
| 101 |
>>> print c.divide(Decimal(0), Decimal(0)) |
|---|
| 102 |
Traceback (most recent call last): |
|---|
| 103 |
... |
|---|
| 104 |
... |
|---|
| 105 |
... |
|---|
| 106 |
InvalidOperation: 0 / 0 |
|---|
| 107 |
>>> print c.flags[InvalidOperation] |
|---|
| 108 |
1 |
|---|
| 109 |
>>> c.flags[InvalidOperation] = 0 |
|---|
| 110 |
>>> c.traps[InvalidOperation] = 0 |
|---|
| 111 |
>>> print c.divide(Decimal(0), Decimal(0)) |
|---|
| 112 |
NaN |
|---|
| 113 |
>>> print c.flags[InvalidOperation] |
|---|
| 114 |
1 |
|---|
| 115 |
>>> |
|---|
| 116 |
""" |
|---|
| 117 |
|
|---|
| 118 |
__all__ = [ |
|---|
| 119 |
# Two major classes |
|---|
| 120 |
'Decimal', 'Context', |
|---|
| 121 |
|
|---|
| 122 |
# Contexts |
|---|
| 123 |
'DefaultContext', 'BasicContext', 'ExtendedContext', |
|---|
| 124 |
|
|---|
| 125 |
# Exceptions |
|---|
| 126 |
'DecimalException', 'Clamped', 'InvalidOperation', 'DivisionByZero', |
|---|
| 127 |
'Inexact', 'Rounded', 'Subnormal', 'Overflow', 'Underflow', |
|---|
| 128 |
|
|---|
| 129 |
# Constants for use in setting up contexts |
|---|
| 130 |
'ROUND_DOWN', 'ROUND_HALF_UP', 'ROUND_HALF_EVEN', 'ROUND_CEILING', |
|---|
| 131 |
'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN', |
|---|
| 132 |
|
|---|
| 133 |
# Functions for manipulating contexts |
|---|
| 134 |
'setcontext', 'getcontext' |
|---|
| 135 |
] |
|---|
| 136 |
|
|---|
| 137 |
import copy as _copy |
|---|
| 138 |
|
|---|
| 139 |
#Rounding |
|---|
| 140 |
ROUND_DOWN = 'ROUND_DOWN' |
|---|
| 141 |
ROUND_HALF_UP = 'ROUND_HALF_UP' |
|---|
| 142 |
ROUND_HALF_EVEN = 'ROUND_HALF_EVEN' |
|---|
| 143 |
ROUND_CEILING = 'ROUND_CEILING' |
|---|
| 144 |
ROUND_FLOOR = 'ROUND_FLOOR' |
|---|
| 145 |
ROUND_UP = 'ROUND_UP' |
|---|
| 146 |
ROUND_HALF_DOWN = 'ROUND_HALF_DOWN' |
|---|
| 147 |
|
|---|
| 148 |
#Rounding decision (not part of the public API) |
|---|
| 149 |
NEVER_ROUND = 'NEVER_ROUND' # Round in division (non-divmod), sqrt ONLY |
|---|
| 150 |
ALWAYS_ROUND = 'ALWAYS_ROUND' # Every operation rounds at end. |
|---|
| 151 |
|
|---|
| 152 |
#Errors |
|---|
| 153 |
|
|---|
| 154 |
class DecimalException(ArithmeticError): |
|---|
| 155 |
"""Base exception class. |
|---|
| 156 |
|
|---|
| 157 |
Used exceptions derive from this. |
|---|
| 158 |
If an exception derives from another exception besides this (such as |
|---|
| 159 |
Underflow (Inexact, Rounded, Subnormal) that indicates that it is only |
|---|
| 160 |
called if the others are present. This isn't actually used for |
|---|
| 161 |
anything, though. |
|---|
| 162 |
|
|---|
| 163 |
handle -- Called when context._raise_error is called and the |
|---|
| 164 |
trap_enabler is set. First argument is self, second is the |
|---|
| 165 |
context. More arguments can be given, those being after |
|---|
| 166 |
the explanation in _raise_error (For example, |
|---|
| 167 |
context._raise_error(NewError, '(-x)!', self._sign) would |
|---|
| 168 |
call NewError().handle(context, self._sign).) |
|---|
| 169 |
|
|---|
| 170 |
To define a new exception, it should be sufficient to have it derive |
|---|
| 171 |
from DecimalException. |
|---|
| 172 |
""" |
|---|
| 173 |
def handle(self, context, *args): |
|---|
| 174 |
pass |
|---|
| 175 |
|
|---|
| 176 |
|
|---|
| 177 |
class Clamped(DecimalException): |
|---|
| 178 |
"""Exponent of a 0 changed to fit bounds. |
|---|
| 179 |
|
|---|
| 180 |
This occurs and signals clamped if the exponent of a result has been |
|---|
| 181 |
altered in order to fit the constraints of a specific concrete |
|---|
| 182 |
representation. This may occur when the exponent of a zero result would |
|---|
| 183 |
be outside the bounds of a representation, or when a large normal |
|---|
| 184 |
number would have an encoded exponent that cannot be represented. In |
|---|
| 185 |
this latter case, the exponent is reduced to fit and the corresponding |
|---|
| 186 |
number of zero digits are appended to the coefficient ("fold-down"). |
|---|
| 187 |
""" |
|---|
| 188 |
|
|---|
| 189 |
|
|---|
| 190 |
class InvalidOperation(DecimalException): |
|---|
| 191 |
"""An invalid operation was performed. |
|---|
| 192 |
|
|---|
| 193 |
Various bad things cause this: |
|---|
| 194 |
|
|---|
| 195 |
Something creates a signaling NaN |
|---|
| 196 |
-INF + INF |
|---|
| 197 |
0 * (+-)INF |
|---|
| 198 |
(+-)INF / (+-)INF |
|---|
| 199 |
x % 0 |
|---|
| 200 |
(+-)INF % x |
|---|
| 201 |
x._rescale( non-integer ) |
|---|
| 202 |
sqrt(-x) , x > 0 |
|---|
| 203 |
0 ** 0 |
|---|
| 204 |
x ** (non-integer) |
|---|
| 205 |
x ** (+-)INF |
|---|
| 206 |
An operand is invalid |
|---|
| 207 |
""" |
|---|
| 208 |
def handle(self, context, *args): |
|---|
| 209 |
if args: |
|---|
| 210 |
if args[0] == 1: #sNaN, must drop 's' but keep diagnostics |
|---|
| 211 |
return Decimal( (args[1]._sign, args[1]._int, 'n') ) |
|---|
| 212 |
return NaN |
|---|
| 213 |
|
|---|
| 214 |
class ConversionSyntax(InvalidOperation): |
|---|
| 215 |
"""Trying to convert badly formed string. |
|---|
| 216 |
|
|---|
| 217 |
This occurs and signals invalid-operation if an string is being |
|---|
| 218 |
converted to a number and it does not conform to the numeric string |
|---|
| 219 |
syntax. The result is [0,qNaN]. |
|---|
| 220 |
""" |
|---|
| 221 |
|
|---|
| 222 |
def handle(self, context, *args): |
|---|
| 223 |
return (0, (0,), 'n') #Passed to something which uses a tuple. |
|---|
| 224 |
|
|---|
| 225 |
class DivisionByZero(DecimalException, ZeroDivisionError): |
|---|
| 226 |
"""Division by 0. |
|---|
| 227 |
|
|---|
| 228 |
This occurs and signals division-by-zero if division of a finite number |
|---|
| 229 |
by zero was attempted (during a divide-integer or divide operation, or a |
|---|
| 230 |
power operation with negative right-hand operand), and the dividend was |
|---|
| 231 |
not zero. |
|---|
| 232 |
|
|---|
| 233 |
The result of the operation is [sign,inf], where sign is the exclusive |
|---|
| 234 |
or of the signs of the operands for divide, or is 1 for an odd power of |
|---|
| 235 |
-0, for power. |
|---|
| 236 |
""" |
|---|
| 237 |
|
|---|
| 238 |
def handle(self, context, sign, double = None, *args): |
|---|
| 239 |
if double is not None: |
|---|
| 240 |
return (Infsign[sign],)*2 |
|---|
| 241 |
return Infsign[sign] |
|---|
| 242 |
|
|---|
| 243 |
class DivisionImpossible(InvalidOperation): |
|---|
| 244 |
"""Cannot perform the division adequately. |
|---|
| 245 |
|
|---|
| 246 |
This occurs and signals invalid-operation if the integer result of a |
|---|
| 247 |
divide-integer or remainder operation had too many digits (would be |
|---|
| 248 |
longer than precision). The result is [0,qNaN]. |
|---|
| 249 |
""" |
|---|
| 250 |
|
|---|
| 251 |
def handle(self, context, *args): |
|---|
| 252 |
return (NaN, NaN) |
|---|
| 253 |
|
|---|
| 254 |
class DivisionUndefined(InvalidOperation, ZeroDivisionError): |
|---|
| 255 |
"""Undefined result of division. |
|---|
| 256 |
|
|---|
| 257 |
This occurs and signals invalid-operation if division by zero was |
|---|
| 258 |
attempted (during a divide-integer, divide, or remainder operation), and |
|---|
| 259 |
the dividend is also zero. The result is [0,qNaN]. |
|---|
| 260 |
""" |
|---|
| 261 |
|
|---|
| 262 |
def handle(self, context, tup=None, *args): |
|---|
| 263 |
if tup is not None: |
|---|
| 264 |
return (NaN, NaN) #for 0 %0, 0 // 0 |
|---|
| 265 |
return NaN |
|---|
| 266 |
|
|---|
| 267 |
class Inexact(DecimalException): |
|---|
| 268 |
"""Had to round, losing information. |
|---|
| 269 |
|
|---|
| 270 |
This occurs and signals inexact whenever the result of an operation is |
|---|
| 271 |
not exact (that is, it needed to be rounded and any discarded digits |
|---|
| 272 |
were non-zero), or if an overflow or underflow condition occurs. The |
|---|
| 273 |
result in all cases is unchanged. |
|---|
| 274 |
|
|---|
| 275 |
The inexact signal may be tested (or trapped) to determine if a given |
|---|
| 276 |
operation (or sequence of operations) was inexact. |
|---|
| 277 |
""" |
|---|
| 278 |
pass |
|---|
| 279 |
|
|---|
| 280 |
class InvalidContext(InvalidOperation): |
|---|
| 281 |
"""Invalid context. Unknown rounding, for example. |
|---|
| 282 |
|
|---|
| 283 |
This occurs and signals invalid-operation if an invalid context was |
|---|
| 284 |
detected during an operation. This can occur if contexts are not checked |
|---|
| 285 |
on creation and either the precision exceeds the capability of the |
|---|
| 286 |
underlying concrete representation or an unknown or unsupported rounding |
|---|
| 287 |
was specified. These aspects of the context need only be checked when |
|---|
| 288 |
the values are required to be used. The result is [0,qNaN]. |
|---|
| 289 |
""" |
|---|
| 290 |
|
|---|
| 291 |
def handle(self, context, *args): |
|---|
| 292 |
return NaN |
|---|
| 293 |
|
|---|
| 294 |
class Rounded(DecimalException): |
|---|
| 295 |
"""Number got rounded (not necessarily changed during rounding). |
|---|
| 296 |
|
|---|
| 297 |
This occurs and signals rounded whenever the result of an operation is |
|---|
| 298 |
rounded (that is, some zero or non-zero digits were discarded from the |
|---|
| 299 |
coefficient), or if an overflow or underflow condition occurs. The |
|---|
| 300 |
result in all cases is unchanged. |
|---|
| 301 |
|
|---|
| 302 |
The rounded signal may be tested (or trapped) to determine if a given |
|---|
| 303 |
operation (or sequence of operations) caused a loss of precision. |
|---|
| 304 |
""" |
|---|
| 305 |
pass |
|---|
| 306 |
|
|---|
| 307 |
class Subnormal(DecimalException): |
|---|
| 308 |
"""Exponent < Emin before rounding. |
|---|
| 309 |
|
|---|
| 310 |
This occurs and signals subnormal whenever the result of a conversion or |
|---|
| 311 |
operation is subnormal (that is, its adjusted exponent is less than |
|---|
| 312 |
Emin, before any rounding). The result in all cases is unchanged. |
|---|
| 313 |
|
|---|
| 314 |
The subnormal signal may be tested (or trapped) to determine if a given |
|---|
| 315 |
or operation (or sequence of operations) yielded a subnormal result. |
|---|
| 316 |
""" |
|---|
| 317 |
pass |
|---|
| 318 |
|
|---|
| 319 |
class Overflow(Inexact, Rounded): |
|---|
| 320 |
"""Numerical overflow. |
|---|
| 321 |
|
|---|
| 322 |
This occurs and signals overflow if the adjusted exponent of a result |
|---|
| 323 |
(from a conversion or from an operation that is not an attempt to divide |
|---|
| 324 |
by zero), after rounding, would be greater than the largest value that |
|---|
| 325 |
can be handled by the implementation (the value Emax). |
|---|
| 326 |
|
|---|
| 327 |
The result depends on the rounding mode: |
|---|
| 328 |
|
|---|
| 329 |
For round-half-up and round-half-even (and for round-half-down and |
|---|
| 330 |
round-up, if implemented), the result of the operation is [sign,inf], |
|---|
| 331 |
where sign is the sign of the intermediate result. For round-down, the |
|---|
| 332 |
result is the largest finite number that can be represented in the |
|---|
| 333 |
current precision, with the sign of the intermediate result. For |
|---|
| 334 |
round-ceiling, the result is the same as for round-down if the sign of |
|---|
| 335 |
the intermediate result is 1, or is [0,inf] otherwise. For round-floor, |
|---|
| 336 |
the result is the same as for round-down if the sign of the intermediate |
|---|
| 337 |
result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded |
|---|
| 338 |
will also be raised. |
|---|
| 339 |
""" |
|---|
| 340 |
|
|---|
| 341 |
def handle(self, context, sign, *args): |
|---|
| 342 |
if context.rounding in (ROUND_HALF_UP, ROUND_HALF_EVEN, |
|---|
| 343 |
ROUND_HALF_DOWN, ROUND_UP): |
|---|
| 344 |
return Infsign[sign] |
|---|
| 345 |
if sign == 0: |
|---|
| 346 |
if context.rounding == ROUND_CEILING: |
|---|
| 347 |
return Infsign[sign] |
|---|
| 348 |
return Decimal((sign, (9,)*context.prec, |
|---|
| 349 |
context.Emax-context.prec+1)) |
|---|
| 350 |
if sign == 1: |
|---|
| 351 |
if context.rounding == ROUND_FLOOR: |
|---|
| 352 |
return Infsign[sign] |
|---|
| 353 |
return Decimal( (sign, (9,)*context.prec, |
|---|
| 354 |
context.Emax-context.prec+1)) |
|---|
| 355 |
|
|---|
| 356 |
|
|---|
| 357 |
class Underflow(Inexact, Rounded, Subnormal): |
|---|
| 358 |
"""Numerical underflow with result rounded to 0. |
|---|
| 359 |
|
|---|
| 360 |
This occurs and signals underflow if a result is inexact and the |
|---|
| 361 |
adjusted exponent of the result would be smaller (more negative) than |
|---|
| 362 |
the smallest value that can be handled by the implementation (the value |
|---|
| 363 |
Emin). That is, the result is both inexact and subnormal. |
|---|
| 364 |
|
|---|
| 365 |
The result after an underflow will be a subnormal number rounded, if |
|---|
| 366 |
necessary, so that its exponent is not less than Etiny. This may result |
|---|
| 367 |
in 0 with the sign of the intermediate result and an exponent of Etiny. |
|---|
| 368 |
|
|---|
| 369 |
In all cases, Inexact, Rounded, and Subnormal will also be raised. |
|---|
| 370 |
""" |
|---|
| 371 |
|
|---|
| 372 |
# List of public traps and flags |
|---|
| 373 |
_signals = [Clamped, DivisionByZero, Inexact, Overflow, Rounded, |
|---|
| 374 |
Underflow, InvalidOperation, Subnormal] |
|---|
| 375 |
|
|---|
| 376 |
# Map conditions (per the spec) to signals |
|---|
| 377 |
_condition_map = {ConversionSyntax:InvalidOperation, |
|---|
| 378 |
DivisionImpossible:InvalidOperation, |
|---|
| 379 |
DivisionUndefined:InvalidOperation, |
|---|
| 380 |
InvalidContext:InvalidOperation} |
|---|
| 381 |
|
|---|
| 382 |
##### Context Functions ####################################### |
|---|
| 383 |
|
|---|
| 384 |
# The getcontext() and setcontext() function manage access to a thread-local |
|---|
| 385 |
# current context. Py2.4 offers direct support for thread locals. If that |
|---|
| 386 |
# is not available, use threading.currentThread() which is slower but will |
|---|
| 387 |
# work for older Pythons. If threads are not part of the build, create a |
|---|
| 388 |
# mock threading object with threading.local() returning the module namespace. |
|---|
| 389 |
|
|---|
| 390 |
try: |
|---|
| 391 |
import threading |
|---|
| 392 |
except ImportError: |
|---|
| 393 |
# Python was compiled without threads; create a mock object instead |
|---|
| 394 |
import sys |
|---|
| 395 |
class MockThreading: |
|---|
| 396 |
def local(self, sys=sys): |
|---|
| 397 |
return sys.modules[__name__] |
|---|
| 398 |
threading = MockThreading() |
|---|
| 399 |
del sys, MockThreading |
|---|
| 400 |
|
|---|
| 401 |
try: |
|---|
| 402 |
threading.local |
|---|
| 403 |
|
|---|
| 404 |
except AttributeError: |
|---|
| 405 |
|
|---|
| 406 |
#To fix reloading, force it to create a new context |
|---|
| 407 |
#Old contexts have different exceptions in their dicts, making problems. |
|---|
| 408 |
if hasattr(threading.currentThread(), '__decimal_context__'): |
|---|
| 409 |
del threading.currentThread().__decimal_context__ |
|---|
| 410 |
|
|---|
| 411 |
def setcontext(context): |
|---|
| 412 |
"""Set this thread's context to context.""" |
|---|
| 413 |
if context in (DefaultContext, BasicContext, ExtendedContext): |
|---|
| 414 |
context = context.copy() |
|---|
| 415 |
context.clear_flags() |
|---|
| 416 |
threading.currentThread().__decimal_context__ = context |
|---|
| 417 |
|
|---|
| 418 |
def getcontext(): |
|---|
| 419 |
"""Returns this thread's context. |
|---|
| 420 |
|
|---|
| 421 |
If this thread does not yet have a context, returns |
|---|
| 422 |
a new context and sets this thread's context. |
|---|
| 423 |
New contexts are copies of DefaultContext. |
|---|
| 424 |
""" |
|---|
| 425 |
try: |
|---|
| 426 |
return threading.currentThread().__decimal_context__ |
|---|
| 427 |
except AttributeError: |
|---|
| 428 |
context = Context() |
|---|
| 429 |
threading.currentThread().__decimal_context__ = context |
|---|
| 430 |
return context |
|---|
| 431 |
|
|---|
| 432 |
else: |
|---|
| 433 |
|
|---|
| 434 |
local = threading.local() |
|---|
| 435 |
if hasattr(local, '__decimal_context__'): |
|---|
| 436 |
del local.__decimal_context__ |
|---|
| 437 |
|
|---|
| 438 |
def getcontext(_local=local): |
|---|
| 439 |
"""Returns this thread's context. |
|---|
| 440 |
|
|---|
| 441 |
If this thread does not yet have a context, returns |
|---|
| 442 |
a new context and sets this thread's context. |
|---|
| 443 |
New contexts are copies of DefaultContext. |
|---|
| 444 |
""" |
|---|
| 445 |
try: |
|---|
| 446 |
return _local.__decimal_context__ |
|---|
| 447 |
except AttributeError: |
|---|
| 448 |
context = Context() |
|---|
| 449 |
_local.__decimal_context__ = context |
|---|
| 450 |
return context |
|---|
| 451 |
|
|---|
| 452 |
def setcontext(context, _local=local): |
|---|
| 453 |
"""Set this thread's context to context.""" |
|---|
| 454 |
if context in (DefaultContext, BasicContext, ExtendedContext): |
|---|
| 455 |
context = context.copy() |
|---|
| 456 |
context.clear_flags() |
|---|
| 457 |
_local.__decimal_context__ = context |
|---|
| 458 |
|
|---|
| 459 |
del threading, local # Don't contaminate the namespace |
|---|
| 460 |
|
|---|
| 461 |
|
|---|
| 462 |
##### Decimal class ########################################### |
|---|
| 463 |
|
|---|
| 464 |
class Decimal(object): |
|---|
| 465 |
"""Floating point class for decimal arithmetic.""" |
|---|
| 466 |
|
|---|
| 467 |
__slots__ = ('_exp','_int','_sign', '_is_special') |
|---|
| 468 |
# Generally, the value of the Decimal instance is given by |
|---|
| 469 |
# (-1)**_sign * _int * 10**_exp |
|---|
| 470 |
# Special values are signified by _is_special == True |
|---|
| 471 |
|
|---|
| 472 |
# We're immutable, so use __new__ not __init__ |
|---|
| 473 |
def __new__(cls, value="0", context=None): |
|---|
| 474 |
"""Create a decimal point instance. |
|---|
| 475 |
|
|---|
| 476 |
>>> Decimal('3.14') # string input |
|---|
| 477 |
Decimal("3.14") |
|---|
| 478 |
>>> Decimal((0, (3, 1, 4), -2)) # tuple input (sign, digit_tuple, exponent) |
|---|
| 479 |
Decimal("3.14") |
|---|
| 480 |
>>> Decimal(314) # int or long |
|---|
| 481 |
Decimal("314") |
|---|
| 482 |
>>> Decimal(Decimal(314)) # another decimal instance |
|---|
| 483 |
Decimal("314") |
|---|
| 484 |
""" |
|---|
| 485 |
|
|---|
| 486 |
self = object.__new__(cls) |
|---|
| 487 |
self._is_special = False |
|---|
| 488 |
|
|---|
| 489 |
# From an internal working value |
|---|
| 490 |
if isinstance(value, _WorkRep): |
|---|
| 491 |
self._sign = value.sign |
|---|
| 492 |
self._int = tuple(map(int, str(value.int))) |
|---|
| 493 |
self._exp = int(value.exp) |
|---|
| 494 |
return self |
|---|
| 495 |
|
|---|
| 496 |
# From another decimal |
|---|
| 497 |
if isinstance(value, Decimal): |
|---|
| 498 |
self._exp = value._exp |
|---|
| 499 |
self._sign = value._sign |
|---|
| 500 |
self._int = value._int |
|---|
| 501 |
self._is_special = value._is_special |
|---|
| 502 |
return self |
|---|
| 503 |
|
|---|
| 504 |
# From an integer |
|---|
| 505 |
if isinstance(value, (int,long)): |
|---|
| 506 |
if value >= 0: |
|---|
| 507 |
self._sign = 0 |
|---|
| 508 |
else: |
|---|
| 509 |
self._sign = 1 |
|---|
| 510 |
self._exp = 0 |
|---|
| 511 |
self._int = tuple(map(int, str(abs(value)))) |
|---|
| 512 |
return self |
|---|
| 513 |
|
|---|
| 514 |
# tuple/list conversion (possibly from as_tuple()) |
|---|
| 515 |
if isinstance(value, (list,tuple)): |
|---|
| 516 |
if len(value) != 3: |
|---|
| 517 |
raise ValueError, 'Invalid arguments' |
|---|
| 518 |
if value[0] not in (0,1): |
|---|
| 519 |
raise ValueError, 'Invalid sign' |
|---|
| 520 |
for digit in value[1]: |
|---|
| 521 |
if not isinstance(digit, (int,long)) or digit < 0: |
|---|
| 522 |
raise ValueError, "The second value in the tuple must be composed of non negative integer elements." |
|---|
| 523 |
|
|---|
| 524 |
self._sign = value[0] |
|---|
| 525 |
self._int = tuple(value[1]) |
|---|
| 526 |
if value[2] in ('F','n','N'): |
|---|
| 527 |
self._exp = value[2] |
|---|
| 528 |
self._is_special = True |
|---|
| 529 |
else: |
|---|
| 530 |
self._exp = int(value[2]) |
|---|
| 531 |
return self |
|---|
| 532 |
|
|---|
| 533 |
if isinstance(value, float): |
|---|
| 534 |
raise TypeError("Cannot convert float to Decimal. " + |
|---|
| 535 |
"First convert the float to a string") |
|---|
| 536 |
|
|---|
| 537 |
# Other argument types may require the context during interpretation |
|---|
| 538 |
if context is None: |
|---|
| 539 |
context = getcontext() |
|---|
| 540 |
|
|---|
| 541 |
# From a string |
|---|
| 542 |
# REs insist on real strings, so we can too. |
|---|
| 543 |
if isinstance(value, basestring): |
|---|
| 544 |
if _isinfinity(value): |
|---|
| 545 |
self._exp = 'F' |
|---|
| 546 |
self._int = (0,) |
|---|
| 547 |
self._is_special = True |
|---|
| 548 |
if _isinfinity(value) == 1: |
|---|
| 549 |
self._sign = 0 |
|---|
| 550 |
else: |
|---|
| 551 |
self._sign = 1 |
|---|
| 552 |
return self |
|---|
| 553 |
if _isnan(value): |
|---|
| 554 |
sig, sign, diag = _isnan(value) |
|---|
| 555 |
self._is_special = True |
|---|
| 556 |
if len(diag) > context.prec: #Diagnostic info too long |
|---|
| 557 |
self._sign, self._int, self._exp = \ |
|---|
| 558 |
context._raise_error(ConversionSyntax) |
|---|
| 559 |
return self |
|---|
| 560 |
if sig == 1: |
|---|
| 561 |
self._exp = 'n' #qNaN |
|---|
| 562 |
else: #sig == 2 |
|---|
| 563 |
self._exp = 'N' #sNaN |
|---|
| 564 |
self._sign = sign |
|---|
| 565 |
self._int = tuple(map(int, diag)) #Diagnostic info |
|---|
| 566 |
return self |
|---|
| 567 |
try: |
|---|
| 568 |
self._sign, self._int, self._exp = _string2exact(value) |
|---|
| 569 |
except ValueError: |
|---|
| 570 |
self._is_special = True |
|---|
| 571 |
self._sign, self._int, self._exp = context._raise_error(ConversionSyntax) |
|---|
| 572 |
return self |
|---|
| 573 |
|
|---|
| 574 |
raise TypeError("Cannot convert %r to Decimal" % value) |
|---|
| 575 |
|
|---|
| 576 |
def _isnan(self): |
|---|
| 577 |
"""Returns whether the number is not actually one. |
|---|
| 578 |
|
|---|
| 579 |
0 if a number |
|---|
| 580 |
1 if NaN |
|---|
| 581 |
2 if sNaN |
|---|
| 582 |
""" |
|---|
| 583 |
if self._is_special: |
|---|
| 584 |
exp = self._exp |
|---|
| 585 |
if exp == 'n': |
|---|
| 586 |
return 1 |
|---|
| 587 |
elif exp == 'N': |
|---|
| 588 |
return 2 |
|---|
| 589 |
return 0 |
|---|
| 590 |
|
|---|
| 591 |
def _isinfinity(self): |
|---|
| 592 |
"""Returns whether the number is infinite |
|---|
| 593 |
|
|---|
| 594 |
0 if finite or not a number |
|---|
| 595 |
1 if +INF |
|---|
| 596 |
-1 if -INF |
|---|
| 597 |
""" |
|---|
| 598 |
if self._exp == 'F': |
|---|
| 599 |
if self._sign: |
|---|
| 600 |
return -1 |
|---|
| 601 |
return 1 |
|---|
| 602 |
return 0 |
|---|
| 603 |
|
|---|
| 604 |
def _check_nans(self, other = None, context=None): |
|---|
| 605 |
"""Returns whether the number is not actually one. |
|---|
| 606 |
|
|---|
| 607 |
if self, other are sNaN, signal |
|---|
| 608 |
if self, other are NaN return nan |
|---|
| 609 |
return 0 |
|---|
| 610 |
|
|---|
| 611 |
Done before operations. |
|---|
| 612 |
""" |
|---|
| 613 |
|
|---|
| 614 |
self_is_nan = self._isnan() |
|---|
| 615 |
if other is None: |
|---|
| 616 |
other_is_nan = False |
|---|
| 617 |
else: |
|---|
| 618 |
other_is_nan = other._isnan() |
|---|
| 619 |
|
|---|
| 620 |
if self_is_nan or other_is_nan: |
|---|
| 621 |
if context is None: |
|---|
| 622 |
context = getcontext() |
|---|
| 623 |
|
|---|
| 624 |
if self_is_nan == 2: |
|---|
| 625 |
return context._raise_error(InvalidOperation, 'sNaN', |
|---|
| 626 |
1, self) |
|---|
| 627 |
if other_is_nan == 2: |
|---|
| 628 |
return context._raise_error(InvalidOperation, 'sNaN', |
|---|
| 629 |
1, other) |
|---|
| 630 |
if self_is_nan: |
|---|
| 631 |
return self |
|---|
| 632 |
|
|---|
| 633 |
return other |
|---|
| 634 |
return 0 |
|---|
| 635 |
|
|---|
| 636 |
def __nonzero__(self): |
|---|
| 637 |
"""Is the number non-zero? |
|---|
| 638 |
|
|---|
| 639 |
0 if self == 0 |
|---|
| 640 |
1 if self != 0 |
|---|
| 641 |
""" |
|---|
| 642 |
if self._is_special: |
|---|
| 643 |
return 1 |
|---|
| 644 |
return sum(self._int) != 0 |
|---|
| 645 |
|
|---|
| 646 |
def __cmp__(self, other, context=None): |
|---|
| 647 |
other = _convert_other(other) |
|---|
| 648 |
if other is NotImplemented: |
|---|
| 649 |
return other |
|---|
| 650 |
|
|---|
| 651 |
if self._is_special or other._is_special: |
|---|
| 652 |
ans = self._check_nans(other, context) |
|---|
| 653 |
if ans: |
|---|
| 654 |
return 1 # Comparison involving NaN's always reports self > other |
|---|
| 655 |
|
|---|
| 656 |
# INF = INF |
|---|
| 657 |
return cmp(self._isinfinity(), other._isinfinity()) |
|---|
| 658 |
|
|---|
| 659 |
if not self and not other: |
|---|
| 660 |
return 0 #If both 0, sign comparison isn't certain. |
|---|
| 661 |
|
|---|
| 662 |
#If different signs, neg one is less |
|---|
| 663 |
if other._sign < self._sign: |
|---|
| 664 |
return -1 |
|---|
| 665 |
if self._sign < other._sign: |
|---|
| 666 |
return 1 |
|---|
| 667 |
|
|---|
| 668 |
self_adjusted = self.adjusted() |
|---|
| 669 |
other_adjusted = other.adjusted() |
|---|
| 670 |
if self_adjusted == other_adjusted and \ |
|---|
| 671 |
self._int + (0,)*(self._exp - other._exp) == \ |
|---|
| 672 |
other._int + (0,)*(other._exp - self._exp): |
|---|
| 673 |
return 0 #equal, except in precision. ([0]*(-x) = []) |
|---|
| 674 |
elif self_adjusted > other_adjusted and self._int[0] != 0: |
|---|
| 675 |
return (-1)**self._sign |
|---|
| 676 |
elif self_adjusted < other_adjusted and other._int[0] != 0: |
|---|
| 677 |
return -((-1)**self._sign) |
|---|
| 678 |
|
|---|
| 679 |
# Need to round, so make sure we have a valid context |
|---|
| 680 |
if context is None: |
|---|
| 681 |
context = getcontext() |
|---|
| 682 |
|
|---|
| 683 |
context = context._shallow_copy() |
|---|
| 684 |
rounding = context._set_rounding(ROUND_UP) |
|---|