blob: b8c1322f6cbd39887b48962812852590fe88c8f9 [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 Hettingerd9c0a7a2004-07-03 10:02:28 +00002157 def clear_flags(self):
2158 """Reset all flags to zero"""
2159 for flag in self.flags:
2160 self.flag = 0
2161
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002162 def copy(self):
2163 """Returns a copy from self."""
2164 nc = Context(self.prec, self.rounding, self.trap_enablers, self.flags,
2165 self._rounding_decision, self.Emin, self.Emax,
2166 self.capitals, self._clamp, self._ignored_flags)
2167 return nc
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002168 __copy__ = copy
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002169
2170 def _raise_error(self, error, explanation = None, *args):
2171 """Handles an error
2172
2173 If the flag is in _ignored_flags, returns the default response.
2174 Otherwise, it increments the flag, then, if the corresponding
2175 trap_enabler is set, it reaises the exception. Otherwise, it returns
2176 the default value after incrementing the flag.
2177 """
2178 if error in self._ignored_flags:
2179 #Don't touch the flag
2180 return error().handle(self, *args)
2181
2182 self.flags[error] += 1
2183 if not self.trap_enablers[error]:
2184 #The errors define how to handle themselves.
2185 return error().handle(self, *args)
2186
2187 # Errors should only be risked on copies of the context
2188 #self._ignored_flags = []
2189 raise error, explanation
2190
2191 def _ignore_all_flags(self):
2192 """Ignore all flags, if they are raised"""
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002193 return self._ignore_flags(*Signals)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002194
2195 def _ignore_flags(self, *flags):
2196 """Ignore the flags, if they are raised"""
2197 # Do not mutate-- This way, copies of a context leave the original
2198 # alone.
2199 self._ignored_flags = (self._ignored_flags + list(flags))
2200 return list(flags)
2201
2202 def _regard_flags(self, *flags):
2203 """Stop ignoring the flags, if they are raised"""
2204 if flags and isinstance(flags[0], (tuple,list)):
2205 flags = flags[0]
2206 for flag in flags:
2207 self._ignored_flags.remove(flag)
2208
2209 def Etiny(self):
2210 """Returns Etiny (= Emin - prec + 1)"""
2211 return int(self.Emin - self.prec + 1)
2212
2213 def Etop(self):
2214 """Returns maximum exponent (= Emin - prec + 1)"""
2215 return int(self.Emax - self.prec + 1)
2216
2217 def _set_rounding_decision(self, type):
2218 """Sets the rounding decision.
2219
2220 Sets the rounding decision, and returns the current (previous)
2221 rounding decision. Often used like:
2222
2223 context = context.copy()
2224 # That so you don't change the calling context
2225 # if an error occurs in the middle (say DivisionImpossible is raised).
2226
2227 rounding = context._set_rounding_decision(NEVER_ROUND)
2228 instance = instance / Decimal(2)
2229 context._set_rounding_decision(rounding)
2230
2231 This will make it not round for that operation.
2232 """
2233
2234 rounding = self._rounding_decision
2235 self._rounding_decision = type
2236 return rounding
2237
2238 def _set_rounding(self, type):
2239 """Sets the rounding type.
2240
2241 Sets the rounding type, and returns the current (previous)
2242 rounding type. Often used like:
2243
2244 context = context.copy()
2245 # so you don't change the calling context
2246 # if an error occurs in the middle.
2247 rounding = context._set_rounding(ROUND_UP)
2248 val = self.__sub__(other, context=context)
2249 context._set_rounding(rounding)
2250
2251 This will make it round up for that operation.
2252 """
2253 rounding = self.rounding
2254 self.rounding= type
2255 return rounding
2256
2257 def create_decimal(self, num):
2258 """Creates a new Decimal instance but using self as context."""
2259 d = Decimal(num, context=self)
2260 return d._fix(context=self)
2261
2262 #Methods
2263 def abs(self, a):
2264 """Returns the absolute value of the operand.
2265
2266 If the operand is negative, the result is the same as using the minus
2267 operation on the operand. Otherwise, the result is the same as using
2268 the plus operation on the operand.
2269
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002270 >>> ExtendedContext.abs(Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002271 Decimal("2.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002272 >>> ExtendedContext.abs(Decimal('-100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002273 Decimal("100")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002274 >>> ExtendedContext.abs(Decimal('101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002275 Decimal("101.5")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002276 >>> ExtendedContext.abs(Decimal('-101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002277 Decimal("101.5")
2278 """
2279 return a.__abs__(context=self)
2280
2281 def add(self, a, b):
2282 """Return the sum of the two operands.
2283
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002284 >>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002285 Decimal("19.00")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002286 >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002287 Decimal("1.02E+4")
2288 """
2289 return a.__add__(b, context=self)
2290
2291 def _apply(self, a):
2292 return str(a._fix(context=self))
2293
2294 def compare(self, a, b):
2295 """Compares values numerically.
2296
2297 If the signs of the operands differ, a value representing each operand
2298 ('-1' if the operand is less than zero, '0' if the operand is zero or
2299 negative zero, or '1' if the operand is greater than zero) is used in
2300 place of that operand for the comparison instead of the actual
2301 operand.
2302
2303 The comparison is then effected by subtracting the second operand from
2304 the first and then returning a value according to the result of the
2305 subtraction: '-1' if the result is less than zero, '0' if the result is
2306 zero or negative zero, or '1' if the result is greater than zero.
2307
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002308 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002309 Decimal("-1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002310 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002311 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002312 >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002313 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002314 >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002315 Decimal("1")
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('-3'), Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002319 Decimal("-1")
2320 """
2321 return a.compare(b, context=self)
2322
2323 def divide(self, a, b):
2324 """Decimal division in a specified context.
2325
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002326 >>> ExtendedContext.divide(Decimal('1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002327 Decimal("0.333333333")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002328 >>> ExtendedContext.divide(Decimal('2'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002329 Decimal("0.666666667")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002330 >>> ExtendedContext.divide(Decimal('5'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002331 Decimal("2.5")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002332 >>> ExtendedContext.divide(Decimal('1'), Decimal('10'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002333 Decimal("0.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002334 >>> ExtendedContext.divide(Decimal('12'), Decimal('12'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002335 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002336 >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002337 Decimal("4.00")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002338 >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002339 Decimal("1.20")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002340 >>> ExtendedContext.divide(Decimal('1000'), Decimal('100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002341 Decimal("10")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002342 >>> ExtendedContext.divide(Decimal('1000'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002343 Decimal("1000")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002344 >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002345 Decimal("1.20E+6")
2346 """
2347 return a.__div__(b, context=self)
2348
2349 def divide_int(self, a, b):
2350 """Divides two numbers and returns the integer part of the result.
2351
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002352 >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002353 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002354 >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002355 Decimal("3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002356 >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002357 Decimal("3")
2358 """
2359 return a.__floordiv__(b, context=self)
2360
2361 def divmod(self, a, b):
2362 return a.__divmod__(b, context=self)
2363
2364 def max(self, a,b):
2365 """max compares two values numerically and returns the maximum.
2366
2367 If either operand is a NaN then the general rules apply.
2368 Otherwise, the operands are compared as as though by the compare
2369 operation. If they are numerically equal then the left-hand operand
2370 is chosen as the result. Otherwise the maximum (closer to positive
2371 infinity) of the two operands is chosen as the result.
2372
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002373 >>> ExtendedContext.max(Decimal('3'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002374 Decimal("3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002375 >>> ExtendedContext.max(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002376 Decimal("3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002377 >>> ExtendedContext.max(Decimal('1.0'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002378 Decimal("1.0")
2379 """
2380 return a.max(b, context=self)
2381
2382 def min(self, a,b):
2383 """min compares two values numerically and returns the minimum.
2384
2385 If either operand is a NaN then the general rules apply.
2386 Otherwise, the operands are compared as as though by the compare
2387 operation. If they are numerically equal then the left-hand operand
2388 is chosen as the result. Otherwise the minimum (closer to negative
2389 infinity) of the two operands is chosen as the result.
2390
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002391 >>> ExtendedContext.min(Decimal('3'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002392 Decimal("2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002393 >>> ExtendedContext.min(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002394 Decimal("-10")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002395 >>> ExtendedContext.min(Decimal('1.0'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002396 Decimal("1.0")
2397 """
2398 return a.min(b, context=self)
2399
2400 def minus(self, a):
2401 """Minus corresponds to unary prefix minus in Python.
2402
2403 The operation is evaluated using the same rules as subtract; the
2404 operation minus(a) is calculated as subtract('0', a) where the '0'
2405 has the same exponent as the operand.
2406
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002407 >>> ExtendedContext.minus(Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002408 Decimal("-1.3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002409 >>> ExtendedContext.minus(Decimal('-1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002410 Decimal("1.3")
2411 """
2412 return a.__neg__(context=self)
2413
2414 def multiply(self, a, b):
2415 """multiply multiplies two operands.
2416
2417 If either operand is a special value then the general rules apply.
2418 Otherwise, the operands are multiplied together ('long multiplication'),
2419 resulting in a number which may be as long as the sum of the lengths
2420 of the two operands.
2421
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002422 >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002423 Decimal("3.60")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002424 >>> ExtendedContext.multiply(Decimal('7'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002425 Decimal("21")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002426 >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002427 Decimal("0.72")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002428 >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002429 Decimal("-0.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002430 >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002431 Decimal("4.28135971E+11")
2432 """
2433 return a.__mul__(b, context=self)
2434
2435 def normalize(self, a):
2436 """normalize reduces its operand to its simplest form.
2437
2438 Essentially a plus operation with all trailing zeros removed from the
2439 result.
2440
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002441 >>> ExtendedContext.normalize(Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002442 Decimal("2.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002443 >>> ExtendedContext.normalize(Decimal('-2.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002444 Decimal("-2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002445 >>> ExtendedContext.normalize(Decimal('1.200'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002446 Decimal("1.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002447 >>> ExtendedContext.normalize(Decimal('-120'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002448 Decimal("-1.2E+2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002449 >>> ExtendedContext.normalize(Decimal('120.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002450 Decimal("1.2E+2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002451 >>> ExtendedContext.normalize(Decimal('0.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002452 Decimal("0")
2453 """
2454 return a.normalize(context=self)
2455
2456 def plus(self, a):
2457 """Plus corresponds to unary prefix plus in Python.
2458
2459 The operation is evaluated using the same rules as add; the
2460 operation plus(a) is calculated as add('0', a) where the '0'
2461 has the same exponent as the operand.
2462
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002463 >>> ExtendedContext.plus(Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002464 Decimal("1.3")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002465 >>> ExtendedContext.plus(Decimal('-1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002466 Decimal("-1.3")
2467 """
2468 return a.__pos__(context=self)
2469
2470 def power(self, a, b, modulo=None):
2471 """Raises a to the power of b, to modulo if given.
2472
2473 The right-hand operand must be a whole number whose integer part (after
2474 any exponent has been applied) has no more than 9 digits and whose
2475 fractional part (if any) is all zeros before any rounding. The operand
2476 may be positive, negative, or zero; if negative, the absolute value of
2477 the power is used, and the left-hand operand is inverted (divided into
2478 1) before use.
2479
2480 If the increased precision needed for the intermediate calculations
2481 exceeds the capabilities of the implementation then an Invalid operation
2482 condition is raised.
2483
2484 If, when raising to a negative power, an underflow occurs during the
2485 division into 1, the operation is not halted at that point but
2486 continues.
2487
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002488 >>> ExtendedContext.power(Decimal('2'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002489 Decimal("8")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002490 >>> ExtendedContext.power(Decimal('2'), Decimal('-3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002491 Decimal("0.125")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002492 >>> ExtendedContext.power(Decimal('1.7'), Decimal('8'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002493 Decimal("69.7575744")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002494 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002495 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002496 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('-1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002497 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002498 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002499 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002500 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002501 Decimal("Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002502 >>> ExtendedContext.power(Decimal('Infinity'), Decimal('2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002503 Decimal("Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002504 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002505 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002506 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('-1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002507 Decimal("-0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002508 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002509 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002510 >>> ExtendedContext.power(Decimal('-Infinity'), Decimal('1'))
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("Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002514 >>> ExtendedContext.power(Decimal('0'), Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002515 Decimal("NaN")
2516 """
2517 return a.__pow__(b, modulo, context=self)
2518
2519 def quantize(self, a, b):
2520 """Returns a value equal to 'a' (rounded) and having the exponent of 'b'.
2521
2522 The coefficient of the result is derived from that of the left-hand
2523 operand. It may be rounded using the current rounding setting (if the
2524 exponent is being increased), multiplied by a positive power of ten (if
2525 the exponent is being decreased), or is unchanged (if the exponent is
2526 already equal to that of the right-hand operand).
2527
2528 Unlike other operations, if the length of the coefficient after the
2529 quantize operation would be greater than precision then an Invalid
2530 operation condition is raised. This guarantees that, unless there is an
2531 error condition, the exponent of the result of a quantize is always
2532 equal to that of the right-hand operand.
2533
2534 Also unlike other operations, quantize will never raise Underflow, even
2535 if the result is subnormal and inexact.
2536
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002537 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002538 Decimal("2.170")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002539 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002540 Decimal("2.17")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002541 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002542 Decimal("2.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002543 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002544 Decimal("2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002545 >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002546 Decimal("0E+1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002547 >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002548 Decimal("-Infinity")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002549 >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002550 Decimal("NaN")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002551 >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002552 Decimal("-0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002553 >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002554 Decimal("-0E+5")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002555 >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002556 Decimal("NaN")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002557 >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002558 Decimal("NaN")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002559 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002560 Decimal("217.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002561 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002562 Decimal("217")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002563 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002564 Decimal("2.2E+2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002565 >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002566 Decimal("2E+2")
2567 """
2568 return a.quantize(b, context=self)
2569
2570 def remainder(self, a, b):
2571 """Returns the remainder from integer division.
2572
2573 The result is the residue of the dividend after the operation of
2574 calculating integer division as described for divide-integer, rounded to
2575 precision digits if necessary. The sign of the result, if non-zero, is
2576 the same as that of the original dividend.
2577
2578 This operation will fail under the same conditions as integer division
2579 (that is, if integer division on the same two operands would fail, the
2580 remainder cannot be calculated).
2581
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002582 >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002583 Decimal("2.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002584 >>> ExtendedContext.remainder(Decimal('10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002585 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002586 >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002587 Decimal("-1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002588 >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002589 Decimal("0.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002590 >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002591 Decimal("0.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002592 >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002593 Decimal("1.0")
2594 """
2595 return a.__mod__(b, context=self)
2596
2597 def remainder_near(self, a, b):
2598 """Returns to be "a - b * n", where n is the integer nearest the exact
2599 value of "x / b" (if two integers are equally near then the even one
2600 is chosen). If the result is equal to 0 then its sign will be the
2601 sign of a.
2602
2603 This operation will fail under the same conditions as integer division
2604 (that is, if integer division on the same two operands would fail, the
2605 remainder cannot be calculated).
2606
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002607 >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002608 Decimal("-0.9")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002609 >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002610 Decimal("-2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002611 >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002612 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002613 >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002614 Decimal("-1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002615 >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002616 Decimal("0.2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002617 >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002618 Decimal("0.1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002619 >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002620 Decimal("-0.3")
2621 """
2622 return a.remainder_near(b, context=self)
2623
2624 def same_quantum(self, a, b):
2625 """Returns True if the two operands have the same exponent.
2626
2627 The result is never affected by either the sign or the coefficient of
2628 either operand.
2629
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002630 >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002631 False
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002632 >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002633 True
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002634 >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002635 False
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002636 >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002637 True
2638 """
2639 return a.same_quantum(b)
2640
2641 def sqrt(self, a):
2642 """Returns the square root of a non-negative number to context precision.
2643
2644 If the result must be inexact, it is rounded using the round-half-even
2645 algorithm.
2646
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002647 >>> ExtendedContext.sqrt(Decimal('0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002648 Decimal("0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002649 >>> ExtendedContext.sqrt(Decimal('-0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002650 Decimal("-0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002651 >>> ExtendedContext.sqrt(Decimal('0.39'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002652 Decimal("0.624499800")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002653 >>> ExtendedContext.sqrt(Decimal('100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002654 Decimal("10")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002655 >>> ExtendedContext.sqrt(Decimal('1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002656 Decimal("1")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002657 >>> ExtendedContext.sqrt(Decimal('1.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002658 Decimal("1.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002659 >>> ExtendedContext.sqrt(Decimal('1.00'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002660 Decimal("1.0")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002661 >>> ExtendedContext.sqrt(Decimal('7'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002662 Decimal("2.64575131")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002663 >>> ExtendedContext.sqrt(Decimal('10'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002664 Decimal("3.16227766")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002665 >>> ExtendedContext.prec
Raymond Hettinger6ea48452004-07-03 12:26:21 +00002666 9
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002667 """
2668 return a.sqrt(context=self)
2669
2670 def subtract(self, a, b):
2671 """Return the sum of the two operands.
2672
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002673 >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002674 Decimal("0.23")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002675 >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002676 Decimal("0.00")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002677 >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002678 Decimal("-0.77")
2679 """
2680 return a.__sub__(b, context=self)
2681
2682 def to_eng_string(self, a):
2683 """Converts a number to a string, using scientific notation.
2684
2685 The operation is not affected by the context.
2686 """
2687 return a.to_eng_string(context=self)
2688
2689 def to_sci_string(self, a):
2690 """Converts a number to a string, using scientific notation.
2691
2692 The operation is not affected by the context.
2693 """
2694 return a.__str__(context=self)
2695
2696 def to_integral(self, a):
2697 """Rounds to an integer.
2698
2699 When the operand has a negative exponent, the result is the same
2700 as using the quantize() operation using the given operand as the
2701 left-hand-operand, 1E+0 as the right-hand-operand, and the precision
2702 of the operand as the precision setting, except that no flags will
2703 be set. The rounding mode is taken from the context.
2704
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002705 >>> ExtendedContext.to_integral(Decimal('2.1'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002706 Decimal("2")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002707 >>> ExtendedContext.to_integral(Decimal('100'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002708 Decimal("100")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002709 >>> ExtendedContext.to_integral(Decimal('100.0'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002710 Decimal("100")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002711 >>> ExtendedContext.to_integral(Decimal('101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002712 Decimal("102")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002713 >>> ExtendedContext.to_integral(Decimal('-101.5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002714 Decimal("-102")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002715 >>> ExtendedContext.to_integral(Decimal('10E+5'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002716 Decimal("1.0E+6")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002717 >>> ExtendedContext.to_integral(Decimal('7.89E+77'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002718 Decimal("7.89E+77")
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002719 >>> ExtendedContext.to_integral(Decimal('-Inf'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002720 Decimal("-Infinity")
2721 """
2722 return a.to_integral(context=self)
2723
2724class _WorkRep(object):
2725 __slots__ = ('sign','int','exp')
2726 # sign: -1 None 1
2727 # int: list
2728 # exp: None, int, or string
2729
2730 def __init__(self, value=None):
2731 if value is None:
2732 self.sign = None
2733 self.int = []
2734 self.exp = None
2735 if isinstance(value, Decimal):
2736 if value._sign:
2737 self.sign = -1
2738 else:
2739 self.sign = 1
2740 self.int = list(value._int)
2741 self.exp = value._exp
2742 if isinstance(value, tuple):
2743 self.sign = value[0]
2744 self.int = value[1]
2745 self.exp = value[2]
2746
2747 def __repr__(self):
2748 return "(%r, %r, %r)" % (self.sign, self.int, self.exp)
2749
2750 __str__ = __repr__
2751
2752 def __neg__(self):
2753 if self.sign == 1:
2754 return _WorkRep( (-1, self.int, self.exp) )
2755 else:
2756 return _WorkRep( (1, self.int, self.exp) )
2757
2758 def __abs__(self):
2759 if self.sign == -1:
2760 return -self
2761 else:
2762 return self
2763
2764 def __cmp__(self, other):
2765 if self.exp != other.exp:
2766 raise ValueError("Operands not normalized: %r, %r" % (self, other))
2767 if self.sign != other.sign:
2768 if self.sign == -1:
2769 return -1
2770 else:
2771 return 1
2772 if self.sign == -1:
2773 direction = -1
2774 else:
2775 direction = 1
2776 int1 = self.int
2777 int2 = other.int
2778 if len(int1) > len(int2):
2779 return direction * 1
2780 if len(int1) < len(int2):
2781 return direction * -1
2782 for i in xrange(len(int1)):
2783 if int1[i] > int2[i]:
2784 return direction * 1
2785 if int1[i] < int2[i]:
2786 return direction * -1
2787 return 0
2788
2789 def _increment(self):
2790 curspot = len(self.int) - 1
2791 self.int[curspot]+= 1
2792 while (self.int[curspot] >= 10):
2793 self.int[curspot] -= 10
2794 if curspot == 0:
2795 self.int[0:0] = [1]
2796 break
2797 self.int[curspot-1] += 1
2798 curspot -= 1
2799
2800 def subtract(self, alist):
2801 """Subtract a list from the current int (in place).
2802
2803 It is assured that (len(list) = len(self.int) and list < self.int) or
2804 len(list) = len(self.int)-1
2805 (i.e. that int(join(list)) < int(join(self.int)))
2806 """
2807
2808 selfint = self.int
2809 selfint.reverse()
2810 alist.reverse()
2811
2812 carry = 0
2813 for x in xrange(len(alist)):
2814 selfint[x] -= alist[x] + carry
2815 if selfint[x] < 0:
2816 carry = 1
2817 selfint[x] += 10
2818 else:
2819 carry = 0
2820 if carry:
2821 selfint[x+1] -= 1
2822 last = len(selfint)-1
2823 while len(selfint) > 1 and selfint[last] == 0:
2824 last -= 1
2825 if last == 0:
2826 break
2827 selfint[last+1:]=[]
2828 selfint.reverse()
2829 alist.reverse()
2830 return
2831
2832
2833def _normalize(op1, op2, shouldround = 0, prec = 0):
2834 """Normalizes op1, op2 to have the same exp and length of coefficient.
2835
2836 Done during addition.
2837 """
2838 # Yes, the exponent is a long, but the difference between exponents
2839 # must be an int-- otherwise you'd get a big memory problem.
2840 numdigits = int(op1.exp - op2.exp)
2841 if numdigits < 0:
2842 numdigits = -numdigits
2843 tmp = op2
2844 other = op1
2845 else:
2846 tmp = op1
2847 other = op2
2848
2849 if shouldround and numdigits > len(other.int) + prec + 1 -len(tmp.int):
2850 # If the difference in adjusted exps is > prec+1, we know
2851 # other is insignificant, so might as well put a 1 after the precision.
2852 # (since this is only for addition.) Also stops MemoryErrors.
2853
2854 extend = prec + 2 -len(tmp.int)
2855 if extend <= 0:
2856 extend = 1
2857 tmp.int.extend([0]*extend)
2858 tmp.exp -= extend
2859 other.int[:] = [0]*(len(tmp.int)-1)+[1]
2860 other.exp = tmp.exp
2861 return op1, op2
2862
2863 tmp.int.extend([0] * numdigits)
2864 tmp.exp = tmp.exp - numdigits
2865 numdigits = len(op1.int) - len(op2.int)
2866 # numdigits != 0 => They have the same exponent, but not the same length
2867 # of the coefficient.
2868 if numdigits < 0:
2869 numdigits = -numdigits
2870 tmp = op1
2871 else:
2872 tmp = op2
2873 tmp.int[0:0] = [0] * numdigits
2874 return op1, op2
2875
2876def _adjust_coefficients(op1, op2):
2877 """Adjust op1, op2 so that op2.int+[0] > op1.int >= op2.int.
2878
2879 Returns the adjusted op1, op2 as well as the change in op1.exp-op2.exp.
2880
2881 Used on _WorkRep instances during division.
2882 """
2883 adjust = 0
2884 #If op1 is smaller, get it to same size
2885 if len(op2.int) > len(op1.int):
2886 diff = len(op2.int) - len(op1.int)
2887 op1.int.extend([0]*diff)
2888 op1.exp -= diff
2889 adjust = diff
2890
2891 #Same length, wrong order
2892 if len(op1.int) == len(op2.int) and op1.int < op2.int:
2893 op1.int.append(0)
2894 op1.exp -= 1
2895 adjust+= 1
2896 return op1, op2, adjust
2897
2898 if len(op1.int) > len(op2.int) + 1:
2899 diff = len(op1.int) - len(op2.int) - 1
2900 op2.int.extend([0]*diff)
2901 op2.exp -= diff
2902 adjust -= diff
2903
2904 if len(op1.int) == len(op2.int)+1 and op1.int > op2.int:
2905
2906 op2.int.append(0)
2907 op2.exp -= 1
2908 adjust -= 1
2909 return op1, op2, adjust
2910
2911##### Helper Functions ########################################
2912
2913_infinity_map = {
2914 'inf' : 1,
2915 'infinity' : 1,
2916 '+inf' : 1,
2917 '+infinity' : 1,
2918 '-inf' : -1,
2919 '-infinity' : -1
2920}
2921
2922def isinfinity(num):
2923 """Determines whether a string or float is infinity.
2924
2925 +1 for positive infinity; 0 for finite ; +1 for positive infinity
2926 """
2927 num = str(num).lower()
2928 return _infinity_map.get(num, 0)
2929
2930def isnan(num):
2931 """Determines whether a string or float is NaN
2932
2933 (1, sign, diagnostic info as string) => NaN
2934 (2, sign, diagnostic info as string) => sNaN
2935 0 => not a NaN
2936 """
2937 num = str(num).lower()
2938 if not num:
2939 return 0
2940
2941 #get the sign, get rid of trailing [+-]
2942 sign = 0
2943 if num[0] == '+':
2944 num = num[1:]
2945 elif num[0] == '-': #elif avoids '+-nan'
2946 num = num[1:]
2947 sign = 1
2948
2949 if num.startswith('nan'):
2950 if len(num) > 3 and not num[3:].isdigit(): #diagnostic info
2951 return 0
2952 return (1, sign, num[3:].lstrip('0'))
2953 if num.startswith('snan'):
2954 if len(num) > 4 and not num[4:].isdigit():
2955 return 0
2956 return (2, sign, num[4:].lstrip('0'))
2957 return 0
2958
2959
2960##### Setup Specific Contexts ################################
2961
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002962_basic_traps = dict.fromkeys(Signals, 1)
2963_basic_traps.update({Inexact:0, Rounded:0, Subnormal:0})
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002964
2965# The default context prototype used by Context()
2966# Is mutable, so than new contexts can have different default values
2967
2968DefaultContext = Context(
Raymond Hettinger6ea48452004-07-03 12:26:21 +00002969 prec=28, rounding=ROUND_HALF_EVEN,
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002970 trap_enablers=dict.fromkeys(Signals, 0),
2971 flags=None,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002972 _rounding_decision=ALWAYS_ROUND,
2973)
2974
2975# Pre-made alternate contexts offered by the specification
2976# Don't change these; the user should be able to select these
2977# contexts and be able to reproduce results from other implementations
2978# of the spec.
2979
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002980BasicContext = Context(
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002981 prec=9, rounding=ROUND_HALF_UP,
2982 trap_enablers=_basic_traps,
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002983 flags=None,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002984 _rounding_decision=ALWAYS_ROUND,
2985)
2986
Raymond Hettinger9ec3e3b2004-07-03 13:48:56 +00002987ExtendedContext = Context(
Raymond Hettinger6ea48452004-07-03 12:26:21 +00002988 prec=9, rounding=ROUND_HALF_EVEN,
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002989 trap_enablers=dict.fromkeys(Signals, 0),
2990 flags=None,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002991 _rounding_decision=ALWAYS_ROUND,
2992)
2993
2994
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00002995##### Useful Constants (internal use only) ####################
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002996
2997#Reusable defaults
2998Inf = Decimal('Inf')
2999negInf = Decimal('-Inf')
3000
3001#Infsign[sign] is infinity w/ that sign
3002Infsign = (Inf, negInf)
3003
3004NaN = Decimal('NaN')
3005
3006
3007##### crud for parsing strings #################################
3008import re
3009
3010# There's an optional sign at the start, and an optional exponent
3011# at the end. The exponent has an optional sign and at least one
3012# digit. In between, must have either at least one digit followed
3013# by an optional fraction, or a decimal point followed by at least
3014# one digit. Yuck.
3015
3016_parser = re.compile(r"""
3017# \s*
3018 (?P<sign>[-+])?
3019 (
3020 (?P<int>\d+) (\. (?P<frac>\d*))?
3021 |
3022 \. (?P<onlyfrac>\d+)
3023 )
3024 ([eE](?P<exp>[-+]? \d+))?
3025# \s*
3026 $
3027""", re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces.
3028
3029del re
3030
3031# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly
3032
3033def _string2exact(s):
3034 m = _parser(s)
3035 if m is None:
3036 raise ValueError("invalid literal for Decimal: %r" % s)
3037
3038 if m.group('sign') == "-":
3039 sign = 1
3040 else:
3041 sign = 0
3042
3043 exp = m.group('exp')
3044 if exp is None:
3045 exp = 0
3046 else:
3047 exp = int(exp)
3048
3049 intpart = m.group('int')
3050 if intpart is None:
3051 intpart = ""
3052 fracpart = m.group('onlyfrac')
3053 else:
3054 fracpart = m.group('frac')
3055 if fracpart is None:
3056 fracpart = ""
3057
3058 exp -= len(fracpart)
3059
3060 mantissa = intpart + fracpart
3061 tmp = map(int, mantissa)
3062 backup = tmp
3063 while tmp and tmp[0] == 0:
3064 del tmp[0]
3065
3066 # It's a zero
3067 if not tmp:
3068 if backup:
3069 return (sign, tuple(backup), exp)
3070 return (sign, (0,), exp)
3071 mantissa = tuple(tmp)
3072
3073 return (sign, mantissa, exp)
3074
3075
3076if __name__ == '__main__':
3077 import doctest, sys
3078 doctest.testmod(sys.modules[__name__])