The single argument Complex constructor

The calling sequence in ?complex states only the two argument form 'Complex(x, y)', but later in the section "Description", in a bit confusing way, two rules for the single argument form are stated:

The Complex(x, y) constructor function returns the following types of objects for the indicated values of x and y.
          * x if x is already of type complex and y is not included in the calling sequence.
          * a one argument complex number (I*x) if x is an extended numeric and y is not included in the calling sequence.

And the first example is:

Complex(2);
                                     2 I

But 2 is an example of an object both type 'complex' and 'extended_numeric':

type(2,complex);type(2,extended_numeric);

                                 true
                                 true

If I understand this correctly, there is a contradiction between both rules. After the first one it should be:

Complex(2);
                                     2 

I do not see an explanation or justification for this choice of the second rule.

Now, I find that the current behavior (ie the use of the second rule) seems mathematically inconsistent. I would expect this 'Complex' constructor to represent the inclusion R subset C. Ie map a syntactically real object like 2 into its complex counterpart (ie 2+0*I). But instead, it maps an object repesenting a point on the real axis to a point on the imaginary axis.

Comments

JacquesC's picture

Disambiguating

The first rule should really read  x if x is already of type complex, x is not of type extended_numeric and y is not included in the calling sequence.

I guess the authors had 'strictly complex' in mind when writing the first rule, but that is not quite what they wrote down.

and the second rule?

What is it good for, this map from reals to imaginary numbers?

JacquesC's picture

To create "purely imaginary" numbers

These are numbers that are known to be exactly on the imaginary axis.  This is one way to get around certain issues of having a +0.0 or -0.0 as "real part" which can get in the way of certain exact computations, especially when branch cuts are concerned.  Making some numbers be "purely imaginary" makes more identities hold.

Make purely imaginary numbers

This map R-> I*R would require its own constructor. I see this completely misleading in operation and name. While the two argument form implements the embedding of R into C, like:

Complex(2,0.0);
                              2. + 0. I

and, as ?complex says:

The complex constructor can be used to prevent the simplification of x + 0.0*I and x - 0.0*I to x

the single argument form implements quite a different operation. For me, 'Complex(2)' should work exactly the same as 'Complex(2,0.0)' and 'Imaginary(2)', say, should yield 2*I.

JacquesC's picture

false economy

Adding new names to the kernel was always regarded as really bad, so it became customary to overload concepts a lot, especially if there was a plausible reasoning that could be applied.  So Complex creates both general complex numbers and 'special' complex numbers,namely the ones which are purely imaginary, through different calling conventions.

When the number of routines in C went above several hundred (once you factor in all the external libraries), this kind of overloading starts to seem silly.  But this particular routine was done at the same time as the kernel grew significantly, so it was really done in the old style.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
}