Open
Description
This should be built as a library (in our /libraries
directory) that uses a parsing framework such as Chumsky that takes a string at runtime and calculates its result, including units and dimensional analysis.
This would make a great solo contribution for somebody interested in developing a robust solution for this problem without needing to learn any of Graphite's code base. It would also make a good university team/solo "capstone" project, which our organization can serve as an "industry sponsor" for.
Here's the spec:
Operators
- Infix operators:
- Addition:
+
- Subtraction:
-
- Multiplication:
*
- Division:
/
- Modulo:
%
- Exponentiation:
^
- Equals:
==
- Not Equals:
!=
- Less Than or Equal To:
<=
,≤
- Greater Than or Equal To:
>=
,≥
- Less Than:
<
- Greater Than:
>
- Or:
||
- And:
&&
- Addition:
- Prefix operators:
- Unary Plus:
+
- Unary Minus:
-
- Square root:
√
- Not:
!
- Unary Plus:
- Postfix operators:
- Factorial:
!
- Factorial:
- Grouping operators:
- Parentheses:
(
and)
- Parentheses:
- Logical operators:
- Equality:
==
,!=
,>=
,<=
,<
,>
,||
,&&
, and!
logical operators to the spec.
- Equality:
Constants
- Infinity:
inf
,INF
,infinity
,INFINITY
,∞
- Imaginary unit:
i
,I
- Pi:
pi
,PI
,π
- Tau:
tau
,TAU
,τ
- Euler's Number:
e
- Golden Ratio:
phi
,PHI
,φ
- Earth's gravitational acceleration:
G
Variables
- Single-letter variables (examples:
x
,y
,z
) - Multi-letter variables (examples:
theta
,alpha
,beta
,gamma
) - Non-Latin letters and symbols (examples:
λ
,あ
,א
,👍
)
Functions
- Trig:
-
sin()
,cos()
,tan()
-
csc()
,sec()
,cot()
-
- Inverse trig (aliases:
ar-
andarc-
prefixes):-
asin()
,acos()
,atan()
,atan2()
-
acsc()
,asec()
,acot()
-
- Hyperbolic:
-
sinh()
,cosh()
,tanh()
-
csch()
,sech()
,coth()
-
- Inverse hyperbolic (aliases:
ar-
andarc-
prefixes):-
asinh()
,acosh()
,atanh()
-
acsch()
,asech()
,acoth()
-
- Logarithm:
- Natural log:
ln()
- Logarithm base 10:
log()
- Logarithm base 2:
log2()
- Logarithm base N:
logN()
(alias:log_N()
)- Examples:
log5()
,log3.25()
,log_8()
- Examples:
- Logarithm with variable base:
log(x, b)
- Natural log:
- Exponential:
- e^x:
exp()
- 2^x:
exp2()
- e^x:
- Roots:
- Square root:
sqrt()
(alias:root()
,root2()
,root_2()
) - Cube root:
cbrt()
(alias:root3()
,root_3()
) - Nth root:
rootN()
(alias:root_N()
)- Examples:
root3()
,root5.237()
,root_27.72()
- Examples:
- Root with variable degree:
root(n, x)
- Example:
root(27, 3)
is equivalent tocbrt(27)
- Example:
- Square root:
- Geometry:
- Hypotenuse equation sqrt(a^2 + b^2):
hypot()
- Hypotenuse equation sqrt(a^2 + b^2):
- Mapping:
- Absolute value:
abs()
(magnitude of a real or complex number) - Floor:
floor()
- Ceiling:
ceil()
- Round:
round()
- Clamp:
clamp(x, min, max)
- Lerp:
lerp(a, b, t)
- Truncate:
trunc()
- Fractional part:
frac()
- Sign:
sign()
- Absolute value:
- Logical
- Is NaN:
isnan()
(returns 1 if the operand is NaN, 0 otherwise) - Equality:
eq()
(returns 1 if both operands and units are equal, 0 otherwise) - Greater than:
greater()
(returns 1 if the left operand is greater than the right operand and units are equal, 0 otherwise) - Greater-or-equal:
greatereq()
(returns 1 if the left operand is greater than or equal to the right operand and units are equal, 0 otherwise) - Less than:
lesser()
(returns 1 if the left operand is less than the right operand and units are equal, 0 otherwise) - Less-or-equal:
lessereq()
(returns 1 if the left operand is less than or equal to the right operand and units are equal, 0 otherwise) - Not:
not()
(returns 1 if the operand is zero, 0 otherwise) - And:
and()
(returns 1 if both operands are non-zero, 0 otherwise) - Or:
or()
(returns 1 if either operand is non-zero, 0 otherwise) - Xor:
xor()
(returns 1 if exactly one operand is non-zero, 0 otherwise) - If:
if(cond, a, b)
(returnsa
ifcond
is non-zero,b
otherwise)- A potential alternative to nonzeroness in these logical functions could be using
true
andfalse
as units with either no value, a value of 0, or a value of 1
- A potential alternative to nonzeroness in these logical functions could be using
- Is NaN:
- Complex numbers:
- Real part:
real()
- Imaginary part:
imag()
- Angle:
arg()
(alias:angle()
)
- Real part:
Number representations
- Integers (examples:
0
,42
,-42
) - Decimals (examples:
0.5
,3.14159
,-2.71828
) - Scientific notation (examples:
1e-6
,2.5E3
) - Imaginary numbers (examples:
3i
,-2.5i
,1.5e-3i
,2.5e3 + 2.1e-2i
) - Units (examples:
5m
,5 m
,3.5kg
,3.5 kg
,2.5m/s^2
,2.5 m/s^2
)
Units
- In addition to the unit abbreviations, full unit names can be used in either singular or plural form
- Math expressions perform dimensional analysis
- The scalar part is simplified while the unit part is kept as a fraction if it cannot be simplified
- Units should only be combined if they are mixed with other units in either the numerator or denominator, defaulting to the unit that would best avoid loss of precision
- Example:
5m + 3m -> 8m
- Example:
5ft + 3ft -> 8ft
- Example:
5m + 3ft -> 5.9144m
(meters are chosen because 1ft = 0.3048m exactly, while its inverse can't be represented exactly)
- Example:
- Values can always be requested for conversion to a specific unit in the API
Unit list
- Unitless
- Pixels:
px
- Length:
- Meter
m
and its prefixes thou
,pc
,pt
,in
/"
,ft
/'
,yd
,mi
,nmi
- Meter
- Area:
- length^2
acre
,are
,hectare
- Volume:
- length^3, area * length
- Paper sizes:
A0
,A1
,A2
,A3
,A4
,A5
,A6
,A7
,A8
,A9
,A10
floz
,cup
,pint
,qt
,gal
l
and its prefixes
- Mass:
- Kilogram
kg
and its prefixes gr
,oz
,lb
,ton
,tonne
- Kilogram
- Time:
- Second
s
and its prefixes min
,hr
,day
- Second
- Angle:
- Degrees:
deg
/°
- Radians:
rad
(unitless is not an angle) - Turns:
turn
- Degrees:
- Velocity:
- length / time
m/s
,km/h
,mph
,knot
- Acceleration:
- velocity / time, length / time^2
m/s^2
,ft/s^2
,g
- Angular velocity:
- angle / time
deg/s
,rad/s
,rpm
,rps
- Angular acceleration:
- angular velocity / time, angle / time^2
deg/s^2
,rad/s^2
- Illumination
- TODO: Research and lay out what these are, like candela, nits, etc.
Unit metric prefixes
- Nano (
n
) - Micro (
µ
,u
) - Milli (
m
) - Centi (
c
) - Deci (
d
) - Deca (
da
) - Hecto (
h
) - Kilo (
k
) - Mega (
M
) - Giga (
G
) - Tera (
T
)
Implicit multiplication
- Automatically handle multiplication without explicit
*
operator- Between numbers and variables/constants (examples:
3x
,2pi
) - Between numbers and functions (example:
4sin(90deg)
) - Between adjacent variables/constants (examples:
xy
,pi r^2
)
- Between numbers and variables/constants (examples:
API features
- Parsing/construction separate from evaluation so the same expression can be run repeatedly with different variables without wasted performance
- Setting the result of one expression to a variable for use in subsequent expressions
- Custom supplied units, unit symbols, functions, and constants
- Syntax highlighting
- Initial library implementation (Add math-parser library #2033)
- Add more features as described in the spec above, such as
abs()
and others
Sub-issues
Metadata
Metadata
Assignees
Type
Projects
Status
Ongoing Projects