From ae9820b39f8d196ec1f9220367d15055073fc1f3 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 16 Jun 2022 03:17:35 +0200 Subject: [PATCH] some testing with Fraction mock class --- packages/core/fraction.mjs | 79 +++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/packages/core/fraction.mjs b/packages/core/fraction.mjs index 5204395d3..f0be0e9a6 100644 --- a/packages/core/fraction.mjs +++ b/packages/core/fraction.mjs @@ -4,9 +4,68 @@ Copyright (C) 2022 Strudel contributors - see . */ -import Fraction from 'fraction.js'; +// import Fraction from 'fraction.js'; import { TimeSpan } from './timespan.mjs'; +// this is a "mock" for fraction.js, using just floats without any rational arithmetic +// to test if the performance gets better without fraction.js +// result: it seems to get better but not by much +// the main jankyness remains for some cpmplicated patterns +// i tried counting the calls of Fraction.add and noticed there can be ~250 million calls per second +// so even if the add function is just a regular add, the sheer number of calls is a problem + +class Fraction { + value; // number + constructor(value) { + if (value instanceof Fraction) { + this.value = value.value; + } else if (typeof value === 'string') { + const [n, d] = value.split('/'); + this.value = n / (d || 1); + } else if (typeof value !== 'number' || isNaN(value)) { + console.warn('Fraction got NaN', value); + } else { + this.value = Number(value); + if (isNaN(this.value)) { + console.warn('Fraction parsed NaN from', value); + } + } + } + add(other) { + return new Fraction(this.value + other); + } + sub(other) { + return new Fraction(this.value - other); + } + mul(other) { + return new Fraction(this.value * other); + } + div(other) { + return new Fraction(this.value / other); + } + toString() { + return this.value + ''; + } + valueOf() { + return this.value; + } + floor() { + return new Fraction(Math.floor(this.value)); + } + abs() { + return new Fraction(Math.abs(this.value)); + } + inverse() { + return new Fraction(1 / this.value); + } + compare(other) { + return this.value - other; + } + equals(other) { + return this.value.valueOf() === other.valueOf(); + } +} + // Returns the start of the cycle. Fraction.prototype.sam = function () { return this.floor(); @@ -63,20 +122,20 @@ Fraction.prototype.or = function (other) { return this.eq(0) ? other : this; }; -const fraction = (n) => { +/* const fraction = (n) => { if (typeof n === 'number') { - /* - https://github.com/infusion/Fraction.js/#doubles - „If you pass a double as it is, Fraction.js will perform a number analysis based on Farey Sequences." - „If you want to keep the number as it is, convert it to a string, as the string parser will not perform any further observations“ + // https://github.com/infusion/Fraction.js/#doubles + // „If you pass a double as it is, Fraction.js will perform a number analysis based on Farey Sequences." + // „If you want to keep the number as it is, convert it to a string, as the string parser will not perform any further observations“ - -> those farey sequences turn out to make pattern querying ~20 times slower! always use strings! - -> still, some optimizations could be done: .mul .div .add .sub calls still use numbers - */ + // -> those farey sequences turn out to make pattern querying ~20 times slower! always use strings! + // -> still, some optimizations could be done: .mul .div .add .sub calls still use numbers n = String(n); } return Fraction(n); -}; +}; */ + +const fraction = (n) => new Fraction(n); export const gcd = (...fractions) => { return fractions.reduce((gcd, fraction) => gcd.gcd(fraction), fraction(1));