[squeak-dev] ASN.1 Floats
Alan Pinch
alan.c.pinch at gmail.com
Sat Oct 14 21:58:26 UTC 2017
It encodes Reals, Fractions and Scaled Decimals, I think. It decodes
base-2, and it may decode base-8 and -16, I do not know. No decimal
tests in base-2. I attempted to signal exceptions where appropriate.
On a different topic, I wondered the best examples of a tree of semantic
stored items, looked up from a leaf dictionary up through import and
parent libraries, a TreeBrancher of sorts. Is this an area where common
approach may help multiple aspects?
On 10/14/2017 05:25 PM, Alan Pinch wrote:
> 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
|