Skip to content

Integer quantities support status #2346

Description

@RBerga06

The docs mention that it makes sense to write Quantity[int] (or Quantity[np.ndarray[<shape>, <integer dtype>]]).

However, I think this poses some problems, because then a lot of operations can break this type invariance: for example, Quantity(3, 'cm').to_root_units() returns Quantity(0.03, "meter").

The real problem comes when we consider inplace operations:

def foo(x: Quantity[int]):
    reveal_type(x.magnitude)  # int (good)
	x.ito_root_units()
	reveal_type(x.magnitude)  # type checker thinks it's int, but might be float at runtime

I don't think there's any way of telling type checkers that an in-place operation might've changed the type of a variable.

Is this expected behaviour? Should the docs be updated with a note about this?


Note: since type checkers think int <: float (and it's still an open problem), as long as MagnitudeT (in Quantity's definition) remains covariant (which simplifies a lot arithmetic method overloads) it's not possible to make the Quantity[int] annotation an error – the best we can do is document it.

However, in the case of numpy arrays, integer and floating dtypes are not in a subtype-supertype relationship, which means we can simply accept floating and complex arrays while the boolean/integer ones will be disallowed by default in the annotations.


Edit: apparently x.ito_root_units() fails at runtime if the magnitude is an integer array. The error is:
numpy._core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'multiply' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'.
This happens because we're essentially doing self.magnitude *= <float> and numpy correctly raises because this operation cannot preserve the LHS type.

However, x.to_root_units() works correctly and returns a float array (following the data type promotion rules).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions