///|
/// Encode the binary64 value as an exact integer times an integral power of two.
/// No floating-point formatting or decimal parsing is involved.
fn real_to_wire(value : Double) -> Json {
  let bits = value.reinterpret_as_uint64()
  let negative = bits >> 63 != 0UL
  let stored_exponent = ((bits >> 52) & 2047UL).to_int()
  let fraction = bits & 0x000fffffffffffffUL
  let mut significand = if stored_exponent == 0 {
    fraction
  } else {
    fraction | 0x0010000000000000UL
  }
  let mut exponent = if stored_exponent == 0 {
    -1074
  } else {
    stored_exponent - 1075
  }
  if significand == 0UL {
    exponent = 0
  } else {
    let zeros = significand.ctz()
    significand = significand >> zeros
    exponent += zeros
  }
  let digits = (if negative { "-" } else { "" }) + significand.to_string()
  Json::array([
    Json::string("real"),
    Json::string(digits),
    Json::string(exponent.to_string()),
  ])
}

///|
/// Only exactly representable finite binary64 pairs are accepted; never round.
fn real_from_binary(
  significand : String,
  exponent : String,
) -> Double raise CdcError {
  let signed = parse_integer(significand)
  if signed < -9007199254740991L || signed > 9007199254740991L {
    raise Invalid("REAL significand exceeds 53 bits")
  }
  let power = parse_integer(exponent)
  if power < -1126L || power > 1023L {
    raise Invalid("REAL binary exponent is out of range")
  }
  let sign = if significand.has_prefix("-") {
    0x8000000000000000UL
  } else {
    0UL
  }
  let magnitude = (if signed < 0L { -signed } else { signed }).reinterpret_as_uint64()
  if magnitude == 0UL {
    if power != 0L {
      raise Invalid("REAL zero requires exponent zero")
    }
    return sign.reinterpret_as_double()
  }
  let top = 63 - magnitude.clz()
  let unbiased = top + power.to_int()
  if unbiased > 1023 {
    raise Invalid("REAL overflows binary64")
  }
  let body = if unbiased >= -1022 {
    let fraction = (magnitude << (52 - top)) & 0x000fffffffffffffUL
    ((unbiased + 1023).to_uint64() << 52) | fraction
  } else {
    let shift = power.to_int() + 1074
    if shift >= 0 {
      magnitude << shift
    } else {
      let discarded = -shift
      if discarded > 52 || (magnitude & ((1UL << discarded) - 1UL)) != 0UL {
        raise Invalid("REAL is smaller than an exact binary64 subnormal")
      }
      magnitude >> discarded
    }
  }
  (sign | body).reinterpret_as_double()
}