Published
Edited
Aug 7, 2019
1 fork
Importers
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
function erf_hastings(x) {
return Math.sign(x) * (1 - Math.exp(-x * x) * hastings_R1(1 / (1 + 0.3275911 * Math.abs(x))));
}
Insert cell
hastings_R1 = R([0, 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429])
Insert cell
Insert cell
function erf_cody(x) {
const xx = x * x;
if (xx <= 0.25) return x * cody_R1(xx);
const xs = Math.sign(x);
const e_xx = Math.exp(-xx);
if (xx <= 16) return xs * (1 - e_xx * cody_R2(Math.abs(x)));
const xxi = 1 / xx;
return xs * (1 - e_xx / x * (0.5641895835477563 - xxi * cody_R3(xxi)));
}
Insert cell
cody_R1 = R([3.209377589138469472562e+3, 3.774852376853020208137e+2, 1.138641541510501556495e+2, 3.161123743870565596947e+0, 1.857777061846031526730e-1], [2.844236833439170622273e+3, 1.282616526077372275645e+3, 2.440246379344441733056e+2, 2.360129095234412093499e+1, 1])
Insert cell
cody_R2 = R([1.23033935479799725272e+3, 2.05107837782607146532e+3, 1.71204761263407058314e+3, 8.81952221241769090411e+2, 2.98635138197400131132e+2, 6.61191906371416294775e+1, 8.88314979438837594118e+0, 5.64188496988670089180e-1, 2.15311535474403846343e-8], [1.23033935480374942043e+3, 3.43936767414372163696e+3, 4.36261909014324715820e+3, 3.29079923573345962678e+3, 1.62138957456669018874e+3, 5.37181101862009857509e+2, 1.17693950891312499305e+2, 1.57449261107098347253e+1])
Insert cell
cody_R3 = R([6.58749161529837803157e-4, 1.60837851487422766278e-2, 1.25781726111229246204e-1, 3.60344899949804439429e-1, 3.05326634961232344035e-1, 1.63153871373020978498e-2], [2.33520497626869185443e-3, 6.05183413124413191178e-2, 5.27905102951428412248e-1, 1.87295284992346047209e+0, 2.56852019228982242072e+0])
Insert cell
Insert cell
Insert cell
function erfc_hastings(x) {
const xs = Math.sign(x);
return 1 - xs + xs * Math.exp(-x * x) * hastings_R1(1 / (1 + 0.3275911 * Math.abs(x)));
}
Insert cell
Insert cell
function erfc_cody(x) {
const xx = x * x;
if (xx <= 0.25) return 1 - x * cody_R1(xx);
const xs = Math.sign(x);
x = Math.abs(x);
const e_xx = Math.exp(-xx);
if (xx <= 16) return (1 - xs) + xs * e_xx * cody_R2(x);
const xxi = 1 / xx;
return (1 - xs) + xs * e_xx / x * (0.5641895835477563 - xxi * cody_R3(xxi));
}
Insert cell
Insert cell
Insert cell
erfinv_winitzki = {
const a = 8 * (Math.PI - 3) / (3 * Math.PI * (4 - Math.PI));
return x => {
const b = Math.log(1 - x * x);
const c = b / 2 + (2 / (Math.PI * a));
return Math.sign(x) * Math.sqrt(Math.sqrt((c * c) - b / a) - c);
};
}
Insert cell
Insert cell
function erfinv_acklam(x) {
return qnorm_acklam((x + 1) * 0.5) * Math.SQRT1_2;
}
Insert cell
Insert cell
Insert cell
pnorm_hastings = x => 0.5 * erfc_hastings(-x * Math.SQRT1_2)
Insert cell
pnorm_cody = x => 0.5 * erfc_cody(-x * Math.SQRT1_2)
Insert cell
Insert cell
Insert cell
qnorm_winitzki = p => Math.SQRT2 * erfinv_winitzki(2 * p - 1)
Insert cell
Insert cell
function qnorm_acklam(p) {
return p < 0.02425 ? acklam_R1(Math.sqrt(-2 * Math.log(p)))
: p > 0.97575 ? -acklam_R1(Math.sqrt(-2 * Math.log(1 - p)))
: (p -= 0.5, p * acklam_R2(p * p));
}
Insert cell
acklam_R1 = R([2.938163982698783, 4.374664141464968, -2.549732539343734, -2.400758277161838, -0.3223964580411365, -0.007784894002430293], [1, 3.754408661907416, 2.445134137142996, 0.3224671290700398, 0.007784695709041462])
Insert cell
acklam_R2 = R([2.506628277459239, -30.66479806614716, 138.357751867269, -275.9285104469687, 220.9460984245205, -39.69683028665376], [1, -13.28068155288572, 66.80131188771972, -155.6989798598866, 161.5858368580409, -54.47609879822406])
Insert cell
Insert cell
erf = erf_cody
Insert cell
erfc = erfc_cody
Insert cell
erfinv = erfinv_acklam
Insert cell
qnorm = qnorm_acklam
Insert cell
pnorm = pnorm_cody
Insert cell
function R(P, Q = []) {
const l = P.length - 1, m = Q.length - 1;
if (l === 5 && m < 0) return R_5(P);
if (l === 4 && m === 4) return R_4_4(P, Q);
if (l === 5 && m === 4) return R_5_4(P, Q);
if (l === 5 && m === 5) return R_5_5(P, Q);
if (l === 6 && m === 5) return R_6_5(P, Q);
if (l === 8 && m === 7) return R_8_7(P, Q);
throw new Error(`unsupported degree ${l},${m}`);
}
Insert cell
function R_5([p0, p1, p2, p3, p4, p5]) {
return z => p0 + z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * p5))));
}
Insert cell
function R_4_4([p0, p1, p2, p3, p4], [q0, q1, q2, q3, q4]) {
return z =>
(p0 + z * (p1 + z * (p2 + z * (p3 + z * p4))))
/ (q0 + z * (q1 + z * (q2 + z * (q3 + z * q4))));
}
Insert cell
function R_5_4([p0, p1, p2, p3, p4, p5], [q0, q1, q2, q3, q4]) {
return z =>
(p0 + z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * p5)))))
/ (q0 + z * (q1 + z * (q2 + z * (q3 + z * q4))));
}
Insert cell
function R_5_5([p0, p1, p2, p3, p4, p5], [q0, q1, q2, q3, q4, q5]) {
return z =>
(p0 + z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * p5)))))
/ (q0 + z * (q1 + z * (q2 + z * (q3 + z * (q4 + z * q5)))));
}
Insert cell
function R_6_5([p0, p1, p2, p3, p4, p5, p6], [q0, q1, q2, q3, q4, q5]) {
return z =>
(p0 + z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * (p5 + z * p6))))))
/ (q0 + z * (q1 + z * (q2 + z * (q3 + z * (q4 + z * q5)))));
}
Insert cell
function R_8_7([p0, p1, p2, p3, p4, p5, p6, p7, p8], [q0, q1, q2, q3, q4, q5, q6, q7]) {
return z =>
(p0 + z * (p1 + z * (p2 + z * (p3 + z * (p4 + z * (p5 + z * (p6 + z * (p7 + z * p8))))))))
/ (q0 + z * (q1 + z * (q2 + z * (q3 + z * (q4 + z * (q5 + z * (q6 + z * q7)))))));
}
Insert cell
function plot(f, {
tdomain = [-2.75, +2.75],
xdomain,
ydomain,
margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 640,
height = 240,
n = width
} = {}) {
const X = d3.range(n).map(d3.scaleLinear([0, n - 1], tdomain));
const Y = X.map(f);

const x = d3.scaleLinear().range([margin.left, width - margin.right]);
const y = d3.scaleLinear().range([height - margin.bottom, margin.top]);
if (xdomain === undefined) x.domain(tdomain).nice(20);
else x.domain(xdomain);
if (ydomain === undefined) y.domain(d3.extent(Y)).nice().domain();
else y.domain(ydomain);

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("max-width", `${width}px`);

svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom + 12})`)
.call(d3.axisBottom(x.copy().interpolate(d3.interpolateRound)))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("stroke-opacity", d => d ? 0.1 : 0.5)
.attr("y1", -height));

svg.append("g")
.attr("transform", `translate(${margin.left - 12},0)`)
.call(d3.axisLeft(y.copy().interpolate(d3.interpolateRound)).ticks(5))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("stroke-opacity", d => d ? 0.1 : 0.5)
.attr("x1", width));

svg.append("path")
.attr("fill", "none")
.attr("stroke", "#c4238f")
.attr("stroke-width", 2)
.attr("d", d3.line().x(d => x(d)).y((d, i) => y(Y[i]))(X));

return svg.node();
}
Insert cell
d3 = require("d3@5")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more