The Machines · Core numerics

eng

Engineering mathematics — machines/eng.shoddy

the eng machine's icon

Summary

eng is the machine you reach for when the arithmetic stops being arithmetic. It collects, on one shelf:

Every word is pure and every word is prefixed Eng.

A Brief History of the Handbook

For most of the twentieth century, applied mathematics was done out of a book. Not a textbook — a handbook: tables of the special functions, the distributions, the constants and the working formulas, kept at the elbow of everyone whose job was getting numbers out rather than proving theorems. The definitive one arrived in 1964, when the U.S. National Bureau of Standards published Milton Abramowitz and Irene Stegun's Handbook of Mathematical Functions. It was a thousand-page slab, assembled in large part by human computers. It became one of the most-cited works in all of science and has never gone out of print. Its real insight was editorial: the hyperbolics, the gamma family, the distributions, the roots and quadratures and constants belong on one shelf, because the person who needs one of them this week will need another next week. eng is that shelf as a machine — not a branch of mathematics but an engineer's working collection, every entry computable instead of tabulated.

Why It's Useful

This is the surface of a good scientific calculator, made into a library that does not lie to you. The formulas are mostly short and mostly famous, and almost every one has a way of producing a plausible wrong number instead of an error. That is what this machine is for.

Angles are radians at every boundary. There is no degree mode, because a mode is state and this machine has none. A trig word whose answer depends on a setting made three screens ago is the single worst thing about the calculators this surface was compiled from. EngRad, EngDeg, EngGradOf and EngFromGrad convert at the edges, and are the only places a 180 or a 200 appears in an angle context.

Coefficients are highest power first. { 1, 0, 0 - 4 } is x^2 - 4. This is the one convention a caller will get backwards. Backwards, it evaluates without complaint to the wrong number. So it is stated here, in the file's banner, and beside every polynomial word.

Never compare complex numbers with =. Structural equality reports EngComplex(0.1 + 0.2, 0) and EngComplex(0.3, 0) as different. That is true of the bits and useless to you. EngCNear is the only comparison offered, and it is the one to use on any root or transform output.

Solvers refuse rather than mislead. EngZeroOf checks that its bracket — the interval you claim holds a root — actually contains a sign change before it starts halving. Bisection (solving by cutting that interval in half again and again) converges perfectly happily on an endpoint when the bracket holds no root. It then hands back a number that is not a root at all — the worst failure available here, and the reason the check is not optional.

The surface is closed. No stats, math, str or seq name appears in a signature or a return type, so you include one machine and get one vocabulary. The wrappers over stats are mandatory rather than polite: this machine includes stats, so a word named Mean here would be a duplicate declaration and the machine would not load.

User's Guide

Complex numbers

Nothing in the tree had a complex type before this one. Every word that can return a complex number does, rather than splitting into real and imaginary halves you have to reassemble:

Include "eng.shoddy"

Def Main()
    Let z = EngComplex(3, 4)
    Print(EngCAbs(z))                    ' 5
    Print(EngCShow(EngConj(z)))          ' 3 - 4i

    ' Euler, which is the test that the exponential is really complex
    Print(EngCShow(EngCExp(EngComplex(0, Pi()))))    ' -1

    ' And the comparison that actually works
    Print(EngCNear(EngCMul(EngComplex(0, 1), EngComplex(0, 1)),
                   EngComplex(0 - 1, 0), 0.0000000001))      ' True

EngCShow drops a zero part and never prints a plus followed by a minus, so a complex number reads the way it is written on paper.

Calculus over a quotation

Differentiation, integration, summation and root-finding all take a quotation — [ Number -- Number ] — and call it:

Print(EngDeriv(Fn(x) => x * x, 3))                    ' 6
Print(EngIntegrate(Fn(x) => Sin(x), 0, Pi(), 100))    ' 2
Print(EngSumOf(Fn(i) => i, 1, 100))                   ' 5050
Print(EngZeroOf(Fn(x) => x * x - 2, 0, 2))            ' 1.41421356...
Print(EngMinOf(Fn(x) => (x - 3) * (x - 3) + 1, 0, 10))    ' 3

The step in EngDeriv is scaled to the size of x, because a fixed step is either noise near zero or lost in the rounding at 109. EngDeriv2 deliberately uses a much larger step. A second difference subtracts three nearly equal numbers, and too small a step loses every significant digit to cancellation — the digit-wipeout that comes from subtracting nearly equal numbers. Expect about eight good digits from the first derivative and four from the second.

EngIntegrate is composite Simpson and wants an even number of intervals. It says so rather than quietly applying the wrong weights. EngNewtonOf is there when you have a good starting point, and it is the unguarded one — it diverges on a bad start where EngZeroOf cannot.

Polynomials

A polynomial is a list of coefficients, highest power first. That is one convention for the whole machine and it matches lin's characteristic polynomials, so the two compose:

Let p = { 1, 0, 0 - 4 }                  ' x^2 - 4
Print(EngPolyEval(p, 3))                 ' 5
Print(EngPolyArea(p, 0, 2))              ' the definite integral

Let d = EngPolyDiv(p, { 1, 0 - 2 })      ' divide by x - 2
Print(EngPolyEval(Quotient(d), 1))       ' 3 — the quotient is x + 2
Print(EngPolyEval(Remainder(d), 7))      ' 0 — it went exactly

EngPolyDiv hands back both halves in one record. A caller who wanted only the quotient has usually assumed the remainder is zero, and this makes them look. EngQuadRoots always returns complex numbers, even when the roots are real: a word that changed its return type depending on the discriminant (the b² − 4ac test that says whether the roots are real) could not be branched on.

Statistics, without leaving

The descriptive statistics are here, prefixed like everything else:

Print(EngMean(xs))
Print(EngStdDev(xs))     ' sample form (n-1), like a spreadsheet's STDEV
Print(EngStdDevP(xs))    ' population form (n)
Print(EngNormCdf(110, 100, 15))   ' raw mean and sd, not a z-score

Both standard-deviation forms are here and each is named for which it is, because picking the wrong one gives a plausible wrong number and no error. (Standard deviation is the typical distance of a value from the average.) The line is drawn at the inferential half. If you want Anova or TTest2 you have left engineering mathematics behind, and you include stats and say so.

Units that check themselves

A unit is a record, not a string, so a conversion between two different quantities is caught rather than performed:

Print(EngConvert(1, EngMile(), EngKilometre()))        ' 1.609344
Print(EngConvert(100, EngCelsius(), EngFahrenheit()))  ' 212
Print(EngConvert(1, EngStone(), EngPound()))           ' 14
' EngConvert(1, EngMetre(), EngSecond()) — aborts, naming both quantities

Temperature is the only quantity here with an offset, and it is why the record carries one at all. A temperature difference converts by the factor alone and must not go through EngConvert.

Printing a result

Print(EngSigFig(0.00123456, 3))     ' 0.00123 — significant figures
Print(EngRoundTo(0.00123456, 3))    ' 0.001   — decimal places
Print(EngMetric(47000, 0))          ' 47k     — what's written on the part
Print(EngSci(12345, 2))             ' 1.23E+4
Print(EngCommas(1234567, 0))        ' 1,234,567

Three Ceilings

Each of these produces a plausible wrong answer rather than an error, so each is worth knowing before it bites.

Word Reference

Every word, and the records they hand back

The records

WordDescription
EngComplex(re, im)Re, Im — a complex number, and its own constructor. Compare with EngCNear, never =.
EngPolarMag, Theta — magnitude and angle in radians.
EngDmsDegs, Mins, Secs. Degs, not Deg: EngDeg is the radians converter and a machine word outranks a field accessor of the same name.
EngStatAvg, Sd, Total — a one-variable summary. Named so rather than Mean/StdDev/Sum because those are stats' words.
EngFitIntercept, Slope, RFit — a fitted curve. RFit is the correlation in the fitted space, which is what a spreadsheet reports.
EngDividedQuotient, Remainder — both halves of a polynomial division.
EngUnitName, Quantity, Factor, Offset. Factor and Offset take a value to the quantity's base unit.
EngConstCName, Value, Units — a physical constant carrying its own units.

Angles

WordDescription
EngRad(deg) / EngDeg(rad)Degrees and radians, both ways.
EngGradOf(rad) / EngFromGrad(grad)Gradians, both ways. 100 to the right angle.
EngDmsOf(deg)Decimal degrees to degrees/minutes/seconds → EngDms. The seconds carry the fraction, so a round trip is exact to the precision of the input.
EngFromDms(d)And back. The sign lives on the degrees.

Trigonometry

WordDescription
EngSec / EngCsc / EngCotThe three reciprocals the runtime does not supply.
EngAsec / EngAcsc / EngAcotAnd their inverses. The first two refuse below |x| = 1.
EngHypot(x, y)The hypotenuse, without squaring into an overflow.
EngDistOf(x0, y0, x1, y1)Distance between two points.
EngAngleOf(dx, dy)The direction of a vector, all four quadrants.
EngRectX(mag, theta) / EngRectY(mag, theta)Polar to rectangular. Two words rather than one returning a pair, because a caller wants one or the other at the point of use.
EngPolarOf(x, y)And rectangular to polar → EngPolar.

Hyperbolics

WordDescription
EngSinh / EngCosh / EngTanhThe three. Sinh and Cosh overflow around |x| > 710.
EngSech / EngCsch / EngCothTheir reciprocals.
EngAsinh / EngAcosh / EngAtanhThe inverses. Acosh refuses below 1, Atanh at or beyond 1.
EngAsech / EngAcsch / EngAcothAnd the reciprocal inverses.

Logarithms, exponentials and roots

WordDescription
EngLogBase(base, x) / EngLog2(x)Logarithms to an arbitrary base, and to 2.
EngLog1p(x) / EngExpm1(x)log(1+x) and e^x - 1, accurate near zero where the naive forms lose most of their significant digits to cancellation.
EngNthRoot(x, n)The real nth root, including the odd root of a negative that x ^ (1/n) gets wrong. Refuses an even root of a negative.

Complex numbers

WordDescription
EngCAdd / EngCSub / EngCMul / EngCDivArithmetic. Division refuses by zero.
EngConj(z)The conjugate.
EngCAbs(z) / EngCArg(z)Modulus and argument.
EngCExp / EngCLog / EngCSqrt / EngCPowThe transcendentals, through the polar form.
EngCFromPolar(mag, theta) / EngCToPolar(z)Between the two representations.
EngCNear(a, b, tol)The only comparison offered. = on two complex records answers about the bits, not the numbers.
EngCShow(z)A readable string. Drops the zero part; never prints a plus followed by a minus.

Statistics

WordDescription
EngSum / EngMean / EngMedianThe everyday three.
EngStdDev / EngStdDevPStandard deviation, sample (n-1) and population (n). Named for which they are, because the wrong one is invisible.
EngVar / EngVarPVariance, the same two ways.
EngMinimum / EngMaximum / EngRangeOfExtremes and their spread.
EngQuantile(xs, p)The value at fraction p — 0..1. The percentile form is deliberately not wrapped, so one fraction convention holds across the whole surface.
EngSkewness / EngKurtosisDistribution shape. Kurtosis is excess: a normal curve is 0.
EngWeightedMean / EngGeoMeanWeighted and geometric averages.
EngCorrel / EngCov / EngSpearmanHow two series move together — linear, raw, and by rank.
EngStat1(xs)Mean, standard deviation and total in one EngStat.
EngNormPdf(x, mean, sd) / EngNormCdf(x, mean, sd)The normal distribution, taking a raw mean and standard deviation where stats takes a z-score.
EngNormInv(p)The standard normal quantile.
EngTCdf / EngTInv / EngChi2Cdf / EngFCdfStudent's t, chi-squared and F.
EngFitOf(xs, ys, model)Fits linear, logarithmic, exponential or power → EngFit. Errors on non-positive inputs for the three log models rather than dropping points.
EngLinear() / EngLogModel() / EngExpModel() / EngPowerModel()Which curve EngFitOf fits.

Number theory

WordDescription
EngGcd(a, b) / EngLcm(a, b)Sign is ignored; the answer is never negative.
EngIQuot(a, b) / EngIRem(a, b)Integer division, truncated toward zero — the remainder takes the sign of the dividend.
EngModPow(base, e, m)Square-and-multiply, so no intermediate leaves 253 even when the exponent is large.
EngModInv(a, m)The modular inverse. Errors when a and m are not coprime, because a caller handed a non-inverse back will not check it.
EngIsPrime(n) / EngPrimes(n)Primality, and every prime up to n.
EngFactorize(n)The prime factors, with multiplicity, in order.
EngDivisors(n) / EngTotient(n)Every divisor, and Euler's totient.

Combinatorics and the gamma family

WordDescription
EngFact(n)Factorial. Exact to 18; past that a double no longer holds whole numbers exactly.
EngComb(n, k)Unordered selections, computed multiplicatively — EngComb(52, 5) is 2598960 exactly.
EngPerm(n, k)Ordered arrangements.
EngFib(n)Fibonacci, iteratively.
EngGammaLn(x)The log of the gamma function, by Lanczos. The one to reach for: it holds where EngGamma overflows, and every distribution here is built on it.
EngGamma(x)The gamma function itself, by reflection below a half.
EngBeta(a, b)The beta function.

Discrete distributions

WordDescription
EngBinomPdf(k, n, p) / EngBinomCdf(k, n, p)Binomial. The Cdf is summed from zero and is inclusive of k.
EngPoissonPdf(k, lambda) / EngPoissonCdf(k, lambda)Poisson, through EngGammaLn rather than a factorial.
EngGeomPdf(k, p) / EngGeomCdf(k, p)Geometric. k counts trials up to and including the first success, so it starts at 1 — the other convention differs by one and looks reasonable either way.
EngHyperPdf(k, draws, wins, popn)Drawing without replacement.
EngExpCdf(x, rate)The exponential distribution.

Numeric calculus

WordDescription
EngDeriv(f, x)Central difference, step scaled to x. About eight good digits.
EngDeriv2(f, x)The second derivative, on a deliberately larger step. About four.
EngIntegrate(f, a, b, n)Composite Simpson over n intervals. n must be even, and the word says so rather than applying the wrong weights.
EngSumOf(f, lo, hi) / EngProdOf(f, lo, hi)Summation and product over an integer range.

Ordinary differential equations

Fixed-step fourth-order Runge–Kutta, over quotations like the rest of the calculus. No stiffness detection — a stiff equation (one mixing very fast and very slow behaviour) explodes rather than erroring, so pick h for the fastest rate in the problem.

WordDescription
EngOdeStep(f, t, y, h)One RK4 step for y′ = f(t, y): the value at t + h. Error per step is of order h⁵.
EngOdeSolve(f, t0, y0, t1, n)The trajectory from t0 to t1 in n equal steps: n + 1 values, the first y0 — one per sample point, which is what a plot wants. Refuses n below 1 or fractional.
EngOdeSysStep(f, t, ys, h)One RK4 step for a system: the state is a List Of Number and the derivative answers one the same length. A second-order equation is a first-order pair — the damped driven oscillator is the state { y, y′ }.
EngOdeSysAt(f, t0, ys0, t1, n)The state at t1, in n equal steps. The final state only; a caller who wants the path walks EngOdeSysStep and keeps what they need.

Roots and optimisation

WordDescription
EngZeroOf(f, lo, hi)Bisection. Checks the bracket first and errors when there is no sign change in it.
EngNewtonOf(f, x0)Newton's method with a numeric derivative, so you supply one quotation rather than two. Unbracketed and therefore unguarded — it diverges on a bad start, and EngZeroOf is the safer word.
EngMinOf(f, lo, hi) / EngMaxOf(f, lo, hi)Golden-section search. Requires the function to be unimodal on the bracket; given two minima it finds one and does not say which.

Polynomials

Coefficients are highest power first. { 1, 0, 0 - 4 } is x^2 - 4. Reversed, every word here still returns a number, and it is the wrong number.

WordDescription
EngPolyEval(cs, x)Horner's method.
EngPolyDegree(cs)Leading zeros do not count.
EngPolyAdd / EngPolySub / EngPolyMul / EngPolyScaleArithmetic, aligned on the lowest power and trimmed afterwards.
EngPolyDiv(a, b)Long division → EngDivided. Both halves, because a caller who wanted only the quotient has usually assumed the remainder is zero.
EngPolyDeriv(cs)Differentiation.
EngPolyIntegral(cs, c0)Integration. The constant is required rather than assumed to be zero.
EngPolyArea(cs, a, b)The definite integral between two points.
EngPolyTrim(cs)Drops leading zeros.
EngQuadRoots(a, b, c)Both roots, always as complex numbers even when they are real — a word with two return types could not be branched on.
EngCubicReal(a, b, c, d)The real roots of a cubic: three by the trigonometric form, one by Cardano's radicals. The length of the answer tells you which case you were in.

Numeric sequences

WordDescription
EngLinSpace(lo, hi, n)n evenly spaced values, reaching the far end exactly.
EngGeomSpace(lo, hi, n)Geometrically spaced. Needs both ends strictly positive: no ratio crosses zero.
EngCumSum(xs)Running total.
EngDiff(xs)Successive differences — one shorter than its input, which is the point.
EngMovAvg(xs, w)Moving average over a window.
EngNormalize(xs)Scaled to 0..1. A flat list becomes zeros rather than dividing by a zero range.
EngDotOf(xs, ys) / EngMagOf(xs)Dot product and Euclidean length of a plain list.

Units

WordDescription
EngConvert(x, src, dst)Converts, and errors when the two quantities differ, naming both.
EngToBase(x, u) / EngFromBase(x, u)To and from the quantity's base unit.
LengthEngMetre EngKilometre EngCentimetre EngMillimetre EngInch EngFoot EngYard EngMile EngNauticalMile
MassEngKilogram EngGram EngTonne EngPound EngOunce EngStone
TimeEngSecond EngMinute EngHour EngDay
TemperatureEngKelvin EngCelsius EngFahrenheit — the only quantity with an offset, and the reason the record carries one.
PressureEngPascal EngKilopascal EngBar EngPsi EngAtm
EnergyEngJoule EngKilojoule EngCalorie EngKwh EngBtu
PowerEngWatt EngKilowatt EngHorsepower — mechanical horsepower, the one James Watt sold engines against.
VolumeEngLitre EngMillilitre EngCubicMetre EngGallonUk EngGallonUs
SpeedEngMps EngKph EngMph EngKnot

Physical constants

Each returns an EngConst carrying its own units, because a bare number is the mistake these exist to prevent. Value(EngLightSpeed()) is the number.

WordDescription
EngLightSpeed / EngPlanck / EngGravitation / EngStdGravity299792458 m/s exactly by definition, and the rest.
EngElectronCharge / EngElectronMass / EngProtonMassThe particle constants.
EngAvogadro / EngBoltzmann / EngGasConstant / EngStefanBoltzmann / EngFaradayThe thermodynamic and chemical ones.
EngVacuumPermittivity / EngVacuumPermeabilityThe electromagnetic ones.
EngE() / EngTau()The two mathematical constants the runtime does not supply. Pi is a builtin and needs no wrapper.

Presentation

WordDescription
EngRoundTo(x, n)Round to n decimal places.
EngSigFig(x, n)Round to n significant figures. Not the same thing: EngSigFig(0.00123456, 3) is 0.00123 and EngRoundTo(0.00123456, 3) is 0.001.
EngSci(x, p)Scientific notation — one digit before the point.
EngMetric(x, p)Engineering notation: the exponent moves in threes and the mantissa carries an SI prefix. 47000 ohms prints as 47k, which is what is written on the part.
EngMetricPrefix(k)The SI prefix for a power-of-1000 exponent, y through Y.
EngCommas(x, p)Grouped thousands.
EngFracOf / EngClamp / EngLerp / EngInvLerp / EngRemap / EngSmoothstepThe interpolation family.
EngSign(x)-1, 0 or 1.
EngNear(a, b, tol)The scalar counterpart of EngCNear, and the same warning applies.

What is deliberately elsewhere. Number bases, bit operations and truth tables are bool. Symbolic factoring and symbolic calculus are alg. Linear algebra over matrix's Matrix is lin. The hypothesis tests are stats. And random numbers stay in math, because wrapping Rnd would make this machine's purity untrue. Polynomial arithmetic over coefficient lists is not symbolic algebra, and ships here.

Who Uses It

MachineWhy
linSummation, the polynomial words under LinCharPoly, and EngZeroOf under LinEigVals.

The Machines It Uses

MachineWhy
mathRad, Deg, Angle, Hypot, LogBase and the interpolation family under their Eng names.
seqAppend builds the factor and quotient lists; CountIf is Euler's totient; ZipWith is the dot product.
statsEvery descriptive statistic and distribution this machine offers, and LinFit under the four regression models.
strToFixed and Commas build EngSci, EngMetric and EngCommas.