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 ;
 |