Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

Exponential Sum Plot Generator

An homage to John D. Cook's Exponential Sum of the Day

The plot shows the partial sums of the exponential sum:

Σ(n=0 to N) exp(2πi(n/m + n²/d + n³/y))

The real part of the sum is plotted on the x-axis, and the imaginary part of the sum is plotted on the y-axis.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { svgServer } from "https://esm.town/v/fil/svgServer";
// Utilities
const gcd = (a, b) => {
while (b !== 0) {
[a, b] = [b, a % b];
}
return a;
};
const lcm = (a, b) => (a * b) / gcd(a, b);
const lcm3 = (a, b, c) => lcm(lcm(a, b), c);
// Constants
const date = new Date();
const CURRENT_MONTH = date.getMonth() + 1;
const CURRENT_DATE = date.getDate();
const CURRENT_YEAR = date.getFullYear() % 100;
const N = 2 * lcm3(CURRENT_MONTH, CURRENT_DATE, CURRENT_YEAR) + 1;
// Calculate exponential sum
function expSumData() {
let sum = { real: 0, imag: 0 };
const data = [{ real: 0, imag: 0 }];
for (let n = 1; n <= N; n++) {
const angle = 2 * Math.PI * (n / CURRENT_MONTH + (n * n) / CURRENT_DATE + (n * n * n) / CURRENT_YEAR);
sum.real += Math.cos(angle);
sum.imag += Math.sin(angle);
data.push({ real: sum.real, imag: sum.imag });
}
return data;
}
// Render exponential sum plot
export async function expSumPlot(req) {
const d3 = await import("npm:d3");
const document = await import("https://esm.sh/linkedom@0.15").then((l) => l.parseHTML("<a>").document);
const data = expSumData();
function render(data) {
const margin = { top: 20, right: 20, bottom: 20, left: 20 };
const width = 500 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
const svg = d3.select(document.body).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("viewBox", [0, 0, width + margin.left + margin.right, height + margin.top + margin.bottom])
.attr("style", "max-width: 100%; height: auto;");
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const xExtent = d3.extent(data, d => d.real);
const yExtent = d3.extent(data, d => d.imag);
const xScale = d3.scaleLinear()
.domain([Math.min(xExtent[0], -1), Math.max(xExtent[1], 1)])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([Math.min(yExtent[0], -1), Math.max(yExtent[1], 1)])
.range([height, 0]);
const line = d3.line()
.x(d => xScale(d.real))
.y(d => yScale(d.imag));
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#4775de")
.attr("stroke-width", 1.5)
.attr("d", line);
return svg.node();
}
return svgServer(req, render(data).outerHTML);
}
hodge-expsumoftheday.web.val.run
August 21, 2024