# ASN.1 Floats

7 messages
Open this post in threaded view
|

## ASN.1 Floats

 On Thu, Oct 12, 2017 at 11:36 AM, Alan Pinch 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.33333325386047361398101.25 exponent=> 201.3333332538604736 timesTwoPower: 20=> 1.39810125e61398101.25 = 1.39810125e6=> trueThe 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 -
Open this post in threaded view
|

## Re: ASN.1 Floats

 2017-10-12 17:46 GMT+02:00 Bert Freudenberg :On Thu, Oct 12, 2017 at 11:36 AM, Alan Pinch 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.33333325386047361398101.25 exponent=> 201.3333332538604736 timesTwoPower: 20=> 1.39810125e61398101.25 = 1.39810125e6=> trueThe 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.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: mantissaOtherwise, 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.
Open this post in threaded view
|

## Re: ASN.1 Floats

 Thanks for the info, this gives me a good start. I started working on the encoding, as the reading is more complex. I'll defer on understanding the Cuis code and get it to work right, as you said. On 10/12/2017 03:21 PM, Nicolas Cellier wrote: 2017-10-12 17:46 GMT+02:00 Bert Freudenberg : On Thu, Oct 12, 2017 at 11:36 AM, Alan Pinch 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. 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 ```
Open this post in threaded view
|

## Re: ASN.1 Floats

 In reply to this post by Nicolas Cellier On 10/12/17, Nicolas Cellier <[hidden email]> wrote: > 2017-10-12 17:46 GMT+02:00 Bert Freudenberg <[hidden email]>: > >> On Thu, Oct 12, 2017 at 11:36 AM, Alan Pinch <[hidden email]> >> 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'   :-) > 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. >
Open this post in threaded view
|

## Re: ASN.1 Floats

 On 10/13/2017 07:31 AM, H. Hirzel wrote: > On 10/12/17, Nicolas Cellier <[hidden email]> wrote: >> 2017-10-12 17:46 GMT+02:00 Bert Freudenberg <[hidden email]>: >> >>> On Thu, Oct 12, 2017 at 11:36 AM, Alan Pinch <[hidden email]> >>> 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