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
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2026 OCamlPro *)
(* Written by the Owi programmers *)
type t = int
let of_i8x2 a b = a land 0xFF lor ((b land 0xFF) lsl 8)
let wrap x = x land 0xFFFF
let wrap_i32 x = Int32.logand x 0xFFFFl |> Int32.to_int
let to_int_s x =
let x = x land 0xFFFF in
if x land 0x8000 <> 0 then x - 0x10000 else x
let to_int_u x = x land 0xFFFF
let to_i32_s x =
if x land 0x8000 <> 0 then Int32.of_int (x lor 0xffff_0000)
else Int32.of_int x
let to_i32_u x = Int32.of_int (x land 0xffff)
let of_int x = wrap x
let add x y = wrap (x + y)
let sub x y = wrap (x - y)
let mul x y = wrap (to_int_s x * to_int_s y)
let neg x = wrap (-to_int_s x)
let abs x = wrap (abs (to_int_s x))
let popcnt x =
let rec loop n acc =
if n = 0 then acc else loop (n lsr 1) (acc + (n land 1))
in
loop (to_int_u x) 0 |> wrap
let eq x y = x = y
let ne x y = x <> y
let lt_s x y = to_int_s x < to_int_s y
let lt_u x y = to_int_u x < to_int_u y
let le_s x y = to_int_s x <= to_int_s y
let le_u x y = to_int_u x <= to_int_u y
let gt_s x y = to_int_s x > to_int_s y
let gt_u x y = to_int_u x > to_int_u y
let ge_s x y = to_int_s x >= to_int_s y
let ge_u x y = to_int_u x >= to_int_u y
let shl x y = wrap (to_int_u x lsl (y land 15))
let shr_s x y = wrap (to_int_s x asr (y land 15))
let shr_u x y = wrap (to_int_u x lsr (y land 15))
let min_s x y = if lt_s x y then x else y
let min_u x y = if lt_u x y then x else y
let max_s x y = if gt_s x y then x else y
let max_u x y = if gt_u x y then x else y
let add_sat_s x y =
let v = to_int_s x + to_int_s y in
if v > 32767 then 0x7FFF else if v < -32768 then 0x8000 else wrap v
let add_sat_u x y =
let v = to_int_u x + to_int_u y in
if v > 65535 then 65535 else v
let sub_sat_s x y =
let v = to_int_s x - to_int_s y in
if v > 32767 then 0x7FFF else if v < -32768 then 0x8000 else wrap v
let sub_sat_u x y =
let v = to_int_u x - to_int_u y in
if v < 0 then 0 else v
let q15mulr_sat_s x y =
let v = ((to_int_s x * to_int_s y) + 0x4000) asr 15 in
if v > 32767 then 0x7FFF else if v < -32768 then 0x8000 else wrap v
let avgr_u x y = (to_int_u x + to_int_u y + 1) / 2
let narrow_i8_s x =
let v = to_int_s x in
if v > 127 then 0x7F else if v < -128 then 0x80 else v land 0xFF
let narrow_i8_u x =
let v = to_int_s x in
if v < 0 then 0 else if v > 255 then 255 else v
let to_i8x2 x = (x land 0xFF, (x lsr 8) land 0xFF)