 
 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
+
 
 # ----
 

      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

  show -> undefined

  log ''
  show -> num(98).gcd 21
  show -> num(77777).gcd 21

  log ''
  show -> a = num Math.pow 2, 13
  show -> LongInt.fromNative a.val
  show -> a.plus 2
  show -> a.times 1
