Skip to content

Commit

Permalink
WIP: Implement a method for accurately measuring the sizes of small c…
Browse files Browse the repository at this point in the history
…ommas
  • Loading branch information
frostburn committed Apr 25, 2024
1 parent 29401f5 commit a43f5a5
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
iteratedEuclid,
norm,
valueToCents,
monzoToCents,
} from '../index';

describe('Array equality tester', () => {
Expand Down Expand Up @@ -382,3 +383,23 @@ describe('Constant structure checker with a margin of equivalence', () => {
expect(hasMarginConstantStructure([1199, 1200], 2)).toBe(false);
});
});

describe('Monzo size measure', () => {
it('calculates the size of the perfect fourth accurately', () => {
expect(monzoToCents([2, -1])).toBeCloseTo(498.0449991346125, 12);
});

it('calculates the size of the neutrino accurately', () => {
expect(monzoToCents([1889, -2145, 138, 424])).toBeCloseTo(
1.6361187484440885e-10,
24
);
});

it('calculates the size of the demiquartervice comma accurately', () => {
expect(monzoToCents([-3, 2, -1, -1, 0, 0, -1, 0, 2])).toBeCloseTo(
0.3636664332386927,
14
);
});
});
27 changes: 27 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {Fraction, mmod} from './fraction';
import {Monzo, monzoToBigInt} from './monzo';
import {PRIME_CENTS} from './primes';

export * from './fraction';
export * from './primes';
Expand Down Expand Up @@ -449,3 +451,28 @@ export function hasMarginConstantStructure(
}
return true;
}

const NATS_TO_CENTS = 1200 / Math.LN2;
const IEEE_LIMIT = 2n ** 1024n;

export function monzoToCents(monzo: Monzo) {
// TODO: dotPrecise
const result = dot(monzo, PRIME_CENTS);
if (Math.abs(result) > 10) {
return result;
}
for (const component of monzo) {
if (!Number.isInteger(component)) {
return result;
}
}
// TODO: monzoToBigNumeratorDenominator
const p = monzoToBigInt(monzo.map(c => Math.max(0, c)));
let q = monzoToBigInt(monzo.map(c => Math.max(0, -c)));
let n = p - q;
while (n > IEEE_LIMIT || q > IEEE_LIMIT) {
n >>= 1n;
q >>= 1n;
}
return Math.log1p(Number(n) / Number(q)) * NATS_TO_CENTS;
}

0 comments on commit a43f5a5

Please sign in to comment.