Snapshot date: 2026-08-09
This document compares Yumemi with Python's Pint library to identify useful capabilities and deliberate differences. It is a feature comparison, not the project roadmap. Current priorities, architectural risks, and deferred work belong in planning.md.
Yumemi is not intended to reproduce every Python or NumPy integration in Pint. Its distinguishing goal is static
dimensional analysis for ordinary PHP values, backed by the same exact runtime engine used by Quantity.
Status labels:
- Done: implemented well enough to rely on for the stated scope.
- Partial: useful behavior exists, but a meaningful portion of the feature remains.
- Absent: no meaningful implementation exists.
- Deliberately absent: excluded from the current product direction unless a concrete use case changes it.
Importance measures value to Yumemi rather than importance to Pint:
- P0: foundational to Yumemi's purpose.
- P1: important for a broadly useful first stable version.
- P2: valuable after the core is stable.
- P3: specialized or ecosystem-dependent.
Difficulty estimates the remaining work: S, M, L, or XL.
Yumemi now has a reliable scalar multiplicative runtime, exact affine points and differences, a configurable formatter,
custom registries, and a substantial PHPStan extension for branded native values, Quantity<'...'>, and
PointQuantity<'...'>. The core architecture remains sound: one parser, registry, expression model, and conversion
engine serve both runtime and static analysis.
Pint remains much broader in runtime convenience, unit systems, contexts, localization, nonlinear units, measurements, NumPy integration, and ecosystem persistence patterns. Much of that breadth is Python-specific or secondary to Yumemi's static analysis goal.
The useful comparison is therefore not a single parity percentage. Yumemi has strong coverage of its chosen exact scalar and PHPStan scope, partial coverage of general-purpose formatting and advanced unit semantics, and intentionally little coverage of scientific-array and uncertainty ecosystems.
Status: Done | Importance: P0 | Remaining difficulty: S
Yumemi represents constants, units, products, and integer powers explicitly. Reduction flattens products, combines
constants and powers, cancels inverse units, and orders factors deterministically. Public expressions support exact
positive integer-degree roots while retaining integral powers and explicit definition substitution. Structural equality
and the hybrid SI-plus-extension Dimension model no longer depend on formatted-string comparisons.
The remaining concern is performance under repeated analysis, not missing algebra for the supported multiplicative model. Rational powers are a separate advanced feature.
Status: Done for the documented grammar | Importance: P0 | Remaining difficulty: M
The generated Bison parser supports identifiers, exact decimal and scientific constants, multiplication, division, integer powers, grouping, Unicode middle dots, and signed superscript powers. Product precedence follows UDUNITS2. Malformed syntax receives bounded caret diagnostics with byte spans.
The grammar intentionally recognizes some upstream forms that semantic layers reject. AST locations now survive
post-parse lookup and unsupported-semantic resolution, including through aliases and stored definitions, so runtime
exceptions and PHPStan parse results can identify the caller-written name or construct. Pint-style ** and arbitrary
real powers remain possible extensions rather than gaps in the documented language.
Status: Done for the current model | Importance: P0 | Remaining difficulty: S/M
Yumemi ships deterministic generated UDUNITS2 data with base and derived units, aliases, symbols, prefixes, explicit plurals, and safe generated plurals. A small authored supplement adds nominal raster samples and exact document units without changing the generated catalog's provenance. Lookup is case-sensitive, exact names precede prefix decomposition, and introspection preserves spelling provenance and semantic capabilities.
Generated indexes now remove repeated whole-catalog grouping from bulk introspection. Additional registry optimization should follow a concrete profile rather than assuming indexing remains unfinished.
Status: Done for programmatic registries | Importance: P1 | Remaining difficulty: M
UnitRegistryBuilder supports mutable programmatic definitions and aliases over either the default catalog or an empty
registry. Each build creates an immutable snapshot, overlays correctly mask base records, and PHPStan can consume the
same registry through a configured factory.
Definition files remain absent. baseUnit() adds user-defined primitive dimensions while retaining the fixed SI vector
and canonical sparse extension powers, and ordinary definitions derive related units from the declared base. Currency is
the acceptance case, but exchange-rate acquisition and money policy remain outside core. Programmatic registries now
cover both project-specific SI scales and independent application dimensions.
Status: Done for exact inputs | Importance: P0 | Remaining difficulty: S
Units::quantity() accepts int or Rational magnitudes, and parseQuantity() parses exact constants from complete
quantity strings. Catalog scale remains in the symbolic unit unless the caller explicitly simplifies or converts.
Direct float construction is intentionally absent because it would undermine the exact input contract. Decimal strings
can be represented through Rational::fromDecimalString() or parsed quantity expressions.
Status: Done for multiplicative quantities | Importance: P0 | Remaining difficulty: M
Yumemi supports exact compatible-unit addition and subtraction, strict same-unit variants, multiplication, division, integer powers, exact positive integer-degree roots, negation, absolute value, exact zero testing, comparisons, symbolic cancellation, and context checks. Addition and subtraction convert the right operand into the left unit; multiplication, division, roots, and absolute value preserve caller-selected symbolic units unless the caller explicitly normalizes or simplifies first.
Additional convenience predicates remain optional. Affine point-versus-difference arithmetic uses the separate
PointQuantity model described below.
Status: Done | Importance: P0 | Remaining difficulty: S/M
The runtime provides exact factors, exact value conversion, float conversion, dimensional compatibility, quantity
conversion, and native helpers. Explicit conversion supports exact affine scale-and-offset transforms; factor APIs
reject offset-dependent conversions. Exact Rational, Quantity, and PointQuantity outputs use strict binary64 range
handling by default and can explicitly select signed infinity or signed zero through FloatRangePolicy; native-float
helper paths remain strict.
Affine point and difference semantics now build on the same conversion boundary.
Status: Done for explicit definition substitution | Importance: P1 | Remaining difficulty: M
normalize() substitutes definitions without changing a quantity's stored magnitude. simplify() also folds resulting
scale into the magnitude. Explicit to() conversion requests a caller-selected target. These semantics are documented
and intentionally distinct.
Preferred-unit profiles apply explicit application targets by dimension, while toCompact() selects an engineering
prefix within one named unit family. Yumemi does not alias simplify() to a system-specific base-unit operation. The
selection design keeps both operations separate without requiring a unit-system
model.
Status: Done | Importance: P0 | Remaining difficulty: S
Dimension exposes the seven SI axes, sparse named extension axes, integer powers, arithmetic, equality, accessors, and
deterministic strings. Units, Quantity, and resolved expressions expose dimensions publicly, while registry metadata
associates one canonical base unit with each custom primitive dimension.
Dimensions deliberately cannot distinguish semantic meanings that share the same axes, such as gray and sievert. That would require a separate quantity-kind model rather than another dimension representation.
Status: Done for the exact core | Importance: P1 | Remaining difficulty: M
Rational supports exact integer and decimal construction, arithmetic, truncating and exact integer output, all PHP 8.4
rounding modes for fixed-scale and significant-digit output, terminating-decimal output, plain and scientific notation,
and correctly rounded binary64 conversion. Exact float output uses strict overflow and underflow handling by default and
can explicitly select signed infinity or signed zero through FloatRangePolicy. Quantity and point extraction converts
to the requested unit first. Approximate decimal arithmetic remains a separate potential model rather than replacing
rational storage.
Status: Partial | Importance: P1 | Remaining difficulty: M/L
Formatting supports preserved, canonical, or symbol names; ASCII or Unicode typography; three dimensionless styles; and fraction or negative-power division. Unicode numeric output round-trips through the parser, and reusable formatters cache resolved names.
Pint additionally supports rich magnitude formatting, HTML, LaTeX, siunitx, localization, compact units, and broader presets. Yumemi should add those only as concrete output targets emerge.
Status: Done for the declared catalog | Importance: P1 | Remaining difficulty: S/M
Generated aliases, explicit and generated plurals, symbols, and longest-prefix-first decomposition use exact catalog metadata. Exact names win before prefix decomposition, lookup remains case-sensitive, and introspection exposes canonical identity and spelling provenance. A typed effective entry centralizes composite-layer precedence while retaining both a materialized prebuilt alias and its catalog metadata when one layer intentionally supplies both. Generated name indexes and dynamically composed custom overlays make repeated introspection constant-time after registry construction without changing lookup policy.
Status: Done for exact points and differences | Importance: P1 | Remaining difficulty: M
Yumemi exactly converts UDUNITS2 and custom affine definitions. PointQuantity represents coordinate points; point
subtraction returns an ordinary multiplicative Quantity, and compatible quantities translate points. Catalog
generation and custom registry construction synthesize explicit delta_* names and Δ°C / Δ°F symbols.
Affine names themselves remain outside expression algebra, prefixes, powers, ordinary Quantity, and native brands.
This is intentional: accepting them directly would make point-versus-difference meaning ambiguous. Possible future work
is limited to demonstrated conveniences or static integrations, not a second affine arithmetic model.
Status: Recognized but not evaluable | Importance: P3 | Remaining difficulty: XL
The catalog classifies logarithmic definitions and preserves their metadata for introspection and diagnostics. Runtime expression and conversion APIs reject evaluation with operation-specific exceptions.
Nonlinear conversion, reference values, compound behavior, and approximation policy make this unsuitable for the exact rational core until a real application justifies a separate model.
Status: Absent | Importance: P2 | Remaining difficulty: XL
Pint contexts permit transformations that are not ordinarily dimensionally compatible, such as wavelength to frequency
through the speed of light. Yumemi's Units object is a registry identity and must not be confused with this feature.
Parameterized transformation graphs would complicate static inference and exactness. Defer them until an important workflow requires cross-dimensional conversion.
Status: Absent | Importance: P2 | Remaining difficulty: L
The catalog contains units from several systems but no metadata describing MKS, CGS, SI, US, or imperial preferences. System-aware base-unit or preferred-unit conversion would require explicit system metadata and collision policy.
Status: Partial | Importance: P2 | Remaining difficulty: M/L
Yumemi implements explicit dimension-matched application preferences through PreferredUnitProfile and
Quantity::toPreferred(), plus exact engineering-prefix compaction through Quantity::toCompact(). The
design record deliberately limits compaction to one caller-selected named family
and avoids catalog-wide scoring, a general preferred-basis optimizer, and implicit system selection. Explicit to()
conversion remains the predictable choice when one static target is known.
Status: Partial | Importance: P2 | Remaining difficulty: M
UDUNITS2 constants are available through the catalog as dimensionless definitions. Decimal source values become exact rationals representing the catalog's finite decimal, not symbolic irrational values.
A dedicated constants API and symbolic constants are absent. Documentation must continue distinguishing an exact stored decimal approximation of pi from mathematical pi.
Status: Done for quantity and point ordering and compatibility | Importance: P1 | Remaining difficulty: S
Quantity and PointQuantity provide exact compatible-unit equality, three-way comparison, and all ordered predicates.
Incompatible dimensions and registry contexts fail explicitly, and PHPStan diagnoses known invalid comparisons.
isZero() tests the exact magnitude independently of its unit. Quantity::isCompatibleWith() and
PointQuantity::isCompatibleWith() return true only for values in the same Units context with compatible
dimensions; incompatible dimensions and different contexts return false without conversion. Strict same-unit
comparison variants remain low value because comparisons do not produce a unit-bearing result.
Status: Partial | Importance: P2 | Remaining difficulty: L
Exact integer pow() exists for rational magnitudes, expressions, dimensions, and quantities. PHPStan preserves branded
units through native ** and pow() when every possible exponent is a statically known integer, and models native
intdiv() with exact quotient unit algebra and truncation-toward-zero integer bounds. Rational::root(),
Dimension::root(), and Quantity::root() support exact positive integer-degree roots while keeping unit powers
integral and symbolic substitution explicit. Native branded sqrt() transforms an exact symbolic square unit and
diagnoses non-rootable brands. Native deg2rad() and rad2deg() preserve canonical angle units; sin(), cos(), and
tan() map canonical radians to unscaled ratios, while asin(), acos(), and atan() map exact unscaled ratios to
canonical radians. Binary atan2() maps definitionally equivalent branded operands to canonical radians, completing the
angle-function design. Fractional and other generalized powers, approximate runtime-object
powers and trigonometry, logarithms, and exponentials remain absent. Approximate runtime-object functions need a
separate precision and rounding contract.
Status: Done for the current core | Importance: P0 | Remaining difficulty: M/L
Yumemi resolves unit_int<'...'>, unit_float<'...'>, unit_numeric_string<'...'>, Quantity<'...'>, and
PointQuantity<'...'>; infers native, quantity, and point operations; validates construction, conversion, extraction,
and comparisons; supports native conversion helpers with strict, semantically unambiguous expressions; preserves finite
unions at runtime-object boundaries; configures custom registries; and provides stable diagnostics.
The separate Yumemi Apocrypha package supplies curated third-party
stubs without expanding core's dependency graph. Branded integer constants and PHPStan integer-range intersections now
propagate through supported arithmetic, allowing exact bounds to distinguish safe integer results, guaranteed float
overflow, and mixed outcomes. Integer-brand extraction inspects only direct values and immediate intersection
constraints, so callables, arrays, and other compound types retain nested brands without collapsing into integers.
Explicit integer/float casts and abs(), ceil(), floor(), and round() preserve native brands. Supported constant
round() inputs, precisions, and half-rounding modes also retain every possible finite result. min() and max()
preserve one definitionally equivalent brand across every possible returning candidate and retain known finite extrema,
while native sqrt() transforms exact symbolic square units. Known finite native float values now survive construction,
conversion factors, direct conversion, supported arithmetic, casts, and modeled scalar functions when the result remains
finite, without being mistaken for exact rational quantities. Remaining work is branded float ranges, additional
built-ins justified by real workflows, more precise diagnostics, and future advanced unit semantics. Dynamic
native-helper expressions are diagnosed by default; explicit runtime parsing APIs remain dynamic, while deliberately
suppressed or configured native-helper calls retain their declared unbranded fallback type.
Status: Done statically; runtime decorators absent | Importance: P1/P2 | Remaining difficulty: M
Ordinary PHPDoc parameters and returns enforce branded native and generic quantity types through PHPStan. Optional
@yumemi-* tags support extension-optional libraries. Yumemi Apocrypha applies those semantics to selected third-party
APIs while owning their stubs and compatibility matrices.
Pint-style runtime decorators or PHP attributes that convert arguments are absent. They should be introduced only if static contracts and explicit runtime conversion prove insufficient.
Status: Done for current value objects | Importance: P2 | Remaining difficulty: S/M
Rational, Dimension, Quantity, PointQuantity, and catalog descriptor value objects expose exact JSON and compact
debug representations. Units::quantityFromJson() and pointFromJson() strictly restore the two runtime value shapes
in an explicit receiving registry. Versioned native serialization preserves exact rational state and symbolic unit
syntax. Default quantities restore through the shared default Units; custom-context values restore through
Units::deserialize(), which validates unit semantics against the selected immutable registry.
One serialized graph may contain default values and values from one custom context. Graphs containing several custom contexts still need stable registry identifiers and an application resolver. JSON intentionally represents value state; its explicit reader uses the receiving registry rather than embedding or reconstructing one.
Status: Partial through native brands | Importance: P3 | Remaining difficulty: L/XL
Branded native values remain ordinary scalars and therefore interoperate naturally with PHP arrays and ordinary APIs. Yumemi has no quantity-array type, vectorized conversion, or dedicated Scientific PHP integration.
Targeted PHPStan extensions for real libraries are preferable to a speculative generic collection framework.
Status: Absent | Importance: P3 | Remaining difficulty: M/L
Uncertainty propagation is a distinct mathematical layer. It should be a separate package or value type composed with
Quantity, not embedded in the unit engine.
Status: Absent | Importance: P3 | Remaining difficulty: M/L
The public Dimension model supplies useful prerequisites, but no Buckingham Pi helpers exist. Add them only if Yumemi
develops a scientific-computing audience.
Status: Supported through custom registries; bundled data deliberately absent | Importance: P3 | Remaining difficulty: M
Bundled rates remain inappropriate because exchange rates are time-varying and application-specific. An application may
model the conventional currency extension dimension by choosing one primitive currency and defining the others through
exact rates in an immutable registry snapshot. Rate sources, effective times, bid/ask spreads, fees, and monetary
rounding remain outside Yumemi; this facility provides dimensional checking and exact declared conversion, not a
complete money model.
Status: Absent | Importance: P3 | Remaining difficulty: M/L
Formatting has no translated names, plural rules, or locale-aware number output. The formatter architecture can grow a localization layer later without making locale part of expression identity.
Status: Partial | Importance: P1 | Remaining difficulty: M
Immutable registries and bounded expression caches make repeated parsing and conversion inexpensive while preserving registry ownership and fresh diagnostics. Catalog indexes avoid repeated full-catalog grouping and dimension scans. PHPBench covers cold and warm runtime workflows, full-catalog introspection, and PHPStan analysis.
The recorded investigations explain the measured gains and why additional
quantity-string, conversion-plan, inference, and selection caches remain deferred. Expression operations still reduce
eagerly, and complete parseQuantity() strings rebuild their derived components. Reconsider those costs only when a
production profile makes them material. See Cache Retention for internal budgets and
Runtime Surface for catalog-index ownership.
Status: Partial but strong | Importance: P1 | Remaining difficulty: M
Syntax errors and post-parse lookup or unsupported-semantic errors include source spans; malformed syntax additionally receives a bounded caret excerpt. Runtime exceptions distinguish unknown units, incompatibility, unsupported syntax, affine factor misuse, logarithmic evaluation, context mismatch, and native range loss. PHPStan supplies stable identifiers and operation-specific diagnostics.
All authored Yumemi exceptions implement one marker interface, including wrappers around the corresponding built-in PHP exception families. Unexpected failures crossing PHPStan extension entry points are attributed to Yumemi and include an actionable issue link without rewriting expected PHPStan internal failures.
Unknown-unit errors carry bounded structured suggestions under a complete deterministic ranking shared by runtime and PHPStan diagnostics. Equivalent immutable registries produce identical suggestion order regardless of insertion or composite-layer enumeration. Post-parse lookup and unsupported-semantic errors retain the caller's source span, including when resolution descends through aliases or stored definitions. Diagnostic identifiers may be split further only where users need more precise suppression.
Status: Done for the current public surface | Importance: P1 | Remaining difficulty: S/M
The root README is a concise landing page, and mdBook contains focused concept, PHPStan, syntax, runtime, and catalog guides. Akashi discovers public PHP examples for execution under PHPUnit and verifies PHPStan-relevant examples against their expected diagnostics. The mdBook build and link check remain available through Composer and Make.
Documentation must continue to evolve with behavior, but the missing infrastructure and organization from the original comparison are now present.
Status: Done for the current manual release policy | Importance: P0/P1 | Remaining difficulty: S
Composer, Nix, treefmt, pre-commit hooks, PHP-CS-Fixer, PHPStan, PHPUnit, generated artifacts, GitHub Actions, and
Infection with enforced mutation-score floors are configured. Catalog and parser regeneration are documented. A
Nix-backed differential suite compares representative conversions against the udunits2 executable, and a deterministic
generative suite exercises bounded expression, quantity, and point identities. An isolated consumer smoke test verifies
runtime use plus automatic and manual PHPStan registration from a release-style Composer archive. The separately
versioned Yumemi Apocrypha project verifies curated upstream integrations without adding their dependencies or
maintenance surface to core. The normal matrix covers PHP 8.2 through PHP 8.5. Fresh Composer solves on PHP 8.2 and PHP
8.5 verify the declared lower bounds and newest permitted releases, respectively. Direct development-branch tools remain
at their lock-file revisions because committed generated or copied integrations are verified against those exact inputs.
The project has tagged 0.1 releases and an explicit manual release and fork-first succession runbook. CI verifies the
exact release commit, and GitHub Pages deploys automatically from master; a human releaser deliberately retains
responsibility for service-access checks, signed tags, GitHub Releases, and Packagist confirmation. Publication
automation is not unfinished parity work under the current policy. Reconsider it only if repeated releases demonstrate
that a narrowly authorized workflow would reduce error without weakening signing, access, or recovery boundaries.
| Feature | Yumemi status | Importance | Remaining difficulty |
|---|---|---|---|
| Expression model and reduction | Done | P0 | S |
| Parser | Done for documented grammar | P0 | M |
| Default catalog | Done | P0 | S/M |
| Custom unit definitions | Done for programmatic registries | P1 | M |
| Quantity creation | Done for exact inputs | P0 | S |
| Quantity arithmetic | Done for multiplicative quantities | P0 | M |
| Explicit conversion | Done | P0 | S/M |
| Normalization and simplification | Done | P1 | M |
| Dimensionality API | Done | P0 | S |
| Numeric output | Done for exact core | P1 | M |
| Formatting | Partial | P1 | M/L |
| Names, prefixes, and plurals | Done | P1 | S/M |
| Affine units | Done for exact points/differences | P1 | M |
| Logarithmic units | Recognized, not evaluable | P3 | XL |
| Pint contexts | Absent | P2 | XL |
| Unit systems | Absent | P2 | L |
| Preferred and compact units | Partial; explicit operations done | P2 | M/L |
| Constants | Partial | P2 | M |
| Comparisons | Done for quantities and points | P1 | S/M |
| Math functions | Integer powers and exact roots | P2 | L |
| PHPStan | Done for current core | P0 | M/L |
| Function boundaries | Static contracts only | P1/P2 | M |
| Serialization | Done for current value objects | P2 | S/M |
| Collections and ecosystems | Native-brand interoperability only | P3 | L/XL |
| Measurements and uncertainty | Absent | P3 | M/L |
| Buckingham Pi theorem | Absent | P3 | M/L |
| Currency | Custom registries; rates unbundled | P3 | M |
| Localization | Absent | P3 | M/L |
| Performance and caching | Partial | P1 | M |
| Errors and developer UX | Partial but strong | P1 | M |
| Documentation | Done for current surface | P1 | S/M |
| Packaging and CI | Done for manual release policy | P0/P1 | S |
Yumemi should continue to optimize for shared runtime and static semantics rather than headline parity with Pint. Its strongest choices remain string unit expressions, generated catalog data, exact rational conversion, explicit registry contexts, and native PHPStan brands alongside exact quantity objects.
The highest-value remaining work is that which improves ordinary PHP workflows without displacing Yumemi's static analysis focus: extending unit-brand preservation only for demonstrated native scalar workflows, maintaining strong diagnostics, and supporting integrations proven by actual applications through Yumemi Apocrypha. Broader formatting and registry resolution for serialized graphs remain useful only when concrete output or multi-context persistence requirements justify them. Contexts, nonlinear units, uncertainty, and scientific-array features should remain independent decisions rather than a presumed route to parity.
See planning.md for the current ordering of work.