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

Inconsistency in complex(::Array) vs complex(::Array, ::Array) #31676

Open
stillyslalom opened this issue Apr 10, 2019 · 12 comments
Open

Inconsistency in complex(::Array) vs complex(::Array, ::Array) #31676

stillyslalom opened this issue Apr 10, 2019 · 12 comments
Labels
arrays [a, r, r, a, y, s] complex Complex numbers linear algebra Linear algebra

Comments

@stillyslalom
Copy link
Contributor

There's some inconsistency in the complex(...) methods:

help?> complex

  complex(r, [i])

  Convert real numbers or arrays to complex. i defaults to zero.

julia> complex(rand(3))
3-element Array{Complex{Float64},1}:
 0.7485012418373351 + 0.0im
 0.9146512879195354 + 0.0im
 0.6380568113960479 + 0.0im

julia> complex(rand(3), rand(3))
ERROR: MethodError: no method matching complex(::Array{Float64,1}, ::Array{Float64,1})
Closest candidates are:
  complex(::AbstractArray{T,N} where N) where T at complex.jl:1012
Stacktrace:
 [1] top-level scope at none:0

You can always broadcast, of course: complex.(rand(3), rand(3)) works fine. But it seems like it should either accept arrays for both arguments, or not at all.

@JeffBezanson JeffBezanson added arrays [a, r, r, a, y, s] complex Complex numbers labels Apr 10, 2019
@StefanKarpinski
Copy link
Sponsor Member

Removing the mixed-shape methods would be technically breaking but if no one is using this in PkgEval then we might be able to change this as a "minor change" in a minor release.

@KristofferC
Copy link
Sponsor Member

Maybe I am missing something but what are "the mixed-shape methods"?

AFAIU, the reason for having complex on an Array work is the same as having real work which was discussed at some point, pretty sure @stevengj argued for that. Don't think that extends to multiple array arguments though. The docs are wrong here, of course.

@stevengj
Copy link
Member

stevengj commented Apr 11, 2019

With a single array argument there is a standard algebraic meaning for "complexifying" a vector space — that is, complex(vector) is a "vector" operation just like array + array, not merely a random operation that we happen to be performing elementwise.

Now that I think about it, in the same sense that you can write array + im*array as a vector operation, and there is a standard meaning for real(array) and imag(array), I suppose you can assign a sensible algebraic meaning to complex(array, array), though this nomenclature isn't very common. So it wouldn't be crazy to add this method. I'm not enthusiastic, however.

@stevengj stevengj added the linear algebra Linear algebra label Apr 11, 2019
@stillyslalom
Copy link
Contributor Author

R^2 is the only real space bijective with C, so if we're keeping things rigorous, let's throw an error if someone passes complex(::Array) anything besides a Vector{<:Real} of length two. In that sense, the current behavior on arrays equates to broadcasting a map R -> R^2 -> C, with the imaginary coordinate always zero. I don't think that's sensible.

@stevengj
Copy link
Member

stevengj commented Apr 11, 2019

@stillyslalom, that's not what complex(x) means: if x is in a real vector space V then it's an injection, not a bijection, into the complexified vector space. (This includes the "scalar" case of x::Real.)

@stillyslalom
Copy link
Contributor Author

I agree that the current behavior serves as an injection, but the function is complex, not complexify: it's more a noun (a constructor) than a verb (an operator). if we're constructing complex numbers in the Cayley-Dickson sense, each coordinate in the complex plane requires an ordered pair (a, b) of reals, and the current behavior sets b to zero.

@StefanKarpinski
Copy link
Sponsor Member

My comment was made under the misapprehension that complex([1,2,3], 1) worked. Since it does not, I retract my comment.

@stevengj
Copy link
Member

stevengj commented Apr 11, 2019

@stillyslalom, in Julia, we name functions complex(x), float(x), string(x), big(x), and in general foo(x) when it constructs a foo-like type from x, and these are all injections. Just because we don't spell it "complexify" doesn't mean that isn't what the function does. complex(x) can be whatever function we want it to be, and the function that we long ago decided we want is the complexification injection. Nor are mathematical questions decided on the basis of spelling.

(The bijection that you are referring to is spelled Complex(x...) in Julia.)

@stillyslalom
Copy link
Contributor Author

The two-array constructor method existed before being deprecated in the "More Dots" push, and the one-array method seems more semantically similar to that than to a complexify function. Regardless of what it's called, I would be surprised if more than a small fraction of extant complex(::Array) calls have the semantic intent of 'complexify', versus simply serving as a vectorized constructor. Since one can get the same thing from Complex.(::Array) as complex(::Array), it seems like the latter can be deprecated: even if it has a sensible algebraic meaning, I'm not sure that meaning is in sufficiently common use to justify inclusion in Base.

@StefanKarpinski
Copy link
Sponsor Member

Sure, we could deprecate that in 2.0.

@JeffBezanson
Copy link
Sponsor Member

I don't think it matters whether callers of complex(::Array) intend vectorized conversion to complex or complexification. They give the same answer whichever way you think about it, so why does it matter?

@stevengj
Copy link
Member

stevengj commented Apr 12, 2019

We should define complex(array) for the same reason we define real(array) and imag(array) and conj(array) and array*scalar and array+array, even though all of these things can be done with dot operations: they have standard algebraic meanings that are part and parcel of being a vector space or a complex vector space.

(A minor advantage is also that complex(array) can avoid making a copy if the elements are already Complex.)

I don’t have an objection to restoring the two argument “vectorized” form as well (for two arrays of the same shape only) since that has a sensible algebraic meaning, though I don’t think it’s as essential.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arrays [a, r, r, a, y, s] complex Complex numbers linear algebra Linear algebra
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants