Repository navigation
Releases
formula-cpp 0.5.0
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
formula-cpp 0.4.0
formula-cpp 0.4.0
The fourth 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 widens exact numbers to 128 bits and makes every number the library writes name its unit:
- Wider exact numbers.
Rationalstores a newformula::Int128, so realistic laboratory statistics that
overflowed 64 bits now answer. The logarithm and exponential take every argument aRationalholds. - A unit on every number. Every value a trace, a rendered formula,
number_textorstd::formatwrites now says
which unit its number is in.
Documentation, with 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
What is new
-
128-bit exact numbers.
-
formula::Int128: a signed 128-bit integer with one API on every compiler. GCC and Clang use the
compiler's own 128-bit integer, andclandclang-cluse portableconstexprcode. It converts to no
built-in integer, implicitly or explicitly.to_int64()andto_uint64()say when a value does not fit, and
std::formatwrites it in decimal. -
Rationalstores its numerator and denominator inInt128. These now answer where they overflowed:- the sample variance of masses read to 6 decimal places of a gram;
- rejection by standard deviations at that resolution;
- a cylinder's strength at every diameter measured.
The numeric headroom page measures how much room each fixture leaves.
-
-
Logarithms and exponentials take every argument a
Rationalholds.- The kernels behind
rounded_ln,rounded_log10androunded_expused to refuse arguments wider than 64 bits.
ln 2^70is now 48.5203 at 4 places. rounded_expanswers up to 88.7, beyond which no result fits aRational: e^45 to 18 places, e^88 to whole
units.- The exponential computes with 192 fraction bits, so a result as wide as a
Rationalis still decided.
- The kernels behind
-
A unit on every value a trace writes.
- Borrowed units. A computed value reads in its operand's unit where that is safe: the outlier-rejection limit
#2 * #3 = 1239/500000is now1239/500 g. Otherwise it reads in the coherent unit, spelt from its base units:
427/125000000 kg^2,60000000 kg/(m s^2). - Inverse units. A unit with nothing above the slash is written with negative exponents, so
20000/413 kg^-1
cannot be read as a fraction divided again. - Precision limits. A precision limit's first pass reads in its level's unit, as its second pass already
did.
- Borrowed units. A computed value reads in its operand's unit where that is safe: the outlier-rejection limit
-
Units with no symbol. A dimensioned unit with no symbol is named by its size wherever a number refers to it:
- a rounding reads
round(#1, to 2 dp of 1/1000 kg), where it readround(#1, to 2 dp); numeric(x, in 1/1000 kg)names the unit the same way;render(),number_textandstd::formatwrite a value declared in such a unit in the coherent unit, as a
trace does:3/1000 kg, not a bare3. This covers constants, table rows and bands, and limits too.
In LaTeX the size is grouped,
\operatorname{round}_{2\,(1/1000\,\mathrm{kg})}, and powers are raised:
\mathrm{kg}^{-1}. - a rounding reads
-
Diagnostics.
explainandchecked_explaingiven a series refuse it in the library's words, and point at
explain_seriesinstead of failing with "no matching function".
Upgrading from 0.3.0
A minor release may break the public API before 1.0, and this one does. The CHANGELOG lists every change under
Changed. These are the ones most likely to need an edit:
- A dimensionless unit with a scale or an offset and no symbol no longer compiles. That covers a quantity's
unit, a constant's, a rounding's, and a table's key or result. Such a unit printed one half in hundredths as a bare
50. Give the unit a symbol (%,ppm, or your own), or declare the quantity in scale 1. The refusal reads
formula: a dimensionless unit with a scale must have a symbol. Rational::IntisInt128, and aRationalis 32 bytes.- Code that stored
numerator()ordenominator()in a built-in integer must narrow withto_int64(), which
returnsstd::optional. Rational's converting constructor takes every built-in integer of at most 64 bits exceptbool, and refuses
a wider one.band(Rational, Rational)andbreakpoint(Rational)refuse a value that does not fit their 64-bit fields.
- Code that stored
- Trace texts changed. Text that a test pins changes wherever a trace showed a dimensioned value bare, an
inverse unit as1/kg, or a rounding in a unit with no symbol.Step::unitnow holds the unit a computed step borrowed.StepgainslookupKeyHigh: a sample-size lookup's count can exceed 2^64 - 1.
- Number text in a unit with no symbol.
number_textandstd::formatof aMeasuredvalue in a dimensioned
unit with no symbol write it in the coherent unit,3/1000 kgor0.003 kg, at that unit's places, where they
wrote a bare3.
formula-cpp 0.3.0
formula-cpp 0.3.0
The third release of formula-cpp, a header-only C++23 library for traceable formulas: written
once in C++, with dimensions checked at compile time and units converted exactly, evaluated in exact
rational arithmetic, rendered as documentation, and traced step by step into an audit trail.
This release gives a shorter spelling to everything the examples repeated, and takes no spelling
away: exact decimal literals, plain numbers in series, one call that reads a result's number or
returns a trace, std::format for results, a rounding named once, and a formula bound to its result
quantity. Every example is rewritten with them.
Documentation, with 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, with an UndefinedBehaviorSanitizer build) and Clang on macOS.
What is new
- Literals and inputs:
27.3_ris the exactRational273/10, where27.3is the double
nearest it. A series takes plain numbers andnot_measuredbeside measured values:
measured_series<Determination>(41.3_r, 43.9_r, formula::not_measured, 45.7_r).
breakpoint(12.7_r)andband(83.7_r, 97.3_r)take exact numbers too. - Reading results:
number_of(x)is the number a result holds, or nothing, as a
std::optional<Rational>, for aMeasured, anOutcome, achecked_evaluateresult and the
other result types:number_of(checked_evaluate<Q>(...)) == 0.5_r. AMeasuredalso has throwing
twins,convert_to<R>,round_to_declaredandwithin_bounds, for callers who would only
rethrow. - Formatting: with
<formula-cpp/format.hpp>,std::format("{}", outcome)writes anOutcome,
aUnit, aDimensionand every enumeration that has adescribe().describenow covers
ConstraintOutcomeKind,RetryEnd,ValueSource,OutcomeKindandFailureSite.
symbol_of<Q>()needs no vocabulary, andrender(x, options)no placeholder one:
std::println("{} = {} ({})", formula::symbol_of<WaterCementRatio>(), *result, result->source()). - Traces:
traced(evaluation)runs any evaluation that takes a sink and returns the outcome with
its trace.explain_method<Tag>,explain_check_method,explain_check,explain_check_all,
explain_conformity,explain_curveandexplain_rejectionare the traced twins of their verbs, and
trace_of<Q>(expression, env)is the trace of an evaluation in one call, whether it succeeds or
fails:render_trace(trace_of(mixCost, inputs), { .maxSteps = 20 }). - A rounding named once:
DecimalRoundingandSignificantRoundinghold a unit, the places or
digits, and a mode, where the three were repeated at every use.
declared_rounding(unit, mode)takes the places the unit declares:
constexpr formula::DecimalRounding wholeCents = formula::declared_rounding(EuroCent, formula::RoundingMode::HalfAwayFromZero);
once, thenrounded<wholeCents>(var<Subtotal> + var<Vat>). - Bound formulas:
yields<Q>(expression)names a formula's result quantity once, where the
formula is written:constexpr auto circularArea = yields<Area>(pi * pow<2>(var<Diameter>) / 4);
thenevaluate(circularArea, environment).Qis still checked against the dimension the
expression computes, never deduced. Misusing a bound formula draws oneformula:message, not an
overload list. That covers a bound series or rejection handed to a verb that answers with one value,
and a bound formula used as an operand or compared. - The examples themselves: 18 example programs, 4705 → 4402 lines; uses of a private
rat()
helper 155 → 0;printf361 → 0 (nowstd::println);measurement().value()chains 60 → 0;
RecordingSinkin hand-built traces 23 → 0.
Upgrading from 0.2.0
A minor release may break the public API before 1.0, and this one does in a few places. Each change
is listed under Changed in the CHANGELOG. The ones most likely to need an edit:
- Argument-dependent lookup. An unqualified call with this library's types as arguments now also
finds the functions this release adds, among themdescribe,number_of,convert_to,
round_to_declared,within_bounds,traced,trace_of, theexplain_*twins,yieldsand
declared_rounding. A consumer's function template of the same name and shape, such as a
template <typename R, typename Q> Measured<R> convert_to(Measured<Q>)helper, is displaced
silently: the library's is more constrained and is chosen, so the helper no longer runs, and
where it returned an absent value on failure the library'sconvert_tothrows
ArithmeticException. A function of another shape, such as a non-template
describe(ConstraintOutcomeKind)or a template taking its argument by value, makes the call
ambiguous. A non-template taking exactly a library template's parameter types is preferred and
keeps working. Rename the helper, remove it, or call it by a qualified name such as::convert_to.
And since_ris in an inline namespace offormula,using namespace formula;brings it into
scope, where a consumer's own_ris ambiguous with it. checked_convert_toacross dimensions is now a compile error. Converting, say, a volume into
a mass, or euros into yen, used to compile and returnArithmeticError::DomainErrorat run time.
The message names the two quantities. A conversion within one dimension is unchanged.- A floating-point
breakpointorbandargument is refused.breakpoint(1.5)used to be
truncated silently tobreakpoint(1). It now fails to compile, with a message that names the exact
spelling for that call, such as12.7_r,Rational { 127, 10 }orband(12.7_r, 17.3_r). std::formatterspecialisations may collide with yours.<formula-cpp/format.hpp>now
specialises it forOutcome<Q>,Unit,Dimensionand every enumeration that has a
describe(). A program that defines its own for one of these now defines it twice, and a generic
formatter for every enumeration is ambiguous for them; remove it and use the library's.- GCC 14 is required. Older GCC is not supported.
- The
with_roundingrefusal text changed. With no citation it now opens
formula: with_rounding<...>() was given no citation, for either spelling.
Using it
Install it with CMake, then consume it with find_package:
cmake -S . -B build -DFORMULA_INSTALL=ON -DCMAKE_INSTALL_PREFIX=/your/prefix
cmake --install buildfind_package(formula-cpp 0.3 CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE formula-cpp::formula-cpp)The package's compatibility is SameMinorVersion, so a request for 0.3 is not satisfied by 0.2 or
by 0.4. Because the library is header-only, copying include/ into your tree also works.
Known limits
- No stable API before 1.0. A minor release may change the public API. Every change is recorded
in the CHANGELOG. - 64-bit rational headroom (#1):
the exact route of some realistic laboratory statistics still overflows 64 bits. It reports an
overflow; it never gives a wrong number. The least-squares fits answer at a declared precision
where their exact route overflows, within the width of their wider integers. The guide
"Numeric headroom" measures where each computation stops. - Units of single-value arithmetic in a trace
(#2): a computed single value, such
as a product or a quotient, is still shown in its coherent SI value with no unit symbol.
The full list of changes is in CHANGELOG.md.
formula-cpp 0.2.0
formula-cpp 0.2.0
The second release of formula-cpp, a header-only C++23 library for traceable formulas: written
once in C++, with dimensions checked at compile time and units converted exactly, evaluated in exact
rational arithmetic, rendered as documentation, and traced step by step into an audit trail.
This release adds calculations whose values depend on each other, worksheets that recalculate only
what a change reaches, and decimals in traces and std::format. It also adds the first formulas
whose true values the exact layer cannot hold: logarithms, exponentials, and least-squares fits over
raw observations. Each such value is written only as the correctly rounded decimal its formula
declares, proved with integer arithmetic, so a trace still never shows a number that is not exact.
Documentation, with the guides, a gallery and the API reference:
https://lastrada-software.github.io/formula-cpp/
Requirements
- C++23 and CMake 3.23 or newer.
- CI builds and tests every change on MSVC
clandclang-cl(Windows), Clang and GCC 14
(Linux, with an UndefinedBehaviorSanitizer build) and Clang on macOS. - Minimum compiler versions are not settled yet.
What is new
- Calculations and worksheets:
define<Q>(expression)binds a quantity to its formula, and a
calculation's dependency graph is known at compile time. A mistake such as a cycle or a dimension
mismatch is one compile error. A worksheet computes each value only when asked, and recalculates
only what a change reaches. A derivation is re-run against the worksheet's current values, so it
is never stale. - Decimals and
std::format: traces, rendered formulas and derivations can show exact decimals,
or approximations that name their rounding mode and always carry≈. An opt-instd::formatter
handlesRationaland measured values; a bad format spec in a literal is a compile error. - Base dimensions an application declares:
base_dimension("EUR")declares a dimension the SI
does not have, so adding euros to yen, or to a bare ratio, fails to compile. No currencies are
shipped, and an exchange rate is data. - Units: watt, kilowatt, watt-hour and kilowatt-hour, with
dim::Power, and Fahrenheit. - Values the exact layer cannot hold:
rounded_output<"slope", Unit, Places, Mode>(fit)reports
an opaque operation's output at the precision the method declares. The rounded decimal is the
step's exact value, and its line says it was rounded. A rounding that cannot be decided is
Overflow, never a guess. The least-squares fits compute in wider integers, so, within those
integers' width, they answer this way where their exact route overflows 64 bits. - Logarithms and exponentials:
ln,log10andexptake a dimensionless argument, checked at
compile time. They are exact where the value is rational (ln 1, exp 0, log10 of a power of ten),
and otherwiseInexact.rounded_ln,rounded_log10androunded_expgive the correctly
rounded decimal at declared places, from an integer kernel. - A line through raw observations:
linear_least_squaresover two sets of observations, whose
number is data, gives the intercept, the slope, R² and the number of points. A fit of values that
are all equal is its own domain error. - Multiple regression:
multiple_least_squares(regressors(x1, ..., xK), y, citation), for one to
eight regressors, gives a constant, one coefficient per regressor in its own unit, R² and the
number of points. The exact route refuses a singular design exactly, by a zero pivot, not by a
tolerance.
Upgrading from 0.1.0
A minor release may break the public API before 1.0, and this one does in a few places. Each change
is listed under Changed in the CHANGELOG. The ones most likely to need an edit:
- New enumerators and members.
StepKindgains seven enumerators, appended.Dimension,
OpaqueCallInfo,OpaqueStepDataandOpaqueCallFailuregain members, so a structured binding
over one needs more names. AswitchoverStepKindthat names every enumerator and has no
defaultnow misses seven. - Argument-dependent lookup. An unqualified call of
ln,log10,exp,fraction_text,
number_textand a few others now also finds the library's function. A consumer's own function of
the same name for the same arguments makes such a call ambiguous. - Includes.
statistics.hppno longer brings inbinning.hpp,band.hpporlookup.hpp;
include them where they are used.
Using it
Install it with CMake, then consume it with find_package:
cmake -S . -B build -DFORMULA_INSTALL=ON -DCMAKE_INSTALL_PREFIX=/your/prefix
cmake --install buildfind_package(formula-cpp 0.2 CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE formula-cpp::formula-cpp)The package's compatibility is SameMinorVersion, so a request for 0.2 is not satisfied by 0.1 or
by 0.3. Because the library is header-only, copying include/ into your tree also works.
Known limits
- No stable API before 1.0. A minor release may change the public API. Every change is recorded
in the CHANGELOG. - 64-bit rational headroom (#1):
the exact route of some realistic laboratory statistics still overflows 64 bits. It reports an
overflow; it never gives a wrong number. The least-squares fits now answer at a declared
precision where their exact route overflows, within the width of their wider integers. The guide
"Numeric headroom" measures where each computation stops. - Units of single-value arithmetic in a trace
(#2): a computed single value, such
as a product or a quotient, is still shown in its coherent SI value with no unit symbol.
The full list of changes is in CHANGELOG.md.
formula-cpp 0.1.0
formula-cpp 0.1.0
The first release of formula-cpp, a header-only C++23 library for traceable formulas. You write
a formula once, in C++. The library checks its dimensions at compile time, converts units exactly,
and evaluates it in exact rational arithmetic, so a number is never silently rounded. It renders
the same formula as documentation. It also records every step of an evaluation, so the result
comes with an audit trail that states each number with its unit and where it came from.
The library is licensed under Apache-2.0.
Documentation, with the guides, a gallery and the API reference:
https://lastrada-software.github.io/formula-cpp/
Requirements
- C++23 and CMake 3.23 or newer.
- CI builds and tests every change on MSVC
clandclang-cl(Windows), Clang and GCC 14
(Linux, with an UndefinedBehaviorSanitizer build) and Clang on macOS. - Minimum compiler versions are not settled yet.
What is in it
- Exact numbers and rounding: a checked rational type that reports overflow instead of
wrapping, with rounding to decimal places, significant digits or multiples under named modes. - Dimensions and units: dimensions with rational exponents, checked at compile time, and units
with exact conversion, including affine ones such as degrees Celsius. - Quantities: declared once with a symbol, a description and a unit, either as an alias or as a
struct. Measurements may be absent without that being an error. - Expressions and evaluation: arithmetic, powers and roots over environments of measured or
hand-entered values. Evaluation yields an outcome that is a value, a verdict, an invalid result
or nothing, never a bare number that hides which. - Citations and documentation:
documented()citations on any part of a formula. Formulas
render as plain text, Markdown or LaTeX, and the library generates documentation with a symbol
table. - Tracing and audit reports: composable sinks, a trace of every step, and a bounded rendering
of it that a person can check line by line. - Rounding and conditionals: rounding as a node of a formula,
when()conditionals, and a
justified escape hatch from units. - Constraints: constraints as peers of formulas. Their verdicts are recorded in the trace, and
a set of constraints is checked without short-circuiting. - Lookup tables: exact, banded and interpolating lookups over tables validated at compile time.
A value outside the table gives no number at all. - Methods and jurisdiction overlays: a method holds variants chosen by tag, together with
rounding rules and constraints. A jurisdiction's overlay can fix constants, derive quantities,
replace formulas, pin or prune variants, and use its own vocabulary of symbols. Every change is
cited in the trace. - Series and grading curves: a quantity at every point of a method's domain, elementwise
arithmetic, running totals, sums, conformity against a limit envelope, snapping, curves,
interpolation, splicing, and binning of raw observations. - Statistics and outlier rejection: mean, variance and range of a sample, precision limits,
critical-value tables read at the sample size, and iterative outlier rejection with its own
abort rules. - Cross-record context and lineage: a formula can read from other samples and tests, with each
value's origin stated in the trace, and can check that records share a lineage. - Opaque operations and least squares: named computations traced by their inputs and outputs,
with the inside marked as not shown. The first of them is a least-squares line. - Bounded retry: a step repeated until it is accepted, at most a fixed number of times. It ends
in exactly one of six stated ways, and ends in the method's verdict when the attempts run out.
Using it
Install it with CMake, then consume it with find_package:
cmake -S . -B build -DFORMULA_INSTALL=ON -DCMAKE_INSTALL_PREFIX=/your/prefix
cmake --install buildfind_package(formula-cpp 0.1 CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE formula-cpp::formula-cpp)The installed package exports the header-only INTERFACE target formula-cpp::formula-cpp and a
version file. Its compatibility is SameMinorVersion, so a request for 0.1 is not satisfied by
0.2. Because the library is header-only, copying include/ into your tree also works.
Known limits
- No stable API before 1.0. A minor release may change the public API. Every change is
recorded in the CHANGELOG. - 64-bit rational headroom (#1):
some realistic laboratory statistics exceed the 64-bit numerator and denominator. Such a
computation reports an overflow; it never gives a wrong number. The guide "Numeric headroom"
describes the limits in detail. - Units of single-value arithmetic in a trace
(#2): a computed single value,
such as a product or a quotient, is shown in its coherent SI value with no unit symbol. The
number is right, but the reader has to know which unit it is in.
The full list of changes is in CHANGELOG.md.