       if cmp(r, rn) then -> step(rn) else rn
     trampoline step s.take n >> 1
 
-  sqrt: ->
+  sqrt__: ->
     if @sign == 0
       asNum 0
     else if @sign > 0
-      NumberBase.downcast new LongInt 1, sqrt @digits
+      new LongInt 1, sqrt @digits
     else
       throw new Error "expected a non-negative number, got #{this}"
 

      x

  operator = (name, f) ->
    NumberBase[name]   = (args...) -> f.call NumberBase, args...
    NumberBase::[name] = (args...) -> NumberBase[name] this, args...

  for name in ['cmp', 'plus', 'minus', 'times', 'div', 'mod']
    do (name) ->
      namex = "#{name}__"
      operator name, (a, b) ->
        [x, y] = upcast a, b
        @downcast x[namex] y

  gcd: (other) ->
    step = (a, b) -> if b.sgn() > 0 then -> step b, a.mod(b) else a

    [a, b] = [@abs(), makeNum(other).abs()]
    if a > b then trampoline step a, b else trampoline step b, a

  pow: (other) ->
    step = (p, r, s) ->
      if s.sgn() > 0
        if s.mod(2).sgn() > 0


asNum = (n) ->
  if Math.abs(n) < BASE then new CheckedInt n else LongInt.fromNative n

# ----

# The `num` function provides the public interface.

num = (n = 0) ->
  switch typeof n
    when 'number'
      num.fromNative n
    when 'string'
      num.parse n
    else
      if n instanceof NumberBase
        n
      else
        throw new Error "expected a number, got #{n}"

num.fromNative = (n) ->
  throw new Error "expected an integer, got #{n}" unless n == Math.floor n
  asNum n

num.parse = (n) ->
  unless /^[+-]?\d+$/.test n
    throw new Error "expected an integer literal, got '#{n}'"

  [s, m] = switch n[0]
    when '-' then [-1, n[1..]]
    when '+' then [ 1, n[1..]]
    else          [ 1, n]

  if m.length <= BASE_LENGTH
    new CheckedInt parseInt n
  else
    parsed = (to) ->
      if to > 0
        from = Math.max 0, to - BASE_LENGTH
        seq.conj parseInt(m[from...to]), -> parsed from
      else
        null

    new LongInt s, parsed m.length


# ----

