Files
nand2tetris/projects/12/Math.jack
2021-04-21 17:01:42 +03:00

143 lines
3.7 KiB
Plaintext

// 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() {
let twoToThe = Array.new(16);
let twoToThe[0] = 1;
let twoToThe[1] = 2;
let twoToThe[2] = 4;
let twoToThe[3] = 8;
let twoToThe[4] = 16;
let twoToThe[5] = 32;
let twoToThe[6] = 64;
let twoToThe[7] = 128;
let twoToThe[8] = 256;
let twoToThe[9] = 512;
let twoToThe[10] = 1024;
let twoToThe[11] = 2048;
let twoToThe[12] = 4096;
let twoToThe[13] = 8192;
let twoToThe[14] = 16384;
let twoToThe[15] = 16384 + 16384;
return;
}
function boolean bit (int x, int i) {
if (x & twoToThe[i] = 0) {
return false;
} else {
return true;
}
}
/** 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(Math.bit(y, i)) {
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 q, tres;
if(x < 0 & y < 0) {
return Math.divide(Math.abs(x), Math.abs(y));
}
if(x < 0 | y < 0) {
return -Math.divide(Math.abs(x), Math.abs(y));
}
if(y > x) {
return 0;
}
if(y < 0) {
return 0;
}
let q = Math.divide(x, 2 * y);
if((x - (2 * q * y)) < y) {
return 2 * q;
} else {
return 2 * q + 1;
}
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
var int y, j;
let y = 0;
let j = 7;
while(j > -1) {
if (~((Math.pow((y + Math.pow(2, j)), 2) > x)) & (Math.pow((y + Math.pow(2, j)), 2) > 0)) {
let y = y + Math.pow(2, j);
}
let j = j - 1;
}
return y;
}
function int pow(int x, int p) {
var int r, i;
let i = 0;
let r = 1;
while (i < p) {
let r = r * x;
let i = i + 1;
}
return r;
}
/** 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 b;
} else {
return a;
}
}
}