@@ -14,7 +14,8 @@ export sin, cos, tan, sinh, cosh, tanh, asin, acos, atan,
14
14
airy, airyai, airyprime, airyaiprime, airybi, airybiprime,
15
15
besselj0, besselj1, besselj, bessely0, bessely1, bessely,
16
16
hankelh1, hankelh2, besseli, besselk, besselh,
17
- beta, lbeta, eta, zeta, digamma
17
+ beta, lbeta, eta, zeta, digamma,
18
+ erfinv, erfcinv
18
19
19
20
import Base. log, Base. exp, Base. sin, Base. cos, Base. tan, Base. sinh, Base. cosh,
20
21
Base. tanh, Base. asin, Base. acos, Base. atan, Base. asinh, Base. acosh,
@@ -695,4 +696,214 @@ for f in (:erfcx, :erfi, :Dawson)
695
696
end
696
697
end
697
698
699
+ # evaluate p[1] + x * (p[2] + x * (....)), i.e. a polynomial via Horner's rule
700
+ macro horner (x, p... )
701
+ ex = p[end ]
702
+ for i = length (p)- 1 : - 1 : 1
703
+ ex = :($ (p[i]) + $ x * $ ex)
704
+ end
705
+ ex
706
+ end
707
+
708
+ # Compute the inverse of the error function: erf(erfinv(x)) == x,
709
+ # using the rational approximants tabulated in:
710
+ # J. M. Blair, C. A. Edwards, and J. H. Johnson, "Rational Chebyshev
711
+ # approximations for the inverse of the error function," Math. Comp. 30,
712
+ # pp. 827--830 (1976).
713
+ # http://dx.doi.org/10.1090/S0025-5718-1976-0421040-7
714
+ # http://www.jstor.org/stable/2005402
715
+ function erfinv (x:: Float64 )
716
+ a = abs (x)
717
+ if a >= 1.0
718
+ if x == 1.0
719
+ return inf (Float64)
720
+ elseif x == - 1.0
721
+ return - inf (Float64)
722
+ end
723
+ throw (DomainError ())
724
+ elseif a <= 0.75 # Table 17 in Blair et al.
725
+ t = x* x - 0.5625
726
+ return x * @horner (t, 0.16030_49558_44066_229311e2 ,
727
+ - 0.90784_95926_29603_26650e2 ,
728
+ 0.18644_91486_16209_87391e3 ,
729
+ - 0.16900_14273_46423_82420e3 ,
730
+ 0.65454_66284_79448_7048e2 ,
731
+ - 0.86421_30115_87247_794e1 ,
732
+ 0.17605_87821_39059_0 ) /
733
+ @horner (t, 0.14780_64707_15138_316110e2 ,
734
+ - 0.91374_16702_42603_13936e2 ,
735
+ 0.21015_79048_62053_17714e3 ,
736
+ - 0.22210_25412_18551_32366e3 ,
737
+ 0.10760_45391_60551_23830e3 ,
738
+ - 0.20601_07303_28265_443e2 ,
739
+ 0.1e1 )
740
+ elseif a <= 0.9375 # Table 37 in Blair et al.
741
+ t = x* x - 0.87890625
742
+ return x * @horner (t, - 0.15238_92634_40726_128e-1 ,
743
+ 0.34445_56924_13612_5216 ,
744
+ - 0.29344_39867_25424_78687e1 ,
745
+ 0.11763_50570_52178_27302e2 ,
746
+ - 0.22655_29282_31011_04193e2 ,
747
+ 0.19121_33439_65803_30163e2 ,
748
+ - 0.54789_27619_59831_8769e1 ,
749
+ 0.23751_66890_24448 ) /
750
+ @horner (t, - 0.10846_51696_02059_954e-1 ,
751
+ 0.26106_28885_84307_8511 ,
752
+ - 0.24068_31810_43937_57995e1 ,
753
+ 0.10695_12997_33870_14469e2 ,
754
+ - 0.23716_71552_15965_81025e2 ,
755
+ 0.24640_15894_39172_84883e2 ,
756
+ - 0.10014_37634_97830_70835e2 ,
757
+ 0.1e1 )
758
+ else # Table 57 in Blair et al.
759
+ t = 1.0 / sqrt (- log (1.0 - a))
760
+ return @horner (t, 0.10501_31152_37334_38116e-3 ,
761
+ 0.10532_61131_42333_38164_25e-1 ,
762
+ 0.26987_80273_62432_83544_516 ,
763
+ 0.23268_69578_89196_90806_414e1 ,
764
+ 0.71678_54794_91079_96810_001e1 ,
765
+ 0.85475_61182_21678_27825_185e1 ,
766
+ 0.68738_08807_35438_39802_913e1 ,
767
+ 0.36270_02483_09587_08930_02e1 ,
768
+ 0.88606_27392_96515_46814_9 ) /
769
+ (copysign (t, x) *
770
+ @horner (t, 0.10501_26668_70303_37690e-3 ,
771
+ 0.10532_86230_09333_27531_11e-1 ,
772
+ 0.27019_86237_37515_54845_553 ,
773
+ 0.23501_43639_79702_53259_123e1 ,
774
+ 0.76078_02878_58012_77064_351e1 ,
775
+ 0.11181_58610_40569_07827_3451e2 ,
776
+ 0.11948_78791_84353_96667_8438e2 ,
777
+ 0.81922_40974_72699_07893_913e1 ,
778
+ 0.40993_87907_63680_15361_45e1 ,
779
+ 0.1e1 ))
780
+ end
781
+ end
782
+
783
+ function erfinv (x:: Float32 )
784
+ a = abs (x)
785
+ if a >= 1.0f0
786
+ if x == 1.0f0
787
+ return inf (Float64)
788
+ elseif x == - 1.0f0
789
+ return - inf (Float64)
790
+ end
791
+ throw (DomainError ())
792
+ elseif a <= 0.75f0 # Table 10 in Blair et al.
793
+ t = x* x - 0.5625f0
794
+ return x * @horner (t, - 0.13095_99674_22f2 ,
795
+ 0.26785_22576_0f2 ,
796
+ - 0.92890_57365f1 ) /
797
+ @horner (t, - 0.12074_94262_97f2 ,
798
+ 0.30960_61452_9f2 ,
799
+ - 0.17149_97799_1f2 ,
800
+ 0.1f1 )
801
+ elseif a <= 0.9375f0 # Table 29 in Blair et al.
802
+ t = x* x - 0.87890625f0
803
+ return x * @horner (t, - 0.12402_56522_1f0 ,
804
+ 0.10688_05957_4f1 ,
805
+ - 0.19594_55607_8f1 ,
806
+ 0.42305_81357f0 ) /
807
+ @horner (t, - 0.88276_97997f-1 ,
808
+ 0.89007_43359f0 ,
809
+ - 0.21757_03119_6f1 ,
810
+ 0.1f1 )
811
+ else # Table 50 in Blair et al.
812
+ t = 1.0f0 / sqrt (- log (1.0f0 - a))
813
+ return @horner (t, 0.15504_70003_116f0 ,
814
+ 0.13827_19649_631f1 ,
815
+ 0.69096_93488_87f0 ,
816
+ - 0.11280_81391_617f1 ,
817
+ 0.68054_42468_25f0 ,
818
+ - 0.16444_15679_1f0 ) /
819
+ (copysign (t, x) *
820
+ @horner (t, 0.15502_48498_22f0 ,
821
+ 0.13852_28141_995f1 ,
822
+ 0.1f1 ))
823
+ end
824
+ end
825
+
826
+ erfinv (x:: Integer ) = erfinv (float (x))
827
+ @vectorize_1arg Real erfinv
828
+
829
+ # Inverse complementary error function: use Blair tables for y = 1-x,
830
+ # exploiting the greater accuracy of y (vs. x) when y is small.
831
+ function erfcinv (y:: Float64 )
832
+ if y > 0.0625
833
+ return erfinv (1.0 - y)
834
+ elseif y <= 0.0
835
+ if y == 0.0
836
+ return inf (Float64)
837
+ end
838
+ throw (DomainError ())
839
+ elseif y >= 1e-100 # Table 57 in Blair et al.
840
+ t = 1.0 / sqrt (- log (y))
841
+ return @horner (t, 0.10501_31152_37334_38116e-3 ,
842
+ 0.10532_61131_42333_38164_25e-1 ,
843
+ 0.26987_80273_62432_83544_516 ,
844
+ 0.23268_69578_89196_90806_414e1 ,
845
+ 0.71678_54794_91079_96810_001e1 ,
846
+ 0.85475_61182_21678_27825_185e1 ,
847
+ 0.68738_08807_35438_39802_913e1 ,
848
+ 0.36270_02483_09587_08930_02e1 ,
849
+ 0.88606_27392_96515_46814_9 ) /
850
+ (t *
851
+ @horner (t, 0.10501_26668_70303_37690e-3 ,
852
+ 0.10532_86230_09333_27531_11e-1 ,
853
+ 0.27019_86237_37515_54845_553 ,
854
+ 0.23501_43639_79702_53259_123e1 ,
855
+ 0.76078_02878_58012_77064_351e1 ,
856
+ 0.11181_58610_40569_07827_3451e2 ,
857
+ 0.11948_78791_84353_96667_8438e2 ,
858
+ 0.81922_40974_72699_07893_913e1 ,
859
+ 0.40993_87907_63680_15361_45e1 ,
860
+ 0.1e1 ))
861
+ else # Table 80 in Blair et al.
862
+ t = 1.0 / sqrt (- log (y))
863
+ return @horner (t, 0.34654_29858_80863_50177e-9 ,
864
+ 0.25084_67920_24075_70520_55e-6 ,
865
+ 0.47378_13196_37286_02986_534e-4 ,
866
+ 0.31312_60375_97786_96408_3388e-2 ,
867
+ 0.77948_76454_41435_36994_854e-1 ,
868
+ 0.70045_68123_35816_43868_271e0 ,
869
+ 0.18710_42034_21679_31668_683e1 ,
870
+ 0.71452_54774_31351_45428_3e0 ) /
871
+ (t * @horner (t, 0.34654_29567_31595_11156e-9 ,
872
+ 0.25084_69079_75880_27114_87e-6 ,
873
+ 0.47379_53129_59749_13536_339e-4 ,
874
+ 0.31320_63536_46177_68848_0813e-2 ,
875
+ 0.78073_48906_27648_97214_733e-1 ,
876
+ 0.70715_04479_95337_58619_993e0 ,
877
+ 0.19998_51543_49112_15105_214e1 ,
878
+ 0.15072_90269_27316_80008_56e1 ,
879
+ 0.1e1 ))
880
+ end
881
+ end
882
+
883
+ function erfcinv (y:: Float32 )
884
+ if y > 0.0625f0
885
+ return erfinv (1.0f0 - y)
886
+ elseif y <= 0.0f0
887
+ if y == 0.0f0
888
+ return inf (Float32)
889
+ end
890
+ throw (DomainError ())
891
+ else # Table 50 in Blair et al.
892
+ t = 1.0f0 / sqrt (- log (y))
893
+ return @horner (t, 0.15504_70003_116f0 ,
894
+ 0.13827_19649_631f1 ,
895
+ 0.69096_93488_87f0 ,
896
+ - 0.11280_81391_617f1 ,
897
+ 0.68054_42468_25f0 ,
898
+ - 0.16444_15679_1f0 ) /
899
+ (t *
900
+ @horner (t, 0.15502_48498_22f0 ,
901
+ 0.13852_28141_995f1 ,
902
+ 0.1f1 ))
903
+ end
904
+ end
905
+
906
+ erfcinv (x:: Integer ) = erfcinv (float (x))
907
+ @vectorize_1arg Real erfcinv
908
+
698
909
end # module
0 commit comments