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

feat: add support for real-valued arrays in real and conj #884

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

ev-br
Copy link

@ev-br ev-br commented Jan 18, 2025

Closes #824 by allowing real and conj to accept real-valued arrays, and leaving imag to still require complex-valued arguments.

One possibly thorny issue is whether xp.real(x) is a view or a copy of of x. This is also discussed in gh-824, not 100% sure what the resolution is though.
In this PR, err on the side of caution and require that both real and conj always return copies.

Prior art is not very consistent AFAICS: numpy can return either a view or a copy depending on the dtype, not sure what other libraries do.

OTOH,

  1. if we always require a copy, we can consider allowing imag to create a new array of zeros.
  2. or maybe we can leave it unspecified and implementation dependent.

@kgryte
Copy link
Contributor

kgryte commented Jan 20, 2025

@ev-br Thanks for opening this PR. My sense is that we should leave it unspecified and implementation-dependent. Forcing a copy is likely a no-go for libraries leveraging strided arrays and focused on performance.

@kgryte kgryte added this to the v2024 milestone Jan 20, 2025
@kgryte kgryte changed the title ENH: allow xp.real and xp.conj of real fp inputs feat: allow xp.real and xp.conj of real fp inputs Jan 20, 2025
@kgryte kgryte added API change Changes to existing functions or objects in the API. topic: Complex Data Types Complex number data types. labels Jan 20, 2025
@ev-br
Copy link
Author

ev-br commented Jan 20, 2025

Agreed. Trying it on numpy, it seems that np.conj returns a copy, while np.real returns a view --- at least for 1D inputs. What it does in higher-dimensions or for arrays with more complicated stride arrangements, who knows. Mandating this seems premature unless all major array libraries agree on something coherent (which is to say, never).

Nonetheless, allowing xp.{conj, real}(real_valued_array) still makes sense IMO: if only for clarity when writing mathematical code where 1) arrays can legitimately be either real floating or complex, and 2) copy-vs-view semantics is not relevant. This is not an edge case. The status quo requires that everybody adds explicit branching on the array dtypes; the proposed wording makes it that only those who want to mutate (or prohibit mutating) the result of xp.real need to copy or branch in the user code. I would expect this to be rare, and the vast majority of the user code benefits.

Therefore, the last commit updates the wording to make the view/semantics explicitly unspecified.

@rgommers
Copy link
Member

Mandating this seems premature unless all major array libraries agree on something coherent (which is to say, never).

A view is not a thing in the standard (xref https://data-apis.org/array-api/latest/design_topics/copies_views_and_mutation.html), so I don't think we will ever want to mandate anything here. View vs. copy is only observable when mutating aliased memory (which should be avoided) and otherwise a performance optimization that isn't visible in syntax or semantics.

@kgryte
Copy link
Contributor

kgryte commented Jan 20, 2025

In principle, we could support a copy kwarg on real and conj to support forcing a copy. We do this for astype and a few other functions.

@kgryte kgryte changed the title feat: allow xp.real and xp.conj of real fp inputs feat: add support for real-valued arrays in real and conj Jan 20, 2025
@ev-br
Copy link
Author

ev-br commented Jan 20, 2025

My only wish is that there's some wording, however mysterious, to show that the spec thought about the semantics and left it to be implementation-defined. For me as a user even "if you plac the output to the left of the assignment sign, the result is implementation-defined" would have been sufficient (and having no note would be worse).

Re: forcing a copy with a keyword, I'd suggest to to have a minimal version in 2024.12 spec for downstream to use, and refine based on usage.
In principle, if the wording in the Notes proves contentious, punting on it --- thus limiting this PR to just "real-valued arrays are allowed" --- would be great at least for scipy.signal.

@rgommers
Copy link
Member

Okay, fine with the current wording then. We can always revise the details of the note later if needed. Just wanted to make sure that you're aware that a view isn't a concept, so we shouldn't overuse it.

@kgryte
Copy link
Contributor

kgryte commented Jan 23, 2025

@ev-br I tweaked the language a bit, removing explicit mention of "views", and I also updated the guidance to require numeric input types. The previous guidance was "should" in order to allow libraries supporting real-valued dtypes to continue doing so. Now that we're expanding the scope of these functions to all numeric dtypes that wiggle room is no longer necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API change Changes to existing functions or objects in the API. topic: Complex Data Types Complex number data types.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFC: revisit requirement that inputs to real, imag, and conj be complex-valued
3 participants