MBF <-> Float (simple, double and full lib)

Share your advanced PureBasic knowledge/code with the community.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

MBF <-> Float (simple, double and full lib)

Post by djes »

As I needed it, two quick and dirty procedures to convert a single precision (4 bytes) and a double (8 bytes) encoded in Microsoft Binary Format (mbf) to our delightful float format (IEEE754). Based on this code : http://www.experts-exchange.com/Program ... 45266.html

Code: Select all

Procedure.f mbf2ieee(src.f)

     Protected dest.f
     ;
     ;unsigned char *msbin = (unsigned char *)src4;
     ;unsigned char *ieee = (unsigned char *)dest4;
     ;unsigned char sign = 0x00;
     ;unsigned char ieee_exp = 0x00;
     ;int i;

     ;/* MS Binary Format                         */
     ;/* byte order =>    m3 | m2 | m1 | exponent */
     ;/* m1 is most significant byte => sbbb|bbbb */
     ;/* m3 is the least significant byte         */
     ;/*      m = mantissa byte                   */
     ;/*      s = sign bit                        */
     ;/*      b = bit                             */

     ;sign = msbin[2] & 0x80;      /* 1000|0000b  */
     sign.b = PeekB(@src + 2) & $80

     ;/* IEEE Single Precision Float Format       */
     ;/*    m3        m2        m1     exponent   */
     ;/* mmmm|mmmm mmmm|mmmm emmm|mmmm seee|eeee  */
     ;/*          s = sign bit                    */
     ;/*          e = exponent bit                */
     ;/*          m = mantissa bit                */

     ;For (i=0; i<4; i++) ieee[i] = 0;   

     ;/* any msbin w/ exponent of zero = zero */
     ;If (msbin[3] == 0) Return 0;
     If PeekB(@src + 3)=0
      ProcedureReturn 0
     EndIf

     ;ieee[3] |= sign;
     PokeB(@dest + 3, sign)

     ;/* MBF is bias 128 And IEEE is bias 127. ALSO, MBF places   */
     ;/* the decimal point before the assumed bit, While          */
     ;/* IEEE places the decimal point after the assumed bit.     */

     ;ieee_exp = msbin[3] - 2;    /* actually, msbin[3]-1-128+127 */

     exp.b = PeekB(@src + 3) - 2

     ;/* the first 7 bits of the exponent in ieee[3] */
     ;ieee[3] |= ieee_exp >> 1;
     PokeB(@dest + 3, PeekB(@dest + 3) | ((exp>>1) & $7F) )

     ;/* the one remaining bit in first bin of ieee[2] */
     ;ieee[2] |= ieee_exp << 7;
     PokeB(@dest + 2, PeekB(@dest + 2) | (exp<<7) )

     ;/* 0111|1111b : mask out the msbin sign bit */
     ;ieee[2] |= msbin[2] & 0x7f;
     PokeB(@dest + 2, PeekB(@dest + 2) | (PeekB(@src + 2) & $7F) )

     ;ieee[1] = msbin[1];
     PokeB(@dest+1, PeekB(@src+1))
     ;ieee[0] = msbin[0];
     PokeB(@dest, PeekB(@src))


     ;Return 0;
     ProcedureReturn dest
;     

EndProcedure

Procedure.d dmbf2ieee(src.d)

  Protected  dest.d, msbin.d
     ;
     ;unsigned char msbin[8];
     ;unsigned char *ieee = (unsigned char *)dest8;
     ;unsigned char sign = 0x00;
     ;unsigned int ieee_exp = 0x0000;
     ;int i;

     ;/* A manipulatable copy of the msbin number     */
     ;strncpy((char *)msbin,(char *)src8,8);
      msbin = src

   ;/* MS Binary Format                                           */
   ;/* byte order =>  m7 | m6 | m5 | m4 | m3 | m2 | m1 | exponent */
   ;/* m1 is most significant byte => smmm|mmmm                   */
   ;/* m7 is the least significant byte                           */
   ;/*      m = mantissa byte                                     */
   ;/*      s = sign bit                                          */
   ;/*      b = bit                                               */

   ;  sign = msbin[6] & 0x80;      /* 1000|0000b  */
    sign.b = PeekB(@msbin + 6) & $80


   ;/* IEEE Single Precision Float Format                         */
   ;/*  byte 8    byte 7    byte 6    byte 5    byte 4  And so on */
   ;/* seee|eeee eeee|mmmm mmmm|mmmm mmmm|mmmm mmmm|mmmm ...      */
   ;/*          s = sign bit                                      */
   ;/*          e = exponent bit                                  */
   ;/*          m = mantissa bit                                  */

   ;  For (i=0; i<8; i++) ieee[i] = 0;

   ;  /* any msbin w/ exponent of zero = zero */
   ;  If (msbin[7] == 0) Return 0;
    If PeekB(@msbin + 7) = 0
      ProcedureReturn 0
    EndIf

     ;ieee[7] |= sign;
      PokeB(@dest+7, sign)

     ;/* MBF is bias 128 And IEEE is bias 1023. ALSO, MBF places  */
     ;/* the decimal point before the assumed bit, While          */
     ;/* IEEE places the decimal point after the assumed bit.     */

     ;ieee_exp = msbin[7] - 128 - 1 + 1023;
     exp.w = (PeekB(@msbin + 7)&$FF) - 128 - 1 + 1023
     
     ;/* First 4 bits of the msbin exponent   */
     ;/* go into the last 4 bits of ieee[7]   */
     ;ieee[7] |= ieee_exp >> 4;
     PokeB(@dest + 7, PeekB(@dest + 7) | ((exp >> 4) & $0FFF))

     ;/* The last 4 bits of msbin exponent    */
     ;/* go into the first 4 bits of ieee[6]  */
     ;ieee[6] |= ieee_exp << 4;
     PokeB(@dest + 6, PeekB(@dest + 6) | ((exp << 4) & $FFF0))

     ;/* The msbin mantissa must be shifted To the right 1 bit.   */
     ;/* Remember that the msbin number has its bytes reversed.   */
     ;For (i=6; i>0; i--)
     For i = 6 To 1 Step -1
     ;    {
     ;    msbin[i] <<= 1;
       PokeB(@msbin + i, (PeekB(@msbin + i) << 1) & $FE)
     ;    msbin[i] |= msbin[i-1] >> 7;
       PokeB(@msbin + i, PeekB(@msbin + i) | ((PeekB(@msbin + i - 1) >> 7) & $01))
     ;    }
     Next i
     ;msbin[0] <<= 1;
     PokeB(@msbin, (PeekB(@msbin) << 1) & $FE)

     ;/* Now the mantissa is put into the ieee array starting in  */
     ;/* the middle of the second To last byte.                   */

     ;For (i=6; i>0; i--)
     For i=6 To 1 Step -1
     ;    {

     ;    ieee[i] |= msbin[i] >> 4;
       PokeB(@dest + i, PeekB(@dest + i) | ((PeekB(@msbin + i) >> 4) & $0F))
     ;    ieee[i-1] |= msbin[i] << 4;
       PokeB(@dest + i - 1, PeekB(@dest + i - 1) | ((PeekB(@msbin + i) << 4) & $F0))

     ;    }
     Next i
     ;ieee[0] |= msbin[0] >> 4;
     PokeB(@dest, PeekB(@dest) | ((PeekB(@msbin) >> 4) & $0F))

   ;/* IEEE has a half byte less For its mantissa.  If the msbin */
   ;/* number has anything in this last half byte, then there is */
   ;/* an overflow.                                              */
   ;  If (msbin[0] & 0x0f)
    If (PeekB(@msbin) & $0F)
      CallDebugger
      Debug "Overflow"
      ;   Return 1;
     ;Else
         ;Return 0;
     ; }
    EndIf

  ProcedureReturn dest

EndProcedure
And here's the import needed to use the MbfIee32.LIB located there : http://www.mdxi.com/

Code: Select all

Import "MBFIEE32.LIB"
 
  DxToIEEEd(*x.d) As "_DxToIEEEd@4"
  DxToIEEEs(*x.s) As "_DxToIEEEs@4"
  DxToMBFd(*x.d) As "_DxToMBFd@4"
  DxToMBFs(*x.s) As "_DxToMBFs@4"
               
EndImport
Last edited by djes on Thu Dec 04, 2008 7:09 pm, edited 6 times in total.
User avatar
idle
Always Here
Always Here
Posts: 5917
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Post by idle »

That would have been fun to convert, I'm sure it'll save someones bacon one day.

:D
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

idle wrote:That would have been fun to convert, I'm sure it'll save someones bacon one day.

:D
:)
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Added the MbfIee32.LIB and the import to use the MicroDexterity provided functions.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Thank you very much. :)

Now to convert back to MBF.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Thank you! I've not the need to do it by now, but you may use the lib linked in the first post.
Post Reply