GraphiteEditor/Graphite

Tracking Issue: Math expression parser/calculator

Open

#2,026 opened on 2024年10月9日

GitHub で見る
 (11 comments) (1 reaction) (1 assignee)Rust (1,176 forks)batch import
Good First IssueHelp Wanted

Repository metrics

Stars
 (25,662 stars)
PR merge metrics
 (平均マージ 6d 9h) (30d で 65 merged PRs)

説明

This is our library at /libraries/math-parser that uses a parsing framework (begun in #2033 with Pest but now switching to 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.

Roadmap

  • Real numbers
  • Complex numbers
  • Vec2/Vec3/Quaternions
  • Units
  • Documentation
  • Error reporting
  • Compiling into Graphene AST

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: &&
  • Prefix operators:
    • Unary Plus: +
    • Unary Minus: -
    • Square root:
    • Not: !
  • Postfix operators:
    • Factorial: !
  • Grouping operators:
    • Parentheses: ( )

Functions

  • Trig:
    • sin(), cos(), tan()
    • csc(), sec(), cot()
  • Inverse trig (aliases: ar- and arc- prefixes):
    • asin(), acos(), atan(), atan2()
    • acsc(), asec(), acot()
  • Hyperbolic:
    • sinh(), cosh(), tanh()
    • csch(), sech(), coth()
  • Inverse hyperbolic (aliases: ar- and arc- prefixes):
    • asinh(), acosh(), atanh()
    • acsch(), asech(), acoth()
  • Logarithm:
    • Natural log: ln()
    • Logarithm base N: logN() (alias: log_N())
      • Examples: log2(), log3.25(), log_10()
    • Logarithm with variable base: log(x, b)
  • Exponents:
    • Power of e: exp(n)
    • Power of N: pow(x, n)
      • Examples: pow2(5), pow3.25(5), pow_10(5)
    • Power with variable exponent: root(x, n)
  • Roots:
    • Square root: sqrt()
    • Cube root: cbrt()
    • Root base N: rootN(x) (alias: root_N(x))
      • Examples: root2(), root3.25(), root_10()
    • Root with variable degree: root(x, n)
  • Geometry:
    • Hypotenuse equation sqrt(a^2 + b^2): hypot()
  • 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)
    • Slerp: slerp(a, b, t) (quaternions only)
    • Remap: remap(value, inA, inB, outA, outB)
    • Truncate: trunc()
    • Fractional part: fract()
    • Sign: sign()
    • Greatest common denominator: gcd() (implemented here)
    • Least common multiple: lcm() (implemented here)
  • Logical
    • Is NaN: isnan()
    • If: if(cond, if_true, if_false)
  • Complex numbers:
    • Real part: real()
    • Imaginary part: imag()
    • Complex conjugate: conj()
    • Angle: arg() (angle from the +real axis in radians)

Constants

  • Infinity: inf, INF, infinity, INFINITY,
  • Basis vectors: i, j, k
  • Pi: pi, PI, π
  • Tau: tau, TAU, τ
  • Euler's Number: e
  • Golden Ratio: phi, PHI, φ

Variables

  • Single-letter variables (examples: x, y, z)
  • Multi-letter variables (examples: theta, alpha, beta, gamma)
  • Non-Latin letters and symbols (examples: λ, , א, 👍)
  • Special character prefixed variables (examples: #foo, $foo, ~foo, etc.)

Number and unit representations

  • Scientific notation (examples: 1e-6, 2.5E3)
  • Units (examples: 5m, 5 m, 3.5kg, 3.5 kg, 2.5m/s^2, 2.5 m/s^2)

Number systems

  • Basis 1: Real numbers (examples: 0, 42, -42, 0.5, 3.14159, -2.71828)
  • Bases 1, i: Complex numbers (examples: 3i, -2.5i, 1.5e-3i, 2.5e3 + 2.1e-2i)
  • Bases 1, i, j, k: Quaternions
    • Vec2 (examples: 3i + 2j, -3i - 2j)
    • Vec3 (examples: 3i + 2j + k, -3i - 2j - k)
    • Full quaternion (examples: 4 + 3i + 2j + k, 4 + 3i + 2j, 4 + 3i)

Reading results

  • Query as f{32, 64}/{u, i}{8, 16, 32, 64, 128} (1 basis -> x, the real part)
  • Query as Vec2 (1, i bases -> x, y, the complex parts)
  • Query as Vec3 (i, j, k bases -> x, y, z, the non-real parts)
  • Query as Vec4 (1, i, j, k bases -> w, x, y, z, all parts)
  • Query as NurbsPoint (1, i, j, k bases -> weight, x, y, z, all parts)
  • Query as Quaternion (1, i, j, k bases -> w, x, y, z, all parts)

Implicit multiplication

  • Automatically handle multiplication without explicit * operator
    • Between numbers and variables/constants (examples: 3x, 2pi)
    • Between numbers and functions (example: 4sin(90deg))
    • Between space-separated adjacent variables/constants (examples: x y, pi r^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)
  • 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
  • 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
  • Time:
    • Second s and its prefixes
    • min, hr, day
  • Angle:
    • Degrees: deg/°
    • Radians: rad (unitless is not an angle)
    • Turns: turn
  • 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)

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

コントリビューターガイド