-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMath.jack
131 lines (121 loc) · 2.85 KB
/
Math.jack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// 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, twoToI;
let twoToThe = Array.new(16);
let i = 0;
let twoToI = 1;
while (i < 16) {
let twoToThe[i] = twoToI;
let twoToI = twoToI + twoToI; // Don't use multiplication
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 true if the j-th bit of the integer x is 1 else false. */
function boolean bit(int x, int j) {
return x & twoToThe[j];
}
/** 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, j;
let sum = 0;
let shiftedX = x;
let j = 0;
while (j < 16) {
if (Math.bit(y, j)) {
let sum = sum + shiftedX;
}
let shiftedX = shiftedX + shiftedX; // Don't use multiplication
let j = j + 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, sign;
if (x > 0) {
if (y > 0) {
let sign = 1;
} else {
let sign = -1;
}
} else {
if (y > 0) {
let sign = -1;
} else {
let sign = 1;
}
}
let x = Math.abs(x);
let y = Math.abs(y);
if (y > x) {
return 0;
}
let q = Math.divide(x, y * 2);
if ((x - (2 * q * y)) < y) {
return sign * 2 * q;
} else {
return sign * ((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;
if (x < 0) {
return -1;
}
while (~(j < 0)) {
if (~((y + twoToThe[j]) * (y + twoToThe[j]) > x)) {
if ((y + twoToThe[j]) * (y + twoToThe[j]) > 0) {
let y = y + twoToThe[j];
}
}
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 b;
} else {
return a;
}
}
}