forked from Noitidart/ostypes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathctypes_math.jsm
146 lines (115 loc) · 3.17 KB
/
ctypes_math.jsm
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* Thanks to @arai-a - https://github.com/arai-a */
var EXPORTED_SYMBOLS = ['ctypes_math'];
var ctypes_math = (function() {
const UInt64 = ctypes.UInt64;
const Int64 = ctypes.Int64;
function ensureUInt64(aArr) {
// makes elements in aArr a UInt64 if it can be made, else throws
for (var i=0; i<aArr.length; i++) {
var cCon = aArr[i].constructor.name;
if (cCon != 'UInt64') {
if (['String', 'Number'].indexOf(cCon) > -1) {
aArr[i] = UInt64(aArr[i]);
} else {
throw new Error('Invalid type at position ' + i + ' it must be a numeric string, a number, or a UInt64. Type is "' + cCon + '"');
}
}
}
}
function UInt64_add(...uint64) {
ensureUInt64(uint64);
var hi = UInt64.hi(uint64[0]);
var lo = UInt64.lo(uint64[0]);;
for (var i=1; i<uint64.length; i++) {
hi += UInt64.hi(uint64[i]);
lo += UInt64.lo(uint64[i]);
if (lo > 0x100000000) {
hi += 1;
}
hi = hi >>> 0;
lo = lo >>> 0;
}
return UInt64.join(hi, lo);
}
function UInt64_sub(a, b) {
var valArr = [a, b];
ensureUInt64(valArr);
a = valArr[0];
b = valArr[1];
var hi = UInt64.hi(a) - UInt64.hi(b);
var lo = UInt64.lo(a) - UInt64.lo(b);
if (lo < 0) {
hi -= 1;
}
return UInt64.join(hi >>> 0, lo >>> 0);
}
function UInt64_mul(a, b) {
var valArr = [a, b];
ensureUInt64(valArr);
a = valArr[0];
b = valArr[1];
var ah = UInt64.hi(a);
var al = UInt64.lo(a);
var bh = UInt64.hi(b);
var bl = UInt64.lo(b);
var a5 = ah >>> 20;
var a4 = (ah >>> 7) & 0x1fff;
var a3 = ((ah << 6) | (al >>> 26)) & 0x1fff;
var a2 = (al >>> 13) & 0x1fff;
var a1 = al & 0x1fff;
var b5 = bh >>> 20;
var b4 = (bh >>> 7) & 0x1fff;
var b3 = ((bh << 6) | (bl >>> 26)) & 0x1fff;
var b2 = (bl >>> 13) & 0x1fff;
var b1 = bl & 0x1fff;
var c1 = a1 * b1;
var c2 = a1 * b2 + a2 * b1;
var c3 = a1 * b3 + a2 * b2 + a3 * b1;
var c4 = a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1;
var c5 = a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1;
c2 += c1 >>> 13;
c1 &= 0x1fff;
c3 += c2 >>> 13;
c2 &= 0x1fff;
c4 += c3 >>> 13;
c3 &= 0x1fff;
c5 += c4 >>> 13;
c4 &= 0x1fff;
var ch = ((c5 << 20) | (c4 << 7) | (c3 >>> 6)) >>> 0;
var cl = ((c3 << 26) | (c2 << 13) | c1) >>> 0;
return UInt64.join(ch, cl);
}
function UInt64_or(...uint64) {
// bitwise OR
// if there are logical OR and bitwise OR, bitwise OR may be named `bor` or `bitor`, but I don't think there could be logical OR, so I think just `or` is the right name
ensureUInt64(uint64);
var hi = 0;
var lo = 0;
for (var i=0; i<uint64.length; i++) {
hi |= UInt64.hi(uint64[i]);
lo |= UInt64.lo(uint64[i]);
}
return UInt64.join(hi >>> 0, lo >>> 0);
}
function UInt64_and(...uint64) {
// bitwise AND could be applied to more than 2 operands, not sure if it's useful tho
ensureUInt64(uint64);
var hi = UInt64.hi(uint64[0]);
var lo = UInt64.lo(uint64[0]);
for (var i=1; i<uint64.length; i++) {
hi &= UInt64.hi(uint64[i]);
lo &= UInt64.lo(uint64[i]);
}
return UInt64.join(hi >>> 0, lo >>> 0);
}
return {
UInt64: {
add: UInt64_add,
sub: UInt64_sub,
mul: UInt64_mul,
or: UInt64_or,
and: UInt64_and
},
Int64: {}
};
})();