10 Commits

Author SHA1 Message Date
Mateusz Pusz 7a03123a01 refactor(utility): move safe_int and constrained into the mp_units::utility namespace
safe_int, constrained, their error policies, and the safe_iN aliases are
non-framework add-ons, so their public names move out of mp_units into the
mp_units::utility extension tier (next to the representation concepts already
there). The headers move to core/include/mp-units/utility/ accordingly but stay
in the core component: safe_int reuses the core 128-bit integer toolkit
(integral, is_signed_v, int128_t, ...) that also backs the scaling engine, so it
bridges to mp_units::detail with a single using-directive rather than relocating
or duplicating that toolkit. overflow_policies stays framework (it backs bounded
quantity point origins). No deprecation shims: these types are unreleased.

Also fixes utility/representation.h, whose public concepts delegated via the
unqualified detail::X. That resolved to mp_units::detail only as long as
mp_units::utility::detail did not exist; now that constrained/safe_int introduce
it, the references are qualified to ::mp_units::detail:: so they stay
order-independent (this surfaced only in the module build).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 23:58:39 +02:00
Mateusz Pusz 703235d1d4 refactor(representation): intrinsic order/field traits and two-tier character concepts
Replace the `disable_vector`/`disable_tensor` opt-outs with intrinsic,
adapter-overridable traits and split representation classification into two tiers.

- `customization_points.h` now owns the customizable surface: the `real`/`imag`/
  `modulus` CPOs plus the `numeric_field` (field axis) and `tensor_order` (order
  axis) traits. Adapters specialize these; the derived concepts stay with the
  rest of the concept model in `representation_concepts.h`.
- `numeric_field` is the single source of truth for the field axis (default:
  `real()`/`imag()` API detection). Field matching is exact and disjoint - a real
  quantity needs a real representation and a complex one a complex representation.
- `tensor_order` is detected structurally (two-index access -> 2, one-index -> 1,
  otherwise 0) and overridable. Order matching is rank-ordered: a lower-order
  representation fills a higher-order slot.
- Character concepts (`Real`/`Complex`, rank-ordered `Scalar`/`Vector`/`Tensor`)
  carry no representation-validity, so in V3 they can also classify a quantity by
  its character. The `*Representation` concepts are `NotQuantity`-first + character
  + `UnitMagnitudeScalable`; leading with `NotQuantity` rejects a quantity before
  its operators are instantiated, avoiding a constraint-satisfaction cycle.
- Eigen/Blaze adapters declare `numeric_field` from their element type (they expose
  `real()`/`imag()` on real types too, which the API default would misread as complex).
- Rename `MagnitudeScalable` -> `UnitMagnitudeScalable` and `UsesMagnitudeAwareScaling`
  -> `UsesUnitMagnitudeAwareScaling` to disambiguate scaling by a `unit_magnitude`
  from the value/L2 magnitude (the `magnitude` CPO).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 19:17:05 +02:00
Mateusz Pusz 01bf044919 fix: resolve MSVC C2666 on safe_int<T> × safe_int<U> via Hidden Friend Injection
Adds heterogeneous arithmetic operators (+ - * / %) to `detail::safe_int_binary_ops`,
following the same idiom already used for `==` and `<=>`.  The non-template homogeneous
inline-friends inside `safe_int<T>` keep winning same-T calls; the new template friends
in the base unambiguously handle the T != U calls without changing the converting-ctor
semantics.  Resolves the ambiguity that triggered C2666 on `safe_int<int> + safe_int<long>`
when `int` and `long` have equal width (Windows).

Also:
  * `mul_overflows<T>` now gates on `integer_rep_width_v<int128_t>` so MSVC's synthetic
    `double_width_int<int64_t>` counts as a usable wider type for the overflow check.
  * Replace the platform-dependent `safe_int<long>` widening test with a portable
    `long long` variant — on Windows the original test's RHS
    `static_cast<long>(INT_MAX) + 1L` is itself constexpr-invalid 32-bit overflow.
  * Add convertibility coverage tests for `safe_int<T> op raw_U` mixing short / int /
    long / uint8_t to lock down that the `safe_int op integral` overload wins by exact
    match over the converting ctor on every platform.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 19:31:09 +02:00
Mateusz Pusz 70eadc49ad feat: cross sign and cross error policy comparisons added for safe_int
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 23:27:31 +02:00
Mateusz Pusz eb5dfa62df feat: int128 types are now universally treated as integral on all platforms and safe_int depends on it
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 13:00:04 +02:00
Mateusz Pusz 659738044a feat: safe_int implicit conversions improved and refactored the operators + widening for scaling now preserves sign
Co-authored-by: Copilot <copilot@github.com>
2026-04-26 16:03:09 +02:00
Mateusz Pusz f080c80317 style: pre-commit 2026-04-12 14:15:13 +02:00
Mateusz Pusz ad77bcc106 feat: safe_int::operator T made explicit 2026-04-12 14:12:15 +02:00
Mateusz Pusz 4b6eb91a61 fix: safe_int_test fixed for freestanding 2026-04-11 20:57:16 +02:00
Mateusz Pusz 12300bcd23 feat: safe_int and blog article about it added 2026-04-11 20:30:28 +02:00