// 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, 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. * 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 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. * 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 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; } } }