package reed-solomon-erasure

  1. Overview
  2. Docs

Source file galois.ml

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
open Tables
open Ctypes
open PosixTypes
open Foreign
open Ops
module Bigstring = Core_kernel.Bigstring

type bigstring = Bigstring.t

let add (a : char) (b : char) : char =
  ((int_of_char a) lxor (int_of_char b)) |> char_of_int

let sub (a : char) (b : char) : char =
  ((int_of_char a) lxor (int_of_char b)) |> char_of_int

let mul (a : char) (b : char) : char =
  mul_table.(int_of_char a).[int_of_char b]

let div (a : char) (b : char) : char =
  if      (int_of_char a) = 0 then
    char_of_int 0
  else if (int_of_char b) = 0 then
    failwith "Divisor is 0"
  else (
    let log_a = log_table.[a |> int_of_char] |> int_of_char in
    let log_b = log_table.[b |> int_of_char] |> int_of_char in
    let log_result = ref (log_a - log_b) in
    if !log_result < 0 then
      log_result := !log_result + 255;
    exp_table.[!log_result]
  )

let exp (a : char) (n : int) : char =
  if      n               = 0 then
    1 |> char_of_int
  else if (int_of_char a) = 0 then
    0 |> char_of_int
  else (
    let log_a = log_table.[a |> int_of_char] |> int_of_char in
    let log_result = ref (log_a * n) in
    while 255 <= !log_result do
      log_result := !log_result - 255;
    done;
    exp_table.[!log_result]
  )

let mul_slice_pure_ocaml
    ?(skip_to : int = 0)
    (c        : char)
    (input    : bigstring)
    (out      : bigstring)
  : unit =
  let mt = mul_table.(c |> int_of_char) in

  assert (Bigstring.length input = Bigstring.length out);

  let len = Bigstring.length input in

  for n = skip_to to (len) - 1 do
    out.&{n} <- mt.%[input.&{n}] |> int_of_char;
  done

let mul_slice_xor_pure_ocaml
    ?(skip_to : int = 0)
    (c        : char)
    (input    : bigstring)
    (out      : bigstring)
  : unit =
  let mt = mul_table.(c |> int_of_char) in

  assert (Bigstring.length input = Bigstring.length out);

  let len = Bigstring.length input in

  for n = skip_to to (len) - 1 do
    out.&{n} <- (mt.%[input.&{n}] |> int_of_char) lxor out.&{n};
  done

let slice_xor (input : bigstring) (out : bigstring) : unit =
  assert (Bigstring.length input = Bigstring.length out);

  let len = Bigstring.length input in

  for n = 0 to (len) - 1 do
    out.&{n} <- input.&{n} lxor out.&{n};
  done

let reedsolomon_gal_mul =
  foreign ~release_runtime_lock:true "reedsolomon_gal_mul"
    (ptr uint8_t @-> ptr uint8_t @-> ptr uint8_t @-> ptr uint8_t @-> size_t @-> returning size_t)

let reedsolomon_gal_mul_xor =
  foreign ~release_runtime_lock:true "reedsolomon_gal_mul_xor"
    (ptr uint8_t @-> ptr uint8_t @-> ptr uint8_t @-> ptr uint8_t @-> size_t @-> returning size_t)

let mul_slice (c : char) (input : bigstring) (out : bigstring) =
  let low  = Bigarray.Array2.slice_left mul_table_low  (c |> int_of_char) in
  let high = Bigarray.Array2.slice_left mul_table_high (c |> int_of_char) in

  assert (Bigstring.length input = Bigstring.length out);

  let size = Bigstring.length input in

  let bytes_done =
    (Unsigned.Size_t.to_int
       (reedsolomon_gal_mul
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 low))
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 high))
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 input))
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 out))
          (Unsigned.Size_t.of_int size)))
  in

  mul_slice_pure_ocaml ~skip_to:bytes_done c input out

let mul_slice_xor (c : char) (input : bigstring) (out : bigstring) =
  let low  = Bigarray.Array2.slice_left mul_table_low  (c |> int_of_char) in
  let high = Bigarray.Array2.slice_left mul_table_high (c |> int_of_char) in

  assert (Bigstring.length input = Bigstring.length out);

  let size = Bigstring.length input in

  let bytes_done =
    (Unsigned.Size_t.to_int
       (reedsolomon_gal_mul_xor
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 low))
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 high))
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 input))
          (coerce (ptr char) (ptr uint8_t) (bigarray_start array1 out))
          (Unsigned.Size_t.of_int size)))
  in

  mul_slice_xor_pure_ocaml ~skip_to:bytes_done c input out
OCaml

Innovation. Community. Security.