let convert a b a_to_b b_to_a =
  if a.num_bits <= b.num_bits then
    ((fun i -> Some (a_to_b i)), a_to_b)
  else
    let min = b_to_a b.min in
    let max = b_to_a b.max in
    let is_in_range i = min <= i && i <= max in
    let convert i = if is_in_range i then Some (a_to_b i) else None in
    let convert_exn i =
      if is_in_range i then
        a_to_b i
      else
        failwith (Printf.sprintf
                     "conversion from %s to %s failed: %s is out of range"
                     a.name b.name (a.to_string i))
    in
    (convert, convert_exn)