Post Reply 
internal number representation
10-05-2016, 03:42 PM
Post: #2
RE: internal number representation
You can directly look at the binary structure of any THPObj (as we call them) by storing the item using AFiles. AFilesB will allow direct return of the item as byte arrays. Another post from cyrille (coincidentally near the same time as your question) talks a bit about the header on the front of the objects.

Quote:Actually, what you are doing when you do:
AFiles("DATO.txt"):="1"
Is that you are storing a string object in a file called DATO.txt...

You can see that by doing
R->B(AFilesB("DATO.txt", 0, 10)) which will return {#FFh,#FFh,#12h,#CDh,#1h,#0h,#0h,#0h,#31h,#0h}
Here, the FFFF means nothing, the 1 is a flag, the 2 means string, CD is a pad, 1, 0, 0, 0 is the size of the string in characters and 31, 0 is the character 1 in 16 bit wchar...

AFiles("num"):=0 followed by AFilesB("num",0,16) returns the full byte representation of the file. In your case, skip the first 8 and look at the last 8 bytes. That is the real number encoding in BCD.

I'm also including some comments from a header file which should be helpful.

Code:
* see the HP_Real structure to see how reals are stored (sign, exponent, mantissa)
 * real range is 1.0E-49999 to 9.99999999999999E49999 (high res, 15 digit mantissa)
 * or            1.0E-499 to 9.99999999999E499 (low res, 12 digit mantissa)
 *
 * The library guaranties at most an error of 1 unit on the 12th significant digit.
 * This is why in most cases, all calculations are performed using the 15 digits and
 * rounded to 12 for user display/return.
 *
 * note that fPack and fUnpack functions allow to pack and unpack low precision reals
 * into a 64 bit structure. cast unto a u64 for convenience. Normal reals are 128 bits.
 * That format is similar to the HP48 calculator format.

Note that we really only use the e499 version from the end user perspective. Other longer use is only internal and even then we don't use the extended exponent capacity at all. Also, when saving to disk the reals get packed to save space. Hence, the return from AFiles only takes 8 bytes for a single real. "Packing" basically means that there is only space for the 12digit BCD, 3 byte exponent, and 1 byte sign vs the 15 digit bcd, 4 byte exponent, and 1 byte sign of the "unpacked" real.

If you're interested, the code to do the packing looks like this:

Code:
PackedHP_Real fPack(HP_Real const *a) 
{
  HP_Real b= *a;
  fNorm_L(ERNone, &b); //normalize to 12 digit result
  u64 r= b.M&0x0ffffffffffff000LL;
  if (b.s==SignNeg) r+= (u64)9LL<<60; else
  if (b.s!=SignPos) r+= (b.s+4LL)<<60;
  r= r|(u64)(b.e&0xfff);
  return r;
}

Heres is more comments about the unpacked HP_Real.

Code:
/// A HP_Real is a group of 3 elements. A Sign (which is also can carry information on 
/// actual datatype Infinite/NaN (Not a Number) information/
///
/// The exponent.
///
/// The mantissa, which contains the 15 decimal digits. 
/// The digits are encoded in binary coded decimal (BCD). I.e., 0x123456789012345 corresponds to the
/// number 123456789012345 rather than 8.19855..E16
/// The most significant digit is always 0 (this is to leave space in algorithms for 
/// operations on the mantissa to carry over without losing any digits).
/// With a zero exponent, the second-most significant digit of the mantissa is in the one's position
/// of the represented real.

typedef i8 Sign;
i8 const SignPos  = 1;        // do not change these signs, some functions
i8 const SignNeg  = -SignPos;       // fPos and fNeg depend on positive numbers having a positive sign
i8 const SignNan  = 0;        // and nan being 0
i8 const SignPInf = 2;
i8 const SignNInf = -SignPInf;

enum { // definitions of flags for the THPObj, THPReal, THPComplex... etc
      [....]
};

typedef struct { u16 EmbeddedRefCount; u8 type:4, Flags:4; ///< type, flags and embedding comes from THPObj. 
                 Sign s; i32 e; union { u32 m[2]; u64 M; }; } HP_Real;

// these max exponents could be changed with no problems...
  enum { 
    MaxExponent=49999, // could be changed up to 0x7fffffff-15;
    MaxExponent_L=499 // could be increased to 0x7ff = 2047
  };


Really, the primary difference between the HP48 series encoding of reals and the newer encoding is that instead of encoding the exponent as BCD, that is encoded as a plain integer value while the mantissa is still kept in BCD. Perhaps someone can link to or find a good reference where the 48 real number encoding is explained???


From this explanation, you can probably pretty easily figure out how a complex is encoded (2 paired reals with a different header), a matrix (size info, followed by reals), a complex matrix, etc.

TW

Although I work for HP, the views and opinions I post here are my own.
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
internal number representation - retoa - 10-05-2016, 06:25 AM
RE: internal number representation - Tim Wessman - 10-05-2016 03:42 PM
RE: internal number representation - retoa - 10-05-2016, 09:27 PM
RE: internal number representation - retoa - 10-07-2016, 07:30 AM
RE: internal number representation - jte - 10-08-2016, 08:37 PM



User(s) browsing this thread: 1 Guest(s)