1 | 1 | 'use strict'; |
2 | | |
3 | | // ---------------------------------------------------------------------- |
4 | | // ----- main exported object |
5 | | // includes: |
6 | | // 1. unit conversions |
7 | | // 2. arithmetic functions |
8 | | // 3. logical operators |
9 | | // 4. helper methods |
10 | | // ---------------------------------------------------------------------- |
11 | | |
12 | 1 | var binary = module.exports = {}; |
13 | | |
14 | | // ----- unit conversion |
15 | | // --------------------------------------- |
16 | 1 | binary.toInt = function(str) { |
17 | 4 | return parseInt(str, 2); |
18 | | }; |
19 | | |
20 | 1 | binary.toHex = function(str) { |
21 | 2 | return parseInt(str, 2).toString(16); |
22 | | }; |
23 | | |
24 | | |
25 | | // @param n {Number | String | Buffer} input |
26 | | // @return {String} 8bit binary conversion |
27 | | // todo: get more test cases & verify |
28 | 1 | binary.toBinary = function(n) { |
29 | | |
30 | 5 | var type = Object.prototype.toString.call(n) |
31 | | |
32 | 5 | switch (type) { |
33 | | |
34 | | case '[object Number]': |
35 | 2 | return n.toString(2); |
36 | | |
37 | | default: // strings and buffers |
38 | | |
39 | 3 | var output = ''; |
40 | | |
41 | 3 | for (var i = 0; i < n.length; i++) { |
42 | | |
43 | 8 | var cur = typeof n[i] === 'number' ? |
44 | | binary.pad(n[i].toString(2), 8) // buffers |
45 | | : binary.pad(n.charCodeAt(i).toString(2), 8); // strings |
46 | | |
47 | 8 | output += cur; |
48 | | |
49 | | } |
50 | | |
51 | 3 | return output; |
52 | | |
53 | | } |
54 | | |
55 | | }; |
56 | | |
57 | | |
58 | | // ----- arithmetic |
59 | | // --------------------------------------- |
60 | | |
61 | | // @param a {String} binary number |
62 | | // @param b {String} binary number |
63 | | // todo: @param n {Number} optional bitLength restriction |
64 | 1 | binary.add = function(a, b) { |
65 | 6 | a = parseInt(a, 2); |
66 | 6 | b = parseInt(b, 2); |
67 | 6 | return (a + b).toString(2); |
68 | | }; |
69 | | |
70 | 1 | binary.addBits = function(a, b) { |
71 | 4 | a = a === '1' ? 1 : 0; |
72 | 4 | b = b === '1' ? 1 : 0; |
73 | | |
74 | 4 | var sum = a ^ b; |
75 | 4 | var carry = a & b; |
76 | | |
77 | 4 | return { |
78 | | sum: sum.toString(), |
79 | | carry: carry.toString() |
80 | | }; |
81 | | }; |
82 | | |
83 | | // @param a {String} binary number |
84 | | // @param b {String} binary number |
85 | | // todo: @param n {Number} optional bitLength restriction |
86 | 1 | binary.multiply = function(a, b) { |
87 | 6 | a = parseInt(a, 2); |
88 | 6 | b = parseInt(b, 2); |
89 | 6 | return (a * b).toString(2); |
90 | | }; |
91 | | |
92 | | // @param a {String} binary number |
93 | | // @param b {String} binary number |
94 | | // todo: @param n {Number} optional bitLength restriction |
95 | 1 | binary.divide = function(a, b) { |
96 | 6 | a = parseInt(a, 2); |
97 | 6 | b = parseInt(b, 2); |
98 | 6 | return (a / b).toString(2); |
99 | | }; |
100 | | |
101 | | |
102 | | // ----- logic |
103 | | // --------------------------------------- |
104 | 1 | binary.not = function(str) { |
105 | 13 | var inverse = ''; |
106 | 13 | for (var i = 0; i < str.length; i++) { |
107 | 79 | inverse += str[i] === '1' ? '0' : '1'; |
108 | | } |
109 | 13 | return inverse; |
110 | | }; |
111 | | |
112 | 1 | binary.and = function(a, b) { |
113 | | |
114 | 7 | var eq = binary.equalize(a, b); |
115 | 7 | a = eq[0]; |
116 | 7 | b = eq[1]; |
117 | | |
118 | 7 | var result = ''; |
119 | | |
120 | 7 | for (var i = 0; i < a.length; i++) { |
121 | 28 | if (a[i] === b[i]) { |
122 | 6 | result += a[i]; |
123 | | } |
124 | | else { |
125 | 22 | result += '0'; |
126 | | } |
127 | | } |
128 | | |
129 | 7 | return result; |
130 | | |
131 | | }; |
132 | | |
133 | 1 | binary.or = function(a, b) { |
134 | | |
135 | 8 | var eq = binary.equalize(a, b); |
136 | 8 | a = eq[0]; |
137 | 8 | b = eq[1]; |
138 | | |
139 | 8 | var result = ''; |
140 | | |
141 | 8 | for (var i = 0; i < a.length; i++) { |
142 | 32 | if (a[i] === '1' || b[i] === '1') { |
143 | 30 | result += '1'; |
144 | | } |
145 | | else { |
146 | 2 | result += '0'; |
147 | | } |
148 | | } |
149 | | |
150 | 8 | return result; |
151 | | |
152 | | }; |
153 | | |
154 | 1 | binary.nand = function(a, b) { |
155 | 3 | var and = binary.and(a, b); |
156 | 3 | return binary.not(and); |
157 | | }; |
158 | | |
159 | 1 | binary.nor = function(a, b) { |
160 | 4 | var or = binary.or(a, b); |
161 | 4 | return binary.not(or); |
162 | | }; |
163 | | |
164 | 1 | binary.xor = function(a, b) { |
165 | | |
166 | 4 | var eq = binary.equalize(a, b); |
167 | 4 | a = eq[0]; |
168 | 4 | b = eq[1]; |
169 | | |
170 | 4 | var result = ''; |
171 | | |
172 | 4 | for (var i = 0; i < a.length; i++) { |
173 | 16 | if (a[i] !== b[i]) { |
174 | 13 | result += '1'; |
175 | | } |
176 | | else { |
177 | 3 | result += '0'; |
178 | | } |
179 | | } |
180 | | |
181 | 4 | return result; |
182 | | |
183 | | }; |
184 | | |
185 | 1 | binary.complement = function(str) { |
186 | 4 | var inverse = binary.not(str); |
187 | 4 | var complement = binary.add(inverse, 1); |
188 | 4 | return binary.pad(complement, str.length); |
189 | | }; |
190 | | |
191 | | |
192 | | // ----- etc |
193 | | // --------------------------------------- |
194 | | |
195 | | // @param str {String} binary string |
196 | | // @param n {Number} length of output |
197 | | // @return {String} left-padded binary string |
198 | 1 | binary.pad = function(str, n) { |
199 | 26 | while (str.length < n) { |
200 | 45 | str = '0' + str; |
201 | | } |
202 | 26 | return str; |
203 | | }; |
204 | | |
205 | | // @param str {String} binary string |
206 | | // @param n {Number} length of output |
207 | | // @param fn {Function} callback |
208 | | // @return {Function} callback(err, result) |
209 | 1 | binary.padSafe = function(str, n, fn) { |
210 | | |
211 | 2 | while (str.length < n) { |
212 | 4 | str = '0' + str; |
213 | | } |
214 | | |
215 | 2 | if (str.length > n) { |
216 | 1 | var err = new Error('input length exceeds expected length of output'); |
217 | 1 | return fn(err, str); |
218 | | } |
219 | | |
220 | 1 | return fn(null, str); |
221 | | |
222 | | }; |
223 | | |
224 | | // @param a {String} binary string |
225 | | // @param b {String} binary string |
226 | | // @return {Array} [(padded) a, (padded) b] |
227 | 1 | binary.equalize = function(a, b) { |
228 | | |
229 | 21 | var aLen = a.length; |
230 | 21 | var bLen = b.length; |
231 | | |
232 | 21 | if (aLen > bLen) { |
233 | 1 | b = binary.pad(b, aLen); |
234 | | } |
235 | | |
236 | 21 | if (bLen > aLen) { |
237 | 10 | a = binary.pad(a, bLen); |
238 | | } |
239 | | |
240 | 21 | return [a, b]; |
241 | | |
242 | | }; |
243 | | |
244 | | // @param str {String} binary string |
245 | | // @param length {Number} number of characters per chunk |
246 | | // @return {Array} |
247 | 1 | binary.split = function(str, length) { |
248 | 2 | var regex = new RegExp('.{1,' + length + '}', 'g'); // /.{1,8}/g |
249 | 2 | return str.match(regex); |
250 | | }; |