xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/src/std/internal/math/errorfunction.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /**
2  * Error Functions and Normal Distribution.
3  *
4  * License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
5  * Copyright: Based on the CEPHES math library, which is
6  *            Copyright (C) 1994 Stephen L. Moshier (moshier@world.std.com).
7  * Authors:   Stephen L. Moshier, ported to D by Don Clugston and David Nadlinger
8  */
9 /**
10  * Macros:
11  *  NAN = $(RED NAN)
12  *  SUP = <span style="vertical-align:super;font-size:smaller">$0</span>
13  *  GAMMA =  &#915;
14  *  INTEGRAL = &#8747;
15  *  INTEGRATE = $(BIG &#8747;<sub>$(SMALL $1)</sub><sup>$2</sup>)
16  *  POWER = $1<sup>$2</sup>
17  *  BIGSUM = $(BIG &Sigma; <sup>$2</sup><sub>$(SMALL $1)</sub>)
18  *  CHOOSE = $(BIG &#40;) <sup>$(SMALL $1)</sup><sub>$(SMALL $2)</sub> $(BIG &#41;)
19  *  TABLE_SV = <table border="1" cellpadding="4" cellspacing="0">
20  *      <caption>Special Values</caption>
21  *      $0</table>
22  *  SVH = $(TR $(TH $1) $(TH $2))
23  *  SV  = $(TR $(TD $1) $(TD $2))
24  */
25 module std.internal.math.errorfunction;
26 import std.math;
27 import core.math : fabs, sqrt;
28 
29 pure:
30 nothrow:
31 @safe:
32 @nogc:
33 
34 private {
35 immutable real EXP_2  = 0.135335283236612691893999494972484403L; /* exp(-2) */
36 enum real SQRT2PI = 2.50662827463100050241576528481104525L; // sqrt(2pi)
37 
38 
39 enum real MAXLOG = 0x1.62e42fefa39ef358p+13L;  // log(real.max)
40 enum real MINLOG = -0x1.6436716d5406e6d8p+13L; // log(real.min*real.epsilon) = log(smallest denormal)
41 }
42 
rationalPoly(T)43 T rationalPoly(T)(T x, const(T) [] numerator, const(T) [] denominator) pure nothrow
44 {
45     return poly(x, numerator)/poly(x, denominator);
46 }
47 
48 
49 private {
50 
51 /* erfc(x) = exp(-x^2) P(1/x)/Q(1/x)
52    1/8 <= 1/x <= 1
53    Peak relative error 5.8e-21  */
54 immutable real[10] P = [ -0x1.30dfa809b3cc6676p-17L, 0x1.38637cd0913c0288p+18L,
55    0x1.2f015e047b4476bp+22L, 0x1.24726f46aa9ab08p+25L, 0x1.64b13c6395dc9c26p+27L,
56    0x1.294c93046ad55b5p+29L, 0x1.5962a82f92576dap+30L, 0x1.11a709299faba04ap+31L,
57    0x1.11028065b087be46p+31L, 0x1.0d8ef40735b097ep+30L
58 ];
59 
60 immutable real[11] Q = [ 0x1.14d8e2a72dec49f4p+19L, 0x1.0c880ff467626e1p+23L,
61    0x1.04417ef060b58996p+26L, 0x1.404e61ba86df4ebap+28L, 0x1.0f81887bc82b873ap+30L,
62    0x1.4552a5e39fb49322p+31L, 0x1.11779a0ceb2a01cep+32L, 0x1.3544dd691b5b1d5cp+32L,
63    0x1.a91781f12251f02ep+31L, 0x1.0d8ef3da605a1c86p+30L, 1.0L
64 ];
65 
66 // For 128 bit quadruple-precision floats, we use a higher-precision implementation
67 // with more polynomial segments.
68 enum isIEEEQuadruple = floatTraits!real.realFormat == RealFormat.ieeeQuadruple;
69 static if (isIEEEQuadruple)
70 {
71     // erfc(x + 0.25) = erfc(0.25) + x R(x)
72     // 0 <= x < 0.125
73     // Peak relative error 1.4e-35
74     immutable real[9] RNr13 = [
75         -2.353707097641280550282633036456457014829E3L,
76         3.871159656228743599994116143079870279866E2L,
77         -3.888105134258266192210485617504098426679E2L,
78         -2.129998539120061668038806696199343094971E1L,
79         -8.125462263594034672468446317145384108734E1L,
80         8.151549093983505810118308635926270319660E0L,
81         -5.033362032729207310462422357772568553670E0L,
82         -4.253956621135136090295893547735851168471E-2L,
83         -8.098602878463854789780108161581050357814E-2L
84     ];
85     immutable real[9] RDr13 = [
86         2.220448796306693503549505450626652881752E3L,
87         1.899133258779578688791041599040951431383E2L,
88         1.061906712284961110196427571557149268454E3L,
89         7.497086072306967965180978101974566760042E1L,
90         2.146796115662672795876463568170441327274E2L,
91         1.120156008362573736664338015952284925592E1L,
92         2.211014952075052616409845051695042741074E1L,
93         6.469655675326150785692908453094054988938E-1L,
94         1.0
95     ];
96 
97     // erfc(0.25) = C13a + C13b to extra precision.
98     immutable real C13a = 0.723663330078125L;
99     immutable real C13b = 1.0279753638067014931732235184287934646022E-5L;
100 
101     // erfc(x + 0.375) = erfc(0.375) + x R(x)
102     // 0 <= x < 0.125
103     // Peak relative error 1.2e-35
104     immutable real[9] RNr14 = [
105         -2.446164016404426277577283038988918202456E3L,
106         6.718753324496563913392217011618096698140E2L,
107         -4.581631138049836157425391886957389240794E2L,
108         -2.382844088987092233033215402335026078208E1L,
109         -7.119237852400600507927038680970936336458E1L,
110         1.313609646108420136332418282286454287146E1L,
111         -6.188608702082264389155862490056401365834E0L,
112         -2.787116601106678287277373011101132659279E-2L,
113         -2.230395570574153963203348263549700967918E-2L
114     ];
115     immutable real[9] RDr14 = [
116         2.495187439241869732696223349840963702875E3L,
117         2.503549449872925580011284635695738412162E2L,
118         1.159033560988895481698051531263861842461E3L,
119         9.493751466542304491261487998684383688622E1L,
120         2.276214929562354328261422263078480321204E2L,
121         1.367697521219069280358984081407807931847E1L,
122         2.276988395995528495055594829206582732682E1L,
123         7.647745753648996559837591812375456641163E-1L,
124         1.0L
125     ];
126 
127     // erfc(0.375) = C14a + C14b to extra precision.
128     immutable real C14a = 0.5958709716796875L;
129     immutable real C14b = 1.2118885490201676174914080878232469565953E-5L;
130 
131     // erfc(x + 0.5) = erfc(0.5) + x R(x)
132     // 0 <= x < 0.125
133     // Peak relative error 4.7e-36
134     immutable real[9] RNr15 = [
135         -2.624212418011181487924855581955853461925E3L,
136         8.473828904647825181073831556439301342756E2L,
137         -5.286207458628380765099405359607331669027E2L,
138         -3.895781234155315729088407259045269652318E1L,
139         -6.200857908065163618041240848728398496256E1L,
140         1.469324610346924001393137895116129204737E1L,
141         -6.961356525370658572800674953305625578903E0L,
142         5.145724386641163809595512876629030548495E-3L,
143         1.990253655948179713415957791776180406812E-2L
144     ];
145     immutable real[9] RDr15 = [
146         2.986190760847974943034021764693341524962E3L,
147         5.288262758961073066335410218650047725985E2L,
148         1.363649178071006978355113026427856008978E3L,
149         1.921707975649915894241864988942255320833E2L,
150         2.588651100651029023069013885900085533226E2L,
151         2.628752920321455606558942309396855629459E1L,
152         2.455649035885114308978333741080991380610E1L,
153         1.378826653595128464383127836412100939126E0L,
154         1.0L
155     ];
156     // erfc(0.5) = C15a + C15b to extra precision.
157     immutable real C15a = 0.4794921875L;
158     immutable real C15b = 7.9346869534623172533461080354712635484242E-6L;
159 
160     // erfc(x + 0.625) = erfc(0.625) + x R(x)
161     // 0 <= x < 0.125
162     // Peak relative error 5.1e-36
163     immutable real[9] RNr16 = [
164         -2.347887943200680563784690094002722906820E3L,
165         8.008590660692105004780722726421020136482E2L,
166         -5.257363310384119728760181252132311447963E2L,
167         -4.471737717857801230450290232600243795637E1L,
168         -4.849540386452573306708795324759300320304E1L,
169         1.140885264677134679275986782978655952843E1L,
170         -6.731591085460269447926746876983786152300E0L,
171         1.370831653033047440345050025876085121231E-1L,
172         2.022958279982138755020825717073966576670E-2L,
173     ];
174     immutable real[9] RDr16 = [
175         3.075166170024837215399323264868308087281E3L,
176         8.730468942160798031608053127270430036627E2L,
177         1.458472799166340479742581949088453244767E3L,
178         3.230423687568019709453130785873540386217E2L,
179         2.804009872719893612081109617983169474655E2L,
180         4.465334221323222943418085830026979293091E1L,
181         2.612723259683205928103787842214809134746E1L,
182         2.341526751185244109722204018543276124997E0L,
183         1.0L
184     ];
185     // erfc(0.625) = C16a + C16b to extra precision.
186     immutable real C16a = 0.3767547607421875L;
187     immutable real C16b = 4.3570693945275513594941232097252997287766E-6L;
188 
189     // erfc(x + 0.75) = erfc(0.75) + x R(x)
190     // 0 <= x < 0.125
191     // Peak relative error 1.7e-35
192     immutable real[9] RNr17 = [
193         -1.767068734220277728233364375724380366826E3L,
194         6.693746645665242832426891888805363898707E2L,
195         -4.746224241837275958126060307406616817753E2L,
196         -2.274160637728782675145666064841883803196E1L,
197         -3.541232266140939050094370552538987982637E1L,
198         6.988950514747052676394491563585179503865E0L,
199         -5.807687216836540830881352383529281215100E0L,
200         3.631915988567346438830283503729569443642E-1L,
201         -1.488945487149634820537348176770282391202E-2L
202     ];
203     immutable real[9] RDr17 = [
204         2.748457523498150741964464942246913394647E3L,
205         1.020213390713477686776037331757871252652E3L,
206         1.388857635935432621972601695296561952738E3L,
207         3.903363681143817750895999579637315491087E2L,
208         2.784568344378139499217928969529219886578E2L,
209         5.555800830216764702779238020065345401144E1L,
210         2.646215470959050279430447295801291168941E1L,
211         2.984905282103517497081766758550112011265E0L,
212         1.0L
213     ];
214     // erfc(0.75) = C17a + C17b to extra precision.
215     immutable real C17a = 0.2888336181640625L;
216     immutable real C17b = 1.0748182422368401062165408589222625794046E-5L;
217 
218 
219     // erfc(x + 0.875) = erfc(0.875) + x R(x)
220     // 0 <= x < 0.125
221     // Peak relative error 2.2e-35
222     immutable real[9] RNr18 = [
223         -1.342044899087593397419622771847219619588E3L,
224         6.127221294229172997509252330961641850598E2L,
225         -4.519821356522291185621206350470820610727E2L,
226         1.223275177825128732497510264197915160235E1L,
227         -2.730789571382971355625020710543532867692E1L,
228         4.045181204921538886880171727755445395862E0L,
229         -4.925146477876592723401384464691452700539E0L,
230         5.933878036611279244654299924101068088582E-1L,
231         -5.557645435858916025452563379795159124753E-2L
232     ];
233     immutable real[9] RDr18 = [
234         2.557518000661700588758505116291983092951E3L,
235         1.070171433382888994954602511991940418588E3L,
236         1.344842834423493081054489613250688918709E3L,
237         4.161144478449381901208660598266288188426E2L,
238         2.763670252219855198052378138756906980422E2L,
239         5.998153487868943708236273854747564557632E1L,
240         2.657695108438628847733050476209037025318E1L,
241         3.252140524394421868923289114410336976512E0L,
242         1.0L
243     ];
244 
245     // erfc(0.875) = C18a + C18b to extra precision.
246     immutable real C18a = 0.215911865234375L;
247     immutable real C18b = 1.3073705765341685464282101150637224028267E-5L;
248 
249     // erfc(x + 1.0) = erfc(1.0) + x R(x)
250     // 0 <= x < 0.125
251     // Peak relative error 1.6e-35
252     immutable real[9] RNr19 = [
253         -1.139180936454157193495882956565663294826E3L,
254         6.134903129086899737514712477207945973616E2L,
255         -4.628909024715329562325555164720732868263E2L,
256         4.165702387210732352564932347500364010833E1L,
257         -2.286979913515229747204101330405771801610E1L,
258         1.870695256449872743066783202326943667722E0L,
259         -4.177486601273105752879868187237000032364E0L,
260         7.533980372789646140112424811291782526263E-1L,
261         -8.629945436917752003058064731308767664446E-2L
262     ];
263     immutable real[9] RDr19 = [
264         2.744303447981132701432716278363418643778E3L,
265         1.266396359526187065222528050591302171471E3L,
266         1.466739461422073351497972255511919814273E3L,
267         4.868710570759693955597496520298058147162E2L,
268         2.993694301559756046478189634131722579643E2L,
269         6.868976819510254139741559102693828237440E1L,
270         2.801505816247677193480190483913753613630E1L,
271         3.604439909194350263552750347742663954481E0L,
272         1.0L
273     ];
274 
275     // erfc(1.0) = C19a + C19b to extra precision.
276     immutable real C19a = 0.15728759765625L;
277     immutable real C19b = 1.1609394035130658779364917390740703933002E-5L;
278 
279     // erfc(x + 1.125) = erfc(1.125) + x R(x)
280     // 0 <= x < 0.125
281     // Peak relative error 3.6e-36
282     immutable real[9] RNr20 = [
283         -9.652706916457973956366721379612508047640E2L,
284         5.577066396050932776683469951773643880634E2L,
285         -4.406335508848496713572223098693575485978E2L,
286         5.202893466490242733570232680736966655434E1L,
287         -1.931311847665757913322495948705563937159E1L,
288         -9.364318268748287664267341457164918090611E-2L,
289         -3.306390351286352764891355375882586201069E0L,
290         7.573806045289044647727613003096916516475E-1L,
291         -9.611744011489092894027478899545635991213E-2L
292     ];
293     immutable real[9] RDr20 = [
294         3.032829629520142564106649167182428189014E3L,
295         1.659648470721967719961167083684972196891E3L,
296         1.703545128657284619402511356932569292535E3L,
297         6.393465677731598872500200253155257708763E2L,
298         3.489131397281030947405287112726059221934E2L,
299         8.848641738570783406484348434387611713070E1L,
300         3.132269062552392974833215844236160958502E1L,
301         4.430131663290563523933419966185230513168E0L,
302         1.0L
303     ];
304 
305     // erfc(1.125) = C20a + C20b to extra precision.
306     immutable real C20a = 0.111602783203125L;
307     immutable real C20b = 8.9850951672359304215530728365232161564636E-6L;
308 
309     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
310     // 7/8 <= 1/x < 1
311     // Peak relative error 1.4e-35
312     immutable real[10] RNr8 = [
313         3.587451489255356250759834295199296936784E1L,
314         5.406249749087340431871378009874875889602E2L,
315         2.931301290625250886238822286506381194157E3L,
316         7.359254185241795584113047248898753470923E3L,
317         9.201031849810636104112101947312492532314E3L,
318         5.749697096193191467751650366613289284777E3L,
319         1.710415234419860825710780802678697889231E3L,
320         2.150753982543378580859546706243022719599E2L,
321         8.740953582272147335100537849981160931197E0L,
322         4.876422978828717219629814794707963640913E-2L
323     ];
324     immutable real[10] RDr8 = [
325         6.358593134096908350929496535931630140282E1L,
326         9.900253816552450073757174323424051765523E2L,
327         5.642928777856801020545245437089490805186E3L,
328         1.524195375199570868195152698617273739609E4L,
329         2.113829644500006749947332935305800887345E4L,
330         1.526438562626465706267943737310282977138E4L,
331         5.561370922149241457131421914140039411782E3L,
332         9.394035530179705051609070428036834496942E2L,
333         6.147019596150394577984175188032707343615E1L,
334         1.0L
335     ];
336 
337     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
338     // 3/4 <= 1/x < 7/8
339     // Peak relative error 1.7e-36
340     immutable real[10] RNr7 = [
341         1.293515364043117601705535485785956592493E2L,
342         2.474534371269189867053251150063459055230E3L,
343         1.756537563959875738809491329250457486510E4L,
344         5.977479535376639763773153344676726091607E4L,
345         1.054313816139671870123172936972055385049E5L,
346         9.754699773487726957401038094714603033904E4L,
347         4.579131242577671038339922925213209214880E4L,
348         1.000710322164510887997115157797717324370E4L,
349         8.496863250712471449526805271633794700452E2L,
350         1.797349831386892396933210199236530557333E1L
351     ];
352     immutable real[11] RDr7 = [
353         2.292696320307033494820399866075534515002E2L,
354         4.500632608295626968062258401895610053116E3L,
355         3.321218723485498111535866988511716659339E4L,
356         1.196084512221845156596781258490840961462E5L,
357         2.287033883912529843927983406878910939930E5L,
358         2.370223495794642027268482075021298394425E5L,
359         1.305173734022437154610938308944995159199E5L,
360         3.589386258485887630236490009835928559621E4L,
361         4.339996864041074149726360516336773136101E3L,
362         1.753135522665469574605384979152863899099E2L,
363         1.0L
364     ];
365 
366     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
367     // 5/8 <= 1/x < 3/4
368     // Peak relative error 1.6e-35
369     immutable real[10] RNr6 = [
370         1.423313561367394923305025174137639124533E1L,
371         3.244462503273003837514629113846075327206E2L,
372         2.784937282403293364911673341412846781934E3L,
373         1.163060685810874867196849890286455473382E4L,
374         2.554141394931962276102205517358731053756E4L,
375         2.982733782500729530503336931258698708782E4L,
376         1.789683564523810605328169719436374742840E4L,
377         5.056032142227470121262177112822018882754E3L,
378         5.605349942234782054561269306895707034586E2L,
379         1.561652599080729507274832243665726064881E1L
380     ];
381     immutable real[11] RDr6 = [
382         2.522757606611479946069351519410222913326E1L,
383         5.876797910931896554014229647006604017806E2L,
384         5.211092128250480712011248211246144751074E3L,
385         2.282679910855404599271496827409168580797E4L,
386         5.371245819205596609986320599133109262447E4L,
387         6.926186102106400355114925675028888924445E4L,
388         4.794366033363621432575096487724913414473E4L,
389         1.673190682734065914573814938835674963896E4L,
390         2.589544846151313120096957014256536236242E3L,
391         1.349438432583208276883323156200117027433E2L,
392         1.0L
393     ];
394 
395     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
396     // 1/2 <= 1/x < 5/8
397     // Peak relative error 4.3e-36
398     immutable real[11] RNr5 = [
399         6.743447478279267339131211137241149796763E-2L,
400         2.031339015932962998168472743355874796350E0L,
401         2.369234815713196480221800940201367484379E1L,
402         1.387819614016107433603101545594790875922E2L,
403         4.435600256936515839937720907171966121786E2L,
404         7.881577949936817507981170892417739733047E2L,
405         7.615749099291545976179905281851765734680E2L,
406         3.752484528663442467089606663006771157777E2L,
407         8.279644286027145214308303292537009564726E1L,
408         6.201462983413738162709722770960040042647E0L,
409         6.649631608720062333043506249503378282697E-2L
410     ];
411     immutable real[11] RDr5 = [
412         1.195244945161889822018178270706903972343E-1L,
413         3.660216908153253021384862427197665991311E0L,
414         4.373405883243078019655721779021995159854E1L,
415         2.653305963056235008916733402786877121865E2L,
416         8.921329790491152046318422124415895506335E2L,
417         1.705552231555600759729260640562363304312E3L,
418         1.832711109606893446763174603477244625325E3L,
419         1.056823953275835649973998168744261083316E3L,
420         2.975561981792909722126456997074344895584E2L,
421         3.393149095158232521894537008472203487436E1L,
422         1.0L
423     ];
424 
425     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
426     // 3/8 <= 1/x < 1/2
427     // Peak relative error 1.8e-36
428     immutable real[11] RNr4 = [
429         3.558685919236420073872459554885612994007E-2L,
430         1.460223642496950651561817195253277924528E0L,
431         2.379856746555189546876720308841066577268E1L,
432         2.005205521246554860334064698817220160117E2L,
433         9.533374928664989955629120027419490517596E2L,
434         2.623024576994438336130421711314560425373E3L,
435         4.126446434603735586340585027628851620886E3L,
436         3.540675861596687801829655387867654030013E3L,
437         1.506037084891064572653273761987617394259E3L,
438         2.630715699182706745867272452228891752353E2L,
439         1.202476629652900619635409242749750364878E1L
440     ];
441     immutable real[12] RDr4 = [
442         6.307606561714590590399683184410336583739E-2L,
443         2.619717051134271249293056836082721776665E0L,
444         4.344441402681725017630451522968410844608E1L,
445         3.752891116408399440953195184301023399176E2L,
446         1.849305988804654653921972804388006355502E3L,
447         5.358505261991675891835885654499883449403E3L,
448         9.091890995405251314631428721090705475825E3L,
449         8.731418313949291797856351745278287516416E3L,
450         4.420211285043270337492325400764271868740E3L,
451         1.031487363021856106882306509107923200832E3L,
452         8.387036084846046121805145056040429461783E1L,
453         1.0L
454     ];
455 
456     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
457     // 1/4 <= 1/x < 3/8
458     // Peak relative error 8.1e-37
459     immutable real[12] RNr3 = [
460         4.584481542956275354582319313040418316755E-5L,
461         2.674923158288848442110883948437930349128E-3L,
462         6.344232532055212248017211243740466847311E-2L,
463         7.985145965992002744933550450451513513963E-1L,
464         5.845078061888281665064746347663123946270E0L,
465         2.566625318816866587482759497608029522596E1L,
466         6.736225182343446605268837827950856640948E1L,
467         1.021796460139598089409347761712730512053E2L,
468         8.344336615515430530929955615400706619764E1L,
469         3.207749011528249356283897356277376306967E1L,
470         4.386185123863412086856423971695142026036E0L,
471         8.971576448581208351826868348023528863856E-2L
472     ];
473     immutable real[12] RDr3 = [
474         8.125781965218112303281657065320409661370E-5L,
475         4.781806762611504685247817818428945295520E-3L,
476         1.147785538413798317790357996845767614561E-1L,
477         1.469285552007088106614218996464752307606E0L,
478         1.101712261349880339221039938999124077650E1L,
479         5.008507527095093413713171655268276861071E1L,
480         1.383058691613468970486425146336829447433E2L,
481         2.264114250278912520501010108736339599752E2L,
482         2.081377197698598680576330179979996940039E2L,
483         9.724438129690013609440151781601781137944E1L,
484         1.907905050771832372089975877589291760121E1L,
485         1.0L
486     ];
487 
488     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
489     // 1/8 <= 1/x < 1/4
490     // Peak relative error 1.5e-36
491     immutable real[12] RNr2 = [
492         6.928615158005256885698045840589513728399E-7L,
493         5.616245938942075826026382337922413007879E-5L,
494         1.871624980715261794832358438894219696113E-3L,
495         3.349922063795792371642023765253747563009E-2L,
496         3.531865233974349943956345502463135695834E-1L,
497         2.264714157625072773976468825160906342360E0L,
498         8.810720294489253776747319730638214883026E0L,
499         2.014056685571655833019183248931442888437E1L,
500         2.524586947657190747039554310814128743320E1L,
501         1.520656940937208886246188940244581671609E1L,
502         3.334145500790963675035841482334493680498E0L,
503         1.122108380007109245896534245151140632457E-1L
504     ];
505     immutable real[12] RDr2 = [
506         1.228065061824874795984937092427781089256E-6L,
507         1.001593999520159167559129042893802235969E-4L,
508         3.366527555699367241421450749821030974446E-3L,
509         6.098626947195865254152265585991861150369E-2L,
510         6.541547922508613985813189387198804660235E-1L,
511         4.301130233305371976727117480925676583204E0L,
512         1.737155892350891711527711121692994762909E1L,
513         4.206892112110558214680649401236873828801E1L,
514         5.787487996025016843403524261574779631219E1L,
515         4.094047148590822715163181507813774861621E1L,
516         1.230603930056944875836549716515643997094E1L,
517         1.0L
518     ];
519 
520     // erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
521     // 1/128 <= 1/x < 1/8
522     // Peak relative error 2.2e-36
523     immutable real[10] RNr1 = [
524         1.293111801138199795250035229383033322539E-6L,
525         9.785224720880980456171438759161161816706E-5L,
526         2.932474396233212166056331430621176065943E-3L,
527         4.496429595719847083917435337780697436921E-2L,
528         3.805989855927720844877478869846718877846E-1L,
529         1.789745532222426292126781724570152590071E0L,
530         4.465737379634389318903237306594171764628E0L,
531         5.268535822258082278401240171488850433767E0L,
532         2.258357766807433839494276681092713991651E0L,
533         1.504459334078750002966538036652860809497E-1L
534     ];
535     immutable real[10] RDr1 = [
536         2.291980991578770070179177302906728371406E-6L,
537         1.745845828808028552029674694534934620384E-4L,
538         5.283248841982102317072923869576785278019E-3L,
539         8.221212297078141470944454807434634848018E-2L,
540         7.120500674861902950423510939060230945621E-1L,
541         3.475435367560809622183983439133664598155E0L,
542         9.243253391989233533874386043611304387113E0L,
543         1.227894792475280941511758877318903197188E1L,
544         6.789361410398841316638617624392719077724E0L,
545         1.0L
546     ];
547 
548     // erf(z+1)  = erfConst + P(z)/Q(z)
549     // -.125 <= z <= 0
550     // Peak relative error 7.3e-36
551     immutable real erfConst = 0.845062911510467529296875L;
552     immutable real[9] TN2 = [
553         -4.088889697077485301010486931817357000235E1L,
554         7.157046430681808553842307502826960051036E3L,
555         -2.191561912574409865550015485451373731780E3L,
556         2.180174916555316874988981177654057337219E3L,
557         2.848578658049670668231333682379720943455E2L,
558         1.630362490952512836762810462174798925274E2L,
559         6.317712353961866974143739396865293596895E0L,
560         2.450441034183492434655586496522857578066E1L,
561         5.127662277706787664956025545897050896203E-1L
562     ];
563     immutable real[10] TD2 = [
564         1.731026445926834008273768924015161048885E4L,
565         1.209682239007990370796112604286048173750E4L,
566         1.160950290217993641320602282462976163857E4L,
567         5.394294645127126577825507169061355698157E3L,
568         2.791239340533632669442158497532521776093E3L,
569         8.989365571337319032943005387378993827684E2L,
570         2.974016493766349409725385710897298069677E2L,
571         6.148192754590376378740261072533527271947E1L,
572         1.178502892490738445655468927408440847480E1L,
573         1.0L
574     ];
575 
576     // erf(x)  = x + x P(x^2)/Q(x^2)
577     // 0 <= x <= 7/8
578     // Peak relative error 1.8e-35
579     immutable real[9] TN1 = [
580         -3.858252324254637124543172907442106422373E10L,
581         9.580319248590464682316366876952214879858E10L,
582         1.302170519734879977595901236693040544854E10L,
583         2.922956950426397417800321486727032845006E9L,
584         1.764317520783319397868923218385468729799E8L,
585         1.573436014601118630105796794840834145120E7L,
586         4.028077380105721388745632295157816229289E5L,
587         1.644056806467289066852135096352853491530E4L,
588         3.390868480059991640235675479463287886081E1L
589     ];
590     immutable real[10] TD1 = [
591         -3.005357030696532927149885530689529032152E11L,
592         -1.342602283126282827411658673839982164042E11L,
593         -2.777153893355340961288511024443668743399E10L,
594         -3.483826391033531996955620074072768276974E9L,
595         -2.906321047071299585682722511260895227921E8L,
596         -1.653347985722154162439387878512427542691E7L,
597         -6.245520581562848778466500301865173123136E5L,
598         -1.402124304177498828590239373389110545142E4L,
599         -1.209368072473510674493129989468348633579E2L,
600         1.0L
601     ];
602 }
603 else
604 {
605     /* erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2)
606        1/128 <= 1/x < 1/8
607        Peak relative error 1.9e-21  */
608     immutable real[5] R = [ 0x1.b9f6d8b78e22459ep-6L, 0x1.1b84686b0a4ea43ap-1L,
609        0x1.b8f6aebe96000c2ap+1L, 0x1.cb1dbedac27c8ec2p+2L, 0x1.cf885f8f572a4c14p+1L
610     ];
611 
612     immutable real[6] S = [
613        0x1.87ae3cae5f65eb5ep-5L, 0x1.01616f266f306d08p+0L, 0x1.a4abe0411eed6c22p+2L,
614        0x1.eac9ce3da600abaap+3L, 0x1.5752a9ac2faebbccp+3L, 1.0L
615     ];
616 
617     /* erf(x)  = x P(x^2)/Q(x^2)
618        0 <= x <= 1
619        Peak relative error 7.6e-23  */
620     immutable real[7] T = [ 0x1.0da01654d757888cp+20L, 0x1.2eb7497bc8b4f4acp+17L,
621        0x1.79078c19530f72a8p+15L, 0x1.4eaf2126c0b2c23p+11L, 0x1.1f2ea81c9d272a2ep+8L,
622        0x1.59ca6e2d866e625p+2L, 0x1.c188e0b67435faf4p-4L
623     ];
624 
625     immutable real[7] U = [ 0x1.dde6025c395ae34ep+19L, 0x1.c4bc8b6235df35aap+18L,
626        0x1.8465900e88b6903ap+16L, 0x1.855877093959ffdp+13L, 0x1.e5c44395625ee358p+9L,
627        0x1.6a0fed103f1c68a6p+5L, 1.0L
628     ];
629 }
630 }
631 
632 /**
633  *  Complementary error function
634  *
635  * erfc(x) = 1 - erf(x), and has high relative accuracy for
636  * values of x far from zero. (For values near zero, use erf(x)).
637  *
638  *  1 - erf(x) =  2/ $(SQRT)(&pi;)
639  *     $(INTEGRAL x, $(INFINITY)) exp( - $(POWER t, 2)) dt
640  *
641  *
642  * For small x, erfc(x) = 1 - erf(x); otherwise rational
643  * approximations are computed.
644  *
645  * A special function expx2(x) is used to suppress error amplification
646  * in computing exp(-x^2).
647  */
erfc(real a)648 real erfc(real a)
649 {
650     if (a == real.infinity)
651         return 0.0;
652     if (a == -real.infinity)
653         return 2.0;
654 
655     immutable x = (a < 0.0) ? -a : a;
656 
657     if (x < (isIEEEQuadruple ? 0.25 : 1.0))
658         return 1.0 - erf(a);
659 
660     static if (isIEEEQuadruple)
661     {
662         if (x < 1.25)
663         {
664             real y;
665             final switch (cast(int)(8.0 * x))
666             {
667                 case 2:
668                     const z = x - 0.25;
669                     y = C13b + z * rationalPoly(z, RNr13, RDr13);
670                     y += C13a;
671                     break;
672                 case 3:
673                     const z = x - 0.375;
674                     y = C14b + z * rationalPoly(z, RNr14, RDr14);
675                     y += C14a;
676                     break;
677                 case 4:
678                     const z = x - 0.5;
679                     y = C15b + z * rationalPoly(z, RNr15, RDr15);
680                     y += C15a;
681                     break;
682                 case 5:
683                     const z = x - 0.625;
684                     y = C16b + z * rationalPoly(z, RNr16, RDr16);
685                     y += C16a;
686                     break;
687                 case 6:
688                     const z = x - 0.75;
689                     y = C17b + z * rationalPoly(z, RNr17, RDr17);
690                     y += C17a;
691                     break;
692                 case 7:
693                     const z = x - 0.875;
694                     y = C18b + z * rationalPoly(z, RNr18, RDr18);
695                     y += C18a;
696                     break;
697                 case 8:
698                     const z = x - 1.0;
699                     y = C19b + z * rationalPoly(z, RNr19, RDr19);
700                     y += C19a;
701                     break;
702                 case 9:
703                     const z = x - 1.125;
704                     y = C20b + z * rationalPoly(z, RNr20, RDr20);
705                     y += C20a;
706                     break;
707             }
708             if (a < 0.0)
709                 y = 2.0 - y;
710             return y;
711         }
712     }
713 
714     if (-a * a < -MAXLOG)
715     {
716         // underflow
717         if (a < 0.0) return 2.0;
718         else return 0.0;
719     }
720 
721     real y;
722     immutable z = expx2(a, -1);
723 
724     static if (isIEEEQuadruple)
725     {
726         y = z * erfce(x);
727     }
728     else
729     {
730         y = 1.0 / x;
731         if (x < 8.0)
732             y = z * rationalPoly(y, P, Q);
733         else
734             y = z * y * rationalPoly(y * y, R, S);
735     }
736 
737     if (a < 0.0)
738         y = 2.0 - y;
739 
740     if (y == 0.0)
741     {
742         // underflow
743         if (a < 0.0) return 2.0;
744         else return 0.0;
745     }
746 
747     return y;
748 }
749 
750 
751 private {
752 /* Exponentially scaled erfc function
753    exp(x^2) erfc(x)
754    valid for x > 1.
755    Use with normalDistribution and expx2.  */
756 static if (isIEEEQuadruple)
757 {
erfce(real x)758     real erfce(real x)
759     {
760         immutable z = 1.0L / (x * x);
761 
762         real p;
763         switch (cast(int)(8.0 / x))
764         {
765             default:
766             case 0:
767                 p = rationalPoly(z, RNr1, RDr1);
768                 break;
769             case 1:
770                 p = rationalPoly(z, RNr2, RDr2);
771                 break;
772             case 2:
773                 p = rationalPoly(z, RNr3, RDr3);
774                 break;
775             case 3:
776                 p = rationalPoly(z, RNr4, RDr4);
777                 break;
778             case 4:
779                 p = rationalPoly(z, RNr5, RDr5);
780                 break;
781             case 5:
782                 p = rationalPoly(z, RNr6, RDr6);
783                 break;
784             case 6:
785                 p = rationalPoly(z, RNr7, RDr7);
786                 break;
787             case 7:
788                 p = rationalPoly(z, RNr8, RDr8);
789                 break;
790         }
791         return p / x;
792     }
793 }
794 else
795 {
erfce(real x)796     real erfce(real x)
797     {
798         real y = 1.0/x;
799 
800         if (x < 8.0)
801         {
802             return rationalPoly(y, P, Q);
803         }
804         else
805         {
806             return y * rationalPoly(y * y, R, S);
807         }
808     }
809 }
810 }
811 
812 /**
813  *  Error function
814  *
815  * The integral is
816  *
817  *  erf(x) =  2/ $(SQRT)(&pi;)
818  *     $(INTEGRAL 0, x) exp( - $(POWER t, 2)) dt
819  *
820  * The magnitude of x is limited to about 106.56 for IEEE 80-bit
821  * arithmetic; 1 or -1 is returned outside this range.
822  *
823  * For 0 <= |x| < 1, a rational polynomials are used; otherwise
824  * erf(x) = 1 - erfc(x).
825  *
826  * ACCURACY:
827  *                      Relative error:
828  * arithmetic   domain     # trials      peak         rms
829  *    IEEE      0,1         50000       2.0e-19     5.7e-20
830  */
erf(real x)831 real erf(real x)
832 {
833     if (x == 0.0)
834         return x; // deal with negative zero
835     if (x == -real.infinity)
836         return -1.0;
837     if (x == real.infinity)
838         return 1.0;
839     immutable ax = fabs(x);
840     if (ax > 1.0L)
841         return 1.0L - erfc(x);
842 
843     static if (isIEEEQuadruple)
844     {
845         immutable z = x * x;
846 
847         real y;
848         if (ax < 0.875)
849         {
850             y = ax + ax * rationalPoly(x * x, TN1, TD1);
851         }
852         else
853         {
854             y = erfConst + rationalPoly(ax - 1.0L, TN2, TD2);
855         }
856 
857         if (x < 0)
858             y = -y;
859         return y;
860     }
861     else
862     {
863         real z = x * x;
864         return x * rationalPoly(x * x, T, U);
865     }
866 }
867 
868 @safe unittest
869 {
870     // High resolution test points.
871     enum real erfc0_250 = 0.723663330078125L + 1.0279753638067014931732235184287934646022E-5L;
872     enum real erfc0_375 = 0.5958709716796875L + 1.2118885490201676174914080878232469565953E-5L;
873     enum real erfc0_500 = 0.4794921875L + 7.9346869534623172533461080354712635484242E-6L;
874     enum real erfc0_625 = 0.3767547607421875L + 4.3570693945275513594941232097252997287766E-6L;
875     enum real erfc0_750 = 0.2888336181640625L + 1.0748182422368401062165408589222625794046E-5L;
876     enum real erfc0_875 = 0.215911865234375L + 1.3073705765341685464282101150637224028267E-5L;
877     enum real erfc1_000 = 0.15728759765625L + 1.1609394035130658779364917390740703933002E-5L;
878     enum real erfc1_125 = 0.111602783203125L + 8.9850951672359304215530728365232161564636E-6L;
879 
880     enum real erf0_875  = (1-0.215911865234375L) - 1.3073705765341685464282101150637224028267E-5L;
881 
isNaNWithPayload(real x,ulong payload)882     static bool isNaNWithPayload(real x, ulong payload) @safe pure nothrow @nogc
883     {
884       return isNaN(x) && getNaNPayload(x) == payload;
885     }
886 
887     assert(feqrel(erfc(0.250L), erfc0_250 )>=real.mant_dig-1);
888     assert(feqrel(erfc(0.375L), erfc0_375 )>=real.mant_dig-0);
889     assert(feqrel(erfc(0.500L), erfc0_500 )>=real.mant_dig-2);
890     assert(feqrel(erfc(0.625L), erfc0_625 )>=real.mant_dig-1);
891     assert(feqrel(erfc(0.750L), erfc0_750 )>=real.mant_dig-1);
892     assert(feqrel(erfc(0.875L), erfc0_875 )>=real.mant_dig-4);
893     assert(feqrel(erfc(1.000L), erfc1_000 )>=real.mant_dig-2);
894     assert(feqrel(erfc(1.125L), erfc1_125 )>=real.mant_dig-2);
895     assert(feqrel(erf(0.875L), erf0_875 )>=real.mant_dig-1);
896     // The DMC implementation of erfc() fails this next test (just).
897     // Test point from Mathematica 11.0.
898     assert(feqrel(erfc(4.1L), 6.70002765408489837272673380763418472e-9L) >= real.mant_dig-5);
899 
900     assert(isIdentical(erf(0.0),0.0));
901     assert(isIdentical(erf(-0.0),-0.0));
902     assert(erf(real.infinity) == 1.0);
903     assert(erf(-real.infinity) == -1.0);
904     assert(isNaNWithPayload(erf(NaN(0xDEF)), 0xDEF));
905     assert(isNaNWithPayload(erfc(NaN(0xDEF)), 0xDEF));
906     assert(isIdentical(erfc(real.infinity),0.0));
907     assert(erfc(-real.infinity) == 2.0);
908     assert(erfc(0) == 1.0);
909 }
910 
911 /*
912  *  Exponential of squared argument
913  *
914  * Computes y = exp(x*x) while suppressing error amplification
915  * that would ordinarily arise from the inexactness of the
916  * exponential argument x*x.
917  *
918  * If sign < 0, the result is inverted; i.e., y = exp(-x*x) .
919  *
920  * ACCURACY:
921  *                      Relative error:
922  * arithmetic      domain        # trials      peak         rms
923  *   IEEE     -106.566, 106.566    10^5       1.6e-19     4.4e-20
924  */
925 
expx2(real x,int sign)926 real expx2(real x, int sign)
927 {
928     /*
929     Cephes Math Library Release 2.9:  June, 2000
930     Copyright 2000 by Stephen L. Moshier
931     */
932     const real M = 32_768.0;
933     const real MINV = 3.0517578125e-5L;
934 
935     x = fabs(x);
936     if (sign < 0)
937         x = -x;
938 
939   /* Represent x as an exact multiple of M plus a residual.
940      M is a power of 2 chosen so that exp(m * m) does not overflow
941      or underflow and so that |x - m| is small.  */
942     real m = MINV * floor(M * x + 0.5L);
943     real f = x - m;
944 
945     /* x^2 = m^2 + 2mf + f^2 */
946     real u = m * m;
947     real u1 = 2 * m * f  +  f * f;
948 
949     if (sign < 0)
950     {
951         u = -u;
952         u1 = -u1;
953     }
954 
955     if ((u+u1) > MAXLOG)
956         return real.infinity;
957 
958     /* u is exact, u1 is small.  */
959     return exp(u) * exp(u1);
960 }
961 
962 
963 /*
964 Computes the normal distribution function.
965 
966 The normal (or Gaussian, or bell-shaped) distribution is
967 defined as:
968 
969 normalDist(x) = 1/$(SQRT) &pi; $(INTEGRAL -$(INFINITY), x) exp( - $(POWER t, 2)/2) dt
970     = 0.5 + 0.5 * erf(x/sqrt(2))
971     = 0.5 * erfc(- x/sqrt(2))
972 
973 To maintain accuracy at high values of x, use
974 normalDistribution(x) = 1 - normalDistribution(-x).
975 
976 Accuracy:
977 Within a few bits of machine resolution over the entire
978 range.
979 
980 References:
981 $(LINK http://www.netlib.org/cephes/ldoubdoc.html),
982 G. Marsaglia, "Evaluating the Normal Distribution",
983 Journal of Statistical Software <b>11</b>, (July 2004).
984 */
normalDistributionImpl(real a)985 real normalDistributionImpl(real a)
986 {
987     real x = a * SQRT1_2;
988     real z = fabs(x);
989 
990     if ( z < 1.0 )
991         return 0.5L + 0.5L * erf(x);
992     else
993     {
994         real y = 0.5L * erfce(z);
995         /* Multiply by exp(-x^2 / 2)  */
996         z = expx2(a, -1);
997         y = y * sqrt(z);
998         if ( x > 0.0L )
999             y = 1.0L - y;
1000         return y;
1001     }
1002 }
1003 
1004 @safe unittest
1005 {
1006 assert(fabs(normalDistributionImpl(1L) - (0.841344746068543L)) < 0.0000000000000005L);
1007 assert(isIdentical(normalDistributionImpl(NaN(0x325)), NaN(0x325)));
1008 }
1009 
1010 /*
1011  * Inverse of Normal distribution function
1012  *
1013  * Returns the argument, x, for which the area under the
1014  * Normal probability density function (integrated from
1015  * minus infinity to x) is equal to p.
1016  *
1017  * For small arguments 0 < p < exp(-2), the program computes
1018  * z = sqrt( -2 log(p) );  then the approximation is
1019  * x = z - log(z)/z  - (1/z) P(1/z) / Q(1/z) .
1020  * For larger arguments,  x/sqrt(2 pi) = w + w^3 R(w^2)/S(w^2)) ,
1021  * where w = p - 0.5.
1022  */
1023 // TODO: isIEEEQuadruple (128 bit) real implementation; not available from CEPHES.
normalDistributionInvImpl(real p)1024 real normalDistributionInvImpl(real p)
1025 in {
1026   assert(p >= 0.0L && p <= 1.0L, "Domain error");
1027 }
1028 do
1029 {
1030 static immutable real[8] P0 =
1031 [ -0x1.758f4d969484bfdcp-7L, 0x1.53cee17a59259dd2p-3L,
1032    -0x1.ea01e4400a9427a2p-1L,  0x1.61f7504a0105341ap+1L, -0x1.09475a594d0399f6p+2L,
1033     0x1.7c59e7a0df99e3e2p+1L, -0x1.87a81da52edcdf14p-1L,  0x1.1fb149fd3f83600cp-7L
1034 ];
1035 
1036 static immutable real[8] Q0 =
1037 [ -0x1.64b92ae791e64bb2p-7L, 0x1.7585c7d597298286p-3L,
1038    -0x1.40011be4f7591ce6p+0L, 0x1.1fc067d8430a425ep+2L, -0x1.21008ffb1e7ccdf2p+3L,
1039    0x1.3d1581cf9bc12fccp+3L, -0x1.53723a89fd8f083cp+2L, 1.0L
1040 ];
1041 
1042 static immutable real[10] P1 =
1043 [ 0x1.20ceea49ea142f12p-13L, 0x1.cbe8a7267aea80bp-7L,
1044    0x1.79fea765aa787c48p-2L, 0x1.d1f59faa1f4c4864p+1L, 0x1.1c22e426a013bb96p+4L,
1045    0x1.a8675a0c51ef3202p+5L, 0x1.75782c4f83614164p+6L, 0x1.7a2f3d90948f1666p+6L,
1046    0x1.5cd116ee4c088c3ap+5L, 0x1.1361e3eb6e3cc20ap+2L
1047 ];
1048 
1049 static immutable real[10] Q1 =
1050 [ 0x1.3a4ce1406cea98fap-13L, 0x1.f45332623335cda2p-7L,
1051    0x1.98f28bbd4b98db1p-2L, 0x1.ec3b24f9c698091cp+1L, 0x1.1cc56ecda7cf58e4p+4L,
1052    0x1.92c6f7376bf8c058p+5L, 0x1.4154c25aa47519b4p+6L, 0x1.1b321d3b927849eap+6L,
1053    0x1.403a5f5a4ce7b202p+4L, 1.0L
1054 ];
1055 
1056 static immutable real[8] P2 =
1057 [ 0x1.8c124a850116a6d8p-21L, 0x1.534abda3c2fb90bap-13L,
1058    0x1.29a055ec93a4718cp-7L, 0x1.6468e98aad6dd474p-3L, 0x1.3dab2ef4c67a601cp+0L,
1059    0x1.e1fb3a1e70c67464p+1L, 0x1.b6cce8035ff57b02p+2L, 0x1.9f4c9e749ff35f62p+1L
1060 ];
1061 
1062 static immutable real[8] Q2 =
1063 [ 0x1.af03f4fc0655e006p-21L, 0x1.713192048d11fb2p-13L,
1064    0x1.4357e5bbf5fef536p-7L, 0x1.7fdac8749985d43cp-3L, 0x1.4a080c813a2d8e84p+0L,
1065    0x1.c3a4b423cdb41bdap+1L, 0x1.8160694e24b5557ap+2L, 1.0L
1066 ];
1067 
1068 static immutable real[8] P3 =
1069 [ -0x1.55da447ae3806168p-34L, -0x1.145635641f8778a6p-24L,
1070  -0x1.abf46d6b48040128p-17L, -0x1.7da550945da790fcp-11L, -0x1.aa0b2a31157775fap-8L,
1071    0x1.b11d97522eed26bcp-3L, 0x1.1106d22f9ae89238p+1L, 0x1.029a358e1e630f64p+1L
1072 ];
1073 
1074 static immutable real[8] Q3 =
1075 [ -0x1.74022dd5523e6f84p-34L, -0x1.2cb60d61e29ee836p-24L,
1076    -0x1.d19e6ec03a85e556p-17L, -0x1.9ea2a7b4422f6502p-11L, -0x1.c54b1e852f107162p-8L,
1077    0x1.e05268dd3c07989ep-3L, 0x1.239c6aff14afbf82p+1L, 1.0L
1078 ];
1079 
1080     if (p <= 0.0L || p >= 1.0L)
1081     {
1082         if (p == 0.0L)
1083             return -real.infinity;
1084         if ( p == 1.0L )
1085             return real.infinity;
1086         return real.nan; // domain error
1087     }
1088     int code = 1;
1089     real y = p;
1090     if ( y > (1.0L - EXP_2) )
1091     {
1092         y = 1.0L - y;
1093         code = 0;
1094     }
1095 
1096     real x, z, y2, x0, x1;
1097 
1098     if ( y > EXP_2 )
1099     {
1100         y = y - 0.5L;
1101         y2 = y * y;
1102         x = y + y * (y2 * rationalPoly( y2, P0, Q0));
1103         return x * SQRT2PI;
1104     }
1105 
1106     x = sqrt( -2.0L * log(y) );
1107     x0 = x - log(x)/x;
1108     z = 1.0L/x;
1109     if ( x < 8.0L )
1110     {
1111         x1 = z * rationalPoly( z, P1, Q1);
1112     }
1113     else if ( x < 32.0L )
1114     {
1115         x1 = z * rationalPoly( z, P2, Q2);
1116     }
1117     else
1118     {
1119         x1 = z * rationalPoly( z, P3, Q3);
1120     }
1121     x = x0 - x1;
1122     if ( code != 0 )
1123     {
1124         x = -x;
1125     }
1126     return x;
1127 }
1128 
1129 
1130 @safe unittest
1131 {
1132     // TODO: Use verified test points.
1133     // The values below are from Excel 2003.
1134     assert(fabs(normalDistributionInvImpl(0.001) - (-3.09023230616779L)) < 0.00000000000005L);
1135     assert(fabs(normalDistributionInvImpl(1e-50) - (-14.9333375347885L)) < 0.00000000000005L);
1136     assert(feqrel(normalDistributionInvImpl(0.999L), -normalDistributionInvImpl(0.001L)) > real.mant_dig-6);
1137 
1138     // Excel 2003 gets all the following values wrong!
1139     assert(normalDistributionInvImpl(0.0) == -real.infinity);
1140     assert(normalDistributionInvImpl(1.0) == real.infinity);
1141     assert(normalDistributionInvImpl(0.5) == 0);
1142     // (Excel 2003 returns norminv(p) = -30 for all p < 1e-200).
1143     // The value tested here is the one the function returned in Jan 2006.
1144     real unknown1 = normalDistributionInvImpl(1e-250L);
1145     assert( fabs(unknown1 -(-33.79958617269L) ) < 0.00000005L);
1146 }
1147