Start adding math directly into bc
diff --git a/include/bc/bc.h b/include/bc/bc.h
index 2c033b5..b6b45a7 100644
--- a/include/bc/bc.h
+++ b/include/bc/bc.h
@@ -67,6 +67,10 @@
 
 typedef void (*BcFreeFunc)(void*);
 
+#define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
+
 #define BC_INVALID_IDX ((size_t) -1)
 
 #define BC_BASE_MAX_DEF (99)
@@ -108,28 +112,30 @@
   BC_STATUS_PARSE_EOF,
   BC_STATUS_PARSE_BUG,
 
-  BC_STATUS_VM_FILE_ERR,
-  BC_STATUS_VM_DIVIDE_BY_ZERO,
-  BC_STATUS_VM_NEG_SQRT,
-  BC_STATUS_VM_MISMATCHED_PARAMS,
-  BC_STATUS_VM_UNDEFINED_FUNC,
-  BC_STATUS_VM_UNDEFINED_VAR,
-  BC_STATUS_VM_UNDEFINED_ARRAY,
-  BC_STATUS_VM_FILE_NOT_EXECUTABLE,
-  BC_STATUS_VM_SIGACTION_FAIL,
-  BC_STATUS_VM_INVALID_SCALE,
-  BC_STATUS_VM_INVALID_IBASE,
-  BC_STATUS_VM_INVALID_OBASE,
-  BC_STATUS_VM_INVALID_STMT,
-  BC_STATUS_VM_INVALID_EXPR,
-  BC_STATUS_VM_INVALID_STRING,
-  BC_STATUS_VM_STRING_LEN,
-  BC_STATUS_VM_INVALID_NAME,
-  BC_STATUS_VM_ARRAY_LENGTH,
-  BC_STATUS_VM_INVALID_TEMP,
-  BC_STATUS_VM_INVALID_READ_EXPR,
-  BC_STATUS_VM_PRINT_ERR,
-  BC_STATUS_VM_HALT,
+  BC_STATUS_MATH_DIVIDE_BY_ZERO,
+  BC_STATUS_MATH_NEG_SQRT,
+  BC_STATUS_MATH_INVALID_STRING,
+
+  BC_STATUS_EXEC_FILE_ERR,
+  BC_STATUS_EXEC_MISMATCHED_PARAMS,
+  BC_STATUS_EXEC_UNDEFINED_FUNC,
+  BC_STATUS_EXEC_UNDEFINED_VAR,
+  BC_STATUS_EXEC_UNDEFINED_ARRAY,
+  BC_STATUS_EXEC_FILE_NOT_EXECUTABLE,
+  BC_STATUS_EXEC_SIGACTION_FAIL,
+  BC_STATUS_EXEC_INVALID_SCALE,
+  BC_STATUS_EXEC_INVALID_IBASE,
+  BC_STATUS_EXEC_INVALID_OBASE,
+  BC_STATUS_EXEC_INVALID_STMT,
+  BC_STATUS_EXEC_INVALID_EXPR,
+  BC_STATUS_EXEC_INVALID_STRING,
+  BC_STATUS_EXEC_STRING_LEN,
+  BC_STATUS_EXEC_INVALID_NAME,
+  BC_STATUS_EXEC_ARRAY_LENGTH,
+  BC_STATUS_EXEC_INVALID_TEMP,
+  BC_STATUS_EXEC_INVALID_READ_EXPR,
+  BC_STATUS_EXEC_PRINT_ERR,
+  BC_STATUS_EXEC_HALT,
 
   BC_STATUS_POSIX_NAME_LEN,
   BC_STATUS_POSIX_SCRIPT_COMMENT,
diff --git a/include/bc/num.h b/include/bc/num.h
new file mode 100644
index 0000000..fc30282
--- /dev/null
+++ b/include/bc/num.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2018 Contributors
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************
+ *
+ * A special license exemption is granted to the Toybox project and to the
+ * Android Open Source Project to use this source under the following BSD
+ * 0-Clause License:
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ *******************************************************************************
+ *
+ * Definitions for the num type.
+ *
+ */
+
+#ifndef BC_NUM_H
+#define BC_NUM_H
+
+// For C++ compatibility.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <bc/bc.h>
+
+#define BC_NUM_MIN_BASE (2)
+
+#define BC_NUM_MAX_INPUT_BASE (16)
+
+#define BC_NUM_MAX_OUTPUT_BASE (99)
+
+#define BC_NUM_DEF_SIZE (16)
+
+#define BC_NUM_FROM_CHAR(c) ((c) -'0')
+
+#define BC_NUM_TO_CHAR(n) ((n) + '0')
+
+typedef struct BcNum {
+
+  char* num;
+  size_t radix;
+  size_t len;
+  size_t unused;
+  bool neg;
+
+} BcNum;
+
+typedef BcStatus (*BcUnaryFunc)(BcNum* a, BcNum* res, size_t scale);
+typedef BcStatus (*BcBinaryFunc)(BcNum* a, BcNum* b, BcNum* res, size_t scale);
+
+BcStatus bc_num_copy(BcNum* dest, BcNum* src);
+
+BcStatus bc_num_parse(BcNum* num, const char* val,
+                       size_t base, size_t scale);
+
+BcStatus bc_num_print(BcNum* num, size_t base);
+BcStatus bc_num_fprint(BcNum* num, size_t base, FILE* f);
+
+BcStatus bc_num_add(BcNum* a, BcNum* b, BcNum* result, size_t scale);
+BcStatus bc_num_sub(BcNum* a, BcNum* b, BcNum* result, size_t scale);
+BcStatus bc_num_mul(BcNum* a, BcNum* b, BcNum* result, size_t scale);
+BcStatus bc_num_div(BcNum* a, BcNum* b, BcNum* result, size_t scale);
+BcStatus bc_num_mod(BcNum* a, BcNum* b, BcNum* result, size_t scale);
+BcStatus bc_num_pow(BcNum* a, BcNum* b, BcNum* result, size_t scale);
+
+BcStatus bc_num_sqrt(BcNum* a, BcNum* result, size_t scale);
+
+bool bc_num_isInteger(BcNum* num);
+
+int bc_num_compare(BcNum* a, BcNum* b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BC_NUM_H
diff --git a/src/bc/bc.c b/src/bc/bc.c
index d76f5ff..7f722db 100644
--- a/src/bc/bc.c
+++ b/src/bc/bc.c
@@ -96,8 +96,11 @@
   "Parse",
   "Parse",
 
-  "Runtime",
-  "Runtime",
+  "Math",
+  "Math",
+  "Math",
+  "Math",
+
   "Runtime",
   "Runtime",
   "Runtime",
@@ -173,9 +176,13 @@
   "end of file",
   "bug in parser",
 
-  "couldn't open file",
   "divide by zero",
   "negative square root",
+  "invalid input base",
+  "invalid output base",
+  "invalid number string",
+
+  "couldn't open file",
   "mismatched parameters",
   "undefined function",
   "undefined variable",
@@ -196,17 +203,17 @@
   "print error",
   "bc was not halted correctly; this is a bug in bc",
 
-  "POSIX bc only allows one character names; the following is invalid:",
-  "POSIX bc does not allow '#' script comments",
-  "POSIX bc does not allow the following keyword:",
-  "POSIX bc requires parentheses around return expressions",
-  "POSIX bc does not allow boolean operators; the following is invalid:",
-  "POSIX bc does not allow comparison operators outside if or loops",
-  "POSIX bc does not allow more than one comparison operator per condition",
-  "POSIX bc does not allow an empty init expression in a for loop",
-  "POSIX bc does not allow an empty condition expression in a for loop",
-  "POSIX bc does not allow an empty update expression in a for loop",
-  "POSIX bc requires the left brace be on the same line as the function header",
+  "POSIX only allows one character names; the following is invalid:",
+  "POSIX does not allow '#' script comments",
+  "POSIX does not allow the following keyword:",
+  "POSIX requires parentheses around return expressions",
+  "POSIX does not allow boolean operators; the following is invalid:",
+  "POSIX does not allow comparison operators outside if or loops",
+  "POSIX does not allow more than one comparison operator per condition",
+  "POSIX does not allow an empty init expression in a for loop",
+  "POSIX does not allow an empty condition expression in a for loop",
+  "POSIX does not allow an empty update expression in a for loop",
+  "POSIX requires the left brace be on the same line as the function header",
 
 };
 
@@ -276,7 +283,7 @@
 void bc_error(BcStatus status) {
 
   if (!status || status == BC_STATUS_PARSE_QUIT ||
-      status == BC_STATUS_VM_HALT ||
+      status == BC_STATUS_EXEC_HALT ||
       status >= BC_STATUS_POSIX_NAME_LEN)
   {
     return;
diff --git a/src/bc/data.c b/src/bc/data.c
index d58133f..5104ca5 100644
--- a/src/bc/data.c
+++ b/src/bc/data.c
@@ -340,7 +340,7 @@
   temp->type = BC_TEMP_NAME;
 
   if (!name) {
-    return BC_STATUS_VM_INVALID_NAME;
+    return BC_STATUS_EXEC_INVALID_NAME;
   }
 
   temp->name = name;
@@ -351,7 +351,7 @@
 BcStatus bc_temp_init(BcTemp* temp, BcTempType type) {
 
   if (type > BC_TEMP_LAST || type == BC_TEMP_NUM || type == BC_TEMP_NAME) {
-    return BC_STATUS_VM_INVALID_TEMP;
+    return BC_STATUS_EXEC_INVALID_TEMP;
   }
 
   temp->type = type;
diff --git a/src/bc/num.c b/src/bc/num.c
new file mode 100644
index 0000000..3f2e50b
--- /dev/null
+++ b/src/bc/num.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright 2018 Contributors
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************
+ *
+ * A special license exemption is granted to the Toybox project and to the
+ * Android Open Source Project to use this source under the following BSD
+ * 0-Clause License:
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ *******************************************************************************
+ *
+ * Code for the number type.
+ *
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <bc/bc.h>
+#include <bc/num.h>
+
+static BcStatus bc_num_construct(BcNum* num, size_t request);
+
+static BcStatus bc_num_expand(BcNum* num, size_t request);
+
+static void bc_num_destruct(BcNum* num);
+
+static BcStatus bc_num_unary(BcNum* a, BcNum* b, size_t scale,
+                               BcUnaryFunc op, size_t req);
+
+static BcStatus bc_num_binary(BcNum* a, BcNum* b, BcNum* c, size_t scale,
+                              BcBinaryFunc op, size_t req);
+
+static BcStatus bc_num_alg_a(BcNum* a, BcNum* b, BcNum* c, size_t scale);
+static BcStatus bc_num_alg_s(BcNum* a, BcNum* b, BcNum* c, size_t scale);
+static BcStatus bc_num_alg_m(BcNum* a, BcNum* b, BcNum* c, size_t scale);
+static BcStatus bc_num_alg_d(BcNum* a, BcNum* b, BcNum* c, size_t scale);
+static BcStatus bc_num_alg_mod(BcNum* a, BcNum* b, BcNum* c, size_t scale);
+static BcStatus bc_num_alg_p(BcNum* a, BcNum* b, BcNum* c, size_t scale);
+
+static BcStatus bc_num_sqrt_newton(BcNum* a, BcNum* b, size_t scale);
+
+static bool bc_num_strValid(const char* val, size_t base);
+
+static BcStatus bc_num_parseDecimal(BcNum *n, const char* val,
+                                     size_t scale);
+static BcStatus bc_num_parseLowBase(BcNum* n, const char* val,
+                                     size_t base, size_t scale);
+static BcStatus bc_num_parseHighBase(BcNum* n, const char* val,
+                                      size_t base, size_t scale);
+
+static BcStatus bc_num_printDecimal(BcNum* n, FILE* f);
+static BcStatus bc_num_printLowBase(BcNum* n, size_t base, FILE* f);
+static BcStatus bc_num_printHighBase(BcNum* n, size_t base, FILE* f);
+static BcStatus bc_num_printHighestBase(BcNum* n, size_t base, FILE* f);
+
+BcStatus bc_num_parse(BcNum* num, const char* val,
+                       size_t base, size_t scale)
+{
+  BcStatus status;
+
+  if (!num || !val) return BC_STATUS_INVALID_PARAM;
+
+  if (base < BC_NUM_MIN_BASE || base > BC_NUM_MAX_INPUT_BASE)
+    return BC_STATUS_EXEC_INVALID_IBASE;
+
+  if (!bc_num_strValid(val, base)) return BC_STATUS_MATH_INVALID_STRING;
+
+  if (base == 10) {
+    status = bc_num_parseDecimal(num, val, scale);
+  }
+  else if (base < 10) {
+    status = bc_num_parseLowBase(num, val, base, scale);
+  }
+  else {
+    status = bc_num_parseHighBase(num, val, base, scale);
+  }
+
+  return status;
+}
+
+BcStatus bc_num_copy(BcNum* dest, BcNum* src) {
+
+  BcStatus status;
+  BcNum* d;
+  BcNum* s;
+
+  d = (BcNum*) dest;
+  s = (BcNum*) src;
+
+  if (!d || !s || d == s) return BC_STATUS_INVALID_PARAM;
+
+  status = bc_num_expand(d, s->len + s->unused);
+
+  if (status) return status;
+
+  d->len = s->len;
+  d->neg = s->neg;
+  d->radix = s->radix;
+
+  memcpy(d->num, s->num, sizeof(char) * d->len);
+
+  return BC_STATUS_SUCCESS;
+}
+
+BcStatus bc_num_print(BcNum* num, size_t base) {
+  return bc_num_fprint(num, base, stdout);
+}
+
+BcStatus bc_num_fprint(BcNum* num, size_t base, FILE* f) {
+
+  BcStatus status;
+
+  if (!num || !f) return BC_STATUS_INVALID_PARAM;
+
+  if (base < BC_NUM_MIN_BASE || base > BC_NUM_MAX_OUTPUT_BASE)
+    return BC_STATUS_EXEC_INVALID_OBASE;
+
+  if (base == 10) {
+    status = bc_num_printDecimal(num, f);
+  }
+  else if (base < 10) {
+    status = bc_num_printLowBase(num, base, f);
+  }
+  else if (base <= 16) {
+    status = bc_num_printHighBase(num, base, f);
+  }
+  else {
+    status = bc_num_printHighestBase(num, base, f);
+  }
+
+  return status;
+}
+
+BcStatus bc_num_add(BcNum* a, BcNum* b, BcNum* result, size_t scale) {
+  return bc_num_binary(a, b, result, scale, bc_num_alg_a, a->len + b->len);
+}
+
+BcStatus bc_num_sub(BcNum* a, BcNum* b, BcNum* result, size_t scale) {
+
+  BcNum* a_num;
+  BcNum* b_num;
+
+  a_num = (BcNum*) a;
+  b_num = (BcNum*) b;
+
+  return bc_num_binary(a_num, b_num, result, scale, bc_num_alg_s,
+                       a_num->len + b_num->len);
+}
+
+BcStatus bc_num_mul(BcNum* a, BcNum* b, BcNum* result, size_t scale) {
+
+  BcNum* a_num;
+  BcNum* b_num;
+
+  a_num = (BcNum*) a;
+  b_num = (BcNum*) b;
+
+  return bc_num_binary(a_num, b_num, result, scale, bc_num_alg_m,
+                       a_num->len + b_num->len);
+}
+
+BcStatus bc_num_div(BcNum* a, BcNum* b, BcNum* result, size_t scale) {
+
+  BcNum* a_num;
+  BcNum* b_num;
+
+  a_num = (BcNum*) a;
+  b_num = (BcNum*) b;
+
+  return bc_num_binary(a_num, b_num, result, scale, bc_num_alg_d,
+                       a_num->len + b_num->len);
+}
+
+BcStatus bc_num_mod(BcNum* a, BcNum* b, BcNum* result, size_t scale) {
+
+  BcNum* a_num;
+  BcNum* b_num;
+
+  a_num = (BcNum*) a;
+  b_num = (BcNum*) b;
+
+  return bc_num_binary(a_num, b_num, result, scale, bc_num_alg_mod,
+                       a_num->len + b_num->len);
+}
+
+BcStatus bc_num_pow(BcNum* a, BcNum* b, BcNum* result, size_t scale) {
+
+  BcNum* a_num;
+  BcNum* b_num;
+
+  a_num = (BcNum*) a;
+  b_num = (BcNum*) b;
+
+  return bc_num_binary(a_num, b_num, result, scale, bc_num_alg_p,
+                       a_num->len + b_num->len);
+}
+
+BcStatus bc_num_sqrt(BcNum* a, BcNum* result, size_t scale) {
+
+  BcNum* a_num;
+
+  a_num = (BcNum*) a;
+
+  return bc_num_unary(a_num, result, scale, bc_num_sqrt_newton, a_num->len * 2);
+}
+
+bool bc_num_isInteger(BcNum* num) {
+
+  BcNum* n;
+
+  n = (BcNum*) num;
+
+  if (!n) return false;
+
+  return n->radix == n->len;
+}
+
+int bc_num_compare(BcNum* a, BcNum* b) {
+
+  BcNum* a2;
+  BcNum* b2;
+  size_t i;
+  size_t max;
+  size_t min;
+  char* max_num;
+  char* min_num;
+  bool a_max;
+
+  a2 = (BcNum*) a;
+  b2 = (BcNum*) b;
+
+  if (!a2) {
+
+    if (b2== NULL) {
+      return 0;
+    }
+    else {
+      return b2->neg ? 1 : -1;
+    }
+  }
+  else if (!b2) {
+    return a2->neg ? -1 : 1;
+  }
+
+  if (a2->radix > b2->radix) {
+    return 1;
+  }
+  else if (b2->radix > a2->radix) {
+    return -1;
+  }
+
+  for (i = 0; i < a2->radix; ++i) {
+
+    char c;
+
+    c = a2->num[i] - b2->num[i];
+
+    if (c) return c;
+  }
+
+  a_max = a2->len > b2->len;
+
+  if (a_max) {
+
+    max = a2->len - a2->radix;
+    min = b2->len - b2->radix;
+
+    max_num = a2->num + a2->radix;
+    min_num = b2->num + b2->radix;
+  }
+  else {
+
+    max = b2->len - b2->radix;
+    min = a2->len - a2->radix;
+
+    max_num = b2->num + b2->radix;
+    min_num = a2->num + a2->radix;
+  }
+
+  for (i = 0; i < min; ++i) {
+
+    char c;
+
+    c = max_num[i] - min_num[i];
+
+    if (c) return a_max ? c : -c;
+  }
+
+  for (; i < max; ++i) {
+    if (max_num[i]) return a_max ? 1 : -1;
+  }
+
+  return 0;
+}
+
+static BcStatus bc_num_construct(BcNum* num, size_t request) {
+
+  if (!num || !request) return BC_STATUS_INVALID_PARAM;
+
+  memset(num, 0, sizeof(BcNum));
+
+  num->num = malloc(request);
+
+  if (!num->num) {
+    return BC_STATUS_MALLOC_FAIL;
+  }
+
+  num->unused = request;
+
+  return BC_STATUS_SUCCESS;
+}
+
+static BcStatus bc_num_expand(BcNum* num, size_t request) {
+
+  if (!num || !request) return BC_STATUS_INVALID_PARAM;
+
+  if (request > num->len + num->unused) {
+
+    size_t extra;
+    char* temp;
+
+    extra = request - (num->len + num->unused);
+
+    temp = realloc(num->num, request);
+
+    if (!temp) {
+      return BC_STATUS_MALLOC_FAIL;
+    }
+
+    num->num = temp;
+
+    num->unused += extra;
+  }
+
+  return BC_STATUS_SUCCESS;
+}
+
+static void bc_num_destruct(BcNum* num) {
+
+  if (!num) return;
+
+  if (num->num) free(num->num);
+
+  memset(num, 0, sizeof(BcNum));
+}
+
+static BcStatus bc_num_unary(BcNum* a, BcNum* b, size_t scale,
+                               BcUnaryFunc op, size_t req)
+{
+  BcStatus status;
+  BcNum a2;
+  BcNum* ptr_a;
+
+  if (!a || !b || !op) return BC_STATUS_INVALID_PARAM;
+
+  if (b == a) {
+
+    memcpy(&a2, b, sizeof(BcNum));
+    ptr_a = &a2;
+
+    status = bc_num_construct(b, req);
+  }
+  else {
+    ptr_a = a;
+    status = bc_num_expand(b, req);
+  }
+
+  if (status) return status;
+
+  status = op(ptr_a, b, scale);
+
+  if (b == a) {
+    bc_num_destruct(&a2);
+  }
+
+  return status;
+}
+
+static BcStatus bc_num_binary(BcNum* a, BcNum* b, BcNum* c,
+                               size_t scale, BcBinaryFunc op, size_t req)
+{
+  BcStatus status;
+  BcNum a2;
+  BcNum b2;
+  BcNum* ptr_a;
+  BcNum* ptr_b;
+  bool init;
+
+  if (!a || !b || !c || !op) return BC_STATUS_INVALID_PARAM;
+
+  init = false;
+
+  if (c == a) {
+    memcpy(&a2, c, sizeof(BcNum));
+    ptr_a = &a2;
+    init = true;
+  }
+  else {
+    ptr_a = a;
+  }
+
+  if (c == b) {
+
+    if (c == a) {
+      ptr_b = ptr_a;
+    }
+    else {
+      memcpy(&b2, c, sizeof(BcNum));
+      ptr_b = &b2;
+      init = true;
+    }
+  }
+  else {
+    ptr_b = b;
+  }
+
+  if (init) {
+    status = bc_num_construct(c, req);
+  }
+  else {
+    status = bc_num_expand(c, req);
+  }
+
+  if (status) return status;
+
+  status = op(ptr_a, ptr_b, c, scale);
+
+  if (c == a) {
+    bc_num_destruct(&a2);
+  }
+  else if (c == b) {
+    bc_num_destruct(&b2);
+  }
+
+  return status;
+}
+
+static BcStatus bc_num_alg_a(BcNum* a, BcNum* b, BcNum* c, size_t scale) {
+
+}
+
+static BcStatus bc_num_alg_s(BcNum* a, BcNum* b, BcNum* c, size_t scale) {
+
+}
+
+static BcStatus bc_num_alg_m(BcNum* a, BcNum* b, BcNum* c, size_t scale) {
+
+}
+
+static BcStatus bc_num_alg_d(BcNum* a, BcNum* b, BcNum* c, size_t scale) {
+
+}
+
+static BcStatus bc_num_alg_mod(BcNum* a, BcNum* b, BcNum* c, size_t scale) {
+
+}
+
+static BcStatus bc_num_alg_p(BcNum* a, BcNum* b, BcNum* c, size_t scale) {
+
+}
+
+static BcStatus bc_num_sqrt_newton(BcNum* a, BcNum* b, size_t scale) {
+
+}
+
+static bool bc_num_strValid(const char* val, size_t base) {
+
+  size_t len;
+  size_t i;
+  char c;
+  char b;
+  bool radix;
+
+  radix = false;
+
+  len = strlen(val);
+
+  if (!len) return true;
+
+  c = val[0];
+
+  i = c == '-' || c == '+' ? 1 : 0;
+
+  if (base <= 10) {
+
+    b = base + '0';
+
+    for (; i < len; ++i) {
+
+      c = val[i];
+
+      if (c == '.') {
+
+        if (radix) return false;
+
+        radix = true;
+
+        continue;
+      }
+
+      if (c < '0' || c >= b) return false;
+    }
+  }
+  else {
+
+    b = base - 9 + 'A';
+
+    for (; i < len; ++i) {
+
+      c = val[i];
+
+      if (c == '.') {
+
+        if (radix) return false;
+
+        radix = true;
+
+        continue;
+      }
+
+      if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= b))) return false;
+    }
+  }
+
+  return true;
+}
+
+static BcStatus bc_num_parseDecimal(BcNum* n, const char* val,
+                                     size_t scale) {
+
+  BcStatus status;
+  size_t len;
+  char c;
+  size_t i;
+  const char* ptr;
+  size_t radix;
+  size_t inv_pow;
+  char* num;
+
+  len = strlen(val);
+
+  n->len = 0;
+  n->neg = false;
+  n->radix = 0;
+
+  if (len) {
+
+    status = bc_num_expand(n, len);
+
+    if (status) return status;
+  }
+  else {
+
+    n->num = malloc(BC_NUM_DEF_SIZE);
+
+    if (!n->num) return BC_STATUS_MALLOC_FAIL;
+
+    memset(n->num, 0, sizeof(char) * BC_NUM_DEF_SIZE);
+
+    return BC_STATUS_SUCCESS;
+  }
+
+  ptr = strchr(val, '.');
+
+  if (ptr) radix = ptr - val;
+  else radix = len;
+
+  c = val[0];
+
+  n->neg = c == '-';
+
+  i = c == '-' || c == '+' ? 1 : 0;
+
+  while (val[i] == '0') ++i;
+
+  ptr = val + i;
+  radix -= i;
+  len -= i;
+
+  for (i = 0; i < radix; ++i) {
+    n->num[i] = BC_NUM_FROM_CHAR(ptr[i]);
+    n->len += 1;
+    n->unused -= 1;
+  }
+
+  ptr += radix + 1;
+
+  n->radix = radix;
+
+  if (i >= len) return BC_STATUS_SUCCESS;
+
+  inv_pow = 0;
+
+  while (inv_pow < scale && ptr[inv_pow] == '0') ++inv_pow;
+
+  if (inv_pow >= scale || ptr[inv_pow] == '\0') {
+
+    if (!n->len) n->neg = false;
+
+    n->radix = n->len;
+
+    return BC_STATUS_SUCCESS;
+  }
+
+  num = n->num + n->len;
+
+  for (i = 0; i < inv_pow; ++i) {
+    num[i] = 0;
+    ++n->len;
+    --n->unused;
+  }
+
+  c = ptr[i];
+
+  while (i < scale && c != '\0') {
+
+    num[i] = BC_NUM_FROM_CHAR(c);
+
+    ++n->len;
+    --n->unused;
+
+    ++i;
+    c = ptr[i];
+  }
+
+  return BC_STATUS_SUCCESS;
+}
+
+static BcStatus bc_num_parseLowBase(BcNum* n, const char* val,
+                                     size_t base, size_t scale)
+{
+  const char* ptr;
+  char* nptr;
+  size_t len;
+  size_t radix;
+  size_t digits;
+  char c;
+  char carry;
+  size_t pow;
+
+  len = strlen(val);
+
+  ptr = strchr(val, '.');
+
+  if (ptr) {
+    --ptr;
+  }
+  else {
+    ptr = val + len - 1;
+  }
+
+  radix = ptr - val;
+
+  nptr = n->num + radix;
+  ++radix;
+
+  c = 0;
+  carry = 0;
+  digits = 0;
+  pow = 1;
+
+  while (ptr >= val) {
+
+    c += BC_NUM_FROM_CHAR(*ptr) * pow;
+    --ptr;
+    pow *= base;
+
+    if (pow > 10) {
+
+      --nptr;
+
+      while (c >= 10) {
+        *nptr += 1;
+        c -= 10;
+      }
+
+      *(nptr + 1) += c;
+      ++digits;
+
+      carry = 1;
+      c = 0;
+      pow = 1;
+    }
+  }
+
+  if (c) {
+    *nptr += c;
+    --nptr;
+    ++digits;
+  }
+
+  if (nptr >= n->num) {
+    memmove(n->num, nptr + 1, digits * sizeof(char));
+  }
+
+  // TODO: After radix.
+
+  return BC_STATUS_SUCCESS;
+}
+static BcStatus bc_num_parseHighBase(BcNum* n, const char* val,
+                                      size_t base, size_t scale)
+{
+
+}
+
+static BcStatus bc_num_printDecimal(BcNum* n, FILE* f) {
+
+  size_t i;
+
+  if (n->len) {
+
+    if (n->neg) fputc('-', f);
+
+    for (i = 0; i < n->radix; ++i) fputc(BC_NUM_TO_CHAR(n->num[i]), f);
+
+    if (i < n->len) {
+
+      fputc('.', f);
+
+      for (; i < n->len; ++i) fputc(BC_NUM_TO_CHAR(n->num[i]), f);
+    }
+  }
+  else {
+    fputc('0', f);
+  }
+
+  fputc('\n', f);
+
+  return BC_STATUS_SUCCESS;
+}
+
+static BcStatus bc_num_printLowBase(BcNum* n, size_t base, FILE* f) {
+
+  size_t size;
+  char* buf;
+  size_t i;
+
+  size = BC_MAX(n->radix, n->len - n->radix) * ((10 * 2) / base);
+
+  buf = malloc(size);
+
+  if (!buf) return BC_STATUS_MALLOC_FAIL;
+
+  i = 0;
+
+  fputc('\n', f);
+
+  free(buf);
+
+  return BC_STATUS_SUCCESS;
+}
+
+static BcStatus bc_num_printHighBase(BcNum* n, size_t base, FILE* f) {
+
+}
+
+static BcStatus bc_num_printHighestBase(BcNum* n, size_t base, FILE* f) {
+
+}
diff --git a/src/bc/parse.c b/src/bc/parse.c
index efa9c73..30034b9 100644
--- a/src/bc/parse.c
+++ b/src/bc/parse.c
@@ -385,7 +385,7 @@
       func = bc_vec_item(&parse->program->funcs, parse->func);
 
       if (!func) {
-        return BC_STATUS_VM_UNDEFINED_FUNC;
+        return BC_STATUS_EXEC_UNDEFINED_FUNC;
       }
 
       status = bc_parse_stmt(parse, &func->code);
@@ -612,7 +612,7 @@
   func = bc_vec_item(&parse->program->funcs, parse->func);
 
   if (!func) {
-    return BC_STATUS_VM_UNDEFINED_FUNC;
+    return BC_STATUS_EXEC_UNDEFINED_FUNC;
   }
 
   type = parse->token.type;
@@ -1602,7 +1602,7 @@
   idx = bc_veco_index(&parse->program->func_map, &entry);
 
   if (idx == BC_INVALID_IDX) {
-    return BC_STATUS_VM_UNDEFINED_FUNC;
+    return BC_STATUS_EXEC_UNDEFINED_FUNC;
   }
 
   status = bc_parse_pushIndex(code, idx);
@@ -2205,7 +2205,7 @@
   func = bc_vec_item(&parse->program->funcs, parse->func);
 
   if (!func) {
-    return BC_STATUS_VM_UNDEFINED_FUNC;
+    return BC_STATUS_EXEC_UNDEFINED_FUNC;
   }
 
   ip.idx = func->labels.len;
@@ -2365,7 +2365,7 @@
   func = bc_vec_item(&parse->program->funcs, parse->func);
 
   if (!func) {
-    return BC_STATUS_VM_UNDEFINED_FUNC;
+    return BC_STATUS_EXEC_UNDEFINED_FUNC;
   }
 
   ip.idx = func->labels.len;
@@ -2479,7 +2479,7 @@
   func = bc_vec_item(&parse->program->funcs, parse->func);
 
   if (!func) {
-    return BC_STATUS_VM_UNDEFINED_FUNC;
+    return BC_STATUS_EXEC_UNDEFINED_FUNC;
   }
 
   cond_idx = func->labels.len;
diff --git a/src/bc/program.c b/src/bc/program.c
index 504aba2..7eac2bf 100644
--- a/src/bc/program.c
+++ b/src/bc/program.c
@@ -417,7 +417,7 @@
     func = bc_vec_item(&p->funcs, *idx);
 
     if (!func) {
-      return BC_STATUS_VM_UNDEFINED_FUNC;
+      return BC_STATUS_EXEC_UNDEFINED_FUNC;
     }
 
     // We need to reset these so the function can be repopulated.
@@ -553,14 +553,14 @@
         idx = bc_program_index(code, &ip->idx);
 
         if (idx >= p->strings.len) {
-          return BC_STATUS_VM_INVALID_STRING;
+          return BC_STATUS_EXEC_INVALID_STRING;
         }
 
         string = bc_vec_item(&p->strings, idx);
 
         pchars = fprintf(stdout, "%s", string);
         status = pchars > 0 ? BC_STATUS_SUCCESS :
-                              BC_STATUS_VM_PRINT_ERR;
+                              BC_STATUS_EXEC_PRINT_ERR;
 
         break;
       }
@@ -572,7 +572,7 @@
         idx = bc_program_index(code, &ip->idx);
 
         if (idx >= p->strings.len) {
-          return BC_STATUS_VM_INVALID_STRING;
+          return BC_STATUS_EXEC_INVALID_STRING;
         }
 
         string = bc_vec_item(&p->strings, idx);
@@ -584,7 +584,7 @@
 
       case BC_INST_HALT:
       {
-        status = BC_STATUS_VM_HALT;
+        status = BC_STATUS_EXEC_HALT;
         break;
       }
 
@@ -599,13 +599,13 @@
         str = *((char**) bc_vec_item(&p->constants, idx));
 
         if (!str) {
-          return BC_STATUS_VM_INVALID_EXPR;
+          return BC_STATUS_EXEC_INVALID_EXPR;
         }
 
         num.num = arb_str2fxdpnt(str);
 
         if (!num.num) {
-          return BC_STATUS_VM_INVALID_EXPR;
+          return BC_STATUS_EXEC_INVALID_EXPR;
         }
 
         num.type = BC_NUM_CONSTANT;
@@ -629,7 +629,7 @@
 
         ptr = bc_vec_top(&p->expr_stack);
 
-        if (!ptr) return BC_STATUS_VM_INVALID_EXPR;
+        if (!ptr) return BC_STATUS_EXEC_INVALID_EXPR;
 
         num2 = *ptr;
 
@@ -639,7 +639,7 @@
 
         ptr = bc_vec_top(&p->expr_stack);
 
-        if (!ptr) return BC_STATUS_VM_INVALID_EXPR;
+        if (!ptr) return BC_STATUS_EXEC_INVALID_EXPR;
 
         num1 = *ptr;
 
@@ -669,7 +669,7 @@
 
       default:
       {
-        return BC_STATUS_VM_INVALID_STMT;
+        return BC_STATUS_EXEC_INVALID_STMT;
       }
     }
   }
@@ -796,7 +796,7 @@
       ++i;
 
       if (i >= len) {
-        return BC_STATUS_VM_INVALID_STRING;
+        return BC_STATUS_EXEC_INVALID_STRING;
       }
 
       c2 = str[i];
@@ -861,7 +861,7 @@
     }
 
     if (err == EOF) {
-      return BC_STATUS_VM_PRINT_ERR;
+      return BC_STATUS_EXEC_PRINT_ERR;
     }
   }
 
@@ -893,7 +893,7 @@
     expr = bc_vec_item(exprs, idx);
 
     if (!expr) {
-      return BC_STATUS_VM_INVALID_EXPR;
+      return BC_STATUS_EXEC_INVALID_EXPR;
     }
 
     etype = expr->type;
@@ -904,21 +904,21 @@
       case BC_EXPR_DEC_PRE:
       {
         if (idx - 1 >= exprs->len) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
         expr = bc_vec_item(exprs, idx - 1);
 
         if (!expr) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
         if (expr->type != BC_EXPR_VAR && expr->type != BC_EXPR_ARRAY_ELEM &&
             !(expr->type < BC_EXPR_SCALE || expr->type > BC_EXPR_LAST))
         {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
@@ -939,14 +939,14 @@
         char sign;
 
         if (p->temps.len <= temp_len) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
         temp_ptr = bc_vec_top(&p->temps);
 
         if (!temp_ptr) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
@@ -970,14 +970,14 @@
         BcMathOpFunc op;
 
         if (p->temps.len < temp_len + 2) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
         b = bc_vec_top(&p->temps);
 
         if (!b) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
@@ -990,7 +990,7 @@
         a = bc_vec_top(&p->temps);
 
         if (!a) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
@@ -1135,7 +1135,7 @@
           arb_newton_sqrt(temp_num, temp.num, 10, p->scale);
         }
         else {
-          status = BC_STATUS_VM_NEG_SQRT;
+          status = BC_STATUS_MATH_NEG_SQRT;
         }
 
         break;
@@ -1148,7 +1148,7 @@
         }
 
         if (p->temps.len != temp_len + 1) {
-          status = BC_STATUS_VM_INVALID_EXPR;
+          status = BC_STATUS_EXEC_INVALID_EXPR;
           break;
         }
 
@@ -1165,7 +1165,7 @@
 
       default:
       {
-        status = BC_STATUS_VM_INVALID_EXPR;
+        status = BC_STATUS_EXEC_INVALID_EXPR;
         break;
       }
     }
@@ -1178,7 +1178,7 @@
   }
 
   if (p->temps.len != temp_len) {
-    return BC_STATUS_VM_INVALID_EXPR;
+    return BC_STATUS_EXEC_INVALID_EXPR;
   }
 
   return status;
@@ -1227,7 +1227,7 @@
 
     default:
     {
-      return BC_STATUS_VM_INVALID_EXPR;
+      return BC_STATUS_EXEC_INVALID_EXPR;
     }
   }
 
@@ -1235,7 +1235,7 @@
 
     case BC_EXPR_ASSIGN_DIVIDE:
       if (!arb_compare(amt, p->zero, 10)) {
-        return BC_STATUS_VM_DIVIDE_BY_ZERO;
+        return BC_STATUS_MATH_DIVIDE_BY_ZERO;
       }
       // Fallthrough.
     case BC_EXPR_ASSIGN_POWER:
@@ -1257,7 +1257,7 @@
 
     default:
     {
-      status = BC_STATUS_VM_INVALID_EXPR;
+      status = BC_STATUS_EXEC_INVALID_EXPR;
       break;
     }
   }
@@ -1316,7 +1316,7 @@
   status = bc_parse_expr(&parse, &code, false, false);
 
   if (status != BC_STATUS_LEX_EOF && status != BC_STATUS_PARSE_EOF) {
-    status = status ? status : BC_STATUS_VM_INVALID_READ_EXPR;
+    status = status ? status : BC_STATUS_EXEC_INVALID_READ_EXPR;
     goto exec_err;
   }
 
diff --git a/src/bc/vm.c b/src/bc/vm.c
index 5f60aef..33f45e4 100644
--- a/src/bc/vm.c
+++ b/src/bc/vm.c
@@ -107,7 +107,7 @@
   act.sa_handler = bc_vm_sigint;
 
   if (sigaction(SIGINT, &act, NULL) < 0) {
-    return BC_STATUS_VM_SIGACTION_FAIL;
+    return BC_STATUS_EXEC_SIGACTION_FAIL;
   }
 
   status = BC_STATUS_SUCCESS;
@@ -132,7 +132,7 @@
 
   if (status) {
     status = status == BC_STATUS_PARSE_QUIT ||
-             status == BC_STATUS_VM_HALT ?
+             status == BC_STATUS_EXEC_HALT ?
                  BC_STATUS_SUCCESS : status;
     goto exec_err;
   }
@@ -140,8 +140,8 @@
   status = bc_vm_execStdin(vm);
 
   status = status == BC_STATUS_PARSE_QUIT ||
-         status == BC_STATUS_VM_HALT ?
-              BC_STATUS_SUCCESS : status;
+           status == BC_STATUS_EXEC_HALT ?
+               BC_STATUS_SUCCESS : status;
 
 exec_err:
 
@@ -168,7 +168,7 @@
   f = fopen(file, "r");
 
   if (!f) {
-    return BC_STATUS_VM_FILE_ERR;
+    return BC_STATUS_EXEC_FILE_ERR;
   }
 
   fseek(f, 0, SEEK_END);
@@ -289,7 +289,7 @@
         }
       }
       else {
-        status = BC_STATUS_VM_FILE_NOT_EXECUTABLE;
+        status = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE;
       }
 
     } while (!status);
@@ -320,7 +320,7 @@
         }
       }
       else {
-        status = BC_STATUS_VM_FILE_NOT_EXECUTABLE;
+        status = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE;
       }
 
     } while (!status);
@@ -568,7 +568,7 @@
   }
 
   status = !status || status == BC_STATUS_PARSE_QUIT ||
-           status == BC_STATUS_VM_HALT ||
+           status == BC_STATUS_EXEC_HALT ||
            status == BC_STATUS_LEX_EOF ||
            status == BC_STATUS_PARSE_EOF ?
                BC_STATUS_SUCCESS : status;
@@ -601,11 +601,11 @@
 
   func = bc_vec_item(&vm->program.funcs, 0);
 
-  if (!func) return BC_STATUS_VM_UNDEFINED_FUNC;
+  if (!func) return BC_STATUS_EXEC_UNDEFINED_FUNC;
 
   ip = bc_vec_top(&vm->program.stack);
 
-  if (!ip) return BC_STATUS_VM_INVALID_STMT;
+  if (!ip) return BC_STATUS_EXEC_INVALID_STMT;
 
   ip->idx = func->code.len;