> 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

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))

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))complex-part-type ',X)))

(typep (imagpart y) `(upgraded-

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 Standardizerscomplex-part-type '(real -1 1)) because the complex could beCOMPLEX-PART-TYPE, and to treat (COMPLEX REAL)

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-

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-

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-part-typecomplex-part-type be a supertype of the given

complex numbers that you can get from feeding objects of type (EQL 0) to

the COMPLEX function. This implies that the upgraded-

of (EQL 0) should be NIL, but of course this breaks the requirement that

the result of upgraded-

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