@neutrium/quantity
Version:
The NeutriumJS unit conversion module.
122 lines (105 loc) • 3.15 kB
text/typescript
import { typeguards, compareArray } from '@neutrium/utilities';
import { Quantity } from '../Quantity.js'
import { throwIncompatibleUnits } from './errors.js';
import { inverse } from './maths.js';
const UNITY_ARRAY = ["<1>"];
export function eq(a: Quantity, b: string | number | Quantity): boolean
{
return compareTo(a, b) === 0;
}
export function lt(a: Quantity, b: string | number | Quantity): boolean
{
return compareTo(a, b) === -1;
}
export function lte(a: Quantity, b: string | number | Quantity): boolean
{
return eq(a,b) || lt(a,b);
}
export function gt(a: Quantity, b: string | number | Quantity): boolean
{
return compareTo(a, b) === 1;
}
export function gte(a: Quantity, b: string | number | Quantity): boolean
{
return eq(a,b) || gt(a,b);
}
// Return true if quantities and units match
// Quantity("100 cm").same(Quantity("100 cm")) # => true
// Quantity("100 cm").same(Quantity("1 m")) # => false
export function same(a: Quantity, b: Quantity): boolean
{
return a.scalar.eq(b.scalar) && (a.units() === b.units());
}
export function isInverse(a: Quantity, b: string | Quantity) : boolean
{
return isCompatible(inverse(a), b);
}
// Compare two Qty objects. Throws an exception if they are not of compatible types.
// Comparisons are done based on the value of the quantity in base SI units.
//
// NOTE: We cannot compare inverses as that breaks the general compareTo contract:
// if a.compareTo(b) < 0 then b.compareTo(a) > 0
// if a.compareTo(b) == 0 then b.compareTo(a) == 0
//
// Since "10S" == ".1ohm" (10 > .1) and "10ohm" == ".1S" (10 > .1)
// Qty("10S").inverse().compareTo("10ohm") == -1
// Qty("10ohm").inverse().compareTo("10S") == -1
//
// If including inverses in the sort is needed, I suggest writing: Qty.sort(qtyArray,units)
export function compareTo(a: Quantity, b: string | number | Quantity)
{
if (typeguards.isString(b) || typeguards.isNumber(b))
{
return compareTo(a, new Quantity(b));
}
if (!isCompatible(a, b))
{
throwIncompatibleUnits();
}
if (a.baseScalar.lt(b.baseScalar))
{
return -1;
}
else if (a.baseScalar.eq(b.baseScalar))
{
return 0;
}
else if (a.baseScalar.gt(b.baseScalar))
{
return 1;
}
}
//
// Check to see if units are compatible, but not the scalar part
// this check is done by comparing signatures for performance reasons
// if passed a string, it will create a unit object with the string and then do the comparison
// this permits a syntax like:
// unit =~ "mm"
// if you want to do a regexp on the unit string do this ...
// unit.units =~ /regexp/
//
export function isCompatible(a: Quantity, b: string | number | Quantity) : boolean
{
if (typeguards.isString(b))
{
return isCompatible(a, new Quantity(b));
}
if (!(b instanceof Quantity))
{
return false;
}
if (b.signature !== undefined)
{
return a.signature === b.signature;
}
else
{
return false;
}
}
// returns true if no associated units
// false, even if the units are "unitless" like 'radians, each, etc'
export function isUnitless(a: Quantity) : boolean
{
return compareArray(a.numerator, UNITY_ARRAY) && compareArray(a.denominator, UNITY_ARRAY);
}