Search code examples
binaryschemechicken-scheme

How can I read and write binary floats with Chicken Scheme?


I am reading a binary data format using Chicken, and so far I've gotten ints working by doing stuff like (fx+ (fxshl (read-byte) 8) (read-byte)) (Big Endian).

How can I read and write floats in? I have to be able to read and write IEEE 754-2008 32-bit and 64-bit binary floats.


Solution

  • I haven't found any good libraries to do this so far, but I've hacked together something that works. Note that I only have read-byte and read-string available to me as input operations.

      ;;
      ;; These are some unfun C routines to convert 4 int-promoted bytes to a float
      ;; by manually assembling the float using bitwise operators
      ;;
      ;; Caveat! These will only work on platforms in which floats are 32-bit Big
      ;; Endian IEEE754-2008 numbers and doubles are 64-bit Big Endian IEEE754-2008
      ;; numbers! Also, stdint.h.
      ;;
      (define (readFloat)
        (let ([c-read-float
                (foreign-lambda* float
                  ((int i1)
                   (int i2)
                   (int i3)
                   (int i4))
                   "uint8_t b1 = (uint8_t) i1;
                    uint8_t b2 = (uint8_t) i2;
                    uint8_t b3 = (uint8_t) i3;
                    uint8_t b4 = (uint8_t) i4;
    
                    uint32_t i = 0;
    
                    i = b1;
                    i = (i << 8) | b2;
                    i = (i << 8) | b3;
                    i = (i << 8) | b4;
    
                    float f = *(float*)&i;
    
                    C_return(f);")])
            (let* ([i1 (read-byte)]
                   [i2 (read-byte)]
                   [i3 (read-byte)]
                   [i4 (read-byte)])
              (c-read-float i1 i2 i3 i4))))