[squeak-dev] ASN.1 Floats
Alan Pinch
alan.c.pinch at gmail.com
Sat Oct 14 21:25:13 UTC 2017
Please see Cryptography for the initial support for ASN1 Reals.
On 10/13/2017 10:08 AM, Alan Pinch wrote:
>
>
> On 10/13/2017 07:31 AM, H. Hirzel wrote:
>> On 10/12/17, Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com> wrote:
>>> 2017-10-12 17:46 GMT+02:00 Bert Freudenberg <bert at freudenbergs.de>:
>>>
>>>> On Thu, Oct 12, 2017 at 11:36 AM, Alan Pinch <alan.c.pinch at gmail.com>
>>>> wrote:
>>>>
>>>>> The same issue exists in ASN1 support, none for float type tag 9. I
>>>>> would
>>>>> love to add this support but I am unsure how to breakdown a float
>>>>> into
>>>>> mantissa, base and exponent. Here is a description of how ASN1
>>>>> formats a
>>>>> REAL into the stream of bytes:
>>>>>
>>>>> Type REAL takes values that are the machine representation of a real
>>>>> number, namely the triplet (m, b, e), where m is the mantissa (a
>>>>> signed
>>>>> number), b the base (2 or 10), and e the exponent (a signed
>>>>> number). For
>>>>> example, the representation of the value 3.14 for the variable Pi,
>>>>> declared
>>>>> as Pi ::= REAL, can be (314, 10, -2). Three special values,
>>>>> PLUS-INFINITY,
>>>>> 0, and MINUS-INFINITY, are also allowed.
>>>>>
>>>>> Here are some sample values:
>>>>>
>>>>>
>>>>> - 09 00 = 0 (zero)
>>>>> - 09 01 40 = +INF (infinity)
>>>>> - 09 01 41 = -INF
>>>>> - 09 08 03 2b 31 2e 30 65 2b 30 = "+1.0e+0" = 1.0 (exact decimal)
>>>>> - 09 05 80 fe 55 55 55 = 1398101.25 (binary, 0x555555 * 2^-2)
>>>>> - 09 06 83 00 fc 00 00 01 = 0.0625 (binary, 0x000001 * 2^-4)
>>>>>
>>>>> I have not parsed out these samples into these components so it's
>>>>> greek.
>>>>>
>>>> Well it's not the same issue as ASN.1 float representation is
>>>> different
>>>> from IEEE 754 format. To convert a Squeak Float into an IEEE 64 bit
>>>> pattern
>>>> we simply access its underlying representation, because the VM uses
>>>> IEEE
>>>> internally.
>>>>
>>>> It sounds like ASN.1 stores mantissa, base, and exponent
>>>> separately. IEEE
>>>> calls the mantissa "significand" and that's the name of the
>>>> corresponding
>>>> Squeak method. The exponent is called "exponent", and the base is
>>>> implicitly 2:
>>>>
>>>> 1398101.25 significand
>>>> => 1.3333332538604736
>>>> 1398101.25 exponent
>>>> => 20
>>>> 1.3333332538604736 timesTwoPower: 20
>>>> => 1.39810125e6
>>>> 1398101.25 = 1.39810125e6
>>>> => true
>>>>
>>>> The IEEE significand/mantissa is normalized to a fractional number
>>>> 1 <= m
>>>> < 2. ASN wants integral numbers, so you could convert it to an integer
>>>> like
>>>> this:
>>>>
>>>> x := 1398101.25.
>>>> mantissa := x significand.
>>>> exponent := x exponent.
>>>> base := 2.
>>>> [mantissa fractionPart isZero] whileFalse:
>>>> [mantissa := mantissa * base.
>>>> exponent := exponent - 1].
>>>> {mantissa asInteger hex. base. exponent}
>>>> #('16r555555' 2 -2)
>>>>
>>>> ... which matches your example.
>>>>
>>>> I'm sure Nicolas will have a much more efficient formula, but this
>>>> would
>>>> work :)
>>>>
>>>> - Bert -
>>>>
>>>>
>>>> make it right > make it fast so it sounds like a good starting
>>>> point :)
>>> since I see a lot of logic in the complex ASN1 spec, it'll be even
>>> worse
>>> when reading!
>>> I see nothing about negative zero, nan seems handled by later
>>> version if we
>>> can trust SO answers.
>>> In any case, like requested on SO, a good reference test database
>>> sounds
>>> mandatory.
>> Please note the words 'in any case' and 'mandatory' :-)
>
> Indeed. I am struggling a little with writing an unsigned mantissa and
> a twos-compliment exponent, ATM. :) I analyzed the first octet to get
> base, sign, scaling factor and number of exponent octets, then made
> calls to specialized encode methods for each...just evolving protocol
> to getting it right, for the moment. Reading is more complex with
> additional bases and encodings...I have not analyzed past base-2 so far.
>
>>> We could also peek what Juan did in Cuis, like:
>>>
>>> Float>>exponentPart
>>> "Alternative implementation for exponent"
>>> ^self partValues: [ :sign :exponent :mantissa | exponent ]
>>>
>>> partValues: aThreeArgumentBlock
>>> ^ self
>>> partValues: aThreeArgumentBlock
>>> ifInfinite: [ self error: 'Can not handle infinity' ]
>>> ifNaN: [ self error: 'Can not handle Not-a-Number' ].
>>>
>>> partValues: aThreeArgumentBlock ifInfinite: aZeroOrOneArgBlock ifNaN:
>>> otherZeroOrOneOrTwoArgBlock
>>> "
>>> Float pi hex print
>>> Float pi partValues: [ :sign :exponent :mantissa | { sign hex.
>>> exponent
>>> hex. mantissa hex} print ]
>>> 0.0 partValues: [ :sign :exponent :mantissa | { sign hex.
>>> exponent hex.
>>> mantissa hex} print ]
>>> For 0.0, exponent will be the minimum possible, i.e. -1023, and
>>> mantissa will be 0.
>>> "
>>> | allBits sign exponent mantissa exponentBits fractionBits |
>>>
>>> " Extract the bits of an IEEE double float "
>>> allBits _ ((self basicAt: 1) bitShift: 32) + (self basicAt: 2).
>>>
>>> " Extract the sign and the biased exponent "
>>> sign _ (allBits bitShift: -63) = 0 ifTrue: [1] ifFalse: [-1].
>>> exponentBits _ (allBits bitShift: -52) bitAnd: 16r7FF.
>>>
>>> " Extract fractional part "
>>> fractionBits _ allBits bitAnd: 16r000FFFFFFFFFFFFF.
>>>
>>> " Special cases: infinites and NaN"
>>> exponentBits = 16r7FF ifTrue: [
>>> ^fractionBits = 0
>>> ifTrue: [ aZeroOrOneArgBlock valueWithPossibleArgument:
>>> self ]
>>> ifFalse: [ otherZeroOrOneOrTwoArgBlock
>>> valueWithPossibleArgument: self and: fractionBits ]].
>>>
>>> " Unbias exponent: 16r3FF is bias"
>>> exponent _ exponentBits - 16r3FF.
>>>
>>> " Replace omitted leading 1 in fraction if appropriate"
>>> "If expPart = 0, I am +/-zero or a denormal value. In such
>>> cases, no
>>> implicit leading bit in mantissa"
>>> exponentBits = 0
>>> ifTrue: [
>>> mantissa _ fractionBits.
>>> exponent _ exponent + 1 ]
>>> ifFalse: [
>>> mantissa _ fractionBits bitOr: 16r0010000000000000 ].
>>>
>>> "Evaluate the block"
>>> ^aThreeArgumentBlock value: sign value: exponent value: mantissa
>>>
>>>
>>> Otherwise, on a 64 bit VM, i would start with significandAsInteger
>>> which is
>>> a SmallInteger, and play with bitShift: 1 - lowbit...
>>> But it would need measurements and is probably a bad idea in 32bits.
>>>
>
--
Thank you for your consideration,
Alan
More information about the Squeak-dev
mailing list
|