summaryrefslogtreecommitdiff
path: root/projects/12/Math.jack
diff options
context:
space:
mode:
Diffstat (limited to 'projects/12/Math.jack')
-rw-r--r--projects/12/Math.jack98
1 files changed, 98 insertions, 0 deletions
diff --git a/projects/12/Math.jack b/projects/12/Math.jack
index a57f023..61e09fc 100644
--- a/projects/12/Math.jack
+++ b/projects/12/Math.jack
@@ -8,13 +8,33 @@
* Note: Jack compilers implement multiplication and division using OS method calls.
*/
class Math {
+ static Array twoToThe;
/** Initializes the library. */
function void init() {
+ var int i, x;
+ let x = 1;
+ let i = 0;
+ let twoToThe = Array.new(16);
+ while (i < 16){
+ let twoToThe[i] = x;
+ let x = x + x;
+ let i = i + 1;
+ }
+ return;
+ }
+
+ function boolean bit(int x, int i) {
+ return ~(x & twoToThe[i] = 0);
}
/** Returns the absolute value of x. */
function int abs(int x) {
+ if (x > 0){
+ return x;
+ } else {
+ return -x;
+ }
}
/** Returns the product of x and y.
@@ -23,6 +43,18 @@ class Math {
* the Jack expressions x*y and multiply(x,y) return the same value.
*/
function int multiply(int x, int y) {
+ var int z, res, shiftedX, i;
+ let shiftedX = x;
+ let i = 0;
+ let res = 0;
+ while ((twoToThe[i] > x) & (i < 16)) {
+ if (Math.bit(y, i)){
+ let res = res + shiftedX;
+ }
+ let shiftedX = shiftedX + shiftedX;
+ let i = i + 1;
+ }
+ return res;
}
/** Returns the integer part of x/y.
@@ -31,17 +63,83 @@ class Math {
* the Jack expressions x/y and divide(x,y) return the same value.
*/
function int divide(int x, int y) {
+ var int ax, ay;
+ if (x > 0) {
+ if (y > 0) {
+ return Math.divide1(x, y);
+ } else {
+ return -Math.divide1(x, -y);
+ }
+ } else {
+ if (y > 0) {
+ return -Math.divide1(-x, y);
+ } else {
+ return Math.divide1(-x, -y);
+ }
+ }
+ }
+
+ function int divide1(int x, int y) {
+ var int q;
+ if (y = 0) {
+ do Output.printString("Error: division by zero.");
+ do Sys.error(0);
+ }
+ if ((y > x) | (y < 0)) {
+ return 0;
+ }
+ let q = Math.divide1(x, y * 2);
+ if (x - (2 * q * y) < y) {
+ return 2 * q;
+ } else {
+ return 2 * q + 1;
+ }
+ }
+
+ function int length(int x){
+ var int n;
+ let n = 14;
+ while (twoToThe[n] > x){
+ let n = n - 1;
+ }
+ return n;
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
+ var int y, k, z, w;
+ if (x < 0) {
+ do Output.printString("Error: square rooting a negative number.");
+ do Sys.error(0);
+ }
+ let k = Math.length(x) / 2;
+ let y = 0;
+ while (~(k < 0)) {
+ let z = y + twoToThe[k];
+ let w = z * z;
+ if ((w < x) & (w > 0)) {
+ let y = z;
+ }
+ let k = k - 1;
+ }
+ return y;
}
/** Returns the greater number. */
function int max(int a, int b) {
+ if (a > b) {
+ return a;
+ } else {
+ return b;
+ }
}
/** Returns the smaller number. */
function int min(int a, int b) {
+ if (a < b) {
+ return a;
+ } else {
+ return b;
+ }
}
}