/* Reprezentace float podle IEEE 754 v little endien */
#include <stdint.h>
typedef __SIZE_TYPE__ size_t;
typedef union {
  float f;
  struct {
    uint32_t frac : 23;
    uint32_t exp  : 8;
    uint32_t sign : 1;
  } u;
} float_unsigned;
typedef union {
  uint32_t u;
  struct {
    uint32_t l : 28;
    uint32_t h :  4;
  } e;
} u2m;
// výstupní znaky
static const char * dec = "0123456789";
// decimální exponent e do bufferu buff
static size_t exp_str (char * buf, const int e) {
  size_t n = 0;
  int exp = 0, res;
  buf [n++] = 'E';
  if (e > 0) {
    buf [n++] = '+';
    exp = e;
  } else if (e < 0) {
    buf [n++] = '-';
    exp = -e;
  } else {
    buf [n++] = '+';
    buf [n++] = '0';
    buf [n++] = '0';
    return n;
  }
  n += 2;
  res = exp % 10;
  buf [n - 1] = dec [res];
  exp = exp / 10;
  res = exp % 10;
  buf [n - 2] = dec [res];
  return n;
}
// konstanty pro decimální normalizaci
static const float exp_plus [] = {
  1.0e+1f, 1.0e+2f, 1.0e+4f, 1.0e+8f, 1.0e+16f, 1.0e+32f, 
};
static const float exp_minus [] = {
  1.0e-1f, 1.0e-2f, 1.0e-4f, 1.0e-8f, 1.0e-16f, 1.0e-32f, 
};
// decimální normalizace f do rozsahu <0.1, 1.0)
static float f_norm (const float f, int * pe) {
  float_unsigned res;
  res.f = f;
  uint32_t s = res.u.sign;  // schovej znaménko
  res.u.sign = 0u;          // dál už počítej jen s absolutní hodnotou
  unsigned n = 5u;
  if (res.f >= 1.0f) {
    do {
      if (res.f >= exp_plus [n]) {
        res.f *= exp_minus [n];
        * pe += 1 << n;
      }
    } while (n--);
    res.f *= 0.1f;
    * pe += 1;
  } else {
    do {
      if (res.f < exp_minus [n]) {
        res.f *= exp_plus [n];
        * pe -= 1 << n;
      }
    } while (n--);
  }
  res.u.sign = s;           // obnov znaménko
  // printf("normalized = %f, decimal exponent = %d\n", res.f, * pe);
  return res.f;
}
static unsigned to_str (const float f, char * buf) {
  int dec_exp = 0;
  float_unsigned fu;
  fu.f = f_norm (f, & dec_exp);
  u2m um;
  // převod formátu pro výstup číslic pomocí celočíselného násobení 10
  um.u = (fu.u.frac | (1lu << 23)) << (fu.u.exp - 122u);
  unsigned n = 0;
  if (fu.u.sign) buf [n++] = '-';
  else           buf [n++] = '+';
  if (fu.f != 0.0f) {
    for (;;) {              // exportuj decimální číslice
      um.u *= 10u;
      const char c = dec [um.e.h];
      um.e.h = 0u;
      if (n == 2) buf [n++] = '.';
      buf [n++] = c;
      if  (n >= 10) break;  // 8 platnych cislic
    }
    n += exp_str (buf + n, dec_exp - 1);
  } else {                  // 0.0f
    buf [n++] = '0';
    for (unsigned i=0; i<12; i++) buf[n++] = ' ';
  }
  buf [n] = '\0';           // ukončení
  return n;
}
#include "print.h"
Print & Print::operator<< (const float num) {
  const unsigned n = to_str(num, buf);
  BlockDown (buf, n);
  return * this;
}