mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Made the various is_* operations return booleans. This was discussed
with Cawlishaw by mail, and he basically confirmed that to these is_* operations, there's no need to return Decimal(0) and Decimal(1) if the language supports the False and True booleans. Also added a few tests for the these functions in extra.decTest, since they are mostly untested (apart from the doctests). Thanks Mark Dickinson
This commit is contained in:
		
							parent
							
								
									31ba8480d8
								
							
						
					
					
						commit
						1a191df14d
					
				
					 3 changed files with 2240 additions and 125 deletions
				
			
		
							
								
								
									
										207
									
								
								Lib/decimal.py
									
										
									
									
									
								
							
							
						
						
									
										207
									
								
								Lib/decimal.py
									
										
									
									
									
								
							|  | @ -679,14 +679,11 @@ def _check_nans(self, other=None, context=None): | |||
|         return 0 | ||||
| 
 | ||||
|     def __nonzero__(self): | ||||
|         """Is the number non-zero? | ||||
|         """Return True if self is nonzero; otherwise return False. | ||||
| 
 | ||||
|         0 if self == 0 | ||||
|         1 if self != 0 | ||||
|         NaNs and infinities are considered nonzero. | ||||
|         """ | ||||
|         if self._is_special: | ||||
|             return True | ||||
|         return sum(self._int) != 0 | ||||
|         return self._is_special or self._int[0] != 0 | ||||
| 
 | ||||
|     def __cmp__(self, other): | ||||
|         other = _convert_other(other) | ||||
|  | @ -2239,15 +2236,18 @@ def quantize(self, exp, rounding=None, context=None, watchexp=True): | |||
|         return ans | ||||
| 
 | ||||
|     def same_quantum(self, other): | ||||
|         """Test whether self and other have the same exponent. | ||||
|         """Return True if self and other have the same exponent; otherwise | ||||
|         return False. | ||||
| 
 | ||||
|         same as self._exp == other._exp, except NaN == sNaN | ||||
|         If either operand is a special value, the following rules are used: | ||||
|            * return True if both operands are infinities | ||||
|            * return True if both operands are NaNs | ||||
|            * otherwise, return False. | ||||
|         """ | ||||
|         other = _convert_other(other, raiseit=True) | ||||
|         if self._is_special or other._is_special: | ||||
|             if self._isnan() or other._isnan(): | ||||
|                 return self._isnan() and other._isnan() and True | ||||
|             if self._isinfinity() or other._isinfinity(): | ||||
|                 return self._isinfinity() and other._isinfinity() and True | ||||
|             return (self.is_nan() and other.is_nan() or | ||||
|                     self.is_infinite() and other.is_infinite()) | ||||
|         return self._exp == other._exp | ||||
| 
 | ||||
|     def _rescale(self, exp, rounding): | ||||
|  | @ -2730,84 +2730,60 @@ def exp(self, context=None): | |||
|         return ans | ||||
| 
 | ||||
|     def is_canonical(self): | ||||
|         """Returns 1 if self is canonical; otherwise returns 0.""" | ||||
|         return Dec_p1 | ||||
|         """Return True if self is canonical; otherwise return False. | ||||
| 
 | ||||
|         Currently, the encoding of a Decimal instance is always | ||||
|         canonical, so this method returns True for any Decimal. | ||||
|         """ | ||||
|         return True | ||||
| 
 | ||||
|     def is_finite(self): | ||||
|         """Returns 1 if self is finite, otherwise returns 0. | ||||
|         """Return True if self is finite; otherwise return False. | ||||
| 
 | ||||
|         For it to be finite, it must be neither infinite nor a NaN. | ||||
|         A Decimal instance is considered finite if it is neither | ||||
|         infinite nor a NaN. | ||||
|         """ | ||||
|         if self._is_special: | ||||
|             return Dec_0 | ||||
|         else: | ||||
|             return Dec_p1 | ||||
|         return not self._is_special | ||||
| 
 | ||||
|     def is_infinite(self): | ||||
|         """Returns 1 if self is an Infinite, otherwise returns 0.""" | ||||
|         if self._isinfinity(): | ||||
|             return Dec_p1 | ||||
|         else: | ||||
|             return Dec_0 | ||||
|         """Return True if self is infinite; otherwise return False.""" | ||||
|         return self._exp == 'F' | ||||
| 
 | ||||
|     def is_nan(self): | ||||
|         """Returns 1 if self is qNaN or sNaN, otherwise returns 0.""" | ||||
|         if self._isnan(): | ||||
|             return Dec_p1 | ||||
|         else: | ||||
|             return Dec_0 | ||||
|         """Return True if self is a qNaN or sNaN; otherwise return False.""" | ||||
|         return self._exp in ('n', 'N') | ||||
| 
 | ||||
|     def is_normal(self, context=None): | ||||
|         """Returns 1 if self is a normal number, otherwise returns 0.""" | ||||
|         if self._is_special: | ||||
|             return Dec_0 | ||||
|         if not self: | ||||
|             return Dec_0 | ||||
|         """Return True if self is a normal number; otherwise return False.""" | ||||
|         if self._is_special or not self: | ||||
|             return False | ||||
|         if context is None: | ||||
|             context = getcontext() | ||||
|         if context.Emin <= self.adjusted() <= context.Emax: | ||||
|             return Dec_p1 | ||||
|         else: | ||||
|             return Dec_0 | ||||
|         return context.Emin <= self.adjusted() <= context.Emax | ||||
| 
 | ||||
|     def is_qnan(self): | ||||
|         """Returns 1 if self is a quiet NaN, otherwise returns 0.""" | ||||
|         if self._isnan() == 1: | ||||
|             return Dec_p1 | ||||
|         else: | ||||
|             return Dec_0 | ||||
|         """Return True if self is a quiet NaN; otherwise return False.""" | ||||
|         return self._exp == 'n' | ||||
| 
 | ||||
|     def is_signed(self): | ||||
|         """Returns 1 if self is negative, otherwise returns 0.""" | ||||
|         return Decimal(self._sign) | ||||
|         """Return True if self is negative; otherwise return False.""" | ||||
|         return self._sign == 1 | ||||
| 
 | ||||
|     def is_snan(self): | ||||
|         """Returns 1 if self is a signaling NaN, otherwise returns 0.""" | ||||
|         if self._isnan() == 2: | ||||
|             return Dec_p1 | ||||
|         else: | ||||
|             return Dec_0 | ||||
|         """Return True if self is a signaling NaN; otherwise return False.""" | ||||
|         return self._exp == 'N' | ||||
| 
 | ||||
|     def is_subnormal(self, context=None): | ||||
|         """Returns 1 if self is subnormal, otherwise returns 0.""" | ||||
|         if self._is_special: | ||||
|             return Dec_0 | ||||
|         if not self: | ||||
|             return Dec_0 | ||||
|         """Return True if self is subnormal; otherwise return False.""" | ||||
|         if self._is_special or not self: | ||||
|             return False | ||||
|         if context is None: | ||||
|             context = getcontext() | ||||
| 
 | ||||
|         r = self._exp + len(self._int) | ||||
|         if r <= context.Emin: | ||||
|             return Dec_p1 | ||||
|         return Dec_0 | ||||
|         return self.adjusted() < context.Emin | ||||
| 
 | ||||
|     def is_zero(self): | ||||
|         """Returns 1 if self is a zero, otherwise returns 0.""" | ||||
|         if self: | ||||
|             return Dec_0 | ||||
|         else: | ||||
|             return Dec_p1 | ||||
|         """Return True if self is a zero; otherwise return False.""" | ||||
|         return not self._is_special and self._int[0] == 0 | ||||
| 
 | ||||
|     def _ln_exp_bound(self): | ||||
|         """Compute a lower bound for the adjusted exponent of self.ln(). | ||||
|  | @ -3871,138 +3847,145 @@ def fma(self, a, b, c): | |||
|         return a.fma(b, c, context=self) | ||||
| 
 | ||||
|     def is_canonical(self, a): | ||||
|         """Returns 1 if the operand is canonical; otherwise returns 0. | ||||
|         """Return True if the operand is canonical; otherwise return False. | ||||
| 
 | ||||
|         Currently, the encoding of a Decimal instance is always | ||||
|         canonical, so this method returns True for any Decimal. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_canonical(Decimal('2.50')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         """ | ||||
|         return Dec_p1 | ||||
|         return a.is_canonical() | ||||
| 
 | ||||
|     def is_finite(self, a): | ||||
|         """Returns 1 if the operand is finite, otherwise returns 0. | ||||
|         """Return True if the operand is finite; otherwise return False. | ||||
| 
 | ||||
|         For it to be finite, it must be neither infinite nor a NaN. | ||||
|         A Decimal instance is considered finite if it is neither | ||||
|         infinite nor a NaN. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_finite(Decimal('2.50')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_finite(Decimal('-0.3')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_finite(Decimal('0')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_finite(Decimal('Inf')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_finite(Decimal('NaN')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         """ | ||||
|         return a.is_finite() | ||||
| 
 | ||||
|     def is_infinite(self, a): | ||||
|         """Returns 1 if the operand is an Infinite, otherwise returns 0. | ||||
|         """Return True if the operand is infinite; otherwise return False. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_infinite(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_infinite(Decimal('-Inf')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_infinite(Decimal('NaN')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         """ | ||||
|         return a.is_infinite() | ||||
| 
 | ||||
|     def is_nan(self, a): | ||||
|         """Returns 1 if the operand is qNaN or sNaN, otherwise returns 0. | ||||
|         """Return True if the operand is a qNaN or sNaN; | ||||
|         otherwise return False. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_nan(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_nan(Decimal('NaN')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_nan(Decimal('-sNaN')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         """ | ||||
|         return a.is_nan() | ||||
| 
 | ||||
|     def is_normal(self, a): | ||||
|         """Returns 1 if the operand is a normal number, otherwise returns 0. | ||||
|         """Return True if the operand is a normal number; | ||||
|         otherwise return False. | ||||
| 
 | ||||
|         >>> c = ExtendedContext.copy() | ||||
|         >>> c.Emin = -999 | ||||
|         >>> c.Emax = 999 | ||||
|         >>> c.is_normal(Decimal('2.50')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> c.is_normal(Decimal('0.1E-999')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> c.is_normal(Decimal('0.00')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> c.is_normal(Decimal('-Inf')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> c.is_normal(Decimal('NaN')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         """ | ||||
|         return a.is_normal(context=self) | ||||
| 
 | ||||
|     def is_qnan(self, a): | ||||
|         """Returns 1 if the operand is a quiet NaN, otherwise returns 0. | ||||
|         """Return True if the operand is a quiet NaN; otherwise return False. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_qnan(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_qnan(Decimal('NaN')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_qnan(Decimal('sNaN')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         """ | ||||
|         return a.is_qnan() | ||||
| 
 | ||||
|     def is_signed(self, a): | ||||
|         """Returns 1 if the operand is negative, otherwise returns 0. | ||||
|         """Return True if the operand is negative; otherwise return False. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_signed(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_signed(Decimal('-12')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_signed(Decimal('-0')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         """ | ||||
|         return a.is_signed() | ||||
| 
 | ||||
|     def is_snan(self, a): | ||||
|         """Returns 1 if the operand is a signaling NaN, otherwise returns 0. | ||||
|         """Return True if the operand is a signaling NaN; | ||||
|         otherwise return False. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_snan(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_snan(Decimal('NaN')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_snan(Decimal('sNaN')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         """ | ||||
|         return a.is_snan() | ||||
| 
 | ||||
|     def is_subnormal(self, a): | ||||
|         """Returns 1 if the operand is subnormal, otherwise returns 0. | ||||
|         """Return True if the operand is subnormal; otherwise return False. | ||||
| 
 | ||||
|         >>> c = ExtendedContext.copy() | ||||
|         >>> c.Emin = -999 | ||||
|         >>> c.Emax = 999 | ||||
|         >>> c.is_subnormal(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> c.is_subnormal(Decimal('0.1E-999')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> c.is_subnormal(Decimal('0.00')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> c.is_subnormal(Decimal('-Inf')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> c.is_subnormal(Decimal('NaN')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         """ | ||||
|         return a.is_subnormal(context=self) | ||||
| 
 | ||||
|     def is_zero(self, a): | ||||
|         """Returns 1 if the operand is a zero, otherwise returns 0. | ||||
|         """Return True if the operand is a zero; otherwise return False. | ||||
| 
 | ||||
|         >>> ExtendedContext.is_zero(Decimal('0')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         >>> ExtendedContext.is_zero(Decimal('2.50')) | ||||
|         Decimal("0") | ||||
|         False | ||||
|         >>> ExtendedContext.is_zero(Decimal('-0E+2')) | ||||
|         Decimal("1") | ||||
|         True | ||||
|         """ | ||||
|         return a.is_zero() | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -95,35 +95,61 @@ def Nonfunction(*args): | |||
| 
 | ||||
| # Name adapter to be able to change the Decimal and Context | ||||
| # interface without changing the test files from Cowlishaw | ||||
| nameAdapter = {'toeng':'to_eng_string', | ||||
|                'tosci':'to_sci_string', | ||||
|                'samequantum':'same_quantum', | ||||
|                'tointegral':'to_integral_value', | ||||
|                'tointegralx':'to_integral_exact', | ||||
|                'remaindernear':'remainder_near', | ||||
|                'divideint':'divide_int', | ||||
|                'squareroot':'sqrt', | ||||
| nameAdapter = {'and':'logical_and', | ||||
|                'apply':'_apply', | ||||
|                'class':'number_class', | ||||
|                'comparesig':'compare_signal', | ||||
|                'comparetotal':'compare_total', | ||||
|                'comparetotmag':'compare_total_mag', | ||||
|                'copyabs':'copy_abs', | ||||
|                'copy':'copy_decimal', | ||||
|                'copyabs':'copy_abs', | ||||
|                'copynegate':'copy_negate', | ||||
|                'copysign':'copy_sign', | ||||
|                'and':'logical_and', | ||||
|                'or':'logical_or', | ||||
|                'xor':'logical_xor', | ||||
|                'divideint':'divide_int', | ||||
|                'invert':'logical_invert', | ||||
|                'iscanonical':'is_canonical', | ||||
|                'isfinite':'is_finite', | ||||
|                'isinfinite':'is_infinite', | ||||
|                'isnan':'is_nan', | ||||
|                'isnormal':'is_normal', | ||||
|                'isqnan':'is_qnan', | ||||
|                'issigned':'is_signed', | ||||
|                'issnan':'is_snan', | ||||
|                'issubnormal':'is_subnormal', | ||||
|                'iszero':'is_zero', | ||||
|                'maxmag':'max_mag', | ||||
|                'minmag':'min_mag', | ||||
|                'nextminus':'next_minus', | ||||
|                'nextplus':'next_plus', | ||||
|                'nexttoward':'next_toward', | ||||
|                'or':'logical_or', | ||||
|                'reduce':'normalize', | ||||
|                'remaindernear':'remainder_near', | ||||
|                'samequantum':'same_quantum', | ||||
|                'squareroot':'sqrt', | ||||
|                'toeng':'to_eng_string', | ||||
|                'tointegral':'to_integral_value', | ||||
|                'tointegralx':'to_integral_exact', | ||||
|                'tosci':'to_sci_string', | ||||
|                'xor':'logical_xor', | ||||
|               } | ||||
| 
 | ||||
| # The following functions return True/False rather than a Decimal instance | ||||
| 
 | ||||
| LOGICAL_FUNCTIONS = ( | ||||
|     'is_canonical', | ||||
|     'is_finite', | ||||
|     'is_infinite', | ||||
|     'is_nan', | ||||
|     'is_normal', | ||||
|     'is_qnan', | ||||
|     'is_signed', | ||||
|     'is_snan', | ||||
|     'is_subnormal', | ||||
|     'is_zero', | ||||
|     'same_quantum', | ||||
|     ) | ||||
| 
 | ||||
| # For some operations (currently exp, ln, log10, power), the decNumber | ||||
| # reference implementation imposes additional restrictions on the | ||||
| # context and operands.  These restrictions are not part of the | ||||
|  | @ -321,7 +347,7 @@ def FixQuotes(val): | |||
|             print "--", self.context | ||||
|         try: | ||||
|             result = str(funct(*vals)) | ||||
|             if fname == 'same_quantum': | ||||
|             if fname in LOGICAL_FUNCTIONS: | ||||
|                 result = str(int(eval(result))) # 'True', 'False' -> '1', '0' | ||||
|         except Signals, error: | ||||
|             self.fail("Raised %s in %s" % (error, s)) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Facundo Batista
						Facundo Batista