Index: node_modules/fraction.js/examples/angles.js
===================================================================
--- node_modules/fraction.js/examples/angles.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/angles.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,26 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+
+// This example generates a list of angles with human readable radians
+
+var Fraction = require('fraction.js');
+
+var tab = [];
+for (var d = 1; d <= 360; d++) {
+
+   var pi = Fraction(2, 360).mul(d);
+   var tau = Fraction(1, 360).mul(d);
+
+   if (pi.d <= 6n && pi.d != 5n)
+      tab.push([
+         d,
+         pi.toFraction() + "pi",
+         tau.toFraction() + "tau"]);
+}
+
+console.table(tab);
Index: node_modules/fraction.js/examples/approx.js
===================================================================
--- node_modules/fraction.js/examples/approx.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/approx.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,54 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+const Fraction = require('fraction.js');
+
+// Another rational approximation, not using Farey Sequences but Binary Search using the mediant
+function approximate(p, precision) {
+
+  var num1 = Math.floor(p);
+  var den1 = 1;
+
+  var num2 = num1 + 1;
+  var den2 = 1;
+
+  if (p !== num1) {
+
+    while (den1 <= precision && den2 <= precision) {
+
+      var m = (num1 + num2) / (den1 + den2);
+
+      if (p === m) {
+
+        if (den1 + den2 <= precision) {
+          den1 += den2;
+          num1 += num2;
+          den2 = precision + 1;
+        } else if (den1 > den2) {
+          den2 = precision + 1;
+        } else {
+          den1 = precision + 1;
+        }
+        break;
+
+      } else if (p < m) {
+        num2 += num1;
+        den2 += den1;
+      } else {
+        num1 += num2;
+        den1 += den2;
+      }
+    }
+  }
+
+  if (den1 > precision) {
+    den1 = den2;
+    num1 = num2;
+  }
+  return new Fraction(num1, den1);
+}
+
Index: node_modules/fraction.js/examples/egyptian.js
===================================================================
--- node_modules/fraction.js/examples/egyptian.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/egyptian.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,24 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+const Fraction = require('fraction.js');
+
+// Based on http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fractions/egyptian.html
+function egyptian(a, b) {
+
+  var res = [];
+
+  do {
+    var t = Math.ceil(b / a);
+    var x = new Fraction(a, b).sub(1, t);
+    res.push(t);
+    a = Number(x.n);
+    b = Number(x.d);
+  } while (a !== 0n);
+  return res;
+}
+console.log("1 / " + egyptian(521, 1050).join(" + 1 / "));
Index: node_modules/fraction.js/examples/hesse-convergence.js
===================================================================
--- node_modules/fraction.js/examples/hesse-convergence.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/hesse-convergence.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,111 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+const Fraction = require('fraction.js');
+
+/*
+We have the polynom f(x) = 1/3x_1^2 + x_2^2 + x_1 * x_2 + 3
+
+The gradient of f(x):
+
+grad(x) = | x_1^2+x_2 |
+          | 2x_2+x_1  |
+
+And thus the Hesse-Matrix H:
+| 2x_1  1 |
+|  1    2 |
+
+The inverse Hesse-Matrix H^-1 is
+| -2 / (1-4x_1)    1 / (1 - 4x_1)     |
+| 1 / (1 - 4x_1)   -2x_1 / (1 - 4x_1) |
+
+We now want to find lim ->oo x[n], with the starting element of (3 2)^T
+
+*/
+
+// Get the Hesse Matrix
+function H(x) {
+
+  var z = Fraction(1).sub(Fraction(4).mul(x[0]));
+
+  return [
+    Fraction(-2).div(z),
+    Fraction(1).div(z),
+    Fraction(1).div(z),
+    Fraction(-2).mul(x[0]).div(z),
+  ];
+}
+
+// Get the gradient of f(x)
+function grad(x) {
+
+  return [
+    Fraction(x[0]).mul(x[0]).add(x[1]),
+    Fraction(2).mul(x[1]).add(x[0])
+  ];
+}
+
+// A simple matrix multiplication helper
+function matrMult(m, v) {
+
+  return [
+    Fraction(m[0]).mul(v[0]).add(Fraction(m[1]).mul(v[1])),
+    Fraction(m[2]).mul(v[0]).add(Fraction(m[3]).mul(v[1]))
+  ];
+}
+
+// A simple vector subtraction helper
+function vecSub(a, b) {
+
+  return [
+    Fraction(a[0]).sub(b[0]),
+    Fraction(a[1]).sub(b[1])
+  ];
+}
+
+// Main function, gets a vector and the actual index
+function run(V, j) {
+
+  var t = H(V);
+  //console.log("H(X)");
+  for (var i in t) {
+
+    //	console.log(t[i].toFraction());
+  }
+
+  var s = grad(V);
+  //console.log("vf(X)");
+  for (var i in s) {
+
+    //	console.log(s[i].toFraction());
+  }
+
+  //console.log("multiplication");
+  var r = matrMult(t, s);
+  for (var i in r) {
+
+    //	console.log(r[i].toFraction());
+  }
+
+  var R = (vecSub(V, r));
+
+  console.log("X" + j);
+  console.log(R[0].toFraction(), "= " + R[0].valueOf());
+  console.log(R[1].toFraction(), "= " + R[1].valueOf());
+  console.log("\n");
+
+  return R;
+}
+
+
+// Set the starting vector
+var v = [3, 2];
+
+for (var i = 0; i < 15; i++) {
+
+  v = run(v, i);
+}
Index: node_modules/fraction.js/examples/integrate.js
===================================================================
--- node_modules/fraction.js/examples/integrate.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/integrate.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,67 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+const Fraction = require('fraction.js');
+
+// NOTE: This is a nice example, but a stable version of this is served with Polynomial.js: 
+// https://github.com/rawify/Polynomial.js
+
+function integrate(poly) {
+
+    poly = poly.replace(/\s+/g, "");
+
+    var regex = /(\([+-]?[0-9/]+\)|[+-]?[0-9/]+)x(?:\^(\([+-]?[0-9/]+\)|[+-]?[0-9]+))?/g;
+    var arr;
+    var res = {};
+    while (null !== (arr = regex.exec(poly))) {
+
+        var a = (arr[1] || "1").replace("(", "").replace(")", "").split("/");
+        var b = (arr[2] || "1").replace("(", "").replace(")", "").split("/");
+
+        var exp = new Fraction(b).add(1);
+        var key = "" + exp;
+
+        if (res[key] !== undefined) {
+            res[key] = { x: new Fraction(a).div(exp).add(res[key].x), e: exp };
+        } else {
+            res[key] = { x: new Fraction(a).div(exp), e: exp };
+        }
+    }
+
+    var str = "";
+    var c = 0;
+    for (var i in res) {
+        if (res[i].x.s !== -1n && c > 0) {
+            str += "+";
+        } else if (res[i].x.s === -1n) {
+            str += "-";
+        }
+        if (res[i].x.n !== res[i].x.d) {
+            if (res[i].x.d !== 1n) {
+                str += res[i].x.n + "/" + res[i].x.d;
+            } else {
+                str += res[i].x.n;
+            }
+        }
+        str += "x";
+        if (res[i].e.n !== res[i].e.d) {
+            str += "^";
+            if (res[i].e.d !== 1n) {
+                str += "(" + res[i].e.n + "/" + res[i].e.d + ")";
+            } else {
+                str += res[i].e.n;
+            }
+        }
+        c++;
+    }
+    return str;
+}
+
+var poly = "-2/3x^3-2x^2+3x+8x^3-1/3x^(4/8)";
+
+console.log("f(x): " + poly);
+console.log("F(x): " + integrate(poly));
Index: node_modules/fraction.js/examples/ratio-chain.js
===================================================================
--- node_modules/fraction.js/examples/ratio-chain.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/ratio-chain.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,24 @@
+/*
+Given the ratio a : b : c = 2 : 3 : 4 
+What is c, given a = 40?
+
+A general ratio chain is a_1 : a_2 : a_3 : ... : a_n = r_1 : r2 : r_3 : ... : r_n.
+Now each term can be expressed as a_i = r_i * x for some unknown proportional constant x.
+If a_k is known it follows that x = a_k / r_k. Substituting x into the first equation yields
+a_i = r_i / r_k * a_k.
+
+Given an array r and a given value a_k, the following function calculates all a_i:
+*/
+
+function calculateRatios(r, a_k, k) {    
+    const x = Fraction(a_k).div(r[k]);
+    return r.map(r_i => x.mul(r_i));
+}
+
+// Example usage:
+const r = [2, 3, 4]; // Ratio array representing a : b : c = 2 : 3 : 4
+const a_k = 40; // Given value of a (corresponding to r[0])
+const k = 0; // Index of the known value (a corresponds to r[0])
+
+const result = calculateRatios(r, a_k, k);
+console.log(result); // Output: [40, 60, 80]
Index: node_modules/fraction.js/examples/rational-pow.js
===================================================================
--- node_modules/fraction.js/examples/rational-pow.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/rational-pow.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,29 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+const Fraction = require('fraction.js');
+ 
+// Calculates (a/b)^(c/d) if result is rational
+// Derivation: https://raw.org/book/analysis/rational-numbers/
+function root(a, b, c, d) {
+
+  // Initial estimate
+  let x = Fraction(100 * (Math.floor(Math.pow(a / b, c / d)) || 1), 100);
+  const abc = Fraction(a, b).pow(c);
+
+  for (let i = 0; i < 30; i++) {
+    const n = abc.mul(x.pow(1 - d)).sub(x).div(d).add(x)
+
+    if (x.n === n.n && x.d === n.d) {
+      return n;
+    }
+    x = n;
+  }
+  return null;
+}
+
+root(18, 2, 1, 2); // 3/1
Index: node_modules/fraction.js/examples/tape-measure.js
===================================================================
--- node_modules/fraction.js/examples/tape-measure.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/tape-measure.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,16 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+const Fraction = require('fraction.js');
+
+function closestTapeMeasure(frac) {
+
+    // A tape measure is usually divided in parts of 1/16
+
+    return Fraction(frac).roundTo("1/16");
+}
+console.log(closestTapeMeasure("1/3")); // 5/16
Index: node_modules/fraction.js/examples/toFraction.js
===================================================================
--- node_modules/fraction.js/examples/toFraction.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/toFraction.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,35 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+
+const Fraction = require('fraction.js');
+
+function toFraction(frac) {
+
+  var map = {
+    '1:4': "¼",
+    '1:2': "½",
+    '3:4': "¾",
+    '1:7': "⅐",
+    '1:9': "⅑",
+    '1:10': "⅒",
+    '1:3': "⅓",
+    '2:3': "⅔",
+    '1:5': "⅕",
+    '2:5': "⅖",
+    '3:5': "⅗",
+    '4:5': "⅘",
+    '1:6': "⅙",
+    '5:6': "⅚",
+    '1:8': "⅛",
+    '3:8': "⅜",
+    '5:8': "⅝",
+    '7:8': "⅞"
+  };
+  return map[frac.n + ":" + frac.d] || frac.toFraction(false);
+}
+console.log(toFraction(Fraction(0.25))); // ¼
Index: node_modules/fraction.js/examples/valueOfPi.js
===================================================================
--- node_modules/fraction.js/examples/valueOfPi.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ node_modules/fraction.js/examples/valueOfPi.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
@@ -0,0 +1,42 @@
+/*
+Fraction.js v5.0.0 10/1/2024
+https://raw.org/article/rational-numbers-in-javascript/
+
+Copyright (c) 2024, Robert Eisele (https://raw.org/)
+Licensed under the MIT license.
+*/
+
+var Fraction = require("fraction.js")
+
+function valueOfPi(val) {
+
+  let minLen = Infinity, minI = 0, min = null;
+  const choose = [val, val * Math.PI, val / Math.PI];
+  for (let i = 0; i < choose.length; i++) {
+    let el = new Fraction(choose[i]).simplify(1e-13);
+    let len = Math.log(Number(el.n) + 1) + Math.log(Number(el.d));
+    if (len < minLen) {
+      minLen = len;
+      minI = i;
+      min = el;
+    }
+  }
+
+  if (minI == 2) {
+    return min.toFraction().replace(/(\d+)(\/\d+)?/, (_, p, q) =>
+      (p == "1" ? "" : p) + "π" + (q || ""));
+  }
+
+  if (minI == 1) {
+    return min.toFraction().replace(/(\d+)(\/\d+)?/, (_, p, q) =>
+      p + (!q ? "/π" : "/(" + q.slice(1) + "π)"));
+  }
+  return min.toFraction();
+}
+
+console.log(valueOfPi(-3)); // -3
+console.log(valueOfPi(4 * Math.PI)); // 4π
+console.log(valueOfPi(3.14)); // 157/50
+console.log(valueOfPi(3 / 2 * Math.PI)); // 3π/2
+console.log(valueOfPi(Math.PI / 2)); // π/2
+console.log(valueOfPi(-1 / (2 * Math.PI))); // -1/(2π)
