Skip to content

Commit

Permalink
Update registry.py
Browse files Browse the repository at this point in the history
Calculate factor by first constructing the scaling fraction, eliminating terms that appear in numerator and denominator and then finally evaluating the fraction.
  • Loading branch information
nneskildsf authored Jan 3, 2025
1 parent 34aacbb commit e0b9ace
Showing 1 changed file with 42 additions and 8 deletions.
50 changes: 42 additions & 8 deletions pint/facets/plain/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,11 +897,44 @@ def _get_root_units(
except KeyError:
pass


accumulators: dict[str | None, int] = defaultdict(int)
accumulators[None] = 1
self._get_root_units_recurse(input_units, 1, accumulators)
fraction: dict[str, dict[Decimal|Float, Decimal|int]] = dict(numerator=dict(), denominator=dict())
self._get_root_units_recurse(input_units, 1, accumulators, fraction)

# Identify if terms appear in both numerator and denominator
def terms_are_unique(fraction):
for n_factor, n_exp in fraction["numerator"].items():
if n_factor in fraction["denominator"]:
return False
return True
# Cancel out terms where factor matches
while not terms_are_unique(fraction):
for n_factor, n_exponent in fraction["numerator"].items():
if n_factor in fraction["denominator"]:
if n_exponent >= fraction["denominator"][n_factor]:
fraction["numerator"][n_factor] -= fraction["denominator"][n_factor]
del fraction["denominator"][n_factor]
continue
for d_factor, d_exponent in fraction["denominator"].items():
if d_factor in fraction["numerator"]:
if d_exponent >= fraction["numerator"][d_factor]:
fraction["denominator"][d_factor] -= fraction["numerator"][d_factor]
del fraction["numerator"][d_factor]
continue

factor = 1
for n_factor, n_exponent in fraction["numerator"].copy().items():
if n_exponent == 0:
del fraction["numerator"][n_factor]
else:
factor *= n_factor**n_exponent
for d_factor, d_exponent in fraction["denominator"].copy().items():
if d_exponent == 0:
del fraction["denominator"][d_factor]
else:
factor /= d_factor**d_exponent

factor = accumulators[None]
units = self.UnitsContainer(
{k: v for k, v in accumulators.items() if k is not None and v != 0}
)
Expand Down Expand Up @@ -948,7 +981,7 @@ def get_base_units(
# TODO: accumulators breaks typing list[int, dict[str, int]]
# So we have changed the behavior here
def _get_root_units_recurse(
self, ref: UnitsContainer, exp: Scalar, accumulators: dict[str | None, int]
self, ref: UnitsContainer, exp: Scalar, accumulators: dict[str | None, int], fraction: dict[str, dict[Decimal|float, Decimal|int]]
) -> None:
"""
Expand All @@ -962,13 +995,14 @@ def _get_root_units_recurse(
if reg.is_base:
accumulators[key] += exp2
else:
# Use division operator for division instead of exponentiation
# Build numerator and denominator
#print(reg.converter.scale, exp2)
if exp2 < 0:
accumulators[None] /= reg.converter.scale**abs(exp2)
fraction['denominator'][reg.converter.scale] = fraction['denominator'].get(reg.converter.scale, 0)-exp2
else:
accumulators[None] *= reg.converter.scale**abs(exp2)
fraction['numerator'][reg.converter.scale] = fraction['numerator'].get(reg.converter.scale, 0)+exp2
if reg.reference is not None:
self._get_root_units_recurse(reg.reference, exp2, accumulators)
self._get_root_units_recurse(reg.reference, exp2, accumulators, fraction)

def get_compatible_units(self, input_units: QuantityOrUnitLike) -> frozenset[UnitT]:
""" """
Expand Down

0 comments on commit e0b9ace

Please sign in to comment.