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