@@ -553,6 +553,107 @@ class TestBadFloor:
553553 self .assertEqual (math .floor (FloatLike (+ 1.0 )), + 1.0 )
554554 self .assertEqual (math .floor (FloatLike (- 1.0 )), - 1.0 )
555555
556+ @requires_IEEE_754
557+ def testSign (self ):
558+ # For compactness
559+ sign = math .sign
560+ isnan = math .isnan
561+ inf = math .inf
562+ Frac = fractions .Fraction
563+ Dec = decimal .Decimal
564+
565+ # --- int
566+ self .assertEqual (sign (- 5 ), - 1 )
567+ self .assertEqual (sign (- 1 ), - 1 )
568+ self .assertEqual (sign (0 ), 0 )
569+ self .assertEqual (sign (1 ), 1 )
570+ self .assertEqual (sign (5 ), 1 )
571+ # ------ bool
572+ self .assertEqual (sign (True ), 1 )
573+ self .assertEqual (sign (False ), 0 )
574+ # ------ big numbers
575+ self .assertEqual (sign (10 ** 1000 ), 1 )
576+ self .assertEqual (sign (- 10 ** 1000 ), - 1 )
577+ self .assertEqual (sign (10 ** 1000 - 10 ** 1000 ), 0 )
578+
579+ # --- float
580+ self .assertEqual (sign (- 5.0 ), - 1 )
581+ self .assertEqual (sign (- 1.0 ), - 1 )
582+ self .assertEqual (sign (0.0 ), 0 )
583+ self .assertEqual (sign (1.0 ), 1 )
584+ self .assertEqual (sign (5.0 ), 1 )
585+ # ------ -0.0 and +0.0
586+ self .assertEqual (sign (float ('-0.0' )), 0 )
587+ self .assertEqual (sign (float ('+0.0' )), 0 )
588+ # ------ -inf and inf
589+ self .assertEqual (sign (NINF ), - 1 )
590+ self .assertEqual (sign (INF ), 1 )
591+ # ------ -nan (the same as nan), nan
592+ self .assertTrue (isnan (sign (NNAN )))
593+ self .assertTrue (isnan (sign (NAN )))
594+ self .assertTrue (isnan (sign (0.0 * NAN )))
595+
596+ # --- Fraction
597+ self .assertEqual (sign (Frac (- 5 , 2 )), - 1 )
598+ self .assertEqual (sign (Frac (- 1 , 2 )), - 1 )
599+ self .assertEqual (sign (Frac (0 , 2 )), 0 )
600+ self .assertEqual (sign (Frac (1 , 2 )), 1 )
601+ self .assertEqual (sign (Frac (5 , 2 )), 1 )
602+
603+ # --- Decimal
604+ self .assertEqual (sign (Dec (- 5.5 )), - 1 )
605+ self .assertEqual (sign (Dec (- 1.5 )), - 1 )
606+ self .assertEqual (sign (Dec (0.0 )), 0 )
607+ self .assertEqual (sign (Dec (1.5 )), 1 )
608+ self .assertEqual (sign (Dec (5.5 )), 1 )
609+ # ------ Decimal NaN
610+ self .assertTrue (isnan (sign (Dec ('NaN' ))))
611+
612+ # --- New custom class (testing possible future extentions)
613+ # This class has no __float__ that tests one subtle branch in the CPython sign
614+ class MyNumber :
615+ def __init__ (self , value ):
616+ self .value = value
617+ def __gt__ (self , other ):
618+ return self .value > other
619+ def __lt__ (self , other ):
620+ return self .value < other
621+ def __eq__ (self , other ):
622+ return self .value == other
623+ def __repr__ (self ):
624+ return f'MyNumber({ self .value } )'
625+
626+ self .assertEqual (sign (MyNumber (- 5 )), - 1 )
627+ self .assertEqual (sign (MyNumber (- 1 )), - 1 )
628+ self .assertEqual (sign (MyNumber (0 )), 0 )
629+ self .assertEqual (sign (MyNumber (1 )), 1 )
630+ self .assertEqual (sign (MyNumber (5 )), 1 )
631+ with self .assertRaisesRegex (TypeError , r'math\.sign: invalid argument `MyNumber\(nan\)`' ):
632+ sign (MyNumber (NAN ))
633+
634+ # Testing inappropriate arguments and types (non-scalar, non-comparable, etc.)
635+ # --- No arguments and three arguments
636+ with self .assertRaisesRegex (TypeError , r'math\.sign\(\) takes exactly one argument \(0 given\)' ):
637+ sign ()
638+ with self .assertRaisesRegex (TypeError , r'math\.sign\(\) takes exactly one argument \(3 given\)' ):
639+ sign (- 1 , 0 , 1 )
640+
641+ # --- None, str, list, complex, set
642+ tests = [(r"`None`" , None ),
643+ (r"`'5\.0'`" , '5.0' ),
644+ (r"`'nan'`" , 'nan' ),
645+ (r"`'number 5'`" , 'number 5' ),
646+ (r"`\[-8\.75\]`" , [- 8.75 ]),
647+ (r"`\(-1\+1j\)`" , - 1 + 1j ),
648+ (r"`\{-3\.14\}`" , {- 3.14 }),
649+ ]
650+
651+ for msg , obj in tests :
652+ with self .subTest (obj = obj ):
653+ with self .assertRaisesRegex (TypeError ,
654+ r'math\.sign: invalid argument ' + msg ):
655+ sign (obj )
656+
556657 def testFmod (self ):
557658 self .assertRaises (TypeError , math .fmod )
558659 self .ftest ('fmod(10, 1)' , math .fmod (10 , 1 ), 0.0 )
0 commit comments