mandelbrot/tests/analytic-interior.mjs

29 lines
1.4 KiB
JavaScript
Raw Normal View History

2026-08-22 20:55:27 +09:00
const fromFraction = (numerator, denominator, bits) => numerator * (1n << BigInt(bits)) / denominator;
function fixedAnalyticInterior(cr, ci, bits) {
const scale = 1n << BigInt(bits);
const x = cr - (scale >> 2n), y = ci, q = x * x + y * y;
if (4n * q * (q + x * scale) <= y * y * scale * scale) return true;
const d = cr + scale;
return 16n * (d * d + y * y) <= scale * scale;
}
const cases = [
{ id: 'origin-cardioid', re: [0n, 1n], im: [0n, 1n], expected: true },
{ id: 'cardioid-cusp', re: [1n, 4n], im: [0n, 1n], expected: true },
{ id: 'period2-center', re: [-1n, 1n], im: [0n, 1n], expected: true },
{ id: 'period2-boundary', re: [-5n, 4n], im: [0n, 1n], expected: true },
{ id: 'right-exterior', re: [13n, 50n], im: [0n, 1n], expected: false },
{ id: 'period3-not-analytic', re: [-123n, 1000n], im: [745n, 1000n], expected: false },
{ id: 'far-exterior', re: [1n, 1n], im: [1n, 1n], expected: false }
];
let checked = 0;
for (const bits of [256, 320]) for (const sample of cases) {
const cr = fromFraction(sample.re[0], sample.re[1], bits);
const ci = fromFraction(sample.im[0], sample.im[1], bits);
const actual = fixedAnalyticInterior(cr, ci, bits);
if (actual !== sample.expected) throw new Error(`${sample.id} at ${bits} bit: expected ${sample.expected}, got ${actual}`);
checked++;
}
console.log(JSON.stringify({ status: 'pass', checked, precisions: [256, 320], proof: 'integer cardioid/period-2 inequalities' }));