// This file is part of www.nand2tetris.org // and the book "The Elements of Computing Systems" // by Nisan and Schocken, MIT Press. // File name: projects/12/Math.jack /** * A library of commonly used mathematical functions. * 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; let twoToThe = Array.new(16); let twoToThe[0] = 1; let i = 1; while (i < 16) { let twoToThe[i] = twoToThe[i-1] + twoToThe[i-1]; let i = i + 1; } return; } /** 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. * When a Jack compiler detects the multiplication operator '*' in the * program's code, it handles it by invoking this method. In other words, * the Jack expressions x*y and multiply(x,y) return the same value. */ function int multiply(int x, int y) { var int sum, shiftedX, i; let sum = 0; let shiftedX = x; let i = 0; while (i < 16) { if (~((y & twoToThe[i]) = 0)) { let sum = sum + shiftedX; } let shiftedX = shiftedX + shiftedX; let i = i + 1; } return sum; } /** Returns the integer part of x/y. * When a Jack compiler detects the multiplication operator '/' in the * program's code, it handles it by invoking this method. In other words, * the Jack expressions x/y and divide(x,y) return the same value. */ function int divide(int x, int y) { var int neg_x, neg_y; var int q; var int result; let neg_x = x < 0; let neg_y = y < 0; let x = Math.abs(x); let y = Math.abs(y); if (y > x) { return 0; } let q = Math.divide(x, y + y); if ((x - ((q + q) * y)) < y) { let result = q + q; } else { let result = q + q + 1; } if (neg_x = neg_y) { return result; } else { return -result; } } /** Returns the integer part of the square root of x. */ function int sqrt(int x) { var int y, j; var int approx; var int approx_squared; let y = 0; let j = 7; // (16 / 2) - 1 while (~(j < 0)) { let approx = y + twoToThe[j]; let approx_squared = approx * approx; if (~(approx_squared > x) & (approx_squared > 0)) { let y = approx; } let j = j - 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; } } }