import { QQ } from '../math/QQ';
import notSupported from '../i18n/notSupported';
const R0 = QQ.valueOf(0, 1)
const R1 = QQ.valueOf(1, 1)
const R2 = QQ.valueOf(2, 1)
const M1 = QQ.valueOf(-1, 1)
function assertArgRational(name: string, arg: QQ): QQ {
if (arg instanceof QQ) {
return arg;
}
else {
throw new Error("Argument '" + arg + "' must be a QQ");
}
}
/**
* Keeps track of the dimensions of a physical quantity using seven rational exponents.
* Each of the exponents corresponds to a dimension in the S.I. system of units.
*/
export class Dimensions {
/**
* All exponents are zero, a dimensionless quantity.
*/
public static ONE = new Dimensions(R0, R0, R0, R0, R0, R0, R0);
/**
* M1
*/
public static MASS = new Dimensions(R1, R0, R0, R0, R0, R0, R0);
/**
* L1
*/
public static LENGTH = new Dimensions(R0, R1, R0, R0, R0, R0, R0);
/**
* T1
*/
public static TIME = new Dimensions(R0, R0, R1, R0, R0, R0, R0);
/**
* Q1
*/
public static CHARGE = new Dimensions(R0, R0, R0, R1, R0, R0, R0);
/**
* Q1T-1
*/
public static CURRENT = new Dimensions(R0, R0, M1, R1, R0, R0, R0);
/**
*
*/
public static TEMPERATURE = new Dimensions(R0, R0, R0, R0, R1, R0, R0);
/**
*
*/
public static AMOUNT = new Dimensions(R0, R0, R0, R0, R0, R1, R0);
/**
*
*/
public static INTENSITY = new Dimensions(R0, R0, R0, R0, R0, R0, R1);
/**
* The Dimensions class captures the physical dimensions associated with a unit of measure.
*
* @param M The mass component of the dimensions object.
* @param L The length component of the dimensions object.
* @param T The time component of the dimensions object.
* @param Q The charge component of the dimensions object.
* @param temperature The temperature component of the dimensions object.
* @param amount The amount component of the dimensions object.
* @param intensity The intensity component of the dimensions object.
*/
constructor(public M: QQ, public L: QQ, public T: QQ, public Q: QQ, public temperature: QQ, public amount: QQ, public intensity: QQ) {
assertArgRational('M', M)
assertArgRational('L', L)
assertArgRational('T', T)
assertArgRational('Q', Q)
assertArgRational('temperature', temperature)
assertArgRational('amount', amount)
assertArgRational('intensity', intensity)
if (arguments.length !== 7) {
throw new Error("Expecting 7 arguments")
}
}
/**
* Returns the dimensions if they are all equal, otherwise throws an Error
*
* @param rhs
* @returns
*/
compatible(rhs: Dimensions): Dimensions {
if (this.M.equals(rhs.M) && this.L.equals(rhs.L) && this.T.equals(rhs.T) && this.Q.equals(rhs.Q) && this.temperature.equals(rhs.temperature) && this.amount.equals(rhs.amount) && this.intensity.equals(rhs.intensity)) {
return this
}
else {
if (this.isOne()) {
if (rhs.isOne()) {
throw new Error()
}
else {
throw new Error("Dimensions must be equal (dimensionless, " + rhs + ")")
}
}
else {
if (rhs.isOne()) {
throw new Error("Dimensions must be equal (" + this + ", dimensionless)")
}
else {
throw new Error("Dimensions must be equal (" + this + ", " + rhs + ")")
}
}
}
}
/**
* Multiplies dimensions by adding rational exponents.
*
* @param rhs
* @returns this * rhs
*/
mul(rhs: Dimensions): Dimensions {
return new Dimensions(this.M.add(rhs.M), this.L.add(rhs.L), this.T.add(rhs.T), this.Q.add(rhs.Q), this.temperature.add(rhs.temperature), this.amount.add(rhs.amount), this.intensity.add(rhs.intensity));
}
/**
* Divides dimensions by subtracting rational exponents.
*
* @param rhs
* @returns this / rhs
*/
div(rhs: Dimensions): Dimensions {
return new Dimensions(this.M.sub(rhs.M), this.L.sub(rhs.L), this.T.sub(rhs.T), this.Q.sub(rhs.Q), this.temperature.sub(rhs.temperature), this.amount.sub(rhs.amount), this.intensity.sub(rhs.intensity));
}
/**
* Computes the power function by multiplying rational exponents.
*
* @param rhs
* @returns pow(this, rhs)
*/
pow(exponent: QQ): Dimensions {
return new Dimensions(this.M.mul(exponent), this.L.mul(exponent), this.T.mul(exponent), this.Q.mul(exponent), this.temperature.mul(exponent), this.amount.mul(exponent), this.intensity.mul(exponent));
}
/**
* Computes the square root by dividing each rational component by two.
*
* @returns
*/
sqrt(): Dimensions {
return new Dimensions(this.M.div(R2), this.L.div(R2), this.T.div(R2), this.Q.div(R2), this.temperature.div(R2), this.amount.div(R2), this.intensity.div(R2));
}
/**
* Determines whether all the exponents of this dimensions number are zero.
* This implies a dimensionless quantity.
*
* @returns true if all the exponents are zero, otherwise false.
*/
isOne(): boolean {
return this.M.isZero() && this.L.isZero() && this.T.isZero() && this.Q.isZero() && this.temperature.isZero() && this.amount.isZero() && this.intensity.isZero();
}
/**
* Computes the multiplicative inverse of this dimensions number.
* This is achived by changing the signs of all the exponent quantities.
*
* @returns
*/
inv(): Dimensions {
return new Dimensions(this.M.neg(), this.L.neg(), this.T.neg(), this.Q.neg(), this.temperature.neg(), this.amount.neg(), this.intensity.neg());
}
/**
* Intentionally undocumented.
*/
neg(): Dimensions {
throw new Error(notSupported('neg').message)
}
/**
* Creates a representation of this Dimensions instance.
*
* @returns
*/
toString(): string {
var stringify = function (rational: QQ, label: string): string {
if (rational.numer === 0) {
return null;
} else if (rational.denom === 1) {
if (rational.numer === 1) {
return "" + label;
} else {
return "" + label + " ** " + rational.numer;
}
}
return "" + label + " ** " + rational;
};
return [stringify(this.M, 'mass'), stringify(this.L, 'length'), stringify(this.T, 'time'), stringify(this.Q, 'charge'), stringify(this.temperature, 'thermodynamic temperature'), stringify(this.amount, 'amount of substance'), stringify(this.intensity, 'luminous intensity')].filter(function (x) {
return typeof x === 'string';
}).join(" * ");
}
/**
* @param rhs
* @returns
*/
__add__(rhs: Dimensions): Dimensions {
if (rhs instanceof Dimensions) {
return this.compatible(rhs)
}
else {
return void 0
}
}
/**
* @param lhs
* @returns
*/
__radd__(lhs: Dimensions): Dimensions {
if (lhs instanceof Dimensions) {
return lhs.compatible(this)
}
else {
return void 0
}
}
/**
*
* @param rhs
* @returns
*/
__sub__(rhs: Dimensions): Dimensions {
if (rhs instanceof Dimensions) {
return this.compatible(rhs)
}
else {
return void 0
}
}
/**
*
* @param lhs
* @returns
*/
__rsub__(lhs: Dimensions): Dimensions {
if (lhs instanceof Dimensions) {
return lhs.compatible(this)
}
else {
return void 0
}
}
/**
*
* @param rhs
* @returns
*/
__mul__(rhs: Dimensions): Dimensions {
if (rhs instanceof Dimensions) {
return this.mul(rhs)
}
else {
return void 0
}
}
/**
*
* @param lhs
* @returns
*/
__rmul__(lhs: Dimensions): Dimensions {
if (lhs instanceof Dimensions) {
return lhs.mul(this)
}
else {
return void 0
}
}
/**
*
* @param rhs
* @returns
*/
__div__(rhs: Dimensions): Dimensions {
if (rhs instanceof Dimensions) {
return this.div(rhs)
}
else {
return void 0
}
}
/**
* @param lhs
* @returns
*/
__rdiv__(lhs: Dimensions): Dimensions {
if (lhs instanceof Dimensions) {
return lhs.div(this)
}
else {
return void 0
}
}
/**
* @returns
*/
__pos__(): Dimensions {
return this
}
/**
*
* @returns
*/
__neg__(): Dimensions {
return this
}
}