]> gitweb.factorcode.org Git - factor.git/blob - extra/picomath/picomath.factor
io.streams.tee: more tests
[factor.git] / extra / picomath / picomath.factor
1 ! Copyright (C) 2011 John Benediktsson
2 ! See http://factorcode.org/license.txt for BSD license
3
4 USING: combinators kernel locals math math.constants
5 math.functions sequences ;
6
7 IN: picomath
8
9 <PRIVATE
10
11 CONSTANT: a1  0.254829592
12 CONSTANT: a2 -0.284496736
13 CONSTANT: a3  1.421413741
14 CONSTANT: a4 -1.453152027
15 CONSTANT: a5  1.061405429
16 CONSTANT: p   0.3275911
17
18 PRIVATE>
19
20 ! Standalone error function erf(x)
21 ! http://www.johndcook.com/blog/2009/01/19/stand-alone-error-function-erf/
22 :: erf ( x -- value )
23     x 0 >= 1 -1 ? :> sign
24     x abs :> x!
25     p x * 1 + recip :> t
26     a5 t * a4 + t * a3 + t * a2 + t * a1 + t *
27     x x neg * e^ * 1 swap - :> y
28     sign y * ;
29
30 :: expm1 ( x -- value )
31     x abs 1e-5 < [ x sq 0.5 * x + ] [ x e^ 1.0 - ] if ;
32
33 ! Standalone implementation of phi(x)
34 :: phi ( x -- value )
35     x 0 >= 1 -1 ? :> sign
36     x abs 2 sqrt / :> x!
37     p x * 1 + recip :> t
38     a5 t * a4 + t * a3 + t * a2 + t * a1 + t *
39     x x neg * e^ * 1 swap - :> y
40     sign y * 1 + 2 / ;
41
42 <PRIVATE
43
44 CONSTANT: lf {
45     0.000000000000000
46     0.000000000000000
47     0.693147180559945
48     1.791759469228055
49     3.178053830347946
50     4.787491742782046
51     6.579251212010101
52     8.525161361065415
53     10.604602902745251
54     12.801827480081469
55     15.104412573075516
56     17.502307845873887
57     19.987214495661885
58     22.552163853123421
59     25.191221182738683
60     27.899271383840894
61     30.671860106080675
62     33.505073450136891
63     36.395445208033053
64     39.339884187199495
65     42.335616460753485
66     45.380138898476908
67     48.471181351835227
68     51.606675567764377
69     54.784729398112319
70     58.003605222980518
71     61.261701761002001
72     64.557538627006323
73     67.889743137181526
74     71.257038967168000
75     74.658236348830158
76     78.092223553315307
77     81.557959456115029
78     85.054467017581516
79     88.580827542197682
80     92.136175603687079
81     95.719694542143202
82     99.330612454787428
83     102.968198614513810
84     106.631760260643450
85     110.320639714757390
86     114.034211781461690
87     117.771881399745060
88     121.533081515438640
89     125.317271149356880
90     129.123933639127240
91     132.952575035616290
92     136.802722637326350
93     140.673923648234250
94     144.565743946344900
95     148.477766951773020
96     152.409592584497350
97     156.360836303078800
98     160.331128216630930
99     164.320112263195170
100     168.327445448427650
101     172.352797139162820
102     176.395848406997370
103     180.456291417543780
104     184.533828861449510
105     188.628173423671600
106     192.739047287844900
107     196.866181672889980
108     201.009316399281570
109     205.168199482641200
110     209.342586752536820
111     213.532241494563270
112     217.736934113954250
113     221.956441819130360
114     226.190548323727570
115     230.439043565776930
116     234.701723442818260
117     238.978389561834350
118     243.268849002982730
119     247.572914096186910
120     251.890402209723190
121     256.221135550009480
122     260.564940971863220
123     264.921649798552780
124     269.291097651019810
125     273.673124285693690
126     278.067573440366120
127     282.474292687630400
128     286.893133295426990
129     291.323950094270290
130     295.766601350760600
131     300.220948647014100
132     304.686856765668720
133     309.164193580146900
134     313.652829949878990
135     318.152639620209300
136     322.663499126726210
137     327.185287703775200
138     331.717887196928470
139     336.261181979198450
140     340.815058870798960
141     345.379407062266860
142     349.954118040770250
143     354.539085519440790
144     359.134205369575340
145     363.739375555563470
146     368.354496072404690
147     372.979468885689020
148     377.614197873918670
149     382.258588773060010
150     386.912549123217560
151     391.575988217329610
152     396.248817051791490
153     400.930948278915760
154     405.622296161144900
155     410.322776526937280
156     415.032306728249580
157     419.750805599544780
158     424.478193418257090
159     429.214391866651570
160     433.959323995014870
161     438.712914186121170
162     443.475088120918940
163     448.245772745384610
164     453.024896238496130
165     457.812387981278110
166     462.608178526874890
167     467.412199571608080
168     472.224383926980520
169     477.044665492585580
170     481.872979229887900
171     486.709261136839360
172     491.553448223298010
173     496.405478487217580
174     501.265290891579240
175     506.132825342034830
176     511.008022665236070
177     515.890824587822520
178     520.781173716044240
179     525.679013515995050
180     530.584288294433580
181     535.496943180169520
182     540.416924105997740
183     545.344177791154950
184     550.278651724285620
185     555.220294146894960
186     560.169054037273100
187     565.124881094874350
188     570.087725725134190
189     575.057539024710200
190     580.034272767130800
191     585.017879388839220
192     590.008311975617860
193     595.005524249382010
194     600.009470555327430
195     605.020105849423770
196     610.037385686238740
197     615.061266207084940
198     620.091704128477430
199     625.128656730891070
200     630.172081847810200
201     635.221937855059760
202     640.278183660408100
203     645.340778693435030
204     650.409682895655240
205     655.484856710889060
206     660.566261075873510
207     665.653857411105950
208     670.747607611912710
209     675.847474039736880
210     680.953419513637530
211     686.065407301994010
212     691.183401114410800
213     696.307365093814040
214     701.437263808737160
215     706.573062245787470
216     711.714725802289990
217     716.862220279103440
218     722.015511873601330
219     727.174567172815840
220     732.339353146739310
221     737.509837141777440
222     742.685986874351220
223     747.867770424643370
224     753.055156230484160
225     758.248113081374300
226     763.446610112640200
227     768.650616799717000
228     773.860102952558460
229     779.075038710167410
230     784.295394535245690
231     789.521141208958970
232     794.752249825813460
233     799.988691788643450
234     805.230438803703120
235     810.477462875863580
236     815.729736303910160
237     820.987231675937890
238     826.249921864842800
239     831.517780023906310
240     836.790779582469900
241     842.068894241700490
242     847.352097970438420
243     852.640365001133090
244     857.933669825857460
245     863.231987192405430
246     868.535292100464630
247     873.843559797865740
248     879.156765776907600
249     884.474885770751830
250     889.797895749890240
251     895.125771918679900
252     900.458490711945270
253     905.796028791646340
254     911.138363043611210
255     916.485470574328820
256     921.837328707804890
257     927.193914982476710
258     932.555207148186240
259     937.921183163208070
260     943.291821191335660
261     948.667099599019820
262     954.046996952560450
263     959.431492015349480
264     964.820563745165940
265     970.214191291518320
266     975.612353993036210
267     981.015031374908400
268     986.422203146368590
269     991.833849198223450
270     997.249949600427840
271     1002.670484599700300
272     1008.095434617181700
273     1013.524780246136200
274     1018.958502249690200
275     1024.396581558613400
276     1029.838999269135500
277     1035.285736640801600
278     1040.736775094367400
279     1046.192096209724900
280     1051.651681723869200
281     1057.115513528895000
282     1062.583573670030100
283     1068.055844343701400
284     1073.532307895632800
285     1079.012946818975000
286     1084.497743752465600
287     1089.986681478622400
288     1095.479742921962700
289     1100.976911147256000
290     1106.478169357800900
291     1111.983500893733000
292     1117.492889230361000
293     1123.006317976526100
294     1128.523770872990800
295     1134.045231790853000
296     1139.570684729984800
297     1145.100113817496100
298     1150.633503306223700
299     1156.170837573242400
300 }
301
302 PRIVATE>
303
304 : log-factorial ( n -- value )
305     {
306         { [ dup 0 < ] [ "invalid input" throw ] }
307         { [ dup 254 > ] [
308                             1 + [| x |
309                                 x 0.5 - x log * x -
310                                 0.5 2 pi * log * +
311                                 1.0 12.0 x * / +
312                             ] call
313                         ] }
314         [ lf nth ]
315     } cond ;
316
317 :: log-one-plus-x ( x -- value )
318     x -1.0 <= [ "argument must be > -1" throw ] when
319     x abs 1e-4 > [ 1.0 x + log ] [ -0.5 x * 1.0 + x * ] if ;
320
321 <PRIVATE
322
323 CONSTANT: c0 2.515517
324 CONSTANT: c1 0.802853
325 CONSTANT: c2 0.010328
326
327 CONSTANT: d0 1.432788
328 CONSTANT: d1 0.189269
329 CONSTANT: d2 0.001308
330
331 PRIVATE>
332
333 :: rational-approximation ( t -- value )
334     c2 t * c1 + t * c0 + :> numerator
335     d2 t * d1 + t * d0 + t * 1.0 + :> denominator
336     t numerator denominator / - ;
337
338 :: normal-cdf-inverse ( p -- value )
339     p [ 0 > ] [ 1 < ] bi and [ p throw ] unless
340     p 0.5 <
341     [ p log -2.0 * sqrt rational-approximation neg ]
342     [ p 1.0 - log -2.0 * sqrt rational-approximation ] if ;
343
344 <PRIVATE
345
346 ! Abramowitz and Stegun 6.1.41
347 ! Asymptotic series should be good to at least 11 or 12 figures
348 ! For error analysis, see Whittiker and Watson
349 ! A Course in Modern Analysis (1927), page 252
350 CONSTANT: c {
351      1/12
352     -1/360
353      1/1260
354     -1/1680
355      1/1188
356     -691/360360
357      1/156
358     -3617/122400
359 }
360
361 CONSTANT: halfLogTwoPi 0.91893853320467274178032973640562
362
363 PRIVATE>
364
365 DEFER: gamma
366
367 :: log-gamma ( x -- value )
368     x 0 <= [ "Invalid input" throw ] when
369     x 12 < [ x gamma abs log ] [
370         1.0 x x * / :> z
371         7 c nth 7 <iota> reverse [ [ z * ] [ c nth ] bi* + ] each x / :> series
372         x 0.5 - x log * x - halfLogTwoPi + series +
373     ] if ;
374
375 <PRIVATE
376
377 CONSTANT: GAMMA 0.577215664901532860606512090 ! Euler's gamma constant
378
379 ! numerator coefficients for approximation over the interval (1,2)
380 CONSTANT: P {
381     -1.71618513886549492533811E+0
382      2.47656508055759199108314E+1
383     -3.79804256470945635097577E+2
384      6.29331155312818442661052E+2
385      8.66966202790413211295064E+2
386     -3.14512729688483675254357E+4
387     -3.61444134186911729807069E+4
388      6.64561438202405440627855E+4
389 }
390
391 ! denominator coefficients for approximation over the interval (1,2)
392 CONSTANT: Q {
393     -3.08402300119738975254353E+1
394      3.15350626979604161529144E+2
395     -1.01515636749021914166146E+3
396     -3.10777167157231109440444E+3
397      2.25381184209801510330112E+4
398      4.75584627752788110767815E+3
399     -1.34659959864969306392456E+5
400     -1.15132259675553483497211E+5
401 }
402
403 :: (gamma) ( x -- value )
404     ! The algorithm directly approximates gamma over (1,2) and uses
405     ! reduction identities to reduce other arguments to this interval.
406     x :> y!
407     0 :> n!
408     y 1.0 < :> arg-was-less-than-one
409     arg-was-less-than-one
410     [ y 1.0 + y! ] [ y floor >integer 1 - n! y n - y! ] if
411     0.0 :> num!
412     1.0 :> den!
413     y 1 - :> z!
414     8 <iota> [
415         [ P nth num + z * num! ]
416         [ Q nth den z * + den! ] bi
417     ] each
418     num den / 1.0 +
419     arg-was-less-than-one
420     [ y 1.0 - / ] [ n [ y * y 1.0 + y! ] times ] if ;
421
422 PRIVATE>
423
424 :: gamma ( x -- value )
425     x 0 <= [ "Invalid input" throw ] when
426     x {
427         { [ dup   0.001 < ] [ GAMMA * 1.0 + x * 1.0 swap / ] }
428         { [ dup    12.0 < ] [ (gamma) ] }
429         { [ dup 171.624 > ] [ drop 1/0. ] }
430         [ log-gamma e^ ]
431     } cond ;