Repository navigation
formula-cpp 0.5.0
The fifth release of formula-cpp, a header-only C++23 library for traceable formulas. You write a formula once
in C++. Dimensions are checked at compile time, units are converted exactly, and evaluation runs in exact rational
arithmetic. The same formula renders as documentation and traces step by step into an audit trail.
This release makes the library easier to learn and lets it take units, limits and numbers that arrive at run time:
- A tutorial. Nine chapters build one compressive-strength test step by step, and six more cover the rest of the
library. Every snippet and every output on its pages comes from a program the test suite builds and runs. - Run-time units, limits and numbers. Unit symbols and ASCII keys from run-time text, one-sided bounds, limits
checked at run time, a quantity's own decimal places, and decimal text parsed into its exact value.
Documentation, with the tutorial, the guides, a gallery and the API reference:
https://lastrada-software.github.io/formula-cpp/
Requirements
- C++23, CMake 3.23 or newer, and GCC 14 or newer.
- CI builds and tests every change on:
- MSVC
clandclang-cl(Windows); - Clang and GCC 14 (Linux), including an UndefinedBehaviorSanitizer build;
- Clang on macOS.
- MSVC
Installation
CPMAddPackage("gh:LASTRADA-Software/formula-cpp@0.5.0")
target_link_libraries(your_target PRIVATE formula-cpp::formula-cpp)find_package(formula-cpp CONFIG REQUIRED) from an install tree, or copying include/, work as well.
What is new
- Documentation.
- A tutorial in two tracks: nine chapters that grow one compressive-strength test, from a first formula
through units, exact numbers, missing and entered values, rounding, constraints, documentation, tracing and
worksheets, and six independent chapters on lookup tables, methods and overlays, series, statistics, records,
and opaque operations with bounded retry. - The README is a short landing page: a minimal example with its output, and installation with CPM,
find_packageor the headers alone. - No drift between pages and code. Tutorial and README code is included from compiled programs, and each
program's whole output is compared with a checked-in file. The documentation describes the library as it is;
the changelog alone records history, and a test enforces it. examples/cycling_speed.cpp, a cyclist's steady-state speed from power, calculated on a worksheet.
- A tutorial in two tracks: nine chapters that grow one compressive-strength test, from a first formula
- Units from run-time text.
checked_symbol()builds a unitSymbolfrom run-time text byte for byte, returning
std::expected<Symbol, SymbolError>(TooLong,EmbeddedNull). It never truncates and never aborts.- A stable ASCII key per unit.
UnitgainsasciiText, a key for serialising the unit that stays the same
when its display symbol is restyled.view_ascii,has_ascii_keyandchecked_ascii_symbol()read and build
it. The built-in units with non-ASCII symbols declare keys:permille,um,degC,degF.
- Limits.
- One-sided bounds.
at_least()andat_most()declare a minimum or a maximum alone, besidebounds(). - Limits held at run time.
checked_within(value, lowEnd, highEnd)checks aRationalor aMeasured
against optional ends from a specification row or a catalogue entry, with noUnitbuilt to carry them.
- One-sided bounds.
- Numbers.
- A quantity's own decimal places.
Quantitytakes an optional fifth parameter,DecimalPlaces, so two
quantities in one unit can read to different precision.same_unitsays whether two units are the same unit,
whatever their declared decimals and bounds. parse_decimal_textreads decimal text from a CSV import, a form field or a configuration value into its
exact value and the places it was typed to:"2.400"is 12/5 at 3 places._rliterals take a 128-bit
mantissa and scale from 10^-38 to 10^38.checked_transformandchecked_combineapply a callback that can fail to measured values, and stay
noexceptwhen the callback is.
- A quantity's own decimal places.
- A bound formula is an operand. A formula bound with
yields<Q>(...)can be used inside another formula, where
it stands for the formula it holds:yields<Strength>(var<Load> / loadedArea). That covers the arithmetic and
comparison operators and every function that builds a formula..expressionstill compiles and means the same. - Coverage reporting. A workflow measures the test suite's coverage of
include/for Codecov.
Upgrading from 0.4.0
A minor release may break the public API before 1.0, and this one does. The CHANGELOG lists every change under
Changed; these four are marked Breaking:
symbol()isconsteval. Its spelling must be a constant expression. Build a symbol from run-time text with
checked_symbol().SymbolCapacityis 32 bytes, up from 16.Symbol,Dimension,Unitand a trace'sStepare larger, so a
trace takes more memory.- A unit whose symbol is not ASCII must declare an ASCII key,
.asciiText = formula::symbol("ug/L")forµg/L,
or its use as a quantity's, constant's, rounding's or table's unit no longer compiles:
formula: a unit whose symbol is not ASCII must declare an ASCII key.Unithas a new member aftersymbolText, so aUnitbuilt with positional initialisers must move to
designated initialisers.- Unit equality compares
asciiTexttoo. Usesame_unitto ask whether two units are the same unit.
Bounds::presentis replaced bylowPresentandhighPresent. ABoundsbuilt with positional initialisers
in the old order no longer compiles;{ true }alone now declares a minimum of 0 and no maximum. Usebounds(),
at_least(),at_most()or designated initialisers. Code that readpresentreadslowPresent || highPresent.
Full changelog: CHANGELOG.md