blob: 1d13767746635d36c4d36e63ea6062907827bb7c [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# 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>
Fred Drake1f34eb12004-07-01 14:28:36 +00007# and Aahz <aahz at pobox.com>
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00008# and Tim Peters
9
10
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000011"""
12This is a Py2.3 implementation of decimal floating point arithmetic based on
13the General Decimal Arithmetic Specification:
14
15 www2.hursley.ibm.com/decimal/decarith.html
16
Raymond Hettinger0ea241e2004-07-04 13:53:24 +000017and IEEE standard 854-1987:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000018
19 www.cs.berkeley.edu/~ejr/projects/754/private/drafts/854-1987/dir.html
20
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000021Decimal floating point has finite precision with arbitrarily large bounds.
22
23The purpose of the module is to support arithmetic using familiar
24"schoolhouse" rules and to avoid the some of tricky representation
25issues associated with binary floating point. The package is especially
26useful for financial applications or for contexts where users have
27expectations that are at odds with binary floating point (for instance,
28in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead
29of the expected Decimal("0.00") returned by decimal floating point).
30
31Here are some examples of using the decimal module:
32
33>>> from decimal import *
Raymond Hettinger6ea48452004-07-03 12:26:21 +000034>>> getcontext().prec=9
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000035>>> Decimal(0)
36Decimal("0")
37>>> Decimal("1")
38Decimal("1")
39>>> Decimal("-.0123")
40Decimal("-0.0123")
41>>> Decimal(123456)
42Decimal("123456")
43>>> Decimal("123.45e12345678901234567890")
44Decimal("1.2345E+12345678901234567892")
45>>> Decimal("1.33") + Decimal("1.27")
46Decimal("2.60")
47>>> Decimal("12.34") + Decimal("3.87") - Decimal("18.41")
48Decimal("-2.20")
49>>> dig = Decimal(1)
50>>> print dig / Decimal(3)
510.333333333
52>>> getcontext().prec = 18
53>>> print dig / Decimal(3)
540.333333333333333333
55>>> print dig.sqrt()
561
57>>> print Decimal(3).sqrt()
581.73205080756887729
59>>> print Decimal(3) ** 123
604.85192780976896427E+58
61>>> inf = Decimal(1) / Decimal(0)
62>>> print inf
63Infinity
64>>> neginf = Decimal(-1) / Decimal(0)
65>>> print neginf
66-Infinity
67>>> print neginf + inf
68NaN
69>>> print neginf * inf
70-Infinity
71>>> print dig / 0
72Infinity
73>>> getcontext().trap_enablers[DivisionByZero] = 1
74>>> print dig / 0
75Traceback (most recent call last):
76 ...
77 ...
78 ...
79DivisionByZero: x / 0
80>>> c = Context()
81>>> c.trap_enablers[DivisionUndefined] = 0
82>>> print c.flags[DivisionUndefined]
830
84>>> c.divide(Decimal(0), Decimal(0))
85Decimal("NaN")
86>>> c.trap_enablers[DivisionUndefined] = 1
87>>> print c.flags[DivisionUndefined]
881
89>>> c.flags[DivisionUndefined] = 0
90>>> print c.flags[DivisionUndefined]
910
92>>> print c.divide(Decimal(0), Decimal(0))
93Traceback (most recent call last):
94 ...
95 ...
96 ...
97DivisionUndefined: 0 / 0
98>>> print c.flags[DivisionUndefined]
991
100>>> c.flags[DivisionUndefined] = 0
101>>> c.trap_enablers[DivisionUndefined] = False
102>>> print c.divide(Decimal(0), Decimal(0))
103NaN
104>>> print c.flags[DivisionUndefined]
1051
106>>>
107"""
108
109__all__ = [
110 # Two major classes
111 'Decimal', 'Context',
112
113 # Contexts
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +0000114 'DefaultContext', 'BasicContext', 'ExtendedContext',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115
116 # Exceptions
117 'DecimalException', 'Clamped', 'InvalidOperation', 'ConversionSyntax',
118 'DivisionByZero', 'DivisionImpossible', 'DivisionUndefined',
119 'Inexact', 'InvalidContext', 'Rounded', 'Subnormal', 'Overflow',
120 'Underflow',
121
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000122 # Constants for use in setting up contexts
123 'ROUND_DOWN', 'ROUND_HALF_UP', 'ROUND_HALF_EVEN', 'ROUND_CEILING',
124 'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN',
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000125 'Signals', # <-- Used for building trap/flag dictionaries
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000126
127 # Functions for manipulating contexts
Raymond Hettinger0ea241e2004-07-04 13:53:24 +0000128 'setcontext', 'getcontext'
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129]
130
131import threading
132import copy
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000133import operator
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000135#Exponent Range
136DEFAULT_MAX_EXPONENT = 999999999
137DEFAULT_MIN_EXPONENT = -999999999
138
139#Rounding
Raymond Hettinger0ea241e2004-07-04 13:53:24 +0000140ROUND_DOWN = 'ROUND_DOWN'
141ROUND_HALF_UP = 'ROUND_HALF_UP'
142ROUND_HALF_EVEN = 'ROUND_HALF_EVEN'
143ROUND_CEILING = 'ROUND_CEILING'
144ROUND_FLOOR = 'ROUND_FLOOR'
145ROUND_UP = 'ROUND_UP'
146ROUND_HALF_DOWN = 'ROUND_HALF_DOWN'
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000147
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +0000148#Rounding decision (not part of the public API)
Raymond Hettinger0ea241e2004-07-04 13:53:24 +0000149NEVER_ROUND = 'NEVER_ROUND' # Round in division (non-divmod), sqrt ONLY
150ALWAYS_ROUND = 'ALWAYS_ROUND' # Every operation rounds at end.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000151
152#Errors
153
154class DecimalException(ArithmeticError):
155 """Base exception class, defines default things.
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 Attributes:
164
165 default -- If the context is basic, the trap_enablers are set to
166 this by default. Extended contexts start out with them set
167 to 0, regardless.
168
169 handle -- Called when context._raise_error is called and the
170 trap_enabler is set. First argument is self, second is the
171 context. More arguments can be given, those being after
172 the explanation in _raise_error (For example,
173 context._raise_error(NewError, '(-x)!', self._sign) would
174 call NewError().handle(context, self._sign).)
175
176 To define a new exception, it should be sufficient to have it derive
177 from DecimalException.
178 """
179 default = 1
180 def handle(self, context, *args):
181 pass
182
183
184class Clamped(DecimalException):
185 """Exponent of a 0 changed to fit bounds.
186
187 This occurs and signals clamped if the exponent of a result has been
188 altered in order to fit the constraints of a specific concrete
189 representation. This may occur when the exponent of a zero result would
190 be outside the bounds of a representation, or when a large normal
191 number would have an encoded exponent that cannot be represented. In
192 this latter case, the exponent is reduced to fit and the corresponding
193 number of zero digits are appended to the coefficient ("fold-down").
194 """
195
196
197class InvalidOperation(DecimalException):
198 """An invalid operation was performed.
199
200 Various bad things cause this:
201
202 Something creates a signaling NaN
203 -INF + INF
204 0 * (+-)INF
205 (+-)INF / (+-)INF
206 x % 0
207 (+-)INF % x
208 x._rescale( non-integer )
209 sqrt(-x) , x > 0
210 0 ** 0
211 x ** (non-integer)
212 x ** (+-)INF
213 An operand is invalid
214 """
215 def handle(self, context, *args):
216 if args:
217 if args[0] == 1: #sNaN, must drop 's' but keep diagnostics
218 return Decimal( (args[1]._sign, args[1]._int, 'n') )
219 return NaN
220
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000221# XXX Is there a logic error in subclassing InvalidOperation?
222# Setting the InvalidOperation trap to zero does not preclude ConversionSyntax.
223# Also, incrementing Conversion syntax flag will not increment InvalidOperation.
224# Both of these issues interfere with cross-language portability because
225# code following the spec would not know about the Python subclasses.
226
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000227class ConversionSyntax(InvalidOperation):
228 """Trying to convert badly formed string.
229
230 This occurs and signals invalid-operation if an string is being
231 converted to a number and it does not conform to the numeric string
232 syntax. The result is [0,qNaN].
233 """
234
235 def handle(self, context, *args):
236 return (0, (0,), 'n') #Passed to something which uses a tuple.
237
238class DivisionByZero(DecimalException, ZeroDivisionError):
239 """Division by 0.
240
241 This occurs and signals division-by-zero if division of a finite number
242 by zero was attempted (during a divide-integer or divide operation, or a
243 power operation with negative right-hand operand), and the dividend was
244 not zero.
245
246 The result of the operation is [sign,inf], where sign is the exclusive
247 or of the signs of the operands for divide, or is 1 for an odd power of
248 -0, for power.
249 """
250
251 def handle(self, context, sign, double = None, *args):
252 if double is not None:
253 return (Infsign[sign],)*2
254 return Infsign[sign]
255
256class DivisionImpossible(InvalidOperation):
257 """Cannot perform the division adequately.
258
259 This occurs and signals invalid-operation if the integer result of a
260 divide-integer or remainder operation had too many digits (would be
261 longer than precision). The result is [0,qNaN].
262 """
263
264 def handle(self, context, *args):
265 return (NaN, NaN)
266
267class DivisionUndefined(InvalidOperation, ZeroDivisionError):
268 """Undefined result of division.
269
270 This occurs and signals invalid-operation if division by zero was
271 attempted (during a divide-integer, divide, or remainder operation), and
272 the dividend is also zero. The result is [0,qNaN].
273 """
274
275 def handle(self, context, tup=None, *args):
276 if tup is not None:
277 return (NaN, NaN) #for 0 %0, 0 // 0
278 return NaN
279
280class Inexact(DecimalException):
281 """Had to round, losing information.
282
283 This occurs and signals inexact whenever the result of an operation is
284 not exact (that is, it needed to be rounded and any discarded digits
285 were non-zero), or if an overflow or underflow condition occurs. The
286 result in all cases is unchanged.
287
288 The inexact signal may be tested (or trapped) to determine if a given
289 operation (or sequence of operations) was inexact.
290 """
291 default = 0
292
293class InvalidContext(InvalidOperation):
294 """Invalid context. Unknown rounding, for example.
295
296 This occurs and signals invalid-operation if an invalid context was
297 detected during an operation. This can occur if contexts are not checked
298 on creation and either the precision exceeds the capability of the
299 underlying concrete representation or an unknown or unsupported rounding
300 was specified. These aspects of the context need only be checked when
301 the values are required to be used. The result is [0,qNaN].
302 """
303
304 def handle(self, context, *args):
305 return NaN
306
307class Rounded(DecimalException):
308 """Number got rounded (not necessarily changed during rounding).
309
310 This occurs and signals rounded whenever the result of an operation is
311 rounded (that is, some zero or non-zero digits were discarded from the
312 coefficient), or if an overflow or underflow condition occurs. The
313 result in all cases is unchanged.
314
315 The rounded signal may be tested (or trapped) to determine if a given
316 operation (or sequence of operations) caused a loss of precision.
317 """
318 default = 0
319
320class Subnormal(DecimalException):
321 """Exponent < Emin before rounding.
322
323 This occurs and signals subnormal whenever the result of a conversion or
324 operation is subnormal (that is, its adjusted exponent is less than
325 Emin, before any rounding). The result in all cases is unchanged.
326
327 The subnormal signal may be tested (or trapped) to determine if a given
328 or operation (or sequence of operations) yielded a subnormal result.
329 """
330 pass
331
332class Overflow(Inexact, Rounded):
333 """Numerical overflow.
334
335 This occurs and signals overflow if the adjusted exponent of a result
336 (from a conversion or from an operation that is not an attempt to divide
337 by zero), after rounding, would be greater than the largest value that
338 can be handled by the implementation (the value Emax).
339
340 The result depends on the rounding mode:
341
342 For round-half-up and round-half-even (and for round-half-down and
343 round-up, if implemented), the result of the operation is [sign,inf],
344 where sign is the sign of the intermediate result. For round-down, the
345 result is the largest finite number that can be represented in the
346 current precision, with the sign of the intermediate result. For
347 round-ceiling, the result is the same as for round-down if the sign of
348 the intermediate result is 1, or is [0,inf] otherwise. For round-floor,
349 the result is the same as for round-down if the sign of the intermediate
350 result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded
351 will also be raised.
352 """
353
354 def handle(self, context, sign, *args):
355 if context.rounding in (ROUND_HALF_UP, ROUND_HALF_EVEN,
356 ROUND_HALF_DOWN, ROUND_UP):
357 return Infsign[sign]
358 if sign == 0:
359 if context.rounding == ROUND_CEILING:
360 return Infsign[sign]
361 return Decimal((sign, (9,)*context.prec,
362 context.Emax-context.prec+1))
363 if sign == 1:
364 if context.rounding == ROUND_FLOOR:
365 return Infsign[sign]
366 return Decimal( (sign, (9,)*context.prec,
367 context.Emax-context.prec+1))
368
369
370class Underflow(Inexact, Rounded, Subnormal):
371 """Numerical underflow with result rounded to 0.
372
373 This occurs and signals underflow if a result is inexact and the
374 adjusted exponent of the result would be smaller (more negative) than
375 the smallest value that can be handled by the implementation (the value
376 Emin). That is, the result is both inexact and subnormal.
377
378 The result after an underflow will be a subnormal number rounded, if
379 necessary, so that its exponent is not less than Etiny. This may result
380 in 0 with the sign of the intermediate result and an exponent of Etiny.
381
382 In all cases, Inexact, Rounded, and Subnormal will also be raised.
383 """
384
385
386def _filterfunc(obj):
387 """Returns true if a subclass of DecimalException"""
388 try:
389 return issubclass(obj, DecimalException)
390 except TypeError:
391 return False
392
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000393#Signals holds the exceptions
394Signals = filter(_filterfunc, globals().values())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395
396del _filterfunc
397
398
399##### Context Functions #######################################
400
401#To fix reloading, force it to create a new context
402#Old contexts have different exceptions in their dicts, making problems.
403if hasattr(threading.currentThread(), '__decimal_context__'):
404 del threading.currentThread().__decimal_context__
405
406def setcontext(context):
407 """Set this thread's context to context."""
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000408 if context == DefaultContext:
409 context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000410 threading.currentThread().__decimal_context__ = context
411
412def getcontext():
413 """Returns this thread's context.
414
415 If this thread does not yet have a context, returns
416 a new context and sets this thread's context.
417 New contexts are copies of DefaultContext.
418 """
419 try:
420 return threading.currentThread().__decimal_context__
421 except AttributeError:
422 context = Context()
423 threading.currentThread().__decimal_context__ = context
424 return context
425
426
427##### Decimal class ###########################################
428
429class Decimal(object):
430 """Floating point class for decimal arithmetic."""
431
432 __slots__ = ('_exp','_int','_sign')
433
434 def __init__(self, value="0", context=None):
435 """Create a decimal point instance.
436
437 >>> Decimal('3.14') # string input
438 Decimal("3.14")
439 >>> Decimal((0, (3, 1, 4), -2)) # tuple input (sign, digit_tuple, exponent)
440 Decimal("3.14")
441 >>> Decimal(314) # int or long
442 Decimal("314")
443 >>> Decimal(Decimal(314)) # another decimal instance
444 Decimal("314")
445 """
446 if context is None:
447 context = getcontext()
448
449 if isinstance(value, (int,long)):
450 value = str(value)
451
452 # String?
453 # REs insist on real strings, so we can too.
454 if isinstance(value, basestring):
Raymond Hettinger0ea241e2004-07-04 13:53:24 +0000455 if _isinfinity(value):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000456 self._exp = 'F'
457 self._int = (0,)
Raymond Hettinger0ea241e2004-07-04 13:53:24 +0000458 sign = _isinfinity(value)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000459 if sign == 1:
460 self._sign = 0
461 else:
462 self._sign = 1
463 return
Raymond Hettinger0ea241e2004-07-04 13:53:24 +0000464 if _isnan(value):
465 sig, sign, diag = _isnan(value)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000466 if len(diag) > context.prec: #Diagnostic info too long
467 self._sign, self._int, self._exp = \
468 context._raise_error(ConversionSyntax)
469 return
470 if sig == 1:
471 self._exp = 'n' #qNaN
472 else: #sig == 2
473 self._exp = 'N' #sNaN
474 self._sign = sign
475 self._int = tuple(map(int, diag)) #Diagnostic info
476 return
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000477 try:
478 self._sign, self._int, self._exp = _string2exact(value)
479 except ValueError:
480 self._sign, self._int, self._exp = context._raise_error(ConversionSyntax)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481 return
482
483 # tuple/list conversion (possibly from as_tuple())
484 if isinstance(value, (list,tuple)):
485 if len(value) != 3:
486 raise ValueError, 'Invalid arguments'
487 if value[0] not in [0,1]:
488 raise ValueError, 'Invalid sign'
489 for digit in value[1]:
490 if not isinstance(digit, (int,long)) or digit < 0:
491 raise ValueError, "The second value in the tuple must be composed of non negative integer elements."
492
493 self._sign = value[0]
494 self._int = tuple(value[1])
495 if value[2] in ('F','n','N'):
496 self._exp = value[2]
497 else:
498 self._exp = int(value[2])
499 return
500
501 # Turn an intermediate value back to Decimal()
502 if isinstance(value, _WorkRep):
503 if value.sign == 1:
504 self._sign = 0
505 else:
506 self._sign = 1
507 self._int = tuple(value.int)
508 self._exp = int(value.exp)
509 return
510
511 if isinstance(value, Decimal):
512 self._exp = value._exp
513 self._sign = value._sign
514 self._int = value._int
515 return
516
517 raise TypeError("Can't convert %r" % value)
518
519 def _convert_other(self, other):
520 """Convert other to Decimal.
521
522 Verifies that it's ok to use in an implicit construction.
523 """
524 if isinstance(other, Decimal):
525 return other
526 if isinstance(other, (int, long)):
527 other = Decimal(other)
528 return other
529
530 raise TypeError, "You can interact Decimal only with int, long or Decimal data types."
531
532 def _isnan(self):
533 """Returns whether the number is not actually one.
534
535 0 if a number
536 1 if NaN
537 2 if sNaN
538 """
539 if self._exp == 'n':
540 return 1
541 elif self._exp == 'N':
542 return 2
543 return 0
544
545 def _isinfinity(self):
546 """Returns whether the number is infinite
547
548 0 if finite or not a number
549 1 if +INF
550 -1 if -INF
551 """
552 if self._exp == 'F':
553 if self._sign:
554 return -1
555 return 1
556 return 0
557
558 def _check_nans(self, other = None, context=None):
559 """Returns whether the number is not actually one.
560
561 if self, other are sNaN, signal
562 if self, other are NaN return nan
563 return 0
564
565 Done before operations.
566 """
567 if context is None:
568 context = getcontext()
569
570 if self._isnan() == 2:
571 return context._raise_error(InvalidOperation, 'sNaN',
572 1, self)
573 if other is not None and other._isnan() == 2:
574 return context._raise_error(InvalidOperation, 'sNaN',
575 1, other)
576 if self._isnan():
577 return self
578 if other is not None and other._isnan():
579 return other
580 return 0
581
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000582 def __nonzero__(self):
583 """Is the number non-zero?
584
585 0 if self == 0
586 1 if self != 0
587 """
588 if isinstance(self._exp, str):
589 return 1
590 return self._int != (0,)*len(self._int)
591
592 def __cmp__(self, other, context=None):
593 if context is None:
594 context = getcontext()
595 other = self._convert_other(other)
596
597 ans = self._check_nans(other, context)
598 if ans:
599 return 1
600
601 if not self and not other:
602 return 0 #If both 0, sign comparison isn't certain.
603
604 #If different signs, neg one is less
605 if other._sign < self._sign:
606 return -1
607 if self._sign < other._sign:
608 return 1
609
610 # INF = INF
611 if self._isinfinity() and other._isinfinity():
612 return 0
613 if self._isinfinity():
614 return (-1)**self._sign
615 if other._isinfinity():
616 return -((-1)**other._sign)
617
618 if self.adjusted() == other.adjusted() and \
619 self._int + (0,)*(self._exp - other._exp) == \
620 other._int + (0,)*(other._exp - self._exp):
621 return 0 #equal, except in precision. ([0]*(-x) = [])
622 elif self.adjusted() > other.adjusted() and self._int[0] != 0:
623 return (-1)**self._sign
624 elif self.adjusted < other.adjusted() and other._int[0] != 0:
625 return -((-1)**self._sign)
626
627 context = context.copy()
628 rounding = context._set_rounding(ROUND_UP) #round away from 0
629
630 flags = context._ignore_all_flags()
631 res = self.__sub__(other, context=context)
632
633 context._regard_flags(*flags)
634
635 context.rounding = rounding
636
637 if not res:
638 return 0
639 elif res._sign:
640 return -1
641 return 1
642
Raymond Hettinger0aeac102004-07-05 22:53:03 +0000643 def __eq__(self, other):
644 if not isinstance(other, (Decimal, int, long)):
645 return False
646 return self.__cmp__(other) == 0
647
648 def __ne__(self, other):
649 if not isinstance(other, (Decimal, int, long)):
650 return True
651 return self.__cmp__(other) != 0
652
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000653 def compare(self, other, context=None):
654 """Compares one to another.
655
656 -1 => a < b
657 0 => a = b
658 1 => a > b
659 NaN => one is NaN
660 Like __cmp__, but returns Decimal instances.
661 """
662 if context is None:
663 context = getcontext()
664 other = self._convert_other(other)
665
666 #compare(NaN, NaN) = NaN
667 ans = self._check_nans(other, context)
668 if ans:
669 return ans
670
671 return Decimal(self.__cmp__(other, context))
672
673 def __hash__(self):
674 """x.__hash__() <==> hash(x)"""
675 # Decimal integers must hash the same as the ints
676 # Non-integer decimals are normalized and hashed as strings
677 # Normalization assures that hast(100E-1) == hash(10)
678 i = int(self)
679 if self == Decimal(i):
680 return hash(i)
681 assert self.__nonzero__() # '-0' handled by integer case
682 return hash(str(self.normalize()))
683
684 def as_tuple(self):
685 """Represents the number as a triple tuple.
686
687 To show the internals exactly as they are.
688 """
689 return (self._sign, self._int, self._exp)
690
691 def __repr__(self):
692 """Represents the number as an instance of Decimal."""
693 # Invariant: eval(repr(d)) == d
694 return 'Decimal("%s")' % str(self)
695
696 def __str__(self, eng = 0, context=None):
697 """Return string representation of the number in scientific notation.
698
699 Captures all of the information in the underlying representation.
700 """
701
702 if self._isnan():
703 minus = '-'*self._sign
704 if self._int == (0,):
705 info = ''
706 else:
707 info = ''.join(map(str, self._int))
708 if self._isnan() == 2:
709 return minus + 'sNaN' + info
710 return minus + 'NaN' + info
711 if self._isinfinity():
712 minus = '-'*self._sign
713 return minus + 'Infinity'
714
715 if context is None:
716 context = getcontext()
717
718 tmp = map(str, self._int)
719 numdigits = len(self._int)
720 leftdigits = self._exp + numdigits
721 if eng and not self: #self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY
722 if self._exp < 0 and self._exp >= -6: #short, no need for e/E
723 s = '-'*self._sign + '0.' + '0'*(abs(self._exp))
724 return s
725 #exp is closest mult. of 3 >= self._exp
726 exp = ((self._exp - 1)// 3 + 1) * 3
727 if exp != self._exp:
728 s = '0.'+'0'*(exp - self._exp)
729 else:
730 s = '0'
731 if exp != 0:
732 if context.capitals:
733 s += 'E'
734 else:
735 s += 'e'
736 if exp > 0:
737 s += '+' #0.0e+3, not 0.0e3
738 s += str(exp)
739 s = '-'*self._sign + s
740 return s
741 if eng:
742 dotplace = (leftdigits-1)%3+1
743 adjexp = leftdigits -1 - (leftdigits-1)%3
744 else:
745 adjexp = leftdigits-1
746 dotplace = 1
747 if self._exp == 0:
748 pass
749 elif self._exp < 0 and adjexp >= 0:
750 tmp.insert(leftdigits, '.')
751 elif self._exp < 0 and adjexp >= -6:
752 tmp[0:0] = ['0'] * int(-leftdigits)
753 tmp.insert(0, '0.')
754 else:
755 if numdigits > dotplace:
756 tmp.insert(dotplace, '.')
757 elif numdigits < dotplace:
758 tmp.extend(['0']*(dotplace-numdigits))
759 if adjexp:
760 if not context.capitals:
761 tmp.append('e')
762 else:
763 tmp.append('E')
764 if adjexp > 0:
765 tmp.append('+')
766 tmp.append(str(adjexp))
767 if eng:
768 while tmp[0:1] == ['0']:
769 tmp[0:1] = []
770 if len(tmp) == 0 or tmp[0] == '.' or tmp[0].lower() == 'e':
771 tmp[0:0] = ['0']
772 if self._sign:
773 tmp.insert(0, '-')
774
775 return ''.join(tmp)
776
777 def to_eng_string(self, context=None):
778 """Convert to engineering-type string.
779
780 Engineering notation has an exponent which is a multiple of 3, so there
781 are up to 3 digits left of the decimal place.
782
783 Same rules for when in exponential and when as a value as in __str__.
784 """
785 if context is None:
786 context = getcontext()
787 return self.__str__(eng=1, context=context)
788
789 def __neg__(self, context=None):
790 """Returns a copy with the sign switched.
791
792 Rounds, if it has reason.
793 """
794 if context is None:
795 context = getcontext()
796 ans = self._check_nans(context=context)
797 if ans:
798 return ans
799
800 if not self:
801 # -Decimal('0') is Decimal('0'), not Decimal('-0')
802 sign = 0
803 elif self._sign:
804 sign = 0
805 else:
806 sign = 1
807 if context._rounding_decision == ALWAYS_ROUND:
808 return Decimal((sign, self._int, self._exp))._fix(context=context)
809 return Decimal( (sign, self._int, self._exp))
810
811 def __pos__(self, context=None):
812 """Returns a copy, unless it is a sNaN.
813
814 Rounds the number (if more then precision digits)
815 """
816 if context is None:
817 context = getcontext()
818 ans = self._check_nans(context=context)
819 if ans:
820 return ans
821
822 sign = self._sign
823 if not self:
824 # + (-0) = 0
825 sign = 0
826
827 if context._rounding_decision == ALWAYS_ROUND:
828 ans = self._fix(context=context)
829 else:
830 ans = Decimal(self)
831 ans._sign = sign
832 return ans
833
834 def __abs__(self, round=1, context=None):
835 """Returns the absolute value of self.
836
837 If the second argument is 0, do not round.
838 """
839 if context is None:
840 context = getcontext()
841 ans = self._check_nans(context=context)
842 if ans:
843 return ans
844
845 if not round:
846 context = context.copy()
847 context._set_rounding_decision(NEVER_ROUND)
848
849 if self._sign:
850 ans = self.__neg__(context=context)
851 else:
852 ans = self.__pos__(context=context)
853
854 return ans
855
856 def __add__(self, other, context=None):
857 """Returns self + other.
858
859 -INF + INF (or the reverse) cause InvalidOperation errors.
860 """
861 if context is None:
862 context = getcontext()
863 other = self._convert_other(other)
864
865 ans = self._check_nans(other, context)
866 if ans:
867 return ans
868
869 if self._isinfinity():
870 #If both INF, same sign => same as both, opposite => error.
871 if self._sign != other._sign and other._isinfinity():
872 return context._raise_error(InvalidOperation, '-INF + INF')
873 return Decimal(self)
874 if other._isinfinity():
875 return Decimal(other) #Can't both be infinity here
876
877 shouldround = context._rounding_decision == ALWAYS_ROUND
878
879 exp = min(self._exp, other._exp)
880 negativezero = 0
881 if context.rounding == ROUND_FLOOR and self._sign != other._sign:
882 #If the answer is 0, the sign should be negative, in this case.
883 negativezero = 1
884
885 if not self and not other:
886 sign = min(self._sign, other._sign)
887 if negativezero:
888 sign = 1
889 return Decimal( (sign, (0,), exp))
890 if not self:
891 if exp < other._exp - context.prec-1:
892 exp = other._exp - context.prec-1
893 ans = other._rescale(exp, watchexp=0, context=context)
894 if shouldround:
895 ans = ans._fix(context=context)
896 return ans
897 if not other:
898 if exp < self._exp - context.prec-1:
899 exp = self._exp - context.prec-1
900 ans = self._rescale(exp, watchexp=0, context=context)
901 if shouldround:
902 ans = ans._fix(context=context)
903 return ans
904
905 op1 = _WorkRep(self)
906 op2 = _WorkRep(other)
907 op1, op2 = _normalize(op1, op2, shouldround, context.prec)
908
909 result = _WorkRep()
910
911 if op1.sign != op2.sign:
912 diff = cmp(abs(op1), abs(op2))
913 # Equal and opposite
914 if diff == 0:
915 if exp < context.Etiny():
916 exp = context.Etiny()
917 context._raise_error(Clamped)
918 return Decimal((negativezero, (0,), exp))
919 if diff < 0:
920 op1, op2 = op2, op1
921 #OK, now abs(op1) > abs(op2)
922 if op1.sign == -1:
923 result.sign = -1
924 op1.sign, op2.sign = op2.sign, op1.sign
925 else:
926 result.sign = 1
927 #So we know the sign, and op1 > 0.
928 elif op1.sign == -1:
929 result.sign = -1
930 op1.sign, op2.sign = (1, 1)
931 else:
932 result.sign = 1
933 #Now, op1 > abs(op2) > 0
934
935 op1.int.reverse()
936 op2.int.reverse()
937
938 if op2.sign == 1:
939 result.int = resultint = map(operator.add, op1.int, op2.int)
940 carry = 0
941 for i in xrange(len(op1.int)):
942 tmp = resultint[i] + carry
943 carry = 0
944 if tmp > 9:
945 carry = 1
946 tmp -= 10
947 resultint[i] = tmp
948 if carry:
949 resultint.append(1)
950 else:
951 result.int = resultint = map(operator.sub, op1.int, op2.int)
952 loan = 0
953 for i in xrange(len(op1.int)):
954 tmp = resultint[i] - loan
955 loan = 0
956 if tmp < 0:
957 loan = 1
958 tmp += 10
959 resultint[i] = tmp
960 assert not loan
961
962 while resultint[-1] == 0:
963 resultint.pop()
964 resultint.reverse()
965
966 result.exp = op1.exp
967 ans = Decimal(result)
968 if shouldround:
969 ans = ans._fix(context=context)
970 return ans
971
972 __radd__ = __add__
973
974 def __sub__(self, other, context=None):
975 """Return self + (-other)"""
976 if context is None:
977 context = getcontext()
978 other = self._convert_other(other)
979
980 ans = self._check_nans(other, context=context)
981 if ans:
982 return ans
983
984 # -Decimal(0) = Decimal(0), which we don't want since
985 # (-0 - 0 = -0 + (-0) = -0, but -0 + 0 = 0.)
986 # so we change the sign directly to a copy
987 tmp = Decimal(other)
988 tmp._sign = 1-tmp._sign
989
990 return self.__add__(tmp, context=context)
991
992 def __rsub__(self, other, context=None):
993 """Return other + (-self)"""
994 if context is None:
995 context = getcontext()
996 other = self._convert_other(other)
997
998 tmp = Decimal(self)
999 tmp._sign = 1 - tmp._sign
1000 return other.__add__(tmp, context=context)
1001
1002 def _increment(self, round=1, context=None):
1003 """Special case of add, adding 1eExponent
1004
1005 Since it is common, (rounding, for example) this adds
1006 (sign)*one E self._exp to the number more efficiently than add.
1007
1008 For example:
1009 Decimal('5.624e10')._increment() == Decimal('5.625e10')
1010 """
1011 if context is None:
1012 context = getcontext()
1013 ans = self._check_nans(context=context)
1014 if ans:
1015 return ans
1016
1017 L = list(self._int)
1018 L[-1] += 1
1019 spot = len(L)-1
1020 while L[spot] == 10:
1021 L[spot] = 0
1022 if spot == 0:
1023 L[0:0] = [1]
1024 break
1025 L[spot-1] += 1
1026 spot -= 1
1027 ans = Decimal((self._sign, L, self._exp))
1028
1029 if round and context._rounding_decision == ALWAYS_ROUND:
1030 ans = ans._fix(context=context)
1031 return ans
1032
1033 def __mul__(self, other, context=None):
1034 """Return self * other.
1035
1036 (+-) INF * 0 (or its reverse) raise InvalidOperation.
1037 """
1038 if context is None:
1039 context = getcontext()
1040 other = self._convert_other(other)
1041
1042 ans = self._check_nans(other, context)
1043 if ans:
1044 return ans
1045
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00001046 resultsign = operator.xor(self._sign, other._sign)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001047 if self._isinfinity():
1048 if not other:
1049 return context._raise_error(InvalidOperation, '(+-)INF * 0')
1050 return Infsign[resultsign]
1051
1052 if other._isinfinity():
1053 if not self:
1054 return context._raise_error(InvalidOperation, '0 * (+-)INF')
1055 return Infsign[resultsign]
1056
1057 resultexp = self._exp + other._exp
1058 shouldround = context._rounding_decision == ALWAYS_ROUND
1059
1060 # Special case for multiplying by zero
1061 if not self or not other:
1062 ans = Decimal((resultsign, (0,), resultexp))
1063 if shouldround:
1064 #Fixing in case the exponent is out of bounds
1065 ans = ans._fix(context=context)
1066 return ans
1067
1068 # Special case for multiplying by power of 10
1069 if self._int == (1,):
1070 ans = Decimal((resultsign, other._int, resultexp))
1071 if shouldround:
1072 ans = ans._fix(context=context)
1073 return ans
1074 if other._int == (1,):
1075 ans = Decimal((resultsign, self._int, resultexp))
1076 if shouldround:
1077 ans = ans._fix(context=context)
1078 return ans
1079
1080 op1 = list(self._int)
1081 op2 = list(other._int)
1082 op1.reverse()
1083 op2.reverse()
1084 # Minimize Decimal additions
1085 if len(op2) > len(op1):
1086 op1, op2 = op2, op1
1087
1088 _divmod = divmod
1089 accumulator = [0]*(len(self._int) + len(other._int))
1090 for i in xrange(len(op2)):
1091 if op2[i] == 0:
1092 continue
1093 mult = op2[i]
1094 carry = 0
1095 for j in xrange(len(op1)):
1096 carry, accumulator[i+j] = _divmod( mult * op1[j] + carry
1097 + accumulator[i+j], 10)
1098
1099 if carry:
1100 accumulator[i + j + 1] += carry
1101 while not accumulator[-1]:
1102 accumulator.pop()
1103 accumulator.reverse()
1104
1105 ans = Decimal( (resultsign, accumulator, resultexp))
1106 if shouldround:
1107 ans = ans._fix(context=context)
1108
1109 return ans
1110 __rmul__ = __mul__
1111
1112 def __div__(self, other, context=None):
1113 """Return self / other."""
1114 return self._divide(other, context=context)
1115 __truediv__ = __div__
1116
1117 def _divide(self, other, divmod = 0, context=None):
1118 """Return a / b, to context.prec precision.
1119
1120 divmod:
1121 0 => true division
1122 1 => (a //b, a%b)
1123 2 => a //b
1124 3 => a%b
1125
1126 Actually, if divmod is 2 or 3 a tuple is returned, but errors for
1127 computing the other value are not raised.
1128 """
1129 if context is None:
1130 context = getcontext()
1131 other = self._convert_other(other)
1132
1133 ans = self._check_nans(other, context)
1134 if ans:
1135 if divmod:
1136 return (ans, ans)
1137 else:
1138 return ans
1139
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00001140 sign = operator.xor(self._sign, other._sign)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001141 if not self and not other:
1142 if divmod:
1143 return context._raise_error(DivisionUndefined, '0 / 0', 1)
1144 return context._raise_error(DivisionUndefined, '0 / 0')
1145 if self._isinfinity() and other._isinfinity():
1146 if not divmod:
1147 return context._raise_error(InvalidOperation, '(+-)INF/(+-)INF')
1148 else:
1149 return (context._raise_error(InvalidOperation,
1150 '(+-)INF // (+-)INF'),
1151 context._raise_error(InvalidOperation,
1152 '(+-)INF % (+-)INF'))
1153
1154 if not divmod:
1155 if other._isinfinity():
1156 context._raise_error(Clamped, 'Division by infinity')
1157 return Decimal((sign, (0,), context.Etiny()))
1158 if self._isinfinity():
1159 return Infsign[sign]
1160 #These two have different precision.
1161 if not self:
1162 exp = self._exp - other._exp
1163 if exp < context.Etiny():
1164 exp = context.Etiny()
1165 context._raise_error(Clamped, '0e-x / y')
1166 if exp > context.Emax:
1167 exp = context.Emax
1168 context._raise_error(Clamped, '0e+x / y')
1169 return Decimal( (sign, (0,), exp) )
1170
1171 if not other:
1172 return context._raise_error(DivisionByZero, 'x / 0', sign)
1173 if divmod:
1174 if other._isinfinity():
1175 return (Decimal((sign, (0,), 0)), Decimal(self))
1176 if self._isinfinity():
1177 if divmod == 1:
1178 return (Infsign[sign],
1179 context._raise_error(InvalidOperation, 'INF % x'))
1180 elif divmod == 2:
1181 return (Infsign[sign], NaN)
1182 elif divmod == 3:
1183 return (Infsign[sign],
1184 context._raise_error(InvalidOperation, 'INF % x'))
1185 if not self:
1186 otherside = Decimal(self)
1187 otherside._exp = min(self._exp, other._exp)
1188 return (Decimal((sign, (0,), 0)), otherside)
1189
1190 if not other:
1191 return context._raise_error(DivisionByZero, 'divmod(x,0)',
1192 sign, 1)
1193
1194 #OK, so neither = 0, INF
1195
1196 shouldround = context._rounding_decision == ALWAYS_ROUND
1197
1198 #If we're dividing into ints, and self < other, stop.
1199 #self.__abs__(0) does not round.
1200 if divmod and (self.__abs__(0, context) < other.__abs__(0, context)):
1201
1202 if divmod == 1 or divmod == 3:
1203 exp = min(self._exp, other._exp)
1204 ans2 = self._rescale(exp, context=context, watchexp=0)
1205 if shouldround:
1206 ans2 = ans2._fix(context=context)
1207 return (Decimal( (sign, (0,), 0) ),
1208 ans2)
1209
1210 elif divmod == 2:
1211 #Don't round the mod part, if we don't need it.
1212 return (Decimal( (sign, (0,), 0) ), Decimal(self))
1213
1214 if sign:
1215 sign = -1
1216 else:
1217 sign = 1
1218 adjust = 0
1219 op1 = _WorkRep(self)
1220 op2 = _WorkRep(other)
1221 op1, op2, adjust = _adjust_coefficients(op1, op2)
1222 res = _WorkRep( (sign, [0], (op1.exp - op2.exp)) )
1223 if divmod and res.exp > context.prec + 1:
1224 return context._raise_error(DivisionImpossible)
1225
1226 ans = None
1227 while 1:
1228 while( (len(op2.int) < len(op1.int) and op1.int[0]) or
1229 (len(op2.int) == len(op1.int) and op2.int <= op1.int)):
1230 #Meaning, while op2.int < op1.int, when normalized.
1231 res._increment()
1232 op1.subtract(op2.int)
1233 if res.exp == 0 and divmod:
1234 if len(res.int) > context.prec and shouldround:
1235 return context._raise_error(DivisionImpossible)
1236 otherside = Decimal(op1)
1237 frozen = context._ignore_all_flags()
1238
1239 exp = min(self._exp, other._exp)
1240 otherside = otherside._rescale(exp, context=context,
1241 watchexp=0)
1242 context._regard_flags(*frozen)
1243 if shouldround:
1244 otherside = otherside._fix(context=context)
1245 return (Decimal(res), otherside)
1246
1247 if op1.int == [0]*len(op1.int) and adjust >= 0 and not divmod:
1248 break
1249 if (len(res.int) > context.prec) and shouldround:
1250 if divmod:
1251 return context._raise_error(DivisionImpossible)
1252 shouldround=1
1253 # Really, the answer is a bit higher, so adding a one to
1254 # the end will make sure the rounding is right.
1255 if op1.int != [0]*len(op1.int):
1256 res.int.append(1)
1257 res.exp -= 1
1258
1259 break
1260 res.exp -= 1
1261 adjust += 1
1262 res.int.append(0)
1263 op1.int.append(0)
1264 op1.exp -= 1
1265
1266 if res.exp == 0 and divmod and (len(op2.int) > len(op1.int) or
1267 (len(op2.int) == len(op1.int) and
1268 op2.int > op1.int)):
1269 #Solves an error in precision. Same as a previous block.
1270
1271 if len(res.int) > context.prec and shouldround:
1272 return context._raise_error(DivisionImpossible)
1273 otherside = Decimal(op1)
1274 frozen = context._ignore_all_flags()
1275
1276 exp = min(self._exp, other._exp)
1277 otherside = otherside._rescale(exp, context=context)
1278
1279 context._regard_flags(*frozen)
1280
1281 return (Decimal(res), otherside)
1282
1283 ans = Decimal(res)
1284 if shouldround:
1285 ans = ans._fix(context=context)
1286 return ans
1287
1288 def __rdiv__(self, other, context=None):
1289 """Swaps self/other and returns __div__."""
1290 other = self._convert_other(other)
1291 return other.__div__(self, context=context)
1292 __rtruediv__ = __rdiv__
1293
1294 def __divmod__(self, other, context=None):
1295 """
1296 (self // other, self % other)
1297 """
1298 return self._divide(other, 1, context)
1299
1300 def __rdivmod__(self, other, context=None):
1301 """Swaps self/other and returns __divmod__."""
1302 other = self._convert_other(other)
1303 return other.__divmod__(self, context=context)
1304
1305 def __mod__(self, other, context=None):
1306 """
1307 self % other
1308 """
1309 if context is None:
1310 context = getcontext()
1311 other = self._convert_other(other)
1312
1313 ans = self._check_nans(other, context)
1314 if ans:
1315 return ans
1316
1317 if self and not other:
1318 return context._raise_error(InvalidOperation, 'x % 0')
1319
1320 return self._divide(other, 3, context)[1]
1321
1322 def __rmod__(self, other, context=None):
1323 """Swaps self/other and returns __mod__."""
1324 other = self._convert_other(other)
1325 return other.__mod__(self, context=context)
1326
1327 def remainder_near(self, other, context=None):
1328 """
1329 Remainder nearest to 0- abs(remainder-near) <= other/2
1330 """
1331 if context is None:
1332 context = getcontext()
1333 other = self._convert_other(other)
1334
1335 ans = self._check_nans(other, context)
1336 if ans:
1337 return ans
1338 if self and not other:
1339 return context._raise_error(InvalidOperation, 'x % 0')
1340
1341 # If DivisionImpossible causes an error, do not leave Rounded/Inexact
1342 # ignored in the calling function.
1343 context = context.copy()
1344 flags = context._ignore_flags(Rounded, Inexact)
1345 #keep DivisionImpossible flags
1346 (side, r) = self.__divmod__(other, context=context)
1347
1348 if r._isnan():
1349 context._regard_flags(*flags)
1350 return r
1351
1352 context = context.copy()
1353 rounding = context._set_rounding_decision(NEVER_ROUND)
1354
1355 if other._sign:
1356 comparison = other.__div__(Decimal(-2), context=context)
1357 else:
1358 comparison = other.__div__(Decimal(2), context=context)
1359
1360 context._set_rounding_decision(rounding)
1361 context._regard_flags(*flags)
1362
1363 s1, s2 = r._sign, comparison._sign
1364 r._sign, comparison._sign = 0, 0
1365
1366 if r < comparison:
1367 r._sign, comparison._sign = s1, s2
1368 #Get flags now
1369 self.__divmod__(other, context=context)
1370 return r._fix(context=context)
1371 r._sign, comparison._sign = s1, s2
1372
1373 rounding = context._set_rounding_decision(NEVER_ROUND)
1374
1375 (side, r) = self.__divmod__(other, context=context)
1376 context._set_rounding_decision(rounding)
1377 if r._isnan():
1378 return r
1379
1380 decrease = not side._iseven()
1381 rounding = context._set_rounding_decision(NEVER_ROUND)
1382 side = side.__abs__(context=context)
1383 context._set_rounding_decision(rounding)
1384
1385 s1, s2 = r._sign, comparison._sign
1386 r._sign, comparison._sign = 0, 0
1387 if r > comparison or decrease and r == comparison:
1388 r._sign, comparison._sign = s1, s2
1389 context.prec += 1
1390 if len(side.__add__(Decimal(1), context=context)._int) >= context.prec:
1391 context.prec -= 1
1392 return context._raise_error(DivisionImpossible)[1]
1393 context.prec -= 1
1394 if self._sign == other._sign:
1395 r = r.__sub__(other, context=context)
1396 else:
1397 r = r.__add__(other, context=context)
1398 else:
1399 r._sign, comparison._sign = s1, s2
1400
1401 return r._fix(context=context)
1402
1403 def __floordiv__(self, other, context=None):
1404 """self // other"""
1405 return self._divide(other, 2, context)[0]
1406
1407 def __rfloordiv__(self, other, context=None):
1408 """Swaps self/other and returns __floordiv__."""
1409 other = self._convert_other(other)
1410 return other.__floordiv__(self, context=context)
1411
1412 def __float__(self):
1413 """Float representation."""
1414 return float(str(self))
1415
1416 def __int__(self):
1417 """Converts self to a int, truncating if necessary."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001418 if self._isnan():
1419 context = getcontext()
1420 return context._raise_error(InvalidContext)
1421 elif self._isinfinity():
1422 raise OverflowError, "Cannot convert infinity to long"
1423 if not self:
1424 return 0
1425 sign = '-'*self._sign
1426 if self._exp >= 0:
1427 s = sign + ''.join(map(str, self._int)) + '0'*self._exp
1428 return int(s)
1429 s = sign + ''.join(map(str, self._int))[:self._exp]
1430 return int(s)
1431 tmp = list(self._int)
1432 tmp.reverse()
1433 val = 0
1434 while tmp:
1435 val *= 10
1436 val += tmp.pop()
1437 return int(((-1) ** self._sign) * val * 10.**int(self._exp))
1438
1439 def __long__(self):
1440 """Converts to a long.
1441
1442 Equivalent to long(int(self))
1443 """
1444 return long(self.__int__())
1445
1446 def _fix(self, prec=None, rounding=None, folddown=None, context=None):
1447 """Round if it is necessary to keep self within prec precision.
1448
1449 Rounds and fixes the exponent. Does not raise on a sNaN.
1450
1451 Arguments:
1452 self - Decimal instance
1453 prec - precision to which to round. By default, the context decides.
1454 rounding - Rounding method. By default, the context decides.
1455 folddown - Fold down high elements, by default context._clamp
1456 context - context used.
1457 """
1458 if self._isinfinity() or self._isnan():
1459 return self
1460 if context is None:
1461 context = getcontext()
1462 if prec is None:
1463 prec = context.prec
1464 ans = Decimal(self)
1465 ans = ans._fixexponents(prec, rounding, folddown=folddown,
1466 context=context)
1467 if len(ans._int) > prec:
1468 ans = ans._round(prec, rounding, context=context)
1469 ans = ans._fixexponents(prec, rounding, folddown=folddown,
1470 context=context)
1471 return ans
1472
1473 def _fixexponents(self, prec=None, rounding=None, folddown=None,
1474 context=None):
1475 """Fix the exponents and return a copy with the exponent in bounds."""
1476 if self._isinfinity():
1477 return self
1478 if context is None:
1479 context = getcontext()
1480 if prec is None:
1481 prec = context.prec
1482 if folddown is None:
1483 folddown = context._clamp
1484 Emin, Emax = context.Emin, context.Emax
1485 Etop = context.Etop()
1486 ans = Decimal(self)
1487 if ans.adjusted() < Emin:
1488 Etiny = context.Etiny()
1489 if ans._exp < Etiny:
1490 if not ans:
1491 ans._exp = Etiny
1492 context._raise_error(Clamped)
1493 return ans
1494 ans = ans._rescale(Etiny, context=context)
1495 #It isn't zero, and exp < Emin => subnormal
1496 context._raise_error(Subnormal)
1497 if context.flags[Inexact]:
1498 context._raise_error(Underflow)
1499 else:
1500 if ans:
1501 #Only raise subnormal if non-zero.
1502 context._raise_error(Subnormal)
1503 elif folddown and ans._exp > Etop:
1504 context._raise_error(Clamped)
1505 ans = ans._rescale(Etop, context=context)
1506 elif ans.adjusted() > Emax:
1507 if not ans:
1508 ans._exp = Emax
1509 context._raise_error(Clamped)
1510 return ans
1511 context._raise_error(Inexact)
1512 context._raise_error(Rounded)
1513 return context._raise_error(Overflow, 'above Emax', ans._sign)
1514 return ans
1515
1516 def _round(self, prec=None, rounding=None, context=None):
1517 """Returns a rounded version of self.
1518
1519 You can specify the precision or rounding method. Otherwise, the
1520 context determines it.
1521 """
1522
1523 if context is None:
1524 context = getcontext()
1525 ans = self._check_nans(context=context)
1526 if ans:
1527 return ans
1528
1529 if self._isinfinity():
1530 return Decimal(self)
1531
1532 if rounding is None:
1533 rounding = context.rounding
1534 if prec is None:
1535 prec = context.prec
1536
1537 if not self:
1538 if prec <= 0:
1539 dig = (0,)
1540 exp = len(self._int) - prec + self._exp
1541 else:
1542 dig = (0,) * prec
1543 exp = len(self._int) + self._exp - prec
1544 ans = Decimal((self._sign, dig, exp))
1545 context._raise_error(Rounded)
1546 return ans
1547
1548 if prec == 0:
1549 temp = Decimal(self)
1550 temp._int = (0,)+temp._int
1551 prec = 1
1552 elif prec < 0:
1553 exp = self._exp + len(self._int) - prec - 1
1554 temp = Decimal( (self._sign, (0, 1), exp))
1555 prec = 1
1556 else:
1557 temp = Decimal(self)
1558
1559 numdigits = len(temp._int)
1560 if prec == numdigits:
1561 return temp
1562
1563 # See if we need to extend precision
1564 expdiff = prec - numdigits
1565 if expdiff > 0:
1566 tmp = list(temp._int)
1567 tmp.extend([0] * expdiff)
1568 ans = Decimal( (temp._sign, tmp, temp._exp - expdiff))
1569 return ans
1570
1571 #OK, but maybe all the lost digits are 0.
1572 lostdigits = self._int[expdiff:]
1573 if lostdigits == (0,) * len(lostdigits):
1574 ans = Decimal( (temp._sign, temp._int[:prec], temp._exp - expdiff))
1575 #Rounded, but not Inexact
1576 context._raise_error(Rounded)
1577 return ans
1578
1579 # Okay, let's round and lose data
1580
1581 this_function = getattr(temp, self._pick_rounding_function[rounding])
1582 #Now we've got the rounding function
1583
1584 if prec != context.prec:
1585 context = context.copy()
1586 context.prec = prec
1587 ans = this_function(prec, expdiff, context)
1588 context._raise_error(Rounded)
1589 context._raise_error(Inexact, 'Changed in rounding')
1590
1591 return ans
1592
1593 _pick_rounding_function = {}
1594
1595 def _round_down(self, prec, expdiff, context):
1596 """Also known as round-towards-0, truncate."""
1597 return Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
1598
1599 def _round_half_up(self, prec, expdiff, context, tmp = None):
1600 """Rounds 5 up (away from 0)"""
1601
1602 if tmp is None:
1603 tmp = Decimal( (self._sign,self._int[:prec], self._exp - expdiff))
1604 if self._int[prec] >= 5:
1605 tmp = tmp._increment(round=0, context=context)
1606 if len(tmp._int) > prec:
1607 return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
1608 return tmp
1609
1610 def _round_half_even(self, prec, expdiff, context):
1611 """Round 5 to even, rest to nearest."""
1612
1613 tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
1614 half = (self._int[prec] == 5)
1615 if half:
1616 for digit in self._int[prec+1:]:
1617 if digit != 0:
1618 half = 0
1619 break
1620 if half:
1621 if self._int[prec-1] %2 == 0:
1622 return tmp
1623 return self._round_half_up(prec, expdiff, context, tmp)
1624
1625 def _round_half_down(self, prec, expdiff, context):
1626 """Round 5 down"""
1627
1628 tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff))
1629 half = (self._int[prec] == 5)
1630 if half:
1631 for digit in self._int[prec+1:]:
1632 if digit != 0:
1633 half = 0
1634 break
1635 if half:
1636 return tmp
1637 return self._round_half_up(prec, expdiff, context, tmp)
1638
1639 def _round_up(self, prec, expdiff, context):
1640 """Rounds away from 0."""
1641 tmp = Decimal( (self._sign, self._int[:prec], self._exp - expdiff) )
1642 for digit in self._int[prec:]:
1643 if digit != 0:
1644 tmp = tmp._increment(round=1, context=context)
1645 if len(tmp._int) > prec:
1646 return Decimal( (tmp._sign, tmp._int[:-1], tmp._exp + 1))
1647 else:
1648 return tmp
1649 return tmp
1650
1651 def _round_ceiling(self, prec, expdiff, context):
1652 """Rounds up (not away from 0 if negative.)"""
1653 if self._sign:
1654 return self._round_down(prec, expdiff, context)
1655 else:
1656 return self._round_up(prec, expdiff, context)
1657
1658 def _round_floor(self, prec, expdiff, context):
1659 """Rounds down (not towards 0 if negative)"""
1660 if not self._sign:
1661 return self._round_down(prec, expdiff, context)
1662 else:
1663 return self._round_up(prec, expdiff, context)
1664
1665 def __pow__(self, n, modulo = None, context=None):
1666 """Return self ** n (mod modulo)
1667
1668 If modulo is None (default), don't take it mod modulo.
1669 """
1670 if context is None:
1671 context = getcontext()
1672 n = self._convert_other(n)
1673
1674 #Because the spot << doesn't work with really big exponents
1675 if n._isinfinity() or n.adjusted() > 8:
1676 return context._raise_error(InvalidOperation, 'x ** INF')
1677
1678 ans = self._check_nans(n, context)
1679 if ans:
1680 return ans
1681
1682 if not n._isinfinity() and not n._isinteger():
1683 return context._raise_error(InvalidOperation, 'x ** (non-integer)')
1684
1685 if not self and not n:
1686 return context._raise_error(InvalidOperation, '0 ** 0')
1687
1688 if not n:
1689 return Decimal(1)
1690
1691 if self == Decimal(1):
1692 return Decimal(1)
1693
1694 sign = self._sign and not n._iseven()
1695 n = int(n)
1696
1697 if self._isinfinity():
1698 if modulo:
1699 return context._raise_error(InvalidOperation, 'INF % x')
1700 if n > 0:
1701 return Infsign[sign]
1702 return Decimal( (sign, (0,), 0) )
1703
1704 #with ludicrously large exponent, just raise an overflow and return inf.
1705 if not modulo and n > 0 and (self._exp + len(self._int) - 1) * n > context.Emax \
1706 and self:
1707
1708 tmp = Decimal('inf')
1709 tmp._sign = sign
1710 context._raise_error(Rounded)
1711 context._raise_error(Inexact)
1712 context._raise_error(Overflow, 'Big power', sign)
1713 return tmp
1714
1715 elength = len(str(abs(n)))
1716 firstprec = context.prec
1717
1718 if not modulo and firstprec + elength + 1 > DEFAULT_MAX_EXPONENT:
1719 return context._raise_error(Overflow, 'Too much precision.', sign)
1720
1721 mul = Decimal(self)
1722 val = Decimal(1)
1723 context = context.copy()
1724 context.prec = firstprec + elength + 1
1725 rounding = context.rounding
1726 if n < 0:
1727 #n is a long now, not Decimal instance
1728 n = -n
1729 mul = Decimal(1).__div__(mul, context=context)
1730
1731 shouldround = context._rounding_decision == ALWAYS_ROUND
1732
1733 spot = 1
1734 while spot <= n:
1735 spot <<= 1
1736
1737 spot >>= 1
1738 #Spot is the highest power of 2 less than n
1739 while spot:
1740 val = val.__mul__(val, context=context)
1741 if val._isinfinity():
1742 val = Infsign[sign]
1743 break
1744 if spot & n:
1745 val = val.__mul__(mul, context=context)
1746 if modulo is not None:
1747 val = val.__mod__(modulo, context=context)
1748 spot >>= 1
1749 context.prec = firstprec
1750
1751 if shouldround:
1752 return val._fix(context=context)
1753 return val
1754
1755 def __rpow__(self, other, context=None):
1756 """Swaps self/other and returns __pow__."""
1757 other = self._convert_other(other)
1758 return other.__pow__(self, context=context)
1759
1760 def normalize(self, context=None):
1761 """Normalize- strip trailing 0s, change anything equal to 0 to 0e0"""
1762 if context is None:
1763 context = getcontext()
1764
1765 ans = self._check_nans(context=context)
1766 if ans:
1767 return ans
1768
1769 dup = self._fix(context=context)
1770 if dup._isinfinity():
1771 return dup
1772
1773 if not dup:
1774 return Decimal( (dup._sign, (0,), 0) )
1775 end = len(dup._int)
1776 exp = dup._exp
1777 while dup._int[end-1] == 0:
1778 exp += 1
1779 end -= 1
1780 return Decimal( (dup._sign, dup._int[:end], exp) )
1781
1782
1783 def quantize(self, exp, rounding = None, context=None, watchexp = 1):
1784 """Quantize self so its exponent is the same as that of exp.
1785
1786 Similar to self._rescale(exp._exp) but with error checking.
1787 """
1788 if context is None:
1789 context = getcontext()
1790
1791 ans = self._check_nans(exp, context)
1792 if ans:
1793 return ans
1794
1795 if exp._isinfinity() or self._isinfinity():
1796 if exp._isinfinity() and self._isinfinity():
1797 return self #if both are inf, it is OK
1798 return context._raise_error(InvalidOperation,
1799 'quantize with one INF')
1800 return self._rescale(exp._exp, rounding, context, watchexp)
1801
1802 def same_quantum(self, other):
1803 """Test whether self and other have the same exponent.
1804
1805 same as self._exp == other._exp, except NaN == sNaN
1806 """
1807 if self._isnan() or other._isnan():
1808 return self._isnan() and other._isnan() and True
1809 if self._isinfinity() or other._isinfinity():
1810 return self._isinfinity() and other._isinfinity() and True
1811 return self._exp == other._exp
1812
1813 def _rescale(self, exp, rounding = None, context=None, watchexp = 1):
1814 """Rescales so that the exponent is exp.
1815
1816 exp = exp to scale to (an integer)
1817 rounding = rounding version
1818 watchexp: if set (default) an error is returned if exp is greater
1819 than Emax or less than Etiny.
1820 """
1821 if context is None:
1822 context = getcontext()
1823
1824 if self._isinfinity():
1825 return context._raise_error(InvalidOperation, 'rescale with an INF')
1826
1827 ans = self._check_nans(context=context)
1828 if ans:
1829 return ans
1830
1831 out = 0
1832
1833 if watchexp and (context.Emax < exp or context.Etiny() > exp):
1834 return context._raise_error(InvalidOperation, 'rescale(a, INF)')
1835
1836 if not self:
1837 ans = Decimal(self)
1838 ans._int = (0,)
1839 ans._exp = exp
1840 return ans
1841
1842 diff = self._exp - exp
1843 digits = len(self._int)+diff
1844
1845 if watchexp and digits > context.prec:
1846 return context._raise_error(InvalidOperation, 'Rescale > prec')
1847
1848 tmp = Decimal(self)
1849 tmp._int = (0,)+tmp._int
1850 digits += 1
1851
1852 prevexact = context.flags[Inexact]
1853 if digits < 0:
1854 tmp._exp = -digits + tmp._exp
1855 tmp._int = (0,1)
1856 digits = 1
1857 tmp = tmp._round(digits, rounding, context=context)
1858
1859 if tmp._int[0] == 0 and len(tmp._int) > 1:
1860 tmp._int = tmp._int[1:]
1861 tmp._exp = exp
1862
1863 if tmp and tmp.adjusted() < context.Emin:
1864 context._raise_error(Subnormal)
1865 elif tmp and tmp.adjusted() > context.Emax:
1866 return context._raise_error(InvalidOperation, 'rescale(a, INF)')
1867 return tmp
1868
1869 def to_integral(self, rounding = None, context=None):
1870 """Rounds to the nearest integer, without raising inexact, rounded."""
1871 if context is None:
1872 context = getcontext()
1873 ans = self._check_nans(context=context)
1874 if ans:
1875 return ans
1876 if self._exp >= 0:
1877 return self
1878 flags = context._ignore_flags(Rounded, Inexact)
1879 ans = self._rescale(0, rounding, context=context)
1880 context._regard_flags(flags)
1881 return ans
1882
1883 def sqrt(self, context=None):
1884 """Return the square root of self.
1885
1886 Uses a converging algorithm (Xn+1 = 0.5*(Xn + self / Xn))
1887 Should quadratically approach the right answer.
1888 """
1889 if context is None:
1890 context = getcontext()
1891
1892 ans = self._check_nans(context=context)
1893 if ans:
1894 return ans
1895
1896 if not self:
1897 #exponent = self._exp / 2, using round_down.
1898 #if self._exp < 0:
1899 # exp = (self._exp+1) // 2
1900 #else:
1901 exp = (self._exp) // 2
1902 if self._sign == 1:
1903 #sqrt(-0) = -0
1904 return Decimal( (1, (0,), exp))
1905 else:
1906 return Decimal( (0, (0,), exp))
1907
1908 if self._sign == 1:
1909 return context._raise_error(InvalidOperation, 'sqrt(-x), x > 0')
1910
1911 if self._isinfinity():
1912 return Decimal(self)
1913
1914 tmp = Decimal(self)
1915
1916 expadd = tmp._exp / 2
1917 if tmp._exp % 2 == 1:
1918 tmp._int += (0,)
1919 tmp._exp = 0
1920 else:
1921 tmp._exp = 0
1922
1923 context = context.copy()
1924 flags = context._ignore_all_flags()
1925 firstprec = context.prec
1926 context.prec = 3
1927 if tmp.adjusted() % 2 == 0:
1928 ans = Decimal( (0, (8,1,9), tmp.adjusted() - 2) )
1929 ans = ans.__add__(tmp.__mul__(Decimal((0, (2,5,9), -2)),
1930 context=context), context=context)
1931 ans._exp -= 1 + tmp.adjusted()/2
1932 else:
1933 ans = Decimal( (0, (2,5,9), tmp._exp + len(tmp._int)- 3) )
1934 ans = ans.__add__(tmp.__mul__(Decimal((0, (8,1,9), -3)),
1935 context=context), context=context)
1936 ans._exp -= 1 + tmp.adjusted()/2
1937
1938 #ans is now a linear approximation.
1939
1940 Emax, Emin = context.Emax, context.Emin
1941 context.Emax, context.Emin = DEFAULT_MAX_EXPONENT, DEFAULT_MIN_EXPONENT
1942
1943
1944 half = Decimal('0.5')
1945
1946 count = 1
1947 maxp = firstprec + 2
1948 rounding = context._set_rounding(ROUND_HALF_EVEN)
1949 while 1:
1950 context.prec = min(2*context.prec - 2, maxp)
1951 ans = half.__mul__(ans.__add__(tmp.__div__(ans, context=context),
1952 context=context), context=context)
1953 if context.prec == maxp:
1954 break
1955
1956 #round to the answer's precision-- the only error can be 1 ulp.
1957 context.prec = firstprec
1958 prevexp = ans.adjusted()
1959 ans = ans._round(context=context)
1960
1961 #Now, check if the other last digits are better.
1962 context.prec = firstprec + 1
1963 # In case we rounded up another digit and we should actually go lower.
1964 if prevexp != ans.adjusted():
1965 ans._int += (0,)
1966 ans._exp -= 1
1967
1968
1969 lower = ans.__sub__(Decimal((0, (5,), ans._exp-1)), context=context)
1970 context._set_rounding(ROUND_UP)
1971 if lower.__mul__(lower, context=context) > (tmp):
1972 ans = ans.__sub__(Decimal((0, (1,), ans._exp)), context=context)
1973
1974 else:
1975 upper = ans.__add__(Decimal((0, (5,), ans._exp-1)),context=context)
1976 context._set_rounding(ROUND_DOWN)
1977 if upper.__mul__(upper, context=context) < tmp:
1978 ans = ans.__add__(Decimal((0, (1,), ans._exp)),context=context)
1979
1980 ans._exp += expadd
1981
1982 context.prec = firstprec
1983 context.rounding = rounding
1984 ans = ans._fix(context=context)
1985
1986 rounding = context._set_rounding_decision(NEVER_ROUND)
1987 if not ans.__mul__(ans, context=context) == self:
1988 # Only rounded/inexact if here.
1989 context._regard_flags(flags)
1990 context._raise_error(Rounded)
1991 context._raise_error(Inexact)
1992 else:
1993 #Exact answer, so let's set the exponent right.
1994 #if self._exp < 0:
1995 # exp = (self._exp +1)// 2
1996 #else:
1997 exp = self._exp // 2
1998 context.prec += ans._exp - exp
1999 ans = ans._rescale(exp, context=context)
2000 context.prec = firstprec
2001 context._regard_flags(flags)
2002 context.Emax, context.Emin = Emax, Emin
2003
2004 return ans._fix(context=context)
2005
2006 def max(self, other, context=None):
2007 """Returns the larger value.
2008
2009 like max(self, other) except if one is not a number, returns
2010 NaN (and signals if one is sNaN). Also rounds.
2011 """
2012 if context is None:
2013 context = getcontext()
2014 other = self._convert_other(other)
2015
2016 ans = self._check_nans(other, context)
2017 if ans:
2018 return ans
2019
2020 ans = self
2021 if self < other:
2022 ans = other
2023 shouldround = context._rounding_decision == ALWAYS_ROUND
2024 if shouldround:
2025 ans = ans._fix(context=context)
2026 return ans
2027
2028 def min(self, other, context=None):
2029 """Returns the smaller value.
2030
2031 like min(self, other) except if one is not a number, returns
2032 NaN (and signals if one is sNaN). Also rounds.
2033 """
2034 if context is None:
2035 context = getcontext()
2036 other = self._convert_other(other)
2037
2038 ans = self._check_nans(other, context)
2039 if ans:
2040 return ans
2041
2042 ans = self
2043
2044 if self > other:
2045 ans = other
2046
2047 if context._rounding_decision == ALWAYS_ROUND:
2048 ans = ans._fix(context=context)
2049
2050 return ans
2051
2052 def _isinteger(self):
2053 """Returns whether self is an integer"""
2054 if self._exp >= 0:
2055 return True
2056 rest = self._int[self._exp:]
2057 return rest == (0,)*len(rest)
2058
2059 def _iseven(self):
2060 """Returns 1 if self is even. Assumes self is an integer."""
2061 if self._exp > 0:
2062 return 1
2063 return self._int[-1+self._exp] % 2 == 0
2064
2065 def adjusted(self):
2066 """Return the adjusted exponent of self"""
2067 try:
2068 return self._exp + len(self._int) - 1
2069 #If NaN or Infinity, self._exp is string
2070 except TypeError:
2071 return 0
2072
2073 #properties to immutability-near feature
2074 def _get_sign(self):
2075 return self._sign
2076 def _get_int(self):
2077 return self._int
2078 def _get_exp(self):
2079 return self._exp
2080 sign = property(_get_sign)
2081 int = property(_get_int)
2082 exp = property(_get_exp)
2083
2084 # support for pickling, copy, and deepcopy
2085 def __reduce__(self):
2086 return (self.__class__, (str(self),))
2087
2088 def __copy__(self):
2089 if type(self) == Decimal:
2090 return self # I'm immutable; therefore I am my own clone
2091 return self.__class__(str(self))
2092
2093 def __deepcopy__(self, memo):
2094 if type(self) == Decimal:
2095 return self # My components are also immutable
2096 return self.__class__(str(self))
2097
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002098##### Context class ###########################################
2099
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002100
2101# get rounding method function:
2102rounding_functions = [name for name in Decimal.__dict__.keys() if name.startswith('_round_')]
2103for name in rounding_functions:
2104 #name is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
2105 globalname = name[1:].upper()
2106 val = globals()[globalname]
2107 Decimal._pick_rounding_function[val] = name
2108
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002109del name, val, globalname, rounding_functions
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002110
2111class Context(object):
2112 """Contains the context for a Decimal instance.
2113
2114 Contains:
2115 prec - precision (for use in rounding, division, square roots..)
2116 rounding - rounding type. (how you round)
2117 _rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
2118 trap_enablers - If trap_enablers[exception] = 1, then the exception is
2119 raised when it is caused. Otherwise, a value is
2120 substituted in.
2121 flags - When an exception is caused, flags[exception] is incremented.
2122 (Whether or not the trap_enabler is set)
2123 Should be reset by user of Decimal instance.
Raymond Hettinger0ea241e2004-07-04 13:53:24 +00002124 Emin - Minimum exponent
2125 Emax - Maximum exponent
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002126 capitals - If 1, 1*10^1 is printed as 1E+1.
2127 If 0, printed as 1e1
Raymond Hettingere0f15812004-07-05 05:36:39 +00002128 _clamp - If 1, change exponents if too high (Default 0)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002129 """
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002130
2131 DefaultLock = threading.Lock()
2132
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002133 def __init__(self, prec=None, rounding=None,
2134 trap_enablers=None, flags=None,
2135 _rounding_decision=None,
Raymond Hettinger0ea241e2004-07-04 13:53:24 +00002136 Emin=None, Emax=None,
Raymond Hettingere0f15812004-07-05 05:36:39 +00002137 capitals=None, _clamp=0,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002138 _ignored_flags=[]):
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002139 if flags is None:
2140 flags = dict.fromkeys(Signals, 0)
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002141 self.DefaultLock.acquire()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002142 for name, val in locals().items():
2143 if val is None:
2144 setattr(self, name, copy.copy(getattr(DefaultContext, name)))
2145 else:
2146 setattr(self, name, val)
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002147 self.DefaultLock.release()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002148 del self.self
2149
Raymond Hettingerb1b605e2004-07-04 01:55:39 +00002150 def __repr__(self):
2151 """Show the current context in readable form, not in a form for eval()."""
2152 s = []
2153 s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d' % vars(self))
2154 s.append('setflags=%r' % [f.__name__ for f, v in self.flags.items() if v])
2155 s.append('settraps=%r' % [t.__name__ for t, v in self.trap_enablers.items() if v])
2156 return ', '.join(s) + ')'
2157
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002158 def clear_flags(self):
2159 """Reset all flags to zero"""
2160 for flag in self.flags:
Raymond Hettingerb1b605e2004-07-04 01:55:39 +00002161 self.flags[flag] = 0
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002162
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002163 def copy(self):
2164 """Returns a copy from self."""
2165 nc = Context(self.prec, self.rounding, self.trap_enablers, self.flags,
2166 self._rounding_decision, self.Emin, self.Emax,
2167 self.capitals, self._clamp, self._ignored_flags)
2168 return nc
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002169 __copy__ = copy
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002170
2171 def _raise_error(self, error, explanation = None, *args):
2172 """Handles an error
2173
2174 If the flag is in _ignored_flags, returns the default response.
2175 Otherwise, it increments the flag, then, if the corresponding
2176 trap_enabler is set, it reaises the exception. Otherwise, it returns
2177 the default value after incrementing the flag.
2178 """
2179 if error in self._ignored_flags:
2180 #Don't touch the flag
2181 return error().handle(self, *args)
2182
2183 self.flags[error] += 1
2184 if not self.trap_enablers[error]:
2185 #The errors define how to handle themselves.
2186 return error().handle(self, *args)
2187
2188 # Errors should only be risked on copies of the context
2189 #self._ignored_flags = []
2190 raise error, explanation
2191
2192 def _ignore_all_flags(self):
2193 """Ignore all flags, if they are raised"""
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002194 return self._ignore_flags(*Signals)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002195
2196 def _ignore_flags(self, *flags):
2197 """Ignore the flags, if they are raised"""
2198 # Do not mutate-- This way, copies of a context leave the original
2199 # alone.
2200 self._ignored_flags = (self._ignored_flags + list(flags))
2201 return list(flags)
2202
2203 def _regard_flags(self, *flags):
2204 """Stop ignoring the flags, if they are raised"""
2205 if flags and isinstance(flags[0], (tuple,list)):
2206 flags = flags[0]
2207 for flag in flags:
2208 self._ignored_flags.remove(flag)
2209
2210 def Etiny(self):
2211 """Returns Etiny (= Emin - prec + 1)"""
2212 return int(self.Emin - self.prec + 1)
2213
2214 def Etop(self):
Raymond Hettingere0f15812004-07-05 05:36:39 +00002215 """Returns maximum exponent (= Emax - prec + 1)"""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002216 return int(self.Emax - self.prec + 1)
2217
2218 def _set_rounding_decision(self, type):
2219 """Sets the rounding decision.
2220
2221 Sets the rounding decision, and returns the current (previous)
2222 rounding decision. Often used like:
2223
2224 context = context.copy()
2225 # That so you don't change the calling context
2226 # if an error occurs in the middle (say DivisionImpossible is raised).
2227
2228 rounding = context._set_rounding_decision(NEVER_ROUND)
2229 instance = instance / Decimal(2)
2230 context._set_rounding_decision(rounding)
2231
2232 This will make it not round for that operation.
2233 """
2234
2235 rounding = self._rounding_decision
2236 self._rounding_decision = type
2237 return rounding
2238
2239 def _set_rounding(self, type):
2240 """Sets the rounding type.
2241
2242 Sets the rounding type, and returns the current (previous)
2243 rounding type. Often used like:
2244
2245 context = context.copy()
2246 # so you don't change the calling context
2247 # if an error occurs in the middle.
2248 rounding = context._set_rounding(ROUND_UP)
2249 val = self.__sub__(other, context=context)
2250 context._set_rounding(rounding)
2251
2252 This will make it round up for that operation.
2253 """
2254 rounding = self.rounding
2255 self.rounding= type
2256 return rounding
2257
2258 def create_decimal(self, num):
2259 """Creates a new Decimal instance but using self as context."""
2260 d = Decimal(num, context=self)
2261 return d._fix(context=self)
2262
2263 #Methods
2264 def abs(self, a):
2265 """Returns the absolute value of the operand.
2266
2267 If the operand is negative, the result is the same as using the minus
2268 operation on the operand. Otherwise, the result is the same as using
2269 the plus operation on the operand.
2270
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002271 >>> ExtendedContext.abs(Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002272 Decimal("2.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002273 >>> ExtendedContext.abs(Decimal('-100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002274 Decimal("100")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002275 >>> ExtendedContext.abs(Decimal('101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002276 Decimal("101.5")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002277 >>> ExtendedContext.abs(Decimal('-101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002278 Decimal("101.5")
2279 """
2280 return a.__abs__(context=self)
2281
2282 def add(self, a, b):
2283 """Return the sum of the two operands.
2284
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002285 >>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002286 Decimal("19.00")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002287 >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002288 Decimal("1.02E+4")
2289 """
2290 return a.__add__(b, context=self)
2291
2292 def _apply(self, a):
2293 return str(a._fix(context=self))
2294
2295 def compare(self, a, b):
2296 """Compares values numerically.
2297
2298 If the signs of the operands differ, a value representing each operand
2299 ('-1' if the operand is less than zero, '0' if the operand is zero or
2300 negative zero, or '1' if the operand is greater than zero) is used in
2301 place of that operand for the comparison instead of the actual
2302 operand.
2303
2304 The comparison is then effected by subtracting the second operand from
2305 the first and then returning a value according to the result of the
2306 subtraction: '-1' if the result is less than zero, '0' if the result is
2307 zero or negative zero, or '1' if the result is greater than zero.
2308
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002309 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002310 Decimal("-1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002311 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002312 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002313 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002314 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002315 >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002316 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002317 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002318 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002319 >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002320 Decimal("-1")
2321 """
2322 return a.compare(b, context=self)
2323
2324 def divide(self, a, b):
2325 """Decimal division in a specified context.
2326
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002327 >>> ExtendedContext.divide(Decimal('1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002328 Decimal("0.333333333")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002329 >>> ExtendedContext.divide(Decimal('2'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002330 Decimal("0.666666667")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002331 >>> ExtendedContext.divide(Decimal('5'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002332 Decimal("2.5")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002333 >>> ExtendedContext.divide(Decimal('1'), Decimal('10'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002334 Decimal("0.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002335 >>> ExtendedContext.divide(Decimal('12'), Decimal('12'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002336 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002337 >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002338 Decimal("4.00")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002339 >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002340 Decimal("1.20")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002341 >>> ExtendedContext.divide(Decimal('1000'), Decimal('100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002342 Decimal("10")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002343 >>> ExtendedContext.divide(Decimal('1000'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002344 Decimal("1000")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002345 >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002346 Decimal("1.20E+6")
2347 """
2348 return a.__div__(b, context=self)
2349
2350 def divide_int(self, a, b):
2351 """Divides two numbers and returns the integer part of the result.
2352
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002353 >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002354 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002355 >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002356 Decimal("3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002357 >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002358 Decimal("3")
2359 """
2360 return a.__floordiv__(b, context=self)
2361
2362 def divmod(self, a, b):
2363 return a.__divmod__(b, context=self)
2364
2365 def max(self, a,b):
2366 """max compares two values numerically and returns the maximum.
2367
2368 If either operand is a NaN then the general rules apply.
2369 Otherwise, the operands are compared as as though by the compare
2370 operation. If they are numerically equal then the left-hand operand
2371 is chosen as the result. Otherwise the maximum (closer to positive
2372 infinity) of the two operands is chosen as the result.
2373
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002374 >>> ExtendedContext.max(Decimal('3'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002375 Decimal("3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002376 >>> ExtendedContext.max(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002377 Decimal("3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002378 >>> ExtendedContext.max(Decimal('1.0'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002379 Decimal("1.0")
2380 """
2381 return a.max(b, context=self)
2382
2383 def min(self, a,b):
2384 """min compares two values numerically and returns the minimum.
2385
2386 If either operand is a NaN then the general rules apply.
2387 Otherwise, the operands are compared as as though by the compare
2388 operation. If they are numerically equal then the left-hand operand
2389 is chosen as the result. Otherwise the minimum (closer to negative
2390 infinity) of the two operands is chosen as the result.
2391
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002392 >>> ExtendedContext.min(Decimal('3'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002393 Decimal("2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002394 >>> ExtendedContext.min(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002395 Decimal("-10")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002396 >>> ExtendedContext.min(Decimal('1.0'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002397 Decimal("1.0")
2398 """
2399 return a.min(b, context=self)
2400
2401 def minus(self, a):
2402 """Minus corresponds to unary prefix minus in Python.
2403
2404 The operation is evaluated using the same rules as subtract; the
2405 operation minus(a) is calculated as subtract('0', a) where the '0'
2406 has the same exponent as the operand.
2407
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002408 >>> ExtendedContext.minus(Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002409 Decimal("-1.3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002410 >>> ExtendedContext.minus(Decimal('-1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002411 Decimal("1.3")
2412 """
2413 return a.__neg__(context=self)
2414
2415 def multiply(self, a, b):
2416 """multiply multiplies two operands.
2417
2418 If either operand is a special value then the general rules apply.
2419 Otherwise, the operands are multiplied together ('long multiplication'),
2420 resulting in a number which may be as long as the sum of the lengths
2421 of the two operands.
2422
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002423 >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002424 Decimal("3.60")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002425 >>> ExtendedContext.multiply(Decimal('7'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002426 Decimal("21")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002427 >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002428 Decimal("0.72")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002429 >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002430 Decimal("-0.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002431 >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002432 Decimal("4.28135971E+11")
2433 """
2434 return a.__mul__(b, context=self)
2435
2436 def normalize(self, a):
Raymond Hettingere0f15812004-07-05 05:36:39 +00002437 """normalize reduces an operand to its simplest form.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002438
2439 Essentially a plus operation with all trailing zeros removed from the
2440 result.
2441
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002442 >>> ExtendedContext.normalize(Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002443 Decimal("2.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002444 >>> ExtendedContext.normalize(Decimal('-2.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002445 Decimal("-2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002446 >>> ExtendedContext.normalize(Decimal('1.200'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002447 Decimal("1.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002448 >>> ExtendedContext.normalize(Decimal('-120'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002449 Decimal("-1.2E+2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002450 >>> ExtendedContext.normalize(Decimal('120.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002451 Decimal("1.2E+2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002452 >>> ExtendedContext.normalize(Decimal('0.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002453 Decimal("0")
2454 """
2455 return a.normalize(context=self)
2456
2457 def plus(self, a):
2458 """Plus corresponds to unary prefix plus in Python.
2459
2460 The operation is evaluated using the same rules as add; the
2461 operation plus(a) is calculated as add('0', a) where the '0'
2462 has the same exponent as the operand.
2463
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002464 >>> ExtendedContext.plus(Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002465 Decimal("1.3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002466 >>> ExtendedContext.plus(Decimal('-1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002467 Decimal("-1.3")
2468 """
2469 return a.__pos__(context=self)
2470
2471 def power(self, a, b, modulo=None):
2472 """Raises a to the power of b, to modulo if given.
2473
2474 The right-hand operand must be a whole number whose integer part (after
2475 any exponent has been applied) has no more than 9 digits and whose
2476 fractional part (if any) is all zeros before any rounding. The operand
2477 may be positive, negative, or zero; if negative, the absolute value of
2478 the power is used, and the left-hand operand is inverted (divided into
2479 1) before use.
2480
2481 If the increased precision needed for the intermediate calculations
2482 exceeds the capabilities of the implementation then an Invalid operation
2483 condition is raised.
2484
2485 If, when raising to a negative power, an underflow occurs during the
2486 division into 1, the operation is not halted at that point but
2487 continues.
2488
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002489 >>> ExtendedContext.power(Decimal('2'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002490 Decimal("8")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002491 >>> ExtendedContext.power(Decimal('2'), Decimal('-3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002492 Decimal("0.125")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002493 >>> ExtendedContext.power(Decimal('1.7'), Decimal('8'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002494 Decimal("69.7575744")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002495 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002496 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002497 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002498 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002499 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002500 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002501 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002502 Decimal("Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002503 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002504 Decimal("Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002505 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002506 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002507 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002508 Decimal("-0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002509 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002510 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002511 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002512 Decimal("-Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002513 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002514 Decimal("Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002515 >>> ExtendedContext.power(Decimal('0'), Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002516 Decimal("NaN")
2517 """
2518 return a.__pow__(b, modulo, context=self)
2519
2520 def quantize(self, a, b):
2521 """Returns a value equal to 'a' (rounded) and having the exponent of 'b'.
2522
2523 The coefficient of the result is derived from that of the left-hand
2524 operand. It may be rounded using the current rounding setting (if the
2525 exponent is being increased), multiplied by a positive power of ten (if
2526 the exponent is being decreased), or is unchanged (if the exponent is
2527 already equal to that of the right-hand operand).
2528
2529 Unlike other operations, if the length of the coefficient after the
2530 quantize operation would be greater than precision then an Invalid
2531 operation condition is raised. This guarantees that, unless there is an
2532 error condition, the exponent of the result of a quantize is always
2533 equal to that of the right-hand operand.
2534
2535 Also unlike other operations, quantize will never raise Underflow, even
2536 if the result is subnormal and inexact.
2537
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002538 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002539 Decimal("2.170")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002540 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002541 Decimal("2.17")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002542 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002543 Decimal("2.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002544 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002545 Decimal("2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002546 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002547 Decimal("0E+1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002548 >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002549 Decimal("-Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002550 >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002551 Decimal("NaN")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002552 >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002553 Decimal("-0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002554 >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002555 Decimal("-0E+5")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002556 >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002557 Decimal("NaN")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002558 >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002559 Decimal("NaN")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002560 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002561 Decimal("217.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002562 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002563 Decimal("217")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002564 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002565 Decimal("2.2E+2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002566 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002567 Decimal("2E+2")
2568 """
2569 return a.quantize(b, context=self)
2570
2571 def remainder(self, a, b):
2572 """Returns the remainder from integer division.
2573
2574 The result is the residue of the dividend after the operation of
2575 calculating integer division as described for divide-integer, rounded to
2576 precision digits if necessary. The sign of the result, if non-zero, is
2577 the same as that of the original dividend.
2578
2579 This operation will fail under the same conditions as integer division
2580 (that is, if integer division on the same two operands would fail, the
2581 remainder cannot be calculated).
2582
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002583 >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002584 Decimal("2.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002585 >>> ExtendedContext.remainder(Decimal('10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002586 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002587 >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002588 Decimal("-1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002589 >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002590 Decimal("0.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002591 >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002592 Decimal("0.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002593 >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002594 Decimal("1.0")
2595 """
2596 return a.__mod__(b, context=self)
2597
2598 def remainder_near(self, a, b):
2599 """Returns to be "a - b * n", where n is the integer nearest the exact
2600 value of "x / b" (if two integers are equally near then the even one
2601 is chosen). If the result is equal to 0 then its sign will be the
2602 sign of a.
2603
2604 This operation will fail under the same conditions as integer division
2605 (that is, if integer division on the same two operands would fail, the
2606 remainder cannot be calculated).
2607
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002608 >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002609 Decimal("-0.9")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002610 >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002611 Decimal("-2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002612 >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002613 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002614 >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002615 Decimal("-1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002616 >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002617 Decimal("0.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002618 >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002619 Decimal("0.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002620 >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002621 Decimal("-0.3")
2622 """
2623 return a.remainder_near(b, context=self)
2624
2625 def same_quantum(self, a, b):
2626 """Returns True if the two operands have the same exponent.
2627
2628 The result is never affected by either the sign or the coefficient of
2629 either operand.
2630
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002631 >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002632 False
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002633 >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002634 True
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002635 >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002636 False
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002637 >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002638 True
2639 """
2640 return a.same_quantum(b)
2641
2642 def sqrt(self, a):
2643 """Returns the square root of a non-negative number to context precision.
2644
2645 If the result must be inexact, it is rounded using the round-half-even
2646 algorithm.
2647
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002648 >>> ExtendedContext.sqrt(Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002649 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002650 >>> ExtendedContext.sqrt(Decimal('-0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002651 Decimal("-0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002652 >>> ExtendedContext.sqrt(Decimal('0.39'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002653 Decimal("0.624499800")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002654 >>> ExtendedContext.sqrt(Decimal('100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002655 Decimal("10")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002656 >>> ExtendedContext.sqrt(Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002657 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002658 >>> ExtendedContext.sqrt(Decimal('1.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002659 Decimal("1.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002660 >>> ExtendedContext.sqrt(Decimal('1.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002661 Decimal("1.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002662 >>> ExtendedContext.sqrt(Decimal('7'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002663 Decimal("2.64575131")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002664 >>> ExtendedContext.sqrt(Decimal('10'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002665 Decimal("3.16227766")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002666 >>> ExtendedContext.prec
Raymond Hettinger6ea48452004-07-03 12:26:21 +00002667 9
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002668 """
2669 return a.sqrt(context=self)
2670
2671 def subtract(self, a, b):
2672 """Return the sum of the two operands.
2673
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002674 >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002675 Decimal("0.23")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002676 >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002677 Decimal("0.00")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002678 >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002679 Decimal("-0.77")
2680 """
2681 return a.__sub__(b, context=self)
2682
2683 def to_eng_string(self, a):
2684 """Converts a number to a string, using scientific notation.
2685
2686 The operation is not affected by the context.
2687 """
2688 return a.to_eng_string(context=self)
2689
2690 def to_sci_string(self, a):
2691 """Converts a number to a string, using scientific notation.
2692
2693 The operation is not affected by the context.
2694 """
2695 return a.__str__(context=self)
2696
2697 def to_integral(self, a):
2698 """Rounds to an integer.
2699
2700 When the operand has a negative exponent, the result is the same
2701 as using the quantize() operation using the given operand as the
2702 left-hand-operand, 1E+0 as the right-hand-operand, and the precision
2703 of the operand as the precision setting, except that no flags will
2704 be set. The rounding mode is taken from the context.
2705
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002706 >>> ExtendedContext.to_integral(Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002707 Decimal("2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002708 >>> ExtendedContext.to_integral(Decimal('100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002709 Decimal("100")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002710 >>> ExtendedContext.to_integral(Decimal('100.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002711 Decimal("100")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002712 >>> ExtendedContext.to_integral(Decimal('101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002713 Decimal("102")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002714 >>> ExtendedContext.to_integral(Decimal('-101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002715 Decimal("-102")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002716 >>> ExtendedContext.to_integral(Decimal('10E+5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002717 Decimal("1.0E+6")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002718 >>> ExtendedContext.to_integral(Decimal('7.89E+77'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002719 Decimal("7.89E+77")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002720 >>> ExtendedContext.to_integral(Decimal('-Inf'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002721 Decimal("-Infinity")
2722 """
2723 return a.to_integral(context=self)
2724
2725class _WorkRep(object):
2726 __slots__ = ('sign','int','exp')
2727 # sign: -1 None 1
2728 # int: list
2729 # exp: None, int, or string
2730
2731 def __init__(self, value=None):
2732 if value is None:
2733 self.sign = None
2734 self.int = []
2735 self.exp = None
2736 if isinstance(value, Decimal):
2737 if value._sign:
2738 self.sign = -1
2739 else:
2740 self.sign = 1
2741 self.int = list(value._int)
2742 self.exp = value._exp
2743 if isinstance(value, tuple):
2744 self.sign = value[0]
2745 self.int = value[1]
2746 self.exp = value[2]
2747
2748 def __repr__(self):
2749 return "(%r, %r, %r)" % (self.sign, self.int, self.exp)
2750
2751 __str__ = __repr__
2752
2753 def __neg__(self):
2754 if self.sign == 1:
2755 return _WorkRep( (-1, self.int, self.exp) )
2756 else:
2757 return _WorkRep( (1, self.int, self.exp) )
2758
2759 def __abs__(self):
2760 if self.sign == -1:
2761 return -self
2762 else:
2763 return self
2764
2765 def __cmp__(self, other):
2766 if self.exp != other.exp:
2767 raise ValueError("Operands not normalized: %r, %r" % (self, other))
2768 if self.sign != other.sign:
2769 if self.sign == -1:
2770 return -1
2771 else:
2772 return 1
2773 if self.sign == -1:
2774 direction = -1
2775 else:
2776 direction = 1
2777 int1 = self.int
2778 int2 = other.int
2779 if len(int1) > len(int2):
2780 return direction * 1
2781 if len(int1) < len(int2):
2782 return direction * -1
2783 for i in xrange(len(int1)):
2784 if int1[i] > int2[i]:
2785 return direction * 1
2786 if int1[i] < int2[i]:
2787 return direction * -1
2788 return 0
2789
2790 def _increment(self):
2791 curspot = len(self.int) - 1
2792 self.int[curspot]+= 1
2793 while (self.int[curspot] >= 10):
2794 self.int[curspot] -= 10
2795 if curspot == 0:
2796 self.int[0:0] = [1]
2797 break
2798 self.int[curspot-1] += 1
2799 curspot -= 1
2800
2801 def subtract(self, alist):
2802 """Subtract a list from the current int (in place).
2803
2804 It is assured that (len(list) = len(self.int) and list < self.int) or
2805 len(list) = len(self.int)-1
2806 (i.e. that int(join(list)) < int(join(self.int)))
2807 """
2808
2809 selfint = self.int
2810 selfint.reverse()
2811 alist.reverse()
2812
2813 carry = 0
2814 for x in xrange(len(alist)):
2815 selfint[x] -= alist[x] + carry
2816 if selfint[x] < 0:
2817 carry = 1
2818 selfint[x] += 10
2819 else:
2820 carry = 0
2821 if carry:
2822 selfint[x+1] -= 1
2823 last = len(selfint)-1
2824 while len(selfint) > 1 and selfint[last] == 0:
2825 last -= 1
2826 if last == 0:
2827 break
2828 selfint[last+1:]=[]
2829 selfint.reverse()
2830 alist.reverse()
2831 return
2832
2833
2834def _normalize(op1, op2, shouldround = 0, prec = 0):
2835 """Normalizes op1, op2 to have the same exp and length of coefficient.
2836
2837 Done during addition.
2838 """
2839 # Yes, the exponent is a long, but the difference between exponents
2840 # must be an int-- otherwise you'd get a big memory problem.
2841 numdigits = int(op1.exp - op2.exp)
2842 if numdigits < 0:
2843 numdigits = -numdigits
2844 tmp = op2
2845 other = op1
2846 else:
2847 tmp = op1
2848 other = op2
2849
2850 if shouldround and numdigits > len(other.int) + prec + 1 -len(tmp.int):
2851 # If the difference in adjusted exps is > prec+1, we know
2852 # other is insignificant, so might as well put a 1 after the precision.
2853 # (since this is only for addition.) Also stops MemoryErrors.
2854
2855 extend = prec + 2 -len(tmp.int)
2856 if extend <= 0:
2857 extend = 1
2858 tmp.int.extend([0]*extend)
2859 tmp.exp -= extend
2860 other.int[:] = [0]*(len(tmp.int)-1)+[1]
2861 other.exp = tmp.exp
2862 return op1, op2
2863
2864 tmp.int.extend([0] * numdigits)
2865 tmp.exp = tmp.exp - numdigits
2866 numdigits = len(op1.int) - len(op2.int)
2867 # numdigits != 0 => They have the same exponent, but not the same length
2868 # of the coefficient.
2869 if numdigits < 0:
2870 numdigits = -numdigits
2871 tmp = op1
2872 else:
2873 tmp = op2
2874 tmp.int[0:0] = [0] * numdigits
2875 return op1, op2
2876
2877def _adjust_coefficients(op1, op2):
2878 """Adjust op1, op2 so that op2.int+[0] > op1.int >= op2.int.
2879
2880 Returns the adjusted op1, op2 as well as the change in op1.exp-op2.exp.
2881
2882 Used on _WorkRep instances during division.
2883 """
2884 adjust = 0
2885 #If op1 is smaller, get it to same size
2886 if len(op2.int) > len(op1.int):
2887 diff = len(op2.int) - len(op1.int)
2888 op1.int.extend([0]*diff)
2889 op1.exp -= diff
2890 adjust = diff
2891
2892 #Same length, wrong order
2893 if len(op1.int) == len(op2.int) and op1.int < op2.int:
2894 op1.int.append(0)
2895 op1.exp -= 1
2896 adjust+= 1
2897 return op1, op2, adjust
2898
2899 if len(op1.int) > len(op2.int) + 1:
2900 diff = len(op1.int) - len(op2.int) - 1
2901 op2.int.extend([0]*diff)
2902 op2.exp -= diff
2903 adjust -= diff
2904
2905 if len(op1.int) == len(op2.int)+1 and op1.int > op2.int:
2906
2907 op2.int.append(0)
2908 op2.exp -= 1
2909 adjust -= 1
2910 return op1, op2, adjust
2911
2912##### Helper Functions ########################################
2913
2914_infinity_map = {
2915 'inf' : 1,
2916 'infinity' : 1,
2917 '+inf' : 1,
2918 '+infinity' : 1,
2919 '-inf' : -1,
2920 '-infinity' : -1
2921}
2922
Raymond Hettinger0ea241e2004-07-04 13:53:24 +00002923def _isinfinity(num):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002924 """Determines whether a string or float is infinity.
2925
Raymond Hettinger0ea241e2004-07-04 13:53:24 +00002926 +1 for negative infinity; 0 for finite ; +1 for positive infinity
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002927 """
2928 num = str(num).lower()
2929 return _infinity_map.get(num, 0)
2930
Raymond Hettinger0ea241e2004-07-04 13:53:24 +00002931def _isnan(num):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002932 """Determines whether a string or float is NaN
2933
2934 (1, sign, diagnostic info as string) => NaN
2935 (2, sign, diagnostic info as string) => sNaN
2936 0 => not a NaN
2937 """
2938 num = str(num).lower()
2939 if not num:
2940 return 0
2941
2942 #get the sign, get rid of trailing [+-]
2943 sign = 0
2944 if num[0] == '+':
2945 num = num[1:]
2946 elif num[0] == '-': #elif avoids '+-nan'
2947 num = num[1:]
2948 sign = 1
2949
2950 if num.startswith('nan'):
2951 if len(num) > 3 and not num[3:].isdigit(): #diagnostic info
2952 return 0
2953 return (1, sign, num[3:].lstrip('0'))
2954 if num.startswith('snan'):
2955 if len(num) > 4 and not num[4:].isdigit():
2956 return 0
2957 return (2, sign, num[4:].lstrip('0'))
2958 return 0
2959
2960
2961##### Setup Specific Contexts ################################
2962
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002963_basic_traps = dict.fromkeys(Signals, 1)
2964_basic_traps.update({Inexact:0, Rounded:0, Subnormal:0})
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002965
2966# The default context prototype used by Context()
2967# Is mutable, so than new contexts can have different default values
2968
2969DefaultContext = Context(
Raymond Hettinger6ea48452004-07-03 12:26:21 +00002970 prec=28, rounding=ROUND_HALF_EVEN,
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002971 trap_enablers=dict.fromkeys(Signals, 0),
2972 flags=None,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002973 _rounding_decision=ALWAYS_ROUND,
Raymond Hettinger0ea241e2004-07-04 13:53:24 +00002974 Emax=DEFAULT_MAX_EXPONENT,
Raymond Hettingere0f15812004-07-05 05:36:39 +00002975 Emin=DEFAULT_MIN_EXPONENT,
2976 capitals=1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002977)
Raymond Hettingerca3cc2f2004-07-05 18:48:22 +00002978DefaultContext.trap_enablers.update({ConversionSyntax : 1})
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002979
2980# Pre-made alternate contexts offered by the specification
2981# Don't change these; the user should be able to select these
2982# contexts and be able to reproduce results from other implementations
2983# of the spec.
2984
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002985BasicContext = Context(
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002986 prec=9, rounding=ROUND_HALF_UP,
2987 trap_enablers=_basic_traps,
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002988 flags=None,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002989 _rounding_decision=ALWAYS_ROUND,
2990)
2991
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002992ExtendedContext = Context(
Raymond Hettinger6ea48452004-07-03 12:26:21 +00002993 prec=9, rounding=ROUND_HALF_EVEN,
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002994 trap_enablers=dict.fromkeys(Signals, 0),
2995 flags=None,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002996 _rounding_decision=ALWAYS_ROUND,
2997)
2998
2999
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00003000##### Useful Constants (internal use only) ####################
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00003001
3002#Reusable defaults
3003Inf = Decimal('Inf')
3004negInf = Decimal('-Inf')
3005
3006#Infsign[sign] is infinity w/ that sign
3007Infsign = (Inf, negInf)
3008
3009NaN = Decimal('NaN')
3010
3011
3012##### crud for parsing strings #################################
3013import re
3014
3015# There's an optional sign at the start, and an optional exponent
3016# at the end. The exponent has an optional sign and at least one
3017# digit. In between, must have either at least one digit followed
3018# by an optional fraction, or a decimal point followed by at least
3019# one digit. Yuck.
3020
3021_parser = re.compile(r"""
3022# \s*
3023 (?P<sign>[-+])?
3024 (
3025 (?P<int>\d+) (\. (?P<frac>\d*))?
3026 |
3027 \. (?P<onlyfrac>\d+)
3028 )
3029 ([eE](?P<exp>[-+]? \d+))?
3030# \s*
3031 $
3032""", re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces.
3033
3034del re
3035
3036# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly
3037
3038def _string2exact(s):
3039 m = _parser(s)
3040 if m is None:
3041 raise ValueError("invalid literal for Decimal: %r" % s)
3042
3043 if m.group('sign') == "-":
3044 sign = 1
3045 else:
3046 sign = 0
3047
3048 exp = m.group('exp')
3049 if exp is None:
3050 exp = 0
3051 else:
3052 exp = int(exp)
3053
3054 intpart = m.group('int')
3055 if intpart is None:
3056 intpart = ""
3057 fracpart = m.group('onlyfrac')
3058 else:
3059 fracpart = m.group('frac')
3060 if fracpart is None:
3061 fracpart = ""
3062
3063 exp -= len(fracpart)
3064
3065 mantissa = intpart + fracpart
3066 tmp = map(int, mantissa)
3067 backup = tmp
3068 while tmp and tmp[0] == 0:
3069 del tmp[0]
3070
3071 # It's a zero
3072 if not tmp:
3073 if backup:
3074 return (sign, tuple(backup), exp)
3075 return (sign, (0,), exp)
3076 mantissa = tuple(tmp)
3077
3078 return (sign, mantissa, exp)
3079
3080
3081if __name__ == '__main__':
3082 import doctest, sys
3083 doctest.testmod(sys.modules[__name__])