/ concept-collection / gcd-visualizer
Sign in
concept-collection / gcd-visualizer
gcd-visualizer / src / workers / gcdWorker.ts
85 lines · 2.4 KBCodeBlameHistory
455d9bbinitialJeremy Magland 1/**
2 * Web Worker for computing GCD table bitmap
3 * Computes n x n ImageData and transfers it back to main thread
4 */
6// Inline color computation function (copied from colorUtils.ts)
7function valueToColor(value: number, max: number): { r: number; g: number; b: number } {
8 const t = value / max;
9
10 // Smooth gradient from dark purple-blue to bright yellow-orange
11 let r: number, g: number, b: number;
13 // Red channel: smooth increase
14 r = Math.floor(13 + 242 * Math.pow(t, 0.5));
16 // Green channel: gentle S-curve for smoothness
17 g = Math.floor(8 + 247 * Math.pow(t, 1.5));
19 // Blue channel: decrease from purple to yellow
20 b = Math.floor(135 * Math.pow(1 - t, 2));
22 // Clamp values to valid range
23 r = Math.min(255, Math.max(0, r));
24 g = Math.min(255, Math.max(0, g));
25 b = Math.min(255, Math.max(0, b));
27 return { r, g, b };
30// Compute GCD using Euclidean algorithm
31function gcd(a: number, b: number): number {
32 while (b !== 0) {
33 const temp = b;
34 b = a % b;
35 a = temp;
36 }
37 return a;
40self.onmessage = (e: MessageEvent<{ n: number }>) => {
41 const { n } = e.data;
43 // Create ImageData for n x n grid
44 const imageData = new ImageData(n, n);
45 const data = imageData.data;
47 // Compute GCD table and fill ImageData
48 // First pass: compute log(gcd) values and find max
49 const logValues: number[] = new Array(n * n);
50 let maxLogValue = 0;
52 for (let i = 1; i <= n; i++) {
53 for (let j = 1; j <= n; j++) {
54 const gcdValue = gcd(i, j);
55 const logValue = Math.log(gcdValue);
56 const index = (i - 1) * n + (j - 1);
57 logValues[index] = logValue;
58 maxLogValue = Math.max(maxLogValue, logValue);
59 }
60 }
62 // Second pass: map log values to colors
63 for (let i = 1; i <= n; i++) {
64 for (let j = 1; j <= n; j++) {
65 const index = (i - 1) * n + (j - 1);
66 const logValue = logValues[index];
67 const color = valueToColor(logValue, maxLogValue);
69 // Calculate pixel index (RGBA format)
70 const pixelIndex = index * 4;
72 data[pixelIndex] = color.r; // Red
73 data[pixelIndex + 1] = color.g; // Green
74 data[pixelIndex + 2] = color.b; // Blue
75 data[pixelIndex + 3] = 255; // Alpha (fully opaque)
76 }
77 }
79 // Transfer ImageData back to main thread using transferable objects
80 self.postMessage(
81 { type: 'complete', imageData },
82 // @ts-expect-error - TypeScript doesn't recognize this overload but it's valid
83 [imageData.data.buffer]
84 );
85};
moveopenescclose