Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compute magnitudes in the "real part" of a type #278

Merged
merged 7 commits into from
Sep 20, 2024

Conversation

chiphogg
Copy link
Contributor

@chiphogg chiphogg commented Aug 3, 2024

A Magnitude is defined to be a real number. But users can ask for
its value in, say, std::complex<int> (either explicitly or
implicitly). This is a problem, because in computing that value, we
check for overflow, which involves less-than comparisons... but complex
numbers are not ordered, so there is no meaningful sense of <!

To fix this, we introduce the notion of RealPart<T>, a type trait that
gives a type related to T that does have a notion of comparability.
(Since Magnitude is defined to be a real number, calling it "real
part" is a good fit.) RealPart<T> is just T in almost all cases,
but it becomes "the type of T{}.real()" whenever that exists. This
lets us support both std::complex and complex number types from other
libraries.

The core of the fix was to make sure all of our Magnitude operations
are taking place in RealPart<T> rather than T. This basically boils
down to the call to base_power_value, and the implementations for
SafeCastingChecker. We also use the real type throughout the
:apply_magnitude targets, for two reasons. First, there's an actual
bug in clang related to complex-complex division. Second, it should be
faster at runtime to only divide by the real part.

This change also has knock-on effects for implicit conversion policy. It
turns out the old implementation of CoreImplicitConversionPolicy was
always silently assuming that the type was already a real number type.
Therefore, we rename it by adding an AssumingReal suffix on the end.
The new CoreImplicitConversionPolicy passes RealPart<Rep> along to
this, after first checking for a new pitfall to guard against: namely,
implicitly converting a complex type to a real type.

Fixes #228.

A `Magnitude` is _defined_ to be a _real_ number.  But users can ask for
its value in, say, `std::complex<int>` (either explicitly or
implicitly).  This is a problem, because in computing that value, we
check for overflow, which involves less-than comparisons... but complex
numbers are not ordered, so there is no meaningful sense of `<`!

To fix this, we introduce the notion of `RealPart<T>`, a type trait that
gives a type related to `T` that does have a notion of comparability.
(Since `Magnitude` is defined to be a real number, calling it "real
part" is a good fit.)  `RealPart<T>` is just `T` in almost all cases,
but it becomes "the type of `T{}.real()`" whenever that exists.  This
lets us support both `std::complex` and complex number types from other
libraries.

The core of the fix was to make sure all of our `Magnitude` operations
are taking place in `RealPart<T>` rather than `T`.  This basically boils
down to the _call_ to `base_power_value`, and the _implementations_ for
`SafeCastingChecker`.

This change also has knock-on effects for implicit conversion policy.
It turns out the old implementation of `CoreImplicitConversionPolicy`
was always silently assuming that the type was already a real number
type. Therefore, we rename it by adding an `AssumingReal` suffix on the
end. The new `CoreImplicitConversionPolicy` passes `RealPart<Rep>` along
to this, after first checking for a new pitfall to guard against:
namely, implicitly converting a complex type to a real type.
clang struggles with complex division.
@chiphogg chiphogg marked this pull request as ready for review September 20, 2024 15:18
@chiphogg chiphogg requested a review from geoffviola September 20, 2024 15:21
Copy link
Contributor

@geoffviola geoffviola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests look good. Thanks!

@chiphogg chiphogg merged commit b295267 into main Sep 20, 2024
10 checks passed
@chiphogg chiphogg deleted the chiphogg/complex-conversion#228 branch September 20, 2024 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Multiplication Support for Complex Types
2 participants