package net.mattmccutchen.measurements; public class MeasurementMath { public static boolean unitsSame(Measurement a, Measurement b) { for (int i = 0; i < Unit.basicUnits.length; i++) if (a.unitPowers[i] != b.unitPowers[i]) return false; return true; } public static boolean isPureNumber(Measurement a) { for (int i = 0; i < Unit.basicUnits.length; i++) if (a.unitPowers[i] != 0) return false; return true; } public static Measurement neg(Measurement a) { if (a == null) return null; return new Measurement(-a.number, a.uncertainty, a.unitPowers); } public static Measurement add(Measurement a, Measurement b) { if (a == null || b == null || !unitsSame(a, b)) return null; return new Measurement(a.number + b.number, a.uncertainty + b.uncertainty, a.unitPowers); } public static Measurement sub(Measurement a, Measurement b) { if (a == null || b == null || !unitsSame(a, b)) return null; return new Measurement(a.number - b.number, a.uncertainty + b.uncertainty, a.unitPowers); } public static Measurement mul(Measurement a, Measurement b) { if (a == null || b == null) return null; int[] up = new int[Unit.basicUnits.length]; for (int i = 0; i < Unit.basicUnits.length; i++) up[i] = a.unitPowers[i] + b.unitPowers[i]; return new Measurement(a.number * b.number, a.uncertainty * Math.abs(b.number) + b.uncertainty * Math.abs(a.number), up); } public static Measurement div(Measurement a, Measurement b) { if (a == null || b == null) return null; int[] up = new int[Unit.basicUnits.length]; for (int i = 0; i < Unit.basicUnits.length; i++) up[i] = a.unitPowers[i] - b.unitPowers[i]; return new Measurement(a.number / b.number, // Compare to quotient rule for differentiation a.uncertainty / Math.abs(b.number) + Math.abs(a.number) * b.uncertainty / (b.number * b.number), up); } public static Measurement powint(Measurement a, int b) { if (a == null) return null; int[] up = new int[Unit.basicUnits.length]; for (int i = 0; i < Unit.basicUnits.length; i++) up[i] = a.unitPowers[i] * b; return new Measurement(Math.pow(a.number, b), b * a.uncertainty * Math.pow(a.number, b-1), up); } public static Measurement rootint(Measurement a, int b) { if (a == null) return null; int[] up = new int[Unit.basicUnits.length]; for (int i = 0; i < Unit.basicUnits.length; i++) { if (Math.abs(a.unitPowers[i]) % b != 0) return null; up[i] = a.unitPowers[i] / b; } return new Measurement(Math.pow(a.number, 1.0/b), a.uncertainty / b * Math.pow(a.number, (1.0/b)-1), up); } public static Measurement pow(Measurement a, Measurement b) { if (a == null || !isPureNumber(a) || b == null || !isPureNumber(b)) return null; return new Measurement(Math.pow(a.number, b.number), b.number * a.uncertainty * Math.pow(a.number, b.number-1) // think: derivative of e^(b ln a) is b' (ln a) e^(b ln a) + b.uncertainty * Math.log(a.number) * Math.pow(a.number, b.number), Measurement.pureNumberUnitPowers); } public static Measurement exp(Measurement m) { if (m == null || !isPureNumber(m)) return null; return new Measurement(Math.exp(m.number), m.uncertainty * Math.exp(m.number), Measurement.pureNumberUnitPowers); } public static Measurement ln(Measurement m) { if (m == null || !isPureNumber(m)) return null; return new Measurement(Math.log(m.number), m.uncertainty / m.number, Measurement.pureNumberUnitPowers); } public static double cmp(Measurement a, Measurement b) { if (a == null || b == null || !unitsSame(a, b)) return Double.NaN; return (a.number - b.number) / (a.uncertainty + b.uncertainty); } }