Add a Namespaces section to the project structure docs describing the three
public tiers (mp_units / mp_units::utility / mp_units::detail), show the
core -> systems -> utility module layering, and list the utility headers.
Update the representation and custom-representation guides to introduce the
built-in cartesian types via mp_units::utility, and update the safe_int /
constrained material (guide, blog posts, tutorials) to the new
<mp-units/utility/...> include paths and mp_units::utility names.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Fix#580: use fixed-point arithmetic for integer unit conversions
Introduce a fixed-point implementation for unit conversions involving
integer representations, avoiding loss of significant digits that
previously occurred when the conversion factor was not a whole number.
New files:
- src/core/include/mp-units/bits/fixed_point.h: double_width_int<T> and
fixed_point<T,n> types for exact rational scaling of integer values.
Uses __int128 when available (__SIZEOF_INT128__) for 64-bit integers.
- src/core/include/mp-units/framework/scaling.h: public scaling_traits<>
customization point and scale<To>(M, value) free function. Provides
built-in specializations for floating-point and integer-like types.
- test/static/fixed_point_test.cpp: static assertions for the new types.
- test/runtime/fixed_point_test.cpp: runtime arithmetic edge-case tests.
Modified:
- sudo_cast.h: replace hand-rolled conversion_value_traits / sudo_cast_value
machinery with a single scale<To::rep>(c_mag, ...) call.
- representation_concepts.h: add MagnitudeScalable concept; replace
ComplexScalar with HasComplexOperations (which is its definition).
- customization_points.h: add unspecified_rep tag and declare the primary
scaling_traits<> template.
- framework.h / CMakeLists.txt: wire in the new headers.
- hacks.h: add MP_UNITS_DIAGNOSTIC_IGNORE_PEDANTIC and
MP_UNITS_DIAGNOSTIC_IGNORE_SIGN_CONVERSION macros.
- example/measurement.cpp: add scaling_traits specializations for
measurement<T> to demonstrate the customization point.
- test/static/{international,usc}_test.cpp: disable two tests that are
blocked on issue #614.
Co-authored-by: Tobias Hanhart <burnpanck@users.noreply.github.com>
* Fix value_Type typo in floating_point_scaling_factor_type specialization
The partial specialization for types with a nested value_type used
'value_Type' (capital T) instead of 'value_type', making the entire
specialization dead code as the requires-clause could never be satisfied.
Also fix 'mantiassa' -> 'mantissa' in the adjacent comment.
* Fix docstring typos in scaling_traits documentation
- 'quantitiy' -> 'quantity'
- 'dictatet' -> 'dictated'
- 'convetrible' -> 'convertible'
- 'implemenation' -> 'implementation'
- 'availabe' -> 'available'
* Fix conflict resolution error: keep ComplexScalar name from master
When resolving the merge conflict in representation_concepts.h, the
PR's renamed version of the concept ('HasComplexOperations') was used
instead of master's established name ('ComplexScalar'). The two concepts
are semantically equivalent — burnpanck simply renamed it in his branch.
Revert to the canonical 'ComplexScalar' name while retaining the new
'MagnitudeScalable' concept which was the actual addition from the PR.
* Fix measurement.cpp: remove duplicate class definition from merge
The PR branched from a version where measurement<T> was defined inline
in measurement.cpp. Master later moved the class to example/include/
measurement.h and changed measurement.cpp to #include that header.
The squash merge therefore introduced a duplicate definition: the class
from the header and the PR's inline class were both visible, causing
an 'ambiguous reference' error. Remove the now-redundant inline class;
the scaling_traits specializations added by the PR work correctly with
the class from measurement.h.
* style: pre-commit
* docs: chapters anchors improved in the "custom representation" chapter
* docs: value conversions chapter improved
* refactor: scaling support refactored
* fix: clang-16 crash fixed
* docs: `measurement` example documentation updated to match changes
* fix: use exact wide-integer arithmetic for rational unit conversions on all platforms
On ARM / Apple Silicon, long double == double (64-bit mantissa). The old
fixed_point<T>(long double) initialiser lost ~12 bits of precision for 64-bit
integer types when representing the scaling ratio, producing an error of ~49
units for the 10/9 (degree → gradian) conversion with a 10^18 input value.
Fix by splitting the integer-path else-branch into two cases:
• Pure rational M (is_integral(M * (denominator(M) / numerator(M))) == true):
use (value * numerator) / denominator via double_width_int_for_t<> arithmetic.
This is exact on every platform regardless of long double width.
• Irrational M (involves π etc.): keep the long double fixed_point approximation.
These conversions are inherently approximate; small values still produce correct
truncated results on all platforms.
Update the test comment to reflect the new exact-arithmetic path.
Fixes CI failures on clang-18/ARM and apple-clang-16.
* fix: replace floating-point TeX-point test with exact integer equivalent
72.27 is not exactly representable as double (it rounds to 72.2699...96).
Multiplying by the conversion factor 100/7227 via long double gives a result
≥ 1.0 on x86 (80-bit long double, 64-bit mantissa) only by chance, but
0.99999...978 on ARM / Apple Silicon where long double == double (52-bit).
The correct mathematical statement is: 7227 tex_point = 100 inch (exact
rational relationship). Use that integer form instead of the inexact 72.27
double literal so the test is correct and platform-independent.
---------
Co-authored-by: Tobias Hanhart <burnpanck@users.noreply.github.com>