@@ -894,66 +894,117 @@ def test_sine_taylor_dekker(dtype):
894894
895895
896896@pytest .mark .parametrize (
897- "func,fma" , [("cos" , "upcast" ), ("cos" , "mul_add" ), ("cos" , "native" ), ("cosm1" , "upcast" ), ("numpy.cos" , None )]
897+ "func,fma" ,
898+ [
899+ ("cos" , "upcast" ),
900+ ("cos" , "mul_add" ),
901+ ("cos" , "native" ),
902+ ("cos_dekker" , "native" ),
903+ ("cos_numpy" , None ),
904+ ("cosm1_dekker" , "native" ),
905+ ("cosm1" , "upcast" ),
906+ ("cosm1_sin" , "upcast" ),
907+ ("cosm1_sin_numpy" , None ),
908+ ("cosm1_numpy" , None ),
909+ ],
898910)
899911def test_cosine_taylor (dtype , fma , func ):
900912 import mpmath
901913 from collections import defaultdict
902914
903915 t_prec = utils .get_precision (dtype )
904916 working_prec = {11 : 50 * 4 , 24 : 50 * 4 , 53 : 74 * 16 }[t_prec ]
905- optimal_order = {11 : 9 , 24 : 11 , 53 : 17 }[t_prec ]
917+ optimal_order = {11 : 9 , 24 : 13 , 53 : 19 }[t_prec ]
906918 size = 1000
907919 samples = list (utils .real_samples (size , dtype = dtype , min_value = dtype (0 ), max_value = dtype (numpy .pi / 4 )))
908920 size = len (samples )
909921 with mpmath .mp .workprec (working_prec ):
910922 mpctx = mpmath .mp
911923 for order in [optimal_order , 1 , 3 , 5 , 7 , 9 , 11 , 13 , 17 , 19 ][:1 ]:
912924
913- @fa .targets .numpy .jit (
914- paths = [fpa ],
915- dtype = dtype ,
916- debug = (1.5 if size <= 10 else 0 ),
917- rewrite_parameters = dict (optimize_cast = False , fma_backend = fma ),
918- )
919- def cos_func (ctx , x ):
920- return fpa .cosine_taylor (ctx , x , order = order , split = False )
921-
922- @fa .targets .numpy .jit (
923- paths = [fpa ],
924- dtype = dtype ,
925- debug = (1.5 if size <= 10 else 0 ),
926- rewrite_parameters = dict (optimize_cast = False , fma_backend = fma ),
927- )
928- def cosm1_func (ctx , x ):
929- return fpa .cosine_taylor (ctx , x , order = order , split = False , drop_leading_term = True )
925+ if func .startswith ("cosm1" ):
926+
927+ def f_expected (x ):
928+ return mpctx .cos (x ) - 1
929+
930+ else :
931+
932+ def f_expected (x ):
933+ return mpctx .cos (x )
934+
935+ if func in {"cos_dekker" , "cosm1_dekker" }:
936+
937+ @fa .targets .numpy .jit (
938+ paths = [fpa ],
939+ dtype = dtype ,
940+ debug = (1.5 if size <= 10 else 0 ),
941+ parameters = dict (series_uses_dekker = True , series_uses_2sum = True ),
942+ )
943+ def f (ctx , x ):
944+ return fpa .cosine_taylor_dekker (ctx , x , order = order , drop_leading_term = func .startswith ("cosm1" ))
945+
946+ elif func == "cos" :
947+
948+ @fa .targets .numpy .jit (
949+ paths = [fpa ],
950+ dtype = dtype ,
951+ debug = (1.5 if size <= 10 else 0 ),
952+ rewrite_parameters = dict (optimize_cast = False , fma_backend = fma ),
953+ )
954+ def f (ctx , x ):
955+ return fpa .cosine_taylor (ctx , x , order = order , split = False )
956+
957+ elif func == "cosm1" :
958+
959+ @fa .targets .numpy .jit (
960+ paths = [fpa ],
961+ dtype = dtype ,
962+ debug = (1.5 if size <= 10 else 0 ),
963+ rewrite_parameters = dict (optimize_cast = False , fma_backend = fma ),
964+ )
965+ def f (ctx , x ):
966+ return fpa .cosine_taylor (ctx , x , order = order , split = False , drop_leading_term = True )
967+
968+ elif func == "cosm1_sin" :
969+
970+ @fa .targets .numpy .jit (
971+ paths = [fpa ],
972+ dtype = dtype ,
973+ debug = (1.5 if size <= 10 else 0 ),
974+ rewrite_parameters = dict (optimize_cast = False , fma_backend = fma ),
975+ )
976+ def f (ctx , x ):
977+ two = ctx .constant (2 , x )
978+ sn = fpa .sine_taylor (ctx , x / two , order = order , split = False )
979+ return - two * sn * sn
980+
981+ elif func == "cos_numpy" :
982+
983+ f = numpy .cos
984+
985+ elif func == "cosm1_numpy" :
986+
987+ def f (x ):
988+ return numpy .cos (x ) - dtype (1 )
989+
990+ elif func == "cosm1_sin_numpy" :
991+
992+ def f (x ):
993+ two = dtype (2 )
994+ sn = numpy .sin (x / two )
995+ return - two * sn * sn
996+
997+ else :
998+ assert 0 , func # not impl
930999
9311000 ulp = defaultdict (int )
9321001 for x in samples :
933- expected_cs = utils .mpf2float (dtype , mpctx .cos (utils .float2mpf (mpctx , x )))
934- if func == "numpy.cos" :
935- cs = numpy .cos (x )
936- u = utils .diff_ulp (cs , expected_cs )
937- elif func == "cos" :
938- cs = cos_func (x )
939- """
940- csh, csl = fpa.cosine_taylor(ctx, x, order=order, split=True)
941- cs2 = utils.mpf2float(dtype, utils.float2mpf(mpctx, csh) + utils.float2mpf(mpctx, csl))
942- assert cs == cs2, (cs, cs2, expected_cs)
943- """
944- u = utils .diff_ulp (cs , expected_cs )
945- elif func == "cosm1" :
946- expected_csm1 = utils .mpf2float (dtype , mpctx .cos (utils .float2mpf (mpctx , x )) - 1 )
947- cs = cosm1_func (x )
948- u = utils .diff_ulp (cs , expected_csm1 , flush_subnormals = True )
949- else :
950- assert 0 , func # unreachable
1002+ expected = utils .mpf2float (dtype , f_expected (utils .float2mpf (mpctx , x )))
1003+ cs = f (x )
1004+ u = utils .diff_ulp (cs , expected )
9511005 ulp [u ] += 1
9521006
953- if 0 :
954- c = "." if u == 0 else ("v" if cs < expected_cs else "^" )
955- print (c , end = "" , flush = True )
956-
1007+ print ()
9571008 show_ulp (ulp )
9581009
9591010
0 commit comments