UNPKG

ultra-mega-enumerator

Version:

Ultra Mega Enumerator is a lightweight library designed to enumerate various combinatorial objects.

313 lines 12.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.PCS12 = void 0; const Utils_1 = require("../Utils"); const ForteCSV_1 = require("../ForteCSV"); const Composition_1 = require("./Composition"); const Combination_1 = require("./Combination"); const ImmutableCombination_1 = require("./ImmutableCombination"); const Necklace_1 = require("./Necklace"); class PCS12 extends ImmutableCombination_1.ImmutableCombination { constructor(set) { super(Combination_1.Combination.createWithSizeAndSet(12, set)); this.symmetries = null; } static identify(input) { if (input.isEmpty()) return _a.empty(); if (input.getN() !== 12) { throw new Error("PCS12::IdentifyChord the combination is not bounded by 12"); } if (input.isEmpty()) { return this.empty(); } return this.ChordCombinationDict.get(input.combinationString()); // Using non-null assertion since checked earlier } static empty() { return new _a(new Set()); } getIntervals() { return Composition_1.Composition.compositionFromCombination(this.transpose(-this.getForteNumberRotation()).combination).getCompositionAsArray(); } static generate() { const output = new Set(); const necklaceSet = Necklace_1.Necklace.generate(12, 2); for (const necklace of necklaceSet) { const period = necklace.getPeriod(); for (let j = 0; j < period; j++) { const currentSet = new Set(); for (let k = 0; k < 12; k++) { if (necklace[k] === 1) { currentSet.add((12 - (k + 1) + j) % 12); } } if (currentSet.size > 0) { output.add(new _a(currentSet)); } } } output.add(_a.empty()); return output; } getForteNumber() { if (this.isEmpty()) return "0-1"; const o = _a.ForteNumbersDict.get(this.combinationString()); return o; } getMean() { let sum = 0.0; let count = this.getK(); // Number of set bits for (let i = 0; i < 12; i++) { if (this.get(i)) { sum += i; } } return count === 0 ? 0 : sum / count; } transpose(t) { return _a.identify(this.rotate(t)); } intersect(other) { return _a.identify(super.intersect(other)); } minus(other) { return _a.identify(super.minus(other)); } static getChords() { const output = new Set(); for (let e of this.ChordCombinationDict.values()) { output.add(e); } return output; } static fillForteNumbersDict() { return __awaiter(this, void 0, void 0, function* () { const forteRows = ForteCSV_1.FORTE_NUMBERS .split("\n") .map(l => l.split(",").map(s => s.replace(/"/g, ''))); const forteNumbersDict = new Map(); const forteNumbersRotationDict = new Map(); const forteNumbersToPCS12Dict = new Map(); const forteNumbersCommonNames = new Map(); for (let row of forteRows) { //console.log("Processing row: " + row.toString()) const forteNumber = row[0]; const ns = (!row[1] || row[1].trim().length === 0) ? [] : row[1].split(/\s+/).map(num => Number(num)); const c = ImmutableCombination_1.ImmutableCombination.createWithSizeAndSet(12, new Set(ns)); const pcs12 = _a.identify(c); if (pcs12.isEmpty()) { forteNumbersDict.set(_a.empty().combinationString(), "0-1"); forteNumbersRotationDict.set(_a.empty().combinationString(), 0); const str = "0-1.00"; forteNumbersToPCS12Dict.set(str, _a.empty()); } else { for (let i = 12; i >= 0; i--) { const transposed = pcs12.transpose(i); forteNumbersDict.set(transposed.combinationString(), forteNumber); forteNumbersRotationDict.set(transposed.combinationString(), i); const str = `${forteNumber}.${String(i).padStart(2, '0')}`; forteNumbersToPCS12Dict.set(str, transposed); } } } _a.ForteNumbersDict = forteNumbersDict; _a.ForteNumbersRotationDict = forteNumbersRotationDict; _a.ForteNumbersToPCS12Dict = forteNumbersToPCS12Dict; const forteNamesRows = ForteCSV_1.COMMON_NAMES .split("\n") .map(l => l.split(",").map(s => s.replace(/"/g, ''))); for (let row of forteNamesRows) { const forteNumber = row[0]; const commonName = row[1]; forteNumbersCommonNames.set(forteNumber, commonName); } _a.ForteNumbersCommonNames = forteNumbersCommonNames; }); } getForteAB() { const f = this.getForteNumber(); return f.includes("A") ? "A" : f.includes("B") ? "B" : ""; } rotatedCompareTo(other, rotate) { return this.combination.rotate(rotate).compareTo(other.combination.rotate(rotate)); } static parseForte(input) { if (!input) { console.warn(`parseForte: Received invalid input "${input}".`); return undefined; // Return undefined if input is invalid } const o = _a.ForteNumbersToPCS12Dict.get(input); if (!o) { console.warn(`parseForte: No PCS12 found for input "${input}".`); } return o; } combineWith(x) { return _a.identify(this.mergeWith(x)); } getCommonName() { const forteNumber = this.getForteNumber(); if (forteNumber === undefined) { return 'Unknown'; // or any other fallback string } return _a.ForteNumbersCommonNames.get(forteNumber); } getForteNumberOrder() { let str = this.getForteNumber(); // Assumes this method is defined str = str.replace("z", "").replace("A", "").replace("B", "").substring(str.indexOf("-") + 1); return Number(str); } getForteNumberRotation() { if (this.isEmpty()) return 0; return _a.ForteNumbersRotationDict.get(this.combinationString()); } toString() { const str = `${this.getForteNumber()}.${String(this.getForteNumberRotation()).padStart(2, '0')}`; return str; } getSymmetries() { if (this.symmetries !== null) return this.symmetries; const o = []; for (let i = 0; i < 24; i++) { const axis = Math.floor(i / 2); let found = true; if (i % 2 === 0) { for (let j = 0; j < 7; j++) { if (this.get((axis + j) % 12) !== this.get((12 + axis - j) % 12)) { found = false; break; } } } else { for (let j = 0; j < 6; j++) { if (this.get((axis + j + 1) % 12) !== this.get((12 + axis - j) % 12)) { found = false; break; } } } if (found) { o.push(i / 2.0); } } this.symmetries = o; return o; } static getForteChordDict() { const chordDict = {}; // Assuming you want to populate it from the existing ChordDict this.ForteNumbersToPCS12Dict.forEach((value, key) => { chordDict[key] = value; }); return chordDict; } static generateMaps() { return __awaiter(this, void 0, void 0, function* () { const chords = this.generate(); const chordCombinationDict = new Map(); for (const chord of chords) { chordCombinationDict.set(chord.combinationString(), chord); } _a.ChordCombinationDict = chordCombinationDict; yield this.fillForteNumbersDict(); // Load forte numbers after generating chords }); } calcCenterTuning(center) { let o = 1.0; const s = this.asSequence(); const m = new Map(); // Populate the map for center tuning with the values for (let i = -5; i < 7; i++) { m.set((center + i + 12) % 12, Math.pow(2.0, (i / 12.0))); } // Calculate product based on the sequence for (const t of s) { o *= m.get(t); } return Math.pow(o, 1.0 / s.length); } getTensionPartition() { const ct = this.asSequence().map((n) => this.calcCenterTuning(n)); // Get unique |1.0 - d| values, sorted const values = Array.from(new Set(ct.map(d => Math.abs(1.0 - d)))).sort((a, b) => a - b); // Map each unique value to an index const map = new Map(); values.forEach((d, i) => map.set(d, i)); // Build the output sequence return ct.map(d => map.get(Math.abs(1.0 - d))); } static init() { return __awaiter(this, void 0, void 0, function* () { if (this._isInitialized) { //console.log("PCS12 is already initialized."); return; } if (this._isInitializing) { //console.log("PCS12 is initializing."); return; } this._isInitializing = true; //console.log("Initializing PCS12..."); yield _a.generateMaps(); //console.log("PCS12 initialized successfully."); this._isInitialized = true; this._isInitializing = false; }); } static isInitialized() { return this._isInitialized; } } exports.PCS12 = PCS12; _a = PCS12; PCS12.ChordCombinationDict = new Map(); PCS12.ForteNumbersDict = new Map(); PCS12.ForteNumbersRotationDict = new Map(); PCS12.ForteNumbersToPCS12Dict = new Map(); PCS12.ForteNumbersCommonNames = new Map(); PCS12.ForteStringComparator = (o1, o2) => { // Add null/undefined checks before proceeding if (!o1 || !o2) { console.error(`ForteStringComparator: Invalid input - o1: "${o1}", o2: "${o2}".`); return 0; // Or handle it according to your logic, for instance, you could always treat undefined as less than defined } const p1 = _a.parseForte(o1); const p2 = _a.parseForte(o2); // Handle undefined cases gracefully if (!p1 && !p2) return 0; // Both are undefined, treat as equal if (!p1) return -1; // p1 is undefined, consider p2 greater if (!p2) return 1; // p2 is undefined, consider p1 greater return Utils_1.CustomComparisonChain.start() .setValues(p1, p2) .compare((x, y) => Utils_1.Ordering.natural().getComparator()(x.getK(), y.getK())) .compare((x, y) => Utils_1.Ordering.natural().getComparator()(x.getForteNumberOrder(), y.getForteNumberOrder())) .compare((x, y) => { const a = x.getForteAB(); const b = y.getForteAB(); return Utils_1.Ordering.natural().nullsFirst().getComparator()(a, b); }) .compare((x, y) => Utils_1.Ordering.natural().getComparator()(x.getForteNumberRotation(), y.getForteNumberRotation())) .result(); }; PCS12.ReverseForteStringComparator = (o1, o2) => _a.ForteStringComparator(o2, o1); PCS12._isInitializing = false; PCS12._isInitialized = false; //# sourceMappingURL=PCS12.js.map