432 lines
10 KiB
Factor
432 lines
10 KiB
Factor
! Copyright (C) 2011 John Benediktsson
|
|
! See http://factorcode.org/license.txt for BSD license
|
|
|
|
USING: combinators kernel locals math math.constants
|
|
math.functions sequences ;
|
|
|
|
IN: picomath
|
|
|
|
<PRIVATE
|
|
|
|
CONSTANT: a1 0.254829592
|
|
CONSTANT: a2 -0.284496736
|
|
CONSTANT: a3 1.421413741
|
|
CONSTANT: a4 -1.453152027
|
|
CONSTANT: a5 1.061405429
|
|
CONSTANT: p 0.3275911
|
|
|
|
PRIVATE>
|
|
|
|
! Standalone error function erf(x)
|
|
! http://www.johndcook.com/blog/2009/01/19/stand-alone-error-function-erf/
|
|
:: erf ( x -- value )
|
|
x 0 >= 1 -1 ? :> sign
|
|
x abs :> x!
|
|
p x * 1 + recip :> t
|
|
a5 t * a4 + t * a3 + t * a2 + t * a1 + t *
|
|
x x neg * e^ * 1 swap - :> y
|
|
sign y * ;
|
|
|
|
:: expm1 ( x -- value )
|
|
x abs 1e-5 < [ x sq 0.5 * x + ] [ x e^ 1.0 - ] if ;
|
|
|
|
! Standalone implementation of phi(x)
|
|
:: phi ( x -- value )
|
|
x 0 >= 1 -1 ? :> sign
|
|
x abs 2 sqrt / :> x!
|
|
p x * 1 + recip :> t
|
|
a5 t * a4 + t * a3 + t * a2 + t * a1 + t *
|
|
x x neg * e^ * 1 swap - :> y
|
|
sign y * 1 + 2 / ;
|
|
|
|
<PRIVATE
|
|
|
|
CONSTANT: lf {
|
|
0.000000000000000
|
|
0.000000000000000
|
|
0.693147180559945
|
|
1.791759469228055
|
|
3.178053830347946
|
|
4.787491742782046
|
|
6.579251212010101
|
|
8.525161361065415
|
|
10.604602902745251
|
|
12.801827480081469
|
|
15.104412573075516
|
|
17.502307845873887
|
|
19.987214495661885
|
|
22.552163853123421
|
|
25.191221182738683
|
|
27.899271383840894
|
|
30.671860106080675
|
|
33.505073450136891
|
|
36.395445208033053
|
|
39.339884187199495
|
|
42.335616460753485
|
|
45.380138898476908
|
|
48.471181351835227
|
|
51.606675567764377
|
|
54.784729398112319
|
|
58.003605222980518
|
|
61.261701761002001
|
|
64.557538627006323
|
|
67.889743137181526
|
|
71.257038967168000
|
|
74.658236348830158
|
|
78.092223553315307
|
|
81.557959456115029
|
|
85.054467017581516
|
|
88.580827542197682
|
|
92.136175603687079
|
|
95.719694542143202
|
|
99.330612454787428
|
|
102.968198614513810
|
|
106.631760260643450
|
|
110.320639714757390
|
|
114.034211781461690
|
|
117.771881399745060
|
|
121.533081515438640
|
|
125.317271149356880
|
|
129.123933639127240
|
|
132.952575035616290
|
|
136.802722637326350
|
|
140.673923648234250
|
|
144.565743946344900
|
|
148.477766951773020
|
|
152.409592584497350
|
|
156.360836303078800
|
|
160.331128216630930
|
|
164.320112263195170
|
|
168.327445448427650
|
|
172.352797139162820
|
|
176.395848406997370
|
|
180.456291417543780
|
|
184.533828861449510
|
|
188.628173423671600
|
|
192.739047287844900
|
|
196.866181672889980
|
|
201.009316399281570
|
|
205.168199482641200
|
|
209.342586752536820
|
|
213.532241494563270
|
|
217.736934113954250
|
|
221.956441819130360
|
|
226.190548323727570
|
|
230.439043565776930
|
|
234.701723442818260
|
|
238.978389561834350
|
|
243.268849002982730
|
|
247.572914096186910
|
|
251.890402209723190
|
|
256.221135550009480
|
|
260.564940971863220
|
|
264.921649798552780
|
|
269.291097651019810
|
|
273.673124285693690
|
|
278.067573440366120
|
|
282.474292687630400
|
|
286.893133295426990
|
|
291.323950094270290
|
|
295.766601350760600
|
|
300.220948647014100
|
|
304.686856765668720
|
|
309.164193580146900
|
|
313.652829949878990
|
|
318.152639620209300
|
|
322.663499126726210
|
|
327.185287703775200
|
|
331.717887196928470
|
|
336.261181979198450
|
|
340.815058870798960
|
|
345.379407062266860
|
|
349.954118040770250
|
|
354.539085519440790
|
|
359.134205369575340
|
|
363.739375555563470
|
|
368.354496072404690
|
|
372.979468885689020
|
|
377.614197873918670
|
|
382.258588773060010
|
|
386.912549123217560
|
|
391.575988217329610
|
|
396.248817051791490
|
|
400.930948278915760
|
|
405.622296161144900
|
|
410.322776526937280
|
|
415.032306728249580
|
|
419.750805599544780
|
|
424.478193418257090
|
|
429.214391866651570
|
|
433.959323995014870
|
|
438.712914186121170
|
|
443.475088120918940
|
|
448.245772745384610
|
|
453.024896238496130
|
|
457.812387981278110
|
|
462.608178526874890
|
|
467.412199571608080
|
|
472.224383926980520
|
|
477.044665492585580
|
|
481.872979229887900
|
|
486.709261136839360
|
|
491.553448223298010
|
|
496.405478487217580
|
|
501.265290891579240
|
|
506.132825342034830
|
|
511.008022665236070
|
|
515.890824587822520
|
|
520.781173716044240
|
|
525.679013515995050
|
|
530.584288294433580
|
|
535.496943180169520
|
|
540.416924105997740
|
|
545.344177791154950
|
|
550.278651724285620
|
|
555.220294146894960
|
|
560.169054037273100
|
|
565.124881094874350
|
|
570.087725725134190
|
|
575.057539024710200
|
|
580.034272767130800
|
|
585.017879388839220
|
|
590.008311975617860
|
|
595.005524249382010
|
|
600.009470555327430
|
|
605.020105849423770
|
|
610.037385686238740
|
|
615.061266207084940
|
|
620.091704128477430
|
|
625.128656730891070
|
|
630.172081847810200
|
|
635.221937855059760
|
|
640.278183660408100
|
|
645.340778693435030
|
|
650.409682895655240
|
|
655.484856710889060
|
|
660.566261075873510
|
|
665.653857411105950
|
|
670.747607611912710
|
|
675.847474039736880
|
|
680.953419513637530
|
|
686.065407301994010
|
|
691.183401114410800
|
|
696.307365093814040
|
|
701.437263808737160
|
|
706.573062245787470
|
|
711.714725802289990
|
|
716.862220279103440
|
|
722.015511873601330
|
|
727.174567172815840
|
|
732.339353146739310
|
|
737.509837141777440
|
|
742.685986874351220
|
|
747.867770424643370
|
|
753.055156230484160
|
|
758.248113081374300
|
|
763.446610112640200
|
|
768.650616799717000
|
|
773.860102952558460
|
|
779.075038710167410
|
|
784.295394535245690
|
|
789.521141208958970
|
|
794.752249825813460
|
|
799.988691788643450
|
|
805.230438803703120
|
|
810.477462875863580
|
|
815.729736303910160
|
|
820.987231675937890
|
|
826.249921864842800
|
|
831.517780023906310
|
|
836.790779582469900
|
|
842.068894241700490
|
|
847.352097970438420
|
|
852.640365001133090
|
|
857.933669825857460
|
|
863.231987192405430
|
|
868.535292100464630
|
|
873.843559797865740
|
|
879.156765776907600
|
|
884.474885770751830
|
|
889.797895749890240
|
|
895.125771918679900
|
|
900.458490711945270
|
|
905.796028791646340
|
|
911.138363043611210
|
|
916.485470574328820
|
|
921.837328707804890
|
|
927.193914982476710
|
|
932.555207148186240
|
|
937.921183163208070
|
|
943.291821191335660
|
|
948.667099599019820
|
|
954.046996952560450
|
|
959.431492015349480
|
|
964.820563745165940
|
|
970.214191291518320
|
|
975.612353993036210
|
|
981.015031374908400
|
|
986.422203146368590
|
|
991.833849198223450
|
|
997.249949600427840
|
|
1002.670484599700300
|
|
1008.095434617181700
|
|
1013.524780246136200
|
|
1018.958502249690200
|
|
1024.396581558613400
|
|
1029.838999269135500
|
|
1035.285736640801600
|
|
1040.736775094367400
|
|
1046.192096209724900
|
|
1051.651681723869200
|
|
1057.115513528895000
|
|
1062.583573670030100
|
|
1068.055844343701400
|
|
1073.532307895632800
|
|
1079.012946818975000
|
|
1084.497743752465600
|
|
1089.986681478622400
|
|
1095.479742921962700
|
|
1100.976911147256000
|
|
1106.478169357800900
|
|
1111.983500893733000
|
|
1117.492889230361000
|
|
1123.006317976526100
|
|
1128.523770872990800
|
|
1134.045231790853000
|
|
1139.570684729984800
|
|
1145.100113817496100
|
|
1150.633503306223700
|
|
1156.170837573242400
|
|
}
|
|
|
|
PRIVATE>
|
|
|
|
: log-factorial ( n -- value )
|
|
{
|
|
{ [ dup 0 < ] [ "invalid input" throw ] }
|
|
{ [ dup 254 > ] [
|
|
1 + [| x |
|
|
x 0.5 - x log * x -
|
|
0.5 2 pi * log * +
|
|
1.0 12.0 x * / +
|
|
] call
|
|
] }
|
|
[ lf nth ]
|
|
} cond ;
|
|
|
|
:: log-one-plus-x ( x -- value )
|
|
x -1.0 <= [ "argument must be > -1" throw ] when
|
|
x abs 1e-4 > [ 1.0 x + log ] [ -0.5 x * 1.0 + x * ] if ;
|
|
|
|
<PRIVATE
|
|
|
|
CONSTANT: c0 2.515517
|
|
CONSTANT: c1 0.802853
|
|
CONSTANT: c2 0.010328
|
|
|
|
CONSTANT: d0 1.432788
|
|
CONSTANT: d1 0.189269
|
|
CONSTANT: d2 0.001308
|
|
|
|
PRIVATE>
|
|
|
|
:: rational-approximation ( t -- value )
|
|
c2 t * c1 + t * c0 + :> numerator
|
|
d2 t * d1 + t * d0 + t * 1.0 + :> denominator
|
|
t numerator denominator / - ;
|
|
|
|
:: normal-cdf-inverse ( p -- value )
|
|
p [ 0 > ] [ 1 < ] bi and [ p throw ] unless
|
|
p 0.5 <
|
|
[ p log -2.0 * sqrt rational-approximation neg ]
|
|
[ p 1.0 - log -2.0 * sqrt rational-approximation ] if ;
|
|
|
|
<PRIVATE
|
|
|
|
! Abramowitz and Stegun 6.1.41
|
|
! Asymptotic series should be good to at least 11 or 12 figures
|
|
! For error analysis, see Whittiker and Watson
|
|
! A Course in Modern Analysis (1927), page 252
|
|
CONSTANT: c {
|
|
1/12
|
|
-1/360
|
|
1/1260
|
|
-1/1680
|
|
1/1188
|
|
-691/360360
|
|
1/156
|
|
-3617/122400
|
|
}
|
|
|
|
CONSTANT: halfLogTwoPi 0.91893853320467274178032973640562
|
|
|
|
PRIVATE>
|
|
|
|
DEFER: gamma
|
|
|
|
:: log-gamma ( x -- value )
|
|
x 0 <= [ "Invalid input" throw ] when
|
|
x 12 < [ x gamma abs log ] [
|
|
1.0 x x * / :> z
|
|
7 c nth 7 <iota> reverse [ [ z * ] [ c nth ] bi* + ] each x / :> series
|
|
x 0.5 - x log * x - halfLogTwoPi + series +
|
|
] if ;
|
|
|
|
<PRIVATE
|
|
|
|
CONSTANT: GAMMA 0.577215664901532860606512090 ! Euler's gamma constant
|
|
|
|
! numerator coefficients for approximation over the interval (1,2)
|
|
CONSTANT: P {
|
|
-1.71618513886549492533811E+0
|
|
2.47656508055759199108314E+1
|
|
-3.79804256470945635097577E+2
|
|
6.29331155312818442661052E+2
|
|
8.66966202790413211295064E+2
|
|
-3.14512729688483675254357E+4
|
|
-3.61444134186911729807069E+4
|
|
6.64561438202405440627855E+4
|
|
}
|
|
|
|
! denominator coefficients for approximation over the interval (1,2)
|
|
CONSTANT: Q {
|
|
-3.08402300119738975254353E+1
|
|
3.15350626979604161529144E+2
|
|
-1.01515636749021914166146E+3
|
|
-3.10777167157231109440444E+3
|
|
2.25381184209801510330112E+4
|
|
4.75584627752788110767815E+3
|
|
-1.34659959864969306392456E+5
|
|
-1.15132259675553483497211E+5
|
|
}
|
|
|
|
:: (gamma) ( x -- value )
|
|
! The algorithm directly approximates gamma over (1,2) and uses
|
|
! reduction identities to reduce other arguments to this interval.
|
|
x :> y!
|
|
0 :> n!
|
|
y 1.0 < :> arg-was-less-than-one
|
|
arg-was-less-than-one
|
|
[ y 1.0 + y! ] [ y floor >integer 1 - n! y n - y! ] if
|
|
0.0 :> num!
|
|
1.0 :> den!
|
|
y 1 - :> z!
|
|
8 <iota> [
|
|
[ P nth num + z * num! ]
|
|
[ Q nth den z * + den! ] bi
|
|
] each
|
|
num den / 1.0 +
|
|
arg-was-less-than-one
|
|
[ y 1.0 - / ] [ n [ y * y 1.0 + y! ] times ] if ;
|
|
|
|
PRIVATE>
|
|
|
|
:: gamma ( x -- value )
|
|
x 0 <= [ "Invalid input" throw ] when
|
|
x {
|
|
{ [ dup 0.001 < ] [ GAMMA * 1.0 + x * 1.0 swap / ] }
|
|
{ [ dup 12.0 < ] [ (gamma) ] }
|
|
{ [ dup 171.624 > ] [ drop 1/0. ] }
|
|
[ log-gamma e^ ]
|
|
} cond ;
|