let rec make (d, lo, hi) =
  let lower (alpha, q) =    (* normalized lower bound *)
    match d with
      | Dom.Int when not(alpha && Q.is_integer q) -> 
          (trueQ.of_z(Q.floor(Q.add q Q.one)))
      | _ -> 
          (alpha, q)
  and upper (p, beta) =   (* normalized upper bound *)
    match d with
      | Dom.Int when not(beta && Q.is_integer p) -> 
          (Q.of_z(Q.ceil(Q.sub p Q.one)), true)
      | _ -> 
          (p, beta)
  in
    match lo, hi with
      | NoneNone -> 
          mk_dom d
      | NoneSome(p, beta) -> 
          let (p', beta') = upper (p, beta) in
          { dom = d; lo = None; hi = Some(p', beta') }
      | Some(alpha, q), None ->
          let (alpha', q') = lower (alpha, q) in
          { dom = d; lo = Some(alpha', q'); hi = None }
      | Some(alpha, q), Some(p, beta) ->
          let (alpha', q') = lower (alpha, q)
          and (p', beta') = upper (p, beta) in
            if alpha' && beta' && Q.gt q' p' then
              mk_empty
            else if not(alpha' && beta') && Q.ge q' p' then
              mk_empty
            else 
              { dom = d; lo = Some(alpha', q'); hi = Some(p', beta') }