@@ -229,18 +229,43 @@ export function __floatuntfdi(value: f64): u64 {
229
229
}
230
230
}
231
231
232
+
233
+ /**
234
+ * Count leading zeros in a 128-bit integer [hi:lo], returning i32 in [0..128].
235
+ * If both hi and lo are 0, returns 128.
236
+ *
237
+ * hi is signed in i128, but we interpret it as unsigned here.
238
+ */
232
239
// @ts -ignore: decorator
233
240
@global @inline
234
- export function __clz128 ( lo : u64 , hi : u64 ) : i32 {
235
- var mask : u64 = < i64 > ( hi ^ ( hi - 1 ) ) >> 63 ;
236
- return < i32 > clz ( ( hi & ~ mask ) | ( lo & mask ) ) + ( < i32 > mask & 64 ) ;
241
+ export function __clz128 ( lo : u64 , hi : i64 ) : i32 {
242
+ let h : u64 = < u64 > hi ; // reinterpret hi as unsigned
243
+ if ( h == 0 ) {
244
+ // If hi is 0, the leading zeros are "64 plus however many are in lo"
245
+ return 64 + < i32 > i64 . clz ( lo ) ;
246
+ } else {
247
+ // The top 64 bits are set => just measure their leading zeros
248
+ return < i32 > i64 . clz ( h ) ;
249
+ }
237
250
}
238
251
252
+ /**
253
+ * Count trailing zeros in a 128-bit integer [hi:lo], returning i32 in [0..128].
254
+ * If both hi and lo are 0, returns 128.
255
+ *
256
+ * For i128 we typically treat hi as signed, but ctz is purely bitwise, so we
257
+ * can pass it as u64 as well.
258
+ */
239
259
// @ts -ignore: decorator
240
260
@global @inline
241
261
export function __ctz128 ( lo : u64 , hi : u64 ) : i32 {
242
- var mask : u64 = < i64 > ( lo ^ ( lo - 1 ) ) >> 63 ;
243
- return < i32 > ctz ( ( hi & mask ) | ( lo & ~ mask ) ) + ( < i32 > mask & 64 ) ;
262
+ if ( lo == 0 ) {
263
+ // Otherwise, ctz is 64 plus ctz(hi)
264
+ return 64 + < i32 > i64 . ctz ( hi ) ;
265
+ } else {
266
+ // If the lower 64 bits are non-zero, measure ctz(lo)
267
+ return < i32 > i64 . ctz ( lo ) ;
268
+ }
244
269
}
245
270
246
271
// @ts -ignore: decorator
0 commit comments