Source file array0.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
(* [Array0] defines array functions that are primitives or can be simply defined in terms
   of [Stdlib.Array].  [Array0] is intended to completely express the part of [Stdlib.Array]
   that [Base] uses -- no other file in Base other than array0.ml should use [Stdlib.Array].
   [Array0] has few dependencies, and so is available early in Base's build order.  All
   Base files that need to use arrays and come before [Base.Array] in build order should
   do [module Array = Array0].  This includes uses of subscript syntax ([x.(i)], [x.(i) <-
   e]), which the OCaml parser desugars into calls to [Array.get] and [Array.set].
   Defining [module Array = Array0] is also necessary because it prevents ocamldep from
   mistakenly causing a file to depend on [Base.Array]. *)


open! Import0
module Sys = Sys0

let invalid_argf = Printf.invalid_argf

module Array = struct
  external create : int -> 'a -> 'a array = "caml_make_vect"
  external create_local : int -> 'a -> ('a array[@local]) = "caml_make_vect"
  external create_float_uninitialized : int -> float array = "caml_make_float_vect"
  external get : ('a array[@local_opt]) -> (int[@local_opt]) -> 'a = "%array_safe_get"
  external length : ('a array[@local_opt]) -> int = "%array_length"

  external set
    :  ('a array[@local_opt])
    -> (int[@local_opt])
    -> 'a
    -> unit
    = "%array_safe_set"

  external unsafe_get
    :  ('a array[@local_opt])
    -> (int[@local_opt])
    -> 'a
    = "%array_unsafe_get"

  external unsafe_set
    :  ('a array[@local_opt])
    -> (int[@local_opt])
    -> 'a
    -> unit
    = "%array_unsafe_set"

  external unsafe_blit
    :  src:('a array[@local_opt])
    -> src_pos:int
    -> dst:('a array[@local_opt])
    -> dst_pos:int
    -> len:int
    -> unit
    = "caml_array_blit"
end

include Array

let max_length = Sys.max_array_length

let create ~len x =
  try create len x with
  | Invalid_argument _ -> invalid_argf "Array.create ~len:%d: invalid length" len ()
;;

let create_local ~len x =
  
    (try create_local len x with
     | Invalid_argument _ ->
       invalid_argf "Array.create_local ~len:%d: invalid length" len ())
;;

let create_float_uninitialized ~len =
  try create_float_uninitialized len with
  | Invalid_argument _ ->
    invalid_argf "Array.create_float_uninitialized ~len:%d: invalid length" len ()
;;

let append = Stdlib.Array.append
let blit = Stdlib.Array.blit
let concat = Stdlib.Array.concat
let copy = Stdlib.Array.copy
let fill = Stdlib.Array.fill

let init len ~f:((f : _ -> _) [@local]) =
  if len = 0
  then [||]
  else if len < 0
  then invalid_arg "Array.init"
  else (
    let res = create ~len (f 0) in
    for i = 1 to Int0.pred len do
      unsafe_set res i (f i)
    done;
    res)
;;

let make_matrix = Stdlib.Array.make_matrix
let of_list = Stdlib.Array.of_list
let sub = Stdlib.Array.sub
let to_list = Stdlib.Array.to_list

let fold t ~init ~f:((f : _ -> _ -> _) [@local]) =
  let r = ref init in
  for i = 0 to length t - 1 do
    r := f !r (unsafe_get t i)
  done;
  !r
;;

let fold_right t ~f:((f : _ -> _ -> _) [@local]) ~init =
  let r = ref init in
  for i = length t - 1 downto 0 do
    r := f (unsafe_get t i) !r
  done;
  !r
;;

let iter t ~f:((f : _ -> _) [@local]) =
  for i = 0 to length t - 1 do
    f (unsafe_get t i)
  done
;;

let iteri t ~f:((f : _ -> _ -> _) [@local]) =
  for i = 0 to length t - 1 do
    f i (unsafe_get t i)
  done
;;

let map t ~f:((f : _ -> _) [@local]) =
  let len = length t in
  if len = 0
  then [||]
  else (
    let r = create ~len (f (unsafe_get t 0)) in
    for i = 1 to len - 1 do
      unsafe_set r i (f (unsafe_get t i))
    done;
    r)
;;

let mapi t ~f:((f : _ -> _ -> _) [@local]) =
  let len = length t in
  if len = 0
  then [||]
  else (
    let r = create ~len (f 0 (unsafe_get t 0)) in
    for i = 1 to len - 1 do
      unsafe_set r i (f i (unsafe_get t i))
    done;
    r)
;;

let stable_sort t ~compare = Stdlib.Array.stable_sort t ~cmp:compare

let swap t i j =
  let elt_i = t.(i) in
  let elt_j = t.(j) in
  unsafe_set t i elt_j;
  unsafe_set t j elt_i
;;