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
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
(* Copyright © 2021-2026 OCamlPro *)
(* Written by the Owi programmers *)

type t = int

let wrap x = x land 0xFF

let wrap_i32 x = Int32.logand x 0xFFl |> Int32.to_int

let to_int_s x =
  let x = x land 0xFF in
  if x land 0x80 <> 0 then x - 0x100 else x

let to_int_u x = x land 0xFF

let add x y = wrap (x + y)

let sub x y = wrap (x - 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

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 7))

let shr_s x y = wrap (to_int_s x asr (y land 7))

let shr_u x y = wrap (to_int_u x lsr (y land 7))

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 > 127 then 127 else if v < -128 then 128 else wrap v

let add_sat_u x y =
  let v = to_int_u x + to_int_u y in
  if v > 255 then 255 else v

let sub_sat_s x y =
  let v = to_int_s x - to_int_s y in
  if v > 127 then 127 else if v < -128 then 128 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 avgr_u x y = (to_int_u x + to_int_u y + 1) / 2