/* Supporting interactive components for the concept page */
const TangentPlot = ({ func, h, a, Tex }) => {
const W = 540, H = 360;
const PAD = 32;
const xMin = -2.4, xMax = 2.4;
// dynamic y range based on function
const yRanges = {
"x²": [-1, 5],
};
// compute by sampling
const samples = [];
const N = 200;
for (let i = 0; i <= N; i++) {
const x = xMin + (xMax - xMin) * (i / N);
const y = func.f(x);
if (isFinite(y)) samples.push([x, y]);
}
let yMin = Math.min(...samples.map(s => s[1]));
let yMax = Math.max(...samples.map(s => s[1]));
// include the tangent neighborhood
const fa = func.f(a);
yMin = Math.min(yMin, fa - 0.5);
yMax = Math.max(yMax, fa + 0.5);
const yPad = (yMax - yMin) * 0.08;
yMin -= yPad; yMax += yPad;
const xToPx = (x) => PAD + (x - xMin) / (xMax - xMin) * (W - 2 * PAD);
const yToPx = (y) => H - PAD - (y - yMin) / (yMax - yMin) * (H - 2 * PAD);
// function path
const path = samples.map(([x,y], i) => `${i ? "L" : "M"} ${xToPx(x).toFixed(2)} ${yToPx(y).toFixed(2)}`).join(" ");
// secant: from (a, f(a)) to (a+h, f(a+h))
const fah = func.f(a + h);
const secSlope = (fah - fa) / h;
// tangent: f(a) + f'(a)(x - a)
const tSlope = func.df(a);
const tx0 = xMin, tx1 = xMax;
const ty0 = fa + tSlope * (tx0 - a);
const ty1 = fa + tSlope * (tx1 - a);
// secant extended a bit beyond endpoints for visual continuation
const sx0 = a - h * 0.4;
const sx1 = a + h * 1.4;
const sy0 = fa + secSlope * (sx0 - a);
const sy1 = fa + secSlope * (sx1 - a);
return (
Plot · {func.label.replace("f(x) =","f(x) =")}
domain ℝ · grid 0.5
{func.label}
Secant · slope {((func.f(a+h)-func.f(a))/h).toFixed(3)}
Tangent · slope {func.df(a).toFixed(3)}
);
};
const LimitTable = ({ func, a, Tex }) => {
const hs = [1, 0.5, 0.1, 0.05, 0.01, 0.005, 0.001, 0.0001];
const exact = func.df(a);
return (
| h |
f(a + h) |
f(a + h) − f(a) |
[f(a + h) − f(a)] / h |
|err| |
{hs.map((h, i) => {
const fah = func.f(a + h);
const fa = func.f(a);
const dq = (fah - fa) / h;
const err = Math.abs(dq - exact);
return (
| {h.toFixed(4)} |
{fah.toFixed(6)} |
{(fah - fa).toFixed(6)} |
{dq.toFixed(6)} |
{err.toExponential(2)} |
);
})}
| → 0 |
f(a) = {func.f(a).toFixed(6)} |
→ 0 |
{exact.toFixed(6)} |
0 |
);
};
const EmbeddingNeighborhood = () => {
// 2D UMAP-style projection — derivative at center, neighbors plotted by semantic distance
const W = 1080, H = 380;
const center = { x: W/2, y: H/2, label: "derivative", kind: "self" };
const neighbors = [
{ x: 0.18, y: 0.32, label: "differential", kind: "definition", d: 0.08, mastery:"frontier" },
{ x: 0.27, y: 0.65, label: "tangent line", kind: "definition", d: 0.12, mastery:"learning" },
{ x: 0.36, y: 0.18, label: "limit", kind: "definition", d: 0.14, mastery:"mastered" },
{ x: 0.62, y: 0.22, label: "secant line", kind: "definition", d: 0.15, mastery:"frontier" },
{ x: 0.72, y: 0.58, label: "rate of change", kind: "definition", d: 0.18, mastery:"mastered" },
{ x: 0.81, y: 0.30, label: "instantaneous velocity", kind: "example", d: 0.22, mastery:"mastered" },
{ x: 0.10, y: 0.50, label: "directional derivative", kind: "definition", d: 0.24, mastery:"locked" },
{ x: 0.45, y: 0.78, label: "partial derivative", kind: "definition", d: 0.26, mastery:"locked" },
{ x: 0.88, y: 0.72, label: "linear approximation", kind: "theorem", d: 0.28, mastery:"learning" },
{ x: 0.20, y: 0.85, label: "differential operator", kind: "definition", d: 0.30, mastery:"locked" },
{ x: 0.93, y: 0.45, label: "Jacobian", kind: "definition", d: 0.32, mastery:"locked" },
{ x: 0.55, y: 0.10, label: "subdifferential", kind: "definition", d: 0.36, mastery:"locked" },
{ x: 0.06, y: 0.18, label: "Newton's method", kind: "procedure", d: 0.34, mastery:"learning" },
{ x: 0.40, y: 0.38, label: "chain rule", kind: "theorem", d: 0.16, mastery:"frontier" },
{ x: 0.66, y: 0.40, label: "MVT", kind: "theorem", d: 0.20, mastery:"locked" },
];
return (
Legend
definition
theorem
procedure
example
·
Distance
cosine, qwen3 1024-dim
);
};
window.TangentPlot = TangentPlot;
window.LimitTable = LimitTable;
window.EmbeddingNeighborhood = EmbeddingNeighborhood;