///|
/// Table entry from `softfloat_approxRecip_1k0s` in `s_approxRecip_1Ks.c`.
fn approx_recip_1k0(index : Int32) -> UInt64 {
  match index {
    0 => 0xFFC4UL
    1 => 0xF0BEUL
    2 => 0xE363UL
    3 => 0xD76FUL
    4 => 0xCCADUL
    5 => 0xC2F0UL
    6 => 0xBA16UL
    7 => 0xB201UL
    8 => 0xAA97UL
    9 => 0xA3C6UL
    10 => 0x9D7AUL
    11 => 0x97A6UL
    12 => 0x923CUL
    13 => 0x8D32UL
    14 => 0x887EUL
    15 => 0x8417UL
    _ => abort("approx_recip_1k0 index out of range")
  }
}

///|
/// Table entry from `softfloat_approxRecip_1k1s` in `s_approxRecip_1Ks.c`.
fn approx_recip_1k1(index : Int32) -> UInt64 {
  match index {
    0 => 0xF0F1UL
    1 => 0xD62CUL
    2 => 0xBFA1UL
    3 => 0xAC77UL
    4 => 0x9C0AUL
    5 => 0x8DDBUL
    6 => 0x8185UL
    7 => 0x76BAUL
    8 => 0x6D3BUL
    9 => 0x64D4UL
    10 => 0x5D5CUL
    11 => 0x56B1UL
    12 => 0x50B6UL
    13 => 0x4B55UL
    14 => 0x4679UL
    15 => 0x4211UL
    _ => abort("approx_recip_1k1 index out of range")
  }
}

///|
/// Ports `softfloat_approxRecip32_1` from `s_approxRecip32_1.c`.
fn approx_recip32_1(a : UInt32) -> UInt32 {
  let index = ((a >> 27) & 0xFU).reinterpret_as_int()
  let eps = ((a >> 11) & 0xFFFFU).to_uint64()
  let r0 = approx_recip_1k0(index) - ((approx_recip_1k1(index) * eps) >> 20)
  let sigma0 = 0xFFFFFFFFU - ((r0 * a.to_uint64()) >> 7).to_uint()
  let sigma0_64 = sigma0.to_uint64()
  let mut r = (r0 << 16) + ((r0 * sigma0_64) >> 24)
  let sqr_sigma0 = (sigma0_64 * sigma0_64) >> 32
  r = r + (((r & 0xFFFFFFFFUL) * sqr_sigma0) >> 48)
  r.to_uint()
}

///|
/// Table entry from `softfloat_approxRecipSqrt_1k0s` in
/// `s_approxRecipSqrt_1Ks.c`.
fn approx_recip_sqrt_1k0(index : Int32) -> UInt64 {
  match index {
    0 => 0xB4C9UL
    1 => 0xFFABUL
    2 => 0xAA7DUL
    3 => 0xF11CUL
    4 => 0xA1C5UL
    5 => 0xE4C7UL
    6 => 0x9A43UL
    7 => 0xDA29UL
    8 => 0x93B5UL
    9 => 0xD0E5UL
    10 => 0x8DEDUL
    11 => 0xC8B7UL
    12 => 0x88C6UL
    13 => 0xC16DUL
    14 => 0x8424UL
    15 => 0xBAE1UL
    _ => abort("approx_recip_sqrt_1k0 index out of range")
  }
}

///|
/// Table entry from `softfloat_approxRecipSqrt_1k1s` in
/// `s_approxRecipSqrt_1Ks.c`.
fn approx_recip_sqrt_1k1(index : Int32) -> UInt64 {
  match index {
    0 => 0xA5A5UL
    1 => 0xEA42UL
    2 => 0x8C21UL
    3 => 0xC62DUL
    4 => 0x788FUL
    5 => 0xAA7FUL
    6 => 0x6928UL
    7 => 0x94B6UL
    8 => 0x5CC7UL
    9 => 0x8335UL
    10 => 0x52A6UL
    11 => 0x74E2UL
    12 => 0x4A3EUL
    13 => 0x68FEUL
    14 => 0x432BUL
    15 => 0x5EFDUL
    _ => abort("approx_recip_sqrt_1k1 index out of range")
  }
}

///|
/// Ports `softfloat_approxRecipSqrt32_1` from
/// `s_approxRecipSqrt32_1.c`.
fn approx_recip_sqrt32_1(odd_exp_a : Bool, a : UInt32) -> UInt32 {
  let index = ((a >> 27) & 0xEU).reinterpret_as_int() +
    (if odd_exp_a { 1 } else { 0 })
  let eps = ((a >> 12) & 0xFFFFU).to_uint64()
  let r0 = approx_recip_sqrt_1k0(index) -
    ((approx_recip_sqrt_1k1(index) * eps) >> 20)
  let e_sqr_r0 = if odd_exp_a { r0 * r0 } else { (r0 * r0) << 1 }
  let sigma0 = 0xFFFFFFFFU -
    (((e_sqr_r0 & 0xFFFFFFFFUL) * a.to_uint64()) >> 23).to_uint()
  let sigma0_64 = sigma0.to_uint64()
  let r = (r0 << 16) + ((r0 * sigma0_64) >> 25)
  let sqr_sigma0 = (sigma0_64 * sigma0_64) >> 32
  let correction = ((r >> 1) + (r >> 3) - (r0 << 14)) & 0xFFFFFFFFUL
  let r = r + ((correction * sqr_sigma0) >> 48)
  if (r & 0x80000000UL) == 0UL {
    0x80000000U
  } else {
    r.to_uint()
  }
}