HP Forums

Full Version: [wp34s] Converting to/from IEEE 754 Binary64 (Double Precision)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

Here's a program to convert to/from IEEE 754 binary64 (double precision) format:

/* Program to convert to/from IEEE 754 binary64 (double precision) format
* Remarks:
* - XEQ A converts DP real numbers to IEEE 754 binary64 (double precision) format
* - XEQ B converts IEEE 754 binary64 (double precision) format numbers to DP real
* - XEQ 'IED' converts to DP real if the calculator is in integer mode, converts to IEEE 754 binary64 otherwise
* - Denormalized numbers (|x|<2.2250738585072014e-308 ) are supported. "Denorm" is shown as a warning in the alpha display.
* If |x|<5e-324, the number will be silently converted to 0.
* - +/- Infinity and NaN are supported. Since the WP-34S has "constants" for these values (see the Const catalog), large numbers
* are not considered to be infinite (see next note).
* - Numbers larger/smaller than +/- 1.7976931348623157e308 generate an Out of range error.
* - Negative 0 is supported. Since the sign may not be visible, depending on the setting of the global D (Danger) flag,
* "Neg 0" is shown in the alpha display
* - The calculator is set to integer sign-with-mantissa, word size 64 (sm64) mode and assumed to be in this mode when working with the
* IEEE 754 binary 64 format. Similarily, on the real side, the calculator is assumed to be in double precision mode.
*/
****LBL'IED'
WSIZE 64 // Operations are performed on sign-with-mantissa, word size 64 integers
SIGNMT
DBLON
INTM?
GTO B

**LBL A // Convert DP real to IEEE 754 binary64 format
LocR 001
CL[alpha]
x=0?
JMP ZeroF
SPEC? // Infinite or NaN
JMP SpecF
ENTER[^]
ABS
LOG[sub-2] // This is why we need to be in DP mode
FLOOR
# 10
2[^x]
DEC X
x<? Y // Punt if number is too large
ERR 08 // Note: Numbers too large for the format are not quietly replaced by infinity
+/-
MAX
STO .00 // Exponent in R.00: Denormalized: -1023; otherwise: -1022 to 1023
# 052
x[<->] Y
-
# 179 // Denormalized values are scaled by 2^1074 before rounding; otherwise, 2 ^ (52 - exponent)
# 6 // 1022 + 52 = 1074 = 179 * 6
[times]
MIN
2[^x]
[times]
ROUNDI
RCL .00
BASE 16 // x: exponent; y: mantissa, including sign
# 10 // Convert exponent
2[^x]
DEC X
+
CF .00 // Flag .00 set for denormalized value
x=0?
SF .00
SL 52
x[<->] Y
MASKR 52 // This removes the hidden bit, if any
+/- // Include sign in the mask
AND
OR // Insert exponent into result
FC? .00 // Warn if denormalized
RTN
"Denorm"
VW[alpha]+ X
RTN
ZeroF:: CF .01
x=-0? // Flag .01 set for negative 0
SF .01
BASE 16
FS? .01
SB 63
RTN
SpecF:: [infinity]? // Handle NaN here, infinity below
JMP InfF
BASE 16
MASKR 12 // Use 0x7FF8000000000000 for NaN
SL 51
[alpha]'NaN'
VW[alpha]+ X
RTN
InfF:: CF .01 // Flag .01 set for negative infinity
x<0?
SF .01
BASE 16
MASKR 11
SL 52
FS? .01
SB 63
RTN

**LBL B // Convert IEEE 754 binary64 format to DP real
LocR 001
CL[alpha]
x=0?
JMP ZeroI
ENTER[^] // Extract the exponent
CB 63
SR 52
# 11 // Are we special?
2[^x]
DEC X
x=? Y
JMP SpecI
DROP
CF .00 // Flag .00: denormalized
x=0?
SF .00
# 001 // Fix the minimum exponent
MAX
# 10
2[^x]
DEC X
-
x[<->] Y
MASKR 11
SL 52
NOT
AND
FC? .00 // Restore hidden bit if not denormalized
SB 52
DECM
x[<->] Y // Apply exponent
# 052
x[<->] Y
-
2[^x]
/
FC? .00 // Warn if denormalized
RTN
"Denorm"
VW[alpha]+ X
RTN
ZeroI:: CF .01 // +/- 0; flag .01 is negative zero
x=-0?
SF .01
DECM
FC? .01
RTN
"Neg 0" // Warn if negative (not visible if D flag not set)
0
+/-
VW[alpha]+ X
RTN
SpecI:: DROP // NaN or +/- infinity; don't need exponent
DROP
ENTER[^]
MASKR 52
AND
x=0? // Handle NaN here; infinity below
JMP InfI
DECM
# NaN
RTN
InfI:: DROP // +/- infinity; don't need mantissa
CF .01 // Flag .01 is negative infinity
x<0?
SF .01
DECM
# [infinity]
FS? .01
+/-
RTN
END

Edited: 15 June 2013, 8:18 p.m.

Nice program. The first time I've seen sign and mantissa mode used in a real program.

A word of caution for people. The 34S's reals are not strictly in either IEEE decimal64 or decimal128 format. They perform the same and have the same number of digits, same exponent range, same extras and even the same general layout in memory, however there is a mapping stage for the triad of decimal digits that we left out for spaces reasons.


Pauli