[fpc-devel] Extended($FFFFFFFFFFFFFFFF) = -1?

Ewald ewald at yellowcouch.org
Mon Mar 3 17:43:45 CET 2014


On 03 Mar 2014, at 12:49, Hans-Peter Diettrich wrote:

> Ewald schrieb:
>> On 03 Mar 2014, at 00:29, Hans-Peter Diettrich wrote:
> 
>>>> `-1` would then be $1 FFFF FFFF FFFF FFFF, whereas $FFFF FFFF
>>>> FFFF FFFF would be $0 FFFF FFFF FFFF FFFF. It really is quite
>>>> easy to store it like that and `fix` things [picking a fitting
>>>> datatype] afterwards.
>>> The datatype has to be constructed/determined first, and *if* there
>>> exists a type with more than 64 bits, then it will be a signed
>>> type, with a 65 bit (unsigned) subrange matching your needs. But if
>>> no such type exists, you are lost.
>> Yes, that is true, but there always is a 64 signed/unsigned type
>> (perhaps not native). On machines where, for example, only 32 bit
>> wide datatypes are allowed, the virtual subrange should be 33 instead
>> of 65 bytes.
> 
> Subranges are expressed in low..hi notation, not in bits, meaning that the hi value must be expressable in a valid signed positive number.

That is why is use the word `virtual`. It is of course a more complex datatype than simply a subrange. See below.

> 
>> Anyway, that is the way how I parse constants. The important rule
>> here is that you don't need the full 65 bit in the final
>> representation. The signedness of the type can fix this loss of the
>> one bit.
> 
> How (which data type) does *your* parser store untyped numerical constants?

Roughly like this (syntax may be a bit awry, but you get the point):

TIntegerNumber = Record
Case SignedNess: TSignedNess of
	snPositive:	UValue: QWord;
	snNegative:  SValue: Int64;
End;

The parser detects wether there is a `-` in front of the constant and stores the right sign in the SignedNess field.

> 
> IMO your problem arises from the fact that a bitpattern, with the highest of 64 bits set, cannot be stored in a larger (signed) type, as required.

Yes, spot on :-)


> All such untyped constants will cause problems when assigned to typed variables. Test yourself what happens when you convert such an QWORD value into Extended.
> 

That was the first example of this thread. The effect is the QWord becomes the mantissa of the extended, the exponent is set right and the sign bit is set to zero. But I believe the compiler must do this for me since (as you mention at the bottom of this quote) there is no instruction to load an unsigned integer into the 8087.


> 
> 
>>> then it's obvious that such a textual representation should cause
>>> an compilation error "not portable...". We know that such an error
>>> message has not yet been implemented, but if you insist on writing
>>> unportable code... :-]
>> I insist on using a constant that is: - 64 bit wide - Only contains
>> 1's - Is interpreted as an unsigned number wherever mathematical
>> operations are performed.
> 
> Then you have to choose a different language. What will C++, C# or Java do in these cases?

Java I'll ignore, my C# is way too rusty and C/C++ won't parse the constant as is, because it overflows the normal 32 bit range. Here you have to type something like 0xffffffffffffffffLLU. I haven't tried casting the bugger into a float though.


> 
>> Those demands are quite portable, no?
> 
> No.

Alright, let me rephrase my demands:
	- I want to store the value 18446744073709551615 in any kind of variable without loss of precision.

Both set of demands are fine by me. Is that a more portable demand? ;-)


> 
>> My original problem was easily solved with a typecast
>> QWord(<gargantuan constant goes here>), so that was no longer an
>> issue. What baffled me though was  the fact that this (mis-: in my
>> opinion) mis-parsing of certain constants is by design.
> 
> What you observed was related to the argument passed to WriteLn. When WriteLn includes code to output a QWord, then the output should reflect the bitpattern (unsigned number). The output of an Extended value reflects the value converted from integral to floating point, and that conversion assumes signed values. IIRC the x87 FPU doesn't have an instruction to load unsigned integral values, so that no compiler has a chance to make it load an unsigned value.

Alright, that I did not know. Thanks for the info. I always assumed there was an instruction FULD, but it isn't there apparently.

--
Ewald




More information about the fpc-devel mailing list