Comment 6 for bug 1733400

Stas Boukarev <email address hidden> writes:

> It was only checking the realpart to be an integer, the fix is checking both.
> Just as the standard is saying that for (typep object '(complex
> type-specifier)) (and (typep realpart 'type-specifier) (typep imagpart
> 'type-specifier)) must hold true. Don't think anything should be
> document beyond that.

But I don't think that's implied! I think the point of upgrading is
that

  (typep y '(complex X))

means

  (and (typep (realpart y) `(upgraded-complex-part-type ',X))
       (typep (imagpart y) `(upgraded-complex-part-type ',X)))

Of course this is all a mess because there's no top to this type
lattice, and there's a hidden bottom when you consider X = (EQL 0)

CLHS says that we can think of (complex X) for X being a subtype of
REAL. It also says that actual complex number objects have real and
imaginary parts that are either both rational or both of the same
floating point type.

REAL is a subtype of REAL, or if you think the Elder Standardizers
really meant "proper subtype" (REAL -1 1) is a proper subtype of REAL.
However, there can be no single upgraded complex part type for
(upgraded-complex-part-type '(real -1 1)) because the complex could be
of a float flavour or a rational flavour depending on what you feed
the COMPLEX function. Probably the best answer in this case is to
return REAL from UPGRADED-COMPLEX-PART-TYPE, and to treat (COMPLEX REAL)
as equivalent to a union of our concrete complex types, much like
(VECTOR *) is effectively a union of all the specialized vector types.

But wait, there's more. (EQL 0) is a subtype of REAL, but there are *no*
complex numbers that you can get from feeding objects of type (EQL 0) to
the COMPLEX function. This implies that the upgraded-complex-part-type
of (EQL 0) should be NIL, but of course this breaks the requirement that
the result of upgraded-complex-part-type be a supertype of the given
type specifier. We currently return (EQL 0) as a cunning hack and
recognize (COMPLEX (EQL 0)) to be NIL as a type specifier.

I think the right answer to fix Paul's original test case is that since
we do not claim that we have a (COMPLEX INTEGER) specialized
representation, we shouldn't test for that in %%TYPEP. The code in
%%TYPEP is/was trying to be clever about handling reals and complexes in
the same code path; I think that detangling that will probably make
things easier to understand. And, yes, this means that #c(1/2 1/2) is of
type '(complex integer), somewhat analgously to how
(make-array 1 :element-type '(integer 1 255) :initial-element 0) is of
type '(simple-array (*) (integer 0 255))

Christophe