My working unpac repository
1(**************************************************************************)
2(* *)
3(* OCaml *)
4(* *)
5(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
6(* Nicolas Ojeda Bar, LexiFi *)
7(* *)
8(* Copyright 2018 Institut National de Recherche en Informatique et *)
9(* en Automatique. *)
10(* *)
11(* All rights reserved. This file is distributed under the terms of *)
12(* the GNU Lesser General Public License version 2.1, with the *)
13(* special exception on linking described in the file LICENSE. *)
14(* *)
15(**************************************************************************)
16
17(* NOTE:
18 If this file is float.template.mli, run tools/sync_stdlib_docs after editing
19 it to generate float.mli.
20
21 If this file is float.mli, do not edit it directly -- edit
22 templates/float.template.mli instead.
23 *)
24
25(** Floating-point arithmetic.
26
27 OCaml's floating-point numbers follow the
28 IEEE 754 standard, using double precision (64 bits) numbers.
29 Floating-point operations never raise an exception on overflow,
30 underflow, division by zero, etc. Instead, special IEEE numbers
31 are returned as appropriate, such as [infinity] for [1.0 /. 0.0],
32 [neg_infinity] for [-1.0 /. 0.0], and [nan] ('not a number')
33 for [0.0 /. 0.0]. These special numbers then propagate through
34 floating-point computations as expected: for instance,
35 [1.0 /. infinity] is [0.0], basic arithmetic operations
36 ([+.], [-.], [*.], [/.]) with [nan] as an argument return [nan], ...
37
38 @since 4.07
39*)
40
41val zero : float
42(** The floating point 0.
43 @since 4.08 *)
44
45val one : float
46(** The floating-point 1.
47 @since 4.08 *)
48
49val minus_one : float
50(** The floating-point -1.
51 @since 4.08 *)
52
53external neg : float -> float = "%negfloat"
54(** Unary negation. *)
55
56external add : float -> float -> float = "%addfloat"
57(** Floating-point addition. *)
58
59external sub : float -> float -> float = "%subfloat"
60(** Floating-point subtraction. *)
61
62external mul : float -> float -> float = "%mulfloat"
63(** Floating-point multiplication. *)
64
65external div : float -> float -> float = "%divfloat"
66(** Floating-point division. *)
67
68external fma : float -> float -> float -> float =
69 "caml_fma_float" "caml_fma" [@@unboxed] [@@noalloc]
70(** [fma x y z] returns [x * y + z], with a best effort for computing
71 this expression with a single rounding, using either hardware
72 instructions (providing full IEEE compliance) or a software
73 emulation.
74
75 On 64-bit Cygwin, 64-bit mingw-w64 and MSVC 2017 and earlier, this function
76 may be emulated owing to known bugs on limitations on these platforms.
77 Note: since software emulation of the fma is costly, make sure that you are
78 using hardware fma support if performance matters.
79
80 @since 4.08 *)
81
82external rem : float -> float -> float = "caml_fmod_float" "fmod"
83[@@unboxed] [@@noalloc]
84(** [rem a b] returns the remainder of [a] with respect to [b]. The returned
85 value is [a -. n *. b], where [n] is the quotient [a /. b] rounded towards
86 zero to an integer. *)
87
88val succ : float -> float
89(** [succ x] returns the floating point number right after [x] i.e.,
90 the smallest floating-point number greater than [x]. See also
91 {!next_after}.
92 @since 4.08 *)
93
94val pred : float -> float
95(** [pred x] returns the floating-point number right before [x] i.e.,
96 the greatest floating-point number smaller than [x]. See also
97 {!next_after}.
98 @since 4.08 *)
99
100external abs : float -> float = "%absfloat"
101(** [abs f] returns the absolute value of [f]. *)
102
103val infinity : float
104(** Positive infinity. *)
105
106val neg_infinity : float
107(** Negative infinity. *)
108
109val nan : float
110(** A special floating-point value denoting the result of an
111 undefined operation such as [0.0 /. 0.0]. Stands for
112 'not a number'. Any floating-point operation with [nan] as
113 argument returns [nan] as result, unless otherwise specified in
114 IEEE 754 standard. As for floating-point comparisons,
115 [=], [<], [<=], [>] and [>=] return [false] and [<>] returns [true]
116 if one or both of their arguments is [nan].
117
118 [nan] is [quiet_nan] since 5.1; it was a signaling NaN before. *)
119
120val signaling_nan : float
121(** Signaling NaN. The corresponding signals do not raise OCaml exception,
122 but the value can be useful for interoperability with C libraries.
123
124 @since 5.1 *)
125
126val quiet_nan : float
127(** Quiet NaN.
128
129 @since 5.1 *)
130
131val pi : float
132(** The constant pi. *)
133
134val max_float : float
135(** The largest positive finite value of type [float]. *)
136
137val min_float : float
138(** The smallest positive, non-zero, non-denormalized value of type [float]. *)
139
140val epsilon : float
141(** The difference between [1.0] and the smallest exactly representable
142 floating-point number greater than [1.0]. *)
143
144val is_finite : float -> bool
145(** [is_finite x] is [true] if and only if [x] is finite i.e., not infinite and
146 not {!nan}.
147
148 @since 4.08 *)
149
150val is_infinite : float -> bool
151(** [is_infinite x] is [true] if and only if [x] is {!infinity} or
152 {!neg_infinity}.
153
154 @since 4.08 *)
155
156val is_nan : float -> bool
157(** [is_nan x] is [true] if and only if [x] is not a number (see {!nan}).
158
159 @since 4.08 *)
160
161val is_integer : float -> bool
162(** [is_integer x] is [true] if and only if [x] is an integer.
163
164 @since 4.08 *)
165
166external of_int : int -> float = "%floatofint"
167(** Convert an integer to floating-point. *)
168
169external to_int : float -> int = "%intoffloat"
170(** Truncate the given floating-point number to an integer.
171 The result is unspecified if the argument is [nan] or falls outside the
172 range of representable integers. *)
173
174external of_string : string -> float = "caml_float_of_string"
175(** Convert the given string to a float. The string is read in decimal
176 (by default) or in hexadecimal (marked by [0x] or [0X]).
177 The format of decimal floating-point numbers is
178 [ [-] dd.ddd (e|E) [+|-] dd ], where [d] stands for a decimal digit.
179 The format of hexadecimal floating-point numbers is
180 [ [-] 0(x|X) hh.hhh (p|P) [+|-] dd ], where [h] stands for an
181 hexadecimal digit and [d] for a decimal digit.
182 In both cases, at least one of the integer and fractional parts must be
183 given; the exponent part is optional.
184 The [_] (underscore) character can appear anywhere in the string
185 and is ignored.
186 Depending on the execution platforms, other representations of
187 floating-point numbers can be accepted, but should not be relied upon.
188 @raise Failure if the given string is not a valid
189 representation of a float. *)
190
191val of_string_opt: string -> float option
192(** Same as [of_string], but returns [None] instead of raising. *)
193
194val to_string : float -> string
195(** Return a string representation of a floating-point number.
196
197 This conversion can involve a loss of precision. For greater control over
198 the manner in which the number is printed, see {!Printf}.
199
200 This function is an alias for {!Stdlib.string_of_float}. *)
201
202type fpclass = Stdlib.fpclass =
203 FP_normal (** Normal number, none of the below *)
204 | FP_subnormal (** Number very close to 0.0, has reduced precision *)
205 | FP_zero (** Number is 0.0 or -0.0 *)
206 | FP_infinite (** Number is positive or negative infinity *)
207 | FP_nan (** Not a number: result of an undefined operation *)
208(** The five classes of floating-point numbers, as determined by
209 the {!classify_float} function. *)
210
211external classify_float : (float [@unboxed]) -> fpclass =
212 "caml_classify_float" "caml_classify_float_unboxed" [@@noalloc]
213(** Return the class of the given floating-point number:
214 normal, subnormal, zero, infinite, or not a number. *)
215
216external pow : float -> float -> float = "caml_power_float" "pow"
217[@@unboxed] [@@noalloc]
218(** Exponentiation. *)
219
220external sqrt : float -> float = "caml_sqrt_float" "sqrt"
221[@@unboxed] [@@noalloc]
222(** Square root. *)
223
224external cbrt : float -> float = "caml_cbrt_float" "caml_cbrt"
225 [@@unboxed] [@@noalloc]
226(** Cube root.
227
228 @since 4.13
229*)
230
231external exp : float -> float = "caml_exp_float" "exp" [@@unboxed] [@@noalloc]
232(** Exponential. *)
233
234external exp2 : float -> float = "caml_exp2_float" "caml_exp2"
235 [@@unboxed] [@@noalloc]
236(** Base 2 exponential function.
237
238 @since 4.13
239*)
240
241external log : float -> float = "caml_log_float" "log" [@@unboxed] [@@noalloc]
242(** Natural logarithm. *)
243
244external log10 : float -> float = "caml_log10_float" "log10"
245[@@unboxed] [@@noalloc]
246(** Base 10 logarithm. *)
247
248external log2 : float -> float = "caml_log2_float" "caml_log2"
249 [@@unboxed] [@@noalloc]
250(** Base 2 logarithm.
251
252 @since 4.13
253*)
254
255external expm1 : float -> float = "caml_expm1_float" "caml_expm1"
256[@@unboxed] [@@noalloc]
257(** [expm1 x] computes [exp x -. 1.0], giving numerically-accurate results
258 even if [x] is close to [0.0]. *)
259
260external log1p : float -> float = "caml_log1p_float" "caml_log1p"
261[@@unboxed] [@@noalloc]
262(** [log1p x] computes [log(1.0 +. x)] (natural logarithm),
263 giving numerically-accurate results even if [x] is close to [0.0]. *)
264
265external cos : float -> float = "caml_cos_float" "cos" [@@unboxed] [@@noalloc]
266(** Cosine. Argument is in radians. *)
267
268external sin : float -> float = "caml_sin_float" "sin" [@@unboxed] [@@noalloc]
269(** Sine. Argument is in radians. *)
270
271external tan : float -> float = "caml_tan_float" "tan" [@@unboxed] [@@noalloc]
272(** Tangent. Argument is in radians. *)
273
274external acos : float -> float = "caml_acos_float" "acos"
275[@@unboxed] [@@noalloc]
276(** Arc cosine. The argument must fall within the range [[-1.0, 1.0]].
277 Result is in radians and is between [0.0] and [pi]. *)
278
279external asin : float -> float = "caml_asin_float" "asin"
280[@@unboxed] [@@noalloc]
281(** Arc sine. The argument must fall within the range [[-1.0, 1.0]].
282 Result is in radians and is between [-pi/2] and [pi/2]. *)
283
284external atan : float -> float = "caml_atan_float" "atan"
285[@@unboxed] [@@noalloc]
286(** Arc tangent.
287 Result is in radians and is between [-pi/2] and [pi/2]. *)
288
289external atan2 : float -> float -> float = "caml_atan2_float" "atan2"
290[@@unboxed] [@@noalloc]
291(** [atan2 y x] returns the arc tangent of [y /. x]. The signs of [x]
292 and [y] are used to determine the quadrant of the result.
293 Result is in radians and is between [-pi] and [pi]. *)
294
295external hypot : float -> float -> float = "caml_hypot_float" "caml_hypot"
296[@@unboxed] [@@noalloc]
297(** [hypot x y] returns [sqrt(x *. x +. y *. y)], that is, the length
298 of the hypotenuse of a right-angled triangle with sides of length
299 [x] and [y], or, equivalently, the distance of the point [(x,y)]
300 to origin. If one of [x] or [y] is infinite, returns [infinity]
301 even if the other is [nan]. *)
302
303external cosh : float -> float = "caml_cosh_float" "cosh"
304[@@unboxed] [@@noalloc]
305(** Hyperbolic cosine. Argument is in radians. *)
306
307external sinh : float -> float = "caml_sinh_float" "sinh"
308[@@unboxed] [@@noalloc]
309(** Hyperbolic sine. Argument is in radians. *)
310
311external tanh : float -> float = "caml_tanh_float" "tanh"
312[@@unboxed] [@@noalloc]
313(** Hyperbolic tangent. Argument is in radians. *)
314
315external acosh : float -> float = "caml_acosh_float" "caml_acosh"
316 [@@unboxed] [@@noalloc]
317(** Hyperbolic arc cosine. The argument must fall within the range
318 [[1.0, inf]].
319 Result is in radians and is between [0.0] and [inf].
320
321 @since 4.13
322*)
323
324external asinh : float -> float = "caml_asinh_float" "caml_asinh"
325 [@@unboxed] [@@noalloc]
326(** Hyperbolic arc sine. The argument and result range over the entire
327 real line.
328 Result is in radians.
329
330 @since 4.13
331*)
332
333external atanh : float -> float = "caml_atanh_float" "caml_atanh"
334 [@@unboxed] [@@noalloc]
335(** Hyperbolic arc tangent. The argument must fall within the range
336 [[-1.0, 1.0]].
337 Result is in radians and ranges over the entire real line.
338
339 @since 4.13
340*)
341
342external erf : float -> float = "caml_erf_float" "caml_erf"
343 [@@unboxed] [@@noalloc]
344(** Error function. The argument ranges over the entire real line.
345 The result is always within [[-1.0, 1.0]].
346
347 @since 4.13
348*)
349
350external erfc : float -> float = "caml_erfc_float" "caml_erfc"
351 [@@unboxed] [@@noalloc]
352(** Complementary error function ([erfc x = 1 - erf x]).
353 The argument ranges over the entire real line.
354 The result is always within [[0.0, 2.0]].
355
356 @since 4.13
357*)
358
359external trunc : float -> float = "caml_trunc_float" "caml_trunc"
360 [@@unboxed] [@@noalloc]
361(** [trunc x] rounds [x] to the nearest integer whose absolute value is
362 less than or equal to [x].
363
364 @since 4.08 *)
365
366external round : float -> float = "caml_round_float" "caml_round"
367 [@@unboxed] [@@noalloc]
368(** [round x] rounds [x] to the nearest integer with ties (fractional
369 values of 0.5) rounded away from zero, regardless of the current
370 rounding direction. If [x] is an integer, [+0.], [-0.], [nan], or
371 infinite, [x] itself is returned.
372
373 On 64-bit mingw-w64, this function may be emulated owing to a bug in the
374 C runtime library (CRT) on this platform.
375
376 @since 4.08 *)
377
378external ceil : float -> float = "caml_ceil_float" "ceil"
379[@@unboxed] [@@noalloc]
380(** Round above to an integer value.
381 [ceil f] returns the least integer value greater than or equal to [f].
382 The result is returned as a float. *)
383
384external floor : float -> float = "caml_floor_float" "floor"
385[@@unboxed] [@@noalloc]
386(** Round below to an integer value.
387 [floor f] returns the greatest integer value less than or
388 equal to [f].
389 The result is returned as a float. *)
390
391external next_after : float -> float -> float
392 = "caml_nextafter_float" "caml_nextafter" [@@unboxed] [@@noalloc]
393(** [next_after x y] returns the next representable floating-point
394 value following [x] in the direction of [y]. More precisely, if
395 [y] is greater (resp. less) than [x], it returns the smallest
396 (resp. largest) representable number greater (resp. less) than [x].
397 If [x] equals [y], the function returns [y]. If [x] or [y] is
398 [nan], a [nan] is returned.
399 Note that [next_after max_float infinity = infinity] and that
400 [next_after 0. infinity] is the smallest denormalized positive number.
401 If [x] is the smallest denormalized positive number,
402 [next_after x 0. = 0.]
403
404 @since 4.08 *)
405
406external copy_sign : float -> float -> float
407 = "caml_copysign_float" "caml_copysign"
408[@@unboxed] [@@noalloc]
409(** [copy_sign x y] returns a float whose absolute value is that of [x]
410 and whose sign is that of [y]. If [x] is [nan], returns [nan].
411 If [y] is [nan], returns either [x] or [-. x], but it is not
412 specified which. *)
413
414external sign_bit : (float [@unboxed]) -> bool
415 = "caml_signbit_float" "caml_signbit" [@@noalloc]
416(** [sign_bit x] is [true] if and only if the sign bit of [x] is set.
417 For example [sign_bit 1.] and [signbit 0.] are [false] while
418 [sign_bit (-1.)] and [sign_bit (-0.)] are [true].
419
420 @since 4.08 *)
421
422external frexp : float -> float * int = "caml_frexp_float"
423(** [frexp f] returns the pair of the significant
424 and the exponent of [f]. When [f] is zero, the
425 significant [x] and the exponent [n] of [f] are equal to
426 zero. When [f] is non-zero, they are defined by
427 [f = x *. 2 ** n] and [0.5 <= abs x < 1.0]. *)
428
429external ldexp : (float [@unboxed]) -> (int [@untagged]) -> (float [@unboxed]) =
430 "caml_ldexp_float" "caml_ldexp_float_unboxed" [@@noalloc]
431(** [ldexp x n] returns [x *. 2 ** n]. *)
432
433external modf : float -> float * float = "caml_modf_float"
434(** [modf f] returns the pair of the fractional and integral
435 part of [f]. *)
436
437type t = float
438(** An alias for the type of floating-point numbers. *)
439
440val compare: t -> t -> int
441(** [compare x y] returns [0] if [x] is equal to [y], a negative integer if [x]
442 is less than [y], and a positive integer if [x] is greater than
443 [y]. [compare] treats [nan] as equal to itself and less than any other float
444 value. This treatment of [nan] ensures that [compare] defines a total
445 ordering relation. *)
446
447val equal: t -> t -> bool
448(** The equal function for floating-point numbers, compared using {!compare}. *)
449
450val min : t -> t -> t
451(** [min x y] returns the minimum of [x] and [y]. It returns [nan]
452 when [x] or [y] is [nan]. Moreover [min (-0.) (+0.) = -0.]
453
454 @since 4.08 *)
455
456val max : float -> float -> float
457(** [max x y] returns the maximum of [x] and [y]. It returns [nan]
458 when [x] or [y] is [nan]. Moreover [max (-0.) (+0.) = +0.]
459
460 @since 4.08 *)
461
462val min_max : float -> float -> float * float
463(** [min_max x y] is [(min x y, max x y)], just more efficient.
464
465 @since 4.08 *)
466
467val min_num : t -> t -> t
468(** [min_num x y] returns the minimum of [x] and [y] treating [nan] as
469 missing values. If both [x] and [y] are [nan], [nan] is returned.
470 Moreover [min_num (-0.) (+0.) = -0.]
471
472 @since 4.08 *)
473
474val max_num : t -> t -> t
475(** [max_num x y] returns the maximum of [x] and [y] treating [nan] as
476 missing values. If both [x] and [y] are [nan] [nan] is returned.
477 Moreover [max_num (-0.) (+0.) = +0.]
478
479 @since 4.08 *)
480
481val min_max_num : float -> float -> float * float
482(** [min_max_num x y] is [(min_num x y, max_num x y)], just more
483 efficient. Note that in particular [min_max_num x nan = (x, x)]
484 and [min_max_num nan y = (y, y)].
485
486 @since 4.08 *)
487
488val seeded_hash : int -> t -> int
489(** A seeded hash function for floats, with the same output value as
490 {!Hashtbl.seeded_hash}. This function allows this module to be passed as
491 argument to the functor {!Hashtbl.MakeSeeded}.
492
493 @since 5.1 *)
494
495val hash : t -> int
496(** An unseeded hash function for floats, with the same output value as
497 {!Hashtbl.hash}. This function allows this module to be passed as argument
498 to the functor {!Hashtbl.Make}. *)
499
500module Array : sig
501 type t = floatarray
502 (** The type of float arrays with packed representation.
503 @since 4.08
504 *)
505
506 val length : t -> int
507 (** Return the length (number of elements) of the given floatarray. *)
508
509 val get : t -> int -> float
510 (** [get a n] returns the element number [n] of floatarray [a].
511 @raise Invalid_argument if [n] is outside the range 0 to
512 [(length a - 1)]. *)
513
514 val set : t -> int -> float -> unit
515 (** [set a n x] modifies floatarray [a] in place, replacing element
516 number [n] with [x].
517 @raise Invalid_argument if [n] is outside the range 0 to
518 [(length a - 1)]. *)
519
520 val make : int -> float -> t
521 (** [make n x] returns a fresh floatarray of length [n], initialized with [x].
522 @raise Invalid_argument if [n < 0] or [n > Sys.max_floatarray_length]. *)
523
524 val create : int -> t
525 (** [create n] returns a fresh floatarray of length [n],
526 with uninitialized data.
527 @raise Invalid_argument if [n < 0] or [n > Sys.max_floatarray_length]. *)
528
529 val init : int -> (int -> float) -> t
530 (** [init n f] returns a fresh floatarray of length [n],
531 with element number [i] initialized to the result of [f i].
532 In other terms, [init n f] tabulates the results of [f]
533 applied to the integers [0] to [n-1].
534 @raise Invalid_argument if [n < 0] or [n > Sys.max_floatarray_length]. *)
535
536 val make_matrix : int -> int -> float -> t array
537 (** [make_matrix dimx dimy e] returns a two-dimensional array
538 (an array of arrays) with first dimension [dimx] and
539 second dimension [dimy], where all elements are initialized with [e].
540
541 @raise Invalid_argument if [dimx] or [dimy] is negative or
542 greater than {!Sys.max_floatarray_length}.
543
544 @since 5.2 *)
545
546 val init_matrix : int -> int -> (int -> int -> float) -> t array
547 (** [init_matrix dimx dimy f] returns a two-dimensional array
548 (an array of arrays)
549 with first dimension [dimx] and second dimension [dimy],
550 where the element at index ([x,y]) is initialized with [f x y].
551
552 @raise Invalid_argument if [dimx] or [dimy] is negative or
553 greater than {!Sys.max_floatarray_length}.
554
555 @since 5.2 *)
556
557 val append : t -> t -> t
558 (** [append v1 v2] returns a fresh floatarray containing the
559 concatenation of the floatarrays [v1] and [v2].
560 @raise Invalid_argument if
561 [length v1 + length v2 > Sys.max_floatarray_length]. *)
562
563 val concat : t list -> t
564 (** Same as {!append}, but concatenates a list of floatarrays. *)
565
566 val sub : t -> int -> int -> t
567 (** [sub a pos len] returns a fresh floatarray of length [len],
568 containing the elements number [pos] to [pos + len - 1]
569 of floatarray [a].
570 @raise Invalid_argument if [pos] and [len] do not
571 designate a valid subarray of [a]; that is, if
572 [pos < 0], or [len < 0], or [pos + len > length a]. *)
573
574 val copy : t -> t
575 (** [copy a] returns a copy of [a], that is, a fresh floatarray
576 containing the same elements as [a]. *)
577
578 val fill : t -> int -> int -> float -> unit
579 (** [fill a pos len x] modifies the floatarray [a] in place,
580 storing [x] in elements number [pos] to [pos + len - 1].
581 @raise Invalid_argument if [pos] and [len] do not
582 designate a valid subarray of [a]. *)
583
584 val blit : t -> int -> t -> int -> int -> unit
585 (** [blit src src_pos dst dst_pos len] copies [len] elements
586 from floatarray [src], starting at element number [src_pos],
587 to floatarray [dst], starting at element number [dst_pos].
588 It works correctly even if
589 [src] and [dst] are the same floatarray, and the source and
590 destination chunks overlap.
591 @raise Invalid_argument if [src_pos] and [len] do not
592 designate a valid subarray of [src], or if [dst_pos] and [len] do not
593 designate a valid subarray of [dst]. *)
594
595 val to_list : t -> float list
596 (** [to_list a] returns the list of all the elements of [a]. *)
597
598 val of_list : float list -> t
599 (** [of_list l] returns a fresh floatarray containing the elements
600 of [l].
601 @raise Invalid_argument if the length of [l] is greater than
602 [Sys.max_floatarray_length].*)
603
604 (** {1:comparison Comparison} *)
605
606 val equal : (float -> float -> bool) -> t -> t -> bool
607 (** [equal eq a b] is [true] if and only if [a] and [b] have the
608 same length [n] and for all [i] in \[[0];[n-1]\], [eq a.(i) b.(i)]
609 is [true].
610
611 @since 5.4 *)
612
613 val compare : (float -> float -> int) -> t -> t -> int
614 (** [compare cmp a b] compares [a] and [b] according to the shortlex order,
615 that is, shorter arrays are smaller and equal-sized arrays are compared
616 in lexicographic order using [cmp] to compare elements.
617
618 @since 5.4 *)
619
620 (** {1 Iterators} *)
621
622 val iter : (float -> unit) -> t -> unit
623 (** [iter f a] applies function [f] in turn to all
624 the elements of [a]. It is equivalent to
625 [f a.(0); f a.(1); ...; f a.(length a - 1); ()]. *)
626
627 val iteri : (int -> float -> unit) -> t -> unit
628 (** Same as {!iter}, but the
629 function is applied with the index of the element as first argument,
630 and the element itself as second argument. *)
631
632 val map : (float -> float) -> t -> t
633 (** [map f a] applies function [f] to all the elements of [a],
634 and builds a floatarray with the results returned by [f]. *)
635
636 val map_inplace : (float -> float) -> t -> unit
637 (** [map_inplace f a] applies function [f] to all elements of [a],
638 and updates their values in place.
639 @since 5.1 *)
640
641 val mapi : (int -> float -> float) -> t -> t
642 (** Same as {!map}, but the
643 function is applied to the index of the element as first argument,
644 and the element itself as second argument. *)
645
646 val mapi_inplace : (int -> float -> float) -> t -> unit
647 (** Same as {!map_inplace}, but the function is applied to the index of the
648 element as first argument, and the element itself as second argument.
649 @since 5.1 *)
650
651 val fold_left : ('acc -> float -> 'acc) -> 'acc -> t -> 'acc
652 (** [fold_left f x init] computes
653 [f (... (f (f x init.(0)) init.(1)) ...) init.(n-1)],
654 where [n] is the length of the floatarray [init]. *)
655
656 val fold_right : (float -> 'acc -> 'acc) -> t -> 'acc -> 'acc
657 (** [fold_right f a init] computes
658 [f a.(0) (f a.(1) ( ... (f a.(n-1) init) ...))],
659 where [n] is the length of the floatarray [a]. *)
660
661 (** {1 Iterators on two arrays} *)
662
663 val iter2 : (float -> float -> unit) -> t -> t -> unit
664 (** [Array.iter2 f a b] applies function [f] to all the elements of [a]
665 and [b].
666 @raise Invalid_argument if the floatarrays are not the same size. *)
667
668 val map2 : (float -> float -> float) -> t -> t -> t
669 (** [map2 f a b] applies function [f] to all the elements of [a]
670 and [b], and builds a floatarray with the results returned by [f]:
671 [[| f a.(0) b.(0); ...; f a.(length a - 1) b.(length b - 1)|]].
672 @raise Invalid_argument if the floatarrays are not the same size. *)
673
674 (** {1 Array scanning} *)
675
676 val for_all : (float -> bool) -> t -> bool
677 (** [for_all f [|a1; ...; an|]] checks if all elements of the floatarray
678 satisfy the predicate [f]. That is, it returns
679 [(f a1) && (f a2) && ... && (f an)]. *)
680
681 val exists : (float -> bool) -> t -> bool
682 (** [exists f [|a1; ...; an|]] checks if at least one element of
683 the floatarray satisfies the predicate [f]. That is, it returns
684 [(f a1) || (f a2) || ... || (f an)]. *)
685
686 val mem : float -> t -> bool
687 (** [mem a set] is true if and only if there is an element of [set] that is
688 structurally equal to [a], i.e. there is an [x] in [set] such
689 that [compare a x = 0]. *)
690
691 val mem_ieee : float -> t -> bool
692 (** Same as {!mem}, but uses IEEE equality instead of structural equality. *)
693
694 (** {1 Array searching} *)
695
696 val find_opt : (float -> bool) -> t -> float option
697 (* [find_opt f a] returns the first element of the array [a] that satisfies
698 the predicate [f]. Returns [None] if there is no value that satisfies [f]
699 in the array [a].
700 @since 5.1 *)
701
702 val find_index : (float-> bool) -> t -> int option
703 (** [find_index f a] returns [Some i], where [i] is the index of the first
704 element of the array [a] that satisfies [f x], if there is such an
705 element.
706
707 It returns [None] if there is no such element.
708 @since 5.1 *)
709
710 val find_map : (float -> 'a option) -> t -> 'a option
711 (* [find_map f a] applies [f] to the elements of [a] in order, and returns
712 the first result of the form [Some v], or [None] if none exist.
713 @since 5.1 *)
714
715 val find_mapi : (int -> float -> 'a option) -> t -> 'a option
716 (** Same as [find_map], but the predicate is applied to the index of
717 the element as first argument (counting from 0), and the element
718 itself as second argument.
719
720 @since 5.1 *)
721
722 (** {1:sorting_and_shuffling Sorting and shuffling} *)
723
724 val sort : (float -> float -> int) -> t -> unit
725 (** Sort a floatarray in increasing order according to a comparison
726 function. The comparison function must return 0 if its arguments
727 compare as equal, a positive integer if the first is greater,
728 and a negative integer if the first is smaller (see below for a
729 complete specification). For example, {!Stdlib.compare} is
730 a suitable comparison function. After calling [sort], the
731 array is sorted in place in increasing order.
732 [sort] is guaranteed to run in constant heap space
733 and (at most) logarithmic stack space.
734
735 The current implementation uses Heap Sort. It runs in constant
736 stack space.
737
738 Specification of the comparison function:
739 Let [a] be the floatarray and [cmp] the comparison function. The following
740 must be true for all [x], [y], [z] in [a] :
741 - [cmp x y] > 0 if and only if [cmp y x] < 0
742 - if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0
743
744 When [sort] returns, [a] contains the same elements as before,
745 reordered in such a way that for all i and j valid indices of [a] :
746 - [cmp a.(i) a.(j)] >= 0 if i >= j
747 *)
748
749 val stable_sort : (float -> float -> int) -> t -> unit
750 (** Same as {!sort}, but the sorting algorithm is stable (i.e.
751 elements that compare equal are kept in their original order) and
752 not guaranteed to run in constant heap space.
753
754 The current implementation uses Merge Sort. It uses a temporary
755 floatarray of length [n/2], where [n] is the length of the floatarray.
756 It is usually faster than the current implementation of {!sort}. *)
757
758 val fast_sort : (float -> float -> int) -> t -> unit
759 (** Same as {!sort} or {!stable_sort}, whichever is faster
760 on typical input. *)
761
762 val shuffle :
763 rand: (* thwart tools/sync_stdlib_docs *) (int -> int) -> t -> unit
764 (** [shuffle rand a] randomly permutes [a]'s elements using [rand]
765 for randomness. The distribution of permutations is uniform.
766
767 [rand] must be such that a call to [rand n] returns a uniformly
768 distributed random number in the range \[[0];[n-1]\].
769 {!Random.int} can be used for this (do not forget to
770 {{!Random.self_init}initialize} the generator).
771
772 @since 5.2 *)
773
774 (** {1 Float arrays and Sequences} *)
775
776 val to_seq : t -> float Seq.t
777 (** Iterate on the floatarray, in increasing order. Modifications of the
778 floatarray during iteration will be reflected in the sequence. *)
779
780 val to_seqi : t -> (int * float) Seq.t
781 (** Iterate on the floatarray, in increasing order, yielding indices along
782 elements. Modifications of the floatarray during iteration will be
783 reflected in the sequence. *)
784
785 val of_seq : float Seq.t -> t
786 (** Create an array from the generator. *)
787
788
789 val map_to_array : (float -> 'a) -> t -> 'a array
790 (** [map_to_array f a] applies function [f] to all the elements of [a],
791 and builds an array with the results returned by [f]:
792 [[| f a.(0); f a.(1); ...; f a.(length a - 1) |]]. *)
793
794 val map_from_array : ('a -> float) -> 'a array -> t
795 (** [map_from_array f a] applies function [f] to all the elements of [a],
796 and builds a floatarray with the results returned by [f]. *)
797
798 (** {1:floatarray_concurrency Arrays and concurrency safety}
799
800 Care must be taken when concurrently accessing float arrays from multiple
801 domains: accessing an array will never crash a program, but unsynchronized
802 accesses might yield surprising (non-sequentially-consistent) results.
803
804 {2:floatarray_atomicity Atomicity}
805
806 Every float array operation that accesses more than one array element is
807 not atomic. This includes iteration, scanning, sorting, splitting and
808 combining arrays.
809
810 For example, consider the following program:
811 {[let size = 100_000_000
812 let a = Float.Array.make size 1.
813 let update a f () =
814 Float.Array.iteri (fun i x -> Float.Array.set a i (f x)) a
815 let d1 = Domain.spawn (update a (fun x -> x +. 1.))
816 let d2 = Domain.spawn (update a (fun x -> 2. *. x +. 1.))
817 let () = Domain.join d1; Domain.join d2
818 ]}
819
820 After executing this code, each field of the float array [a] is either
821 [2.], [3.], [4.] or [5.]. If atomicity is required, then the user must
822 implement their own synchronization (for example, using {!Mutex.t}).
823
824 {2:floatarray_data_race Data races}
825
826 If two domains only access disjoint parts of the array, then the
827 observed behaviour is the equivalent to some sequential interleaving of
828 the operations from the two domains.
829
830 A data race is said to occur when two domains access the same array
831 element without synchronization and at least one of the accesses is a
832 write. In the absence of data races, the observed behaviour is equivalent
833 to some sequential interleaving of the operations from different domains.
834
835 Whenever possible, data races should be avoided by using synchronization
836 to mediate the accesses to the array elements.
837
838 Indeed, in the presence of data races, programs will not crash but the
839 observed behaviour may not be equivalent to any sequential interleaving of
840 operations from different domains. Nevertheless, even in the presence of
841 data races, a read operation will return the value of some prior write to
842 that location with a few exceptions.
843
844
845 {2:floatarray_datarace_tearing Tearing }
846
847 Float arrays have two supplementary caveats in the presence of data races.
848
849 First, the blit operation might copy an array byte-by-byte. Data races
850 between such a blit operation and another operation might produce
851 surprising values due to tearing: partial writes interleaved with other
852 operations can create float values that would not exist with a sequential
853 execution.
854
855 For instance, at the end of
856 {[let zeros = Float.Array.make size 0.
857 let max_floats = Float.Array.make size Float.max_float
858 let res = Float.Array.copy zeros
859 let d1 = Domain.spawn (fun () -> Float.Array.blit zeros 0 res 0 size)
860 let d2 = Domain.spawn (fun () -> Float.Array.blit max_floats 0 res 0 size)
861 let () = Domain.join d1; Domain.join d2
862 ]}
863
864 the [res] float array might contain values that are neither [0.]
865 nor [max_float].
866
867 Second, on 32-bit architectures, getting or setting a field involves two
868 separate memory accesses. In the presence of data races, the user may
869 observe tearing on any operation.
870 *)
871
872 (**/**)
873
874 (** {1 Undocumented functions} *)
875
876 (* These functions are for system use only. Do not call directly. *)
877 external unsafe_get : t -> int -> float = "%floatarray_unsafe_get"
878 external unsafe_set : t -> int -> float -> unit = "%floatarray_unsafe_set"
879
880end
881(** Float arrays with packed representation. *)
882
883module ArrayLabels : sig
884 type t = floatarray
885 (** The type of float arrays with packed representation.
886 @since 4.08
887 *)
888
889 val length : t -> int
890 (** Return the length (number of elements) of the given floatarray. *)
891
892 val get : t -> int -> float
893 (** [get a n] returns the element number [n] of floatarray [a].
894 @raise Invalid_argument if [n] is outside the range 0 to
895 [(length a - 1)]. *)
896
897 val set : t -> int -> float -> unit
898 (** [set a n x] modifies floatarray [a] in place, replacing element
899 number [n] with [x].
900 @raise Invalid_argument if [n] is outside the range 0 to
901 [(length a - 1)]. *)
902
903 val make : int -> float -> t
904 (** [make n x] returns a fresh floatarray of length [n], initialized with [x].
905 @raise Invalid_argument if [n < 0] or [n > Sys.max_floatarray_length]. *)
906
907 val create : int -> t
908 (** [create n] returns a fresh floatarray of length [n],
909 with uninitialized data.
910 @raise Invalid_argument if [n < 0] or [n > Sys.max_floatarray_length]. *)
911
912 val init : int -> f:(int -> float) -> t
913 (** [init n ~f] returns a fresh floatarray of length [n],
914 with element number [i] initialized to the result of [f i].
915 In other terms, [init n ~f] tabulates the results of [f]
916 applied to the integers [0] to [n-1].
917 @raise Invalid_argument if [n < 0] or [n > Sys.max_floatarray_length]. *)
918
919 val make_matrix : dimx:int -> dimy:int -> float -> t array
920 (** [make_matrix ~dimx ~dimy e] returns a two-dimensional array
921 (an array of arrays) with first dimension [dimx] and
922 second dimension [dimy], where all elements are initialized with [e].
923
924 @raise Invalid_argument if [dimx] or [dimy] is negative or
925 greater than {!Sys.max_floatarray_length}.
926
927 @since 5.2 *)
928
929 val init_matrix : dimx:int -> dimy:int -> f:(int -> int -> float) -> t array
930 (** [init_matrix ~dimx ~dimy ~f] returns a two-dimensional array
931 (an array of arrays)
932 with first dimension [dimx] and second dimension [dimy],
933 where the element at index ([x,y]) is initialized with [f x y].
934
935 @raise Invalid_argument if [dimx] or [dimy] is negative or
936 greater than {!Sys.max_floatarray_length}.
937
938 @since 5.2 *)
939
940 val append : t -> t -> t
941 (** [append v1 v2] returns a fresh floatarray containing the
942 concatenation of the floatarrays [v1] and [v2].
943 @raise Invalid_argument if
944 [length v1 + length v2 > Sys.max_floatarray_length]. *)
945
946 val concat : t list -> t
947 (** Same as {!append}, but concatenates a list of floatarrays. *)
948
949 val sub : t -> pos:int -> len:int -> t
950 (** [sub a ~pos ~len] returns a fresh floatarray of length [len],
951 containing the elements number [pos] to [pos + len - 1]
952 of floatarray [a].
953 @raise Invalid_argument if [pos] and [len] do not
954 designate a valid subarray of [a]; that is, if
955 [pos < 0], or [len < 0], or [pos + len > length a]. *)
956
957 val copy : t -> t
958 (** [copy a] returns a copy of [a], that is, a fresh floatarray
959 containing the same elements as [a]. *)
960
961 val fill : t -> pos:int -> len:int -> float -> unit
962 (** [fill a ~pos ~len x] modifies the floatarray [a] in place,
963 storing [x] in elements number [pos] to [pos + len - 1].
964 @raise Invalid_argument if [pos] and [len] do not
965 designate a valid subarray of [a]. *)
966
967 val blit : src:t -> src_pos:int -> dst:t -> dst_pos:int -> len:int -> unit
968 (** [blit ~src ~src_pos ~dst ~dst_pos ~len] copies [len] elements
969 from floatarray [src], starting at element number [src_pos],
970 to floatarray [dst], starting at element number [dst_pos].
971 It works correctly even if
972 [src] and [dst] are the same floatarray, and the source and
973 destination chunks overlap.
974 @raise Invalid_argument if [src_pos] and [len] do not
975 designate a valid subarray of [src], or if [dst_pos] and [len] do not
976 designate a valid subarray of [dst]. *)
977
978 val to_list : t -> float list
979 (** [to_list a] returns the list of all the elements of [a]. *)
980
981 val of_list : float list -> t
982 (** [of_list l] returns a fresh floatarray containing the elements
983 of [l].
984 @raise Invalid_argument if the length of [l] is greater than
985 [Sys.max_floatarray_length].*)
986
987 (** {1:comparison Comparison} *)
988
989 val equal : eq:(float -> float -> bool) -> t -> t -> bool
990 (** [equal eq a b] is [true] if and only if [a] and [b] have the
991 same length [n] and for all [i] in \[[0];[n-1]\], [eq a.(i) b.(i)]
992 is [true].
993
994 @since 5.4 *)
995
996 val compare : cmp:(float -> float -> int) -> t -> t -> int
997 (** [compare cmp a b] compares [a] and [b] according to the shortlex order,
998 that is, shorter arrays are smaller and equal-sized arrays are compared
999 in lexicographic order using [cmp] to compare elements.
1000
1001 @since 5.4 *)
1002
1003 (** {1 Iterators} *)
1004
1005 val iter : f:(float -> unit) -> t -> unit
1006 (** [iter ~f a] applies function [f] in turn to all
1007 the elements of [a]. It is equivalent to
1008 [f a.(0); f a.(1); ...; f a.(length a - 1); ()]. *)
1009
1010 val iteri : f:(int -> float -> unit) -> t -> unit
1011 (** Same as {!iter}, but the
1012 function is applied with the index of the element as first argument,
1013 and the element itself as second argument. *)
1014
1015 val map : f:(float -> float) -> t -> t
1016 (** [map ~f a] applies function [f] to all the elements of [a],
1017 and builds a floatarray with the results returned by [f]. *)
1018
1019 val map_inplace : f:(float -> float) -> t -> unit
1020 (** [map_inplace f a] applies function [f] to all elements of [a],
1021 and updates their values in place.
1022 @since 5.1 *)
1023
1024 val mapi : f:(int -> float -> float) -> t -> t
1025 (** Same as {!map}, but the
1026 function is applied to the index of the element as first argument,
1027 and the element itself as second argument. *)
1028
1029 val mapi_inplace : f:(int -> float -> float) -> t -> unit
1030 (** Same as {!map_inplace}, but the function is applied to the index of the
1031 element as first argument, and the element itself as second argument.
1032 @since 5.1 *)
1033
1034 val fold_left : f:('acc -> float -> 'acc) -> init:'acc -> t -> 'acc
1035 (** [fold_left ~f x ~init] computes
1036 [f (... (f (f x init.(0)) init.(1)) ...) init.(n-1)],
1037 where [n] is the length of the floatarray [init]. *)
1038
1039 val fold_right : f:(float -> 'acc -> 'acc) -> t -> init:'acc -> 'acc
1040 (** [fold_right f a init] computes
1041 [f a.(0) (f a.(1) ( ... (f a.(n-1) init) ...))],
1042 where [n] is the length of the floatarray [a]. *)
1043
1044 (** {1 Iterators on two arrays} *)
1045
1046 val iter2 : f:(float -> float -> unit) -> t -> t -> unit
1047 (** [Array.iter2 ~f a b] applies function [f] to all the elements of [a]
1048 and [b].
1049 @raise Invalid_argument if the floatarrays are not the same size. *)
1050
1051 val map2 : f:(float -> float -> float) -> t -> t -> t
1052 (** [map2 ~f a b] applies function [f] to all the elements of [a]
1053 and [b], and builds a floatarray with the results returned by [f]:
1054 [[| f a.(0) b.(0); ...; f a.(length a - 1) b.(length b - 1)|]].
1055 @raise Invalid_argument if the floatarrays are not the same size. *)
1056
1057 (** {1 Array scanning} *)
1058
1059 val for_all : f:(float -> bool) -> t -> bool
1060 (** [for_all ~f [|a1; ...; an|]] checks if all elements of the floatarray
1061 satisfy the predicate [f]. That is, it returns
1062 [(f a1) && (f a2) && ... && (f an)]. *)
1063
1064 val exists : f:(float -> bool) -> t -> bool
1065 (** [exists f [|a1; ...; an|]] checks if at least one element of
1066 the floatarray satisfies the predicate [f]. That is, it returns
1067 [(f a1) || (f a2) || ... || (f an)]. *)
1068
1069 val mem : float -> set:t -> bool
1070 (** [mem a ~set] is true if and only if there is an element of [set] that is
1071 structurally equal to [a], i.e. there is an [x] in [set] such
1072 that [compare a x = 0]. *)
1073
1074 val mem_ieee : float -> set:t -> bool
1075 (** Same as {!mem}, but uses IEEE equality instead of structural equality. *)
1076
1077 (** {1 Array searching} *)
1078
1079 val find_opt : f:(float -> bool) -> t -> float option
1080 (* [find_opt ~f a] returns the first element of the array [a] that satisfies
1081 the predicate [f]. Returns [None] if there is no value that satisfies [f]
1082 in the array [a].
1083 @since 5.1 *)
1084
1085 val find_index : f:(float-> bool) -> t -> int option
1086 (** [find_index ~f a] returns [Some i], where [i] is the index of the first
1087 element of the array [a] that satisfies [f x], if there is such an
1088 element.
1089
1090 It returns [None] if there is no such element.
1091 @since 5.1 *)
1092
1093 val find_map : f:(float -> 'a option) -> t -> 'a option
1094 (* [find_map ~f a] applies [f] to the elements of [a] in order, and returns
1095 the first result of the form [Some v], or [None] if none exist.
1096 @since 5.1 *)
1097
1098 val find_mapi : f:(int -> float -> 'a option) -> t -> 'a option
1099 (** Same as [find_map], but the predicate is applied to the index of
1100 the element as first argument (counting from 0), and the element
1101 itself as second argument.
1102
1103 @since 5.1 *)
1104
1105 (** {1:sorting_and_shuffling Sorting and shuffling} *)
1106
1107 val sort : cmp:(float -> float -> int) -> t -> unit
1108 (** Sort a floatarray in increasing order according to a comparison
1109 function. The comparison function must return 0 if its arguments
1110 compare as equal, a positive integer if the first is greater,
1111 and a negative integer if the first is smaller (see below for a
1112 complete specification). For example, {!Stdlib.compare} is
1113 a suitable comparison function. After calling [sort], the
1114 array is sorted in place in increasing order.
1115 [sort] is guaranteed to run in constant heap space
1116 and (at most) logarithmic stack space.
1117
1118 The current implementation uses Heap Sort. It runs in constant
1119 stack space.
1120
1121 Specification of the comparison function:
1122 Let [a] be the floatarray and [cmp] the comparison function. The following
1123 must be true for all [x], [y], [z] in [a] :
1124 - [cmp x y] > 0 if and only if [cmp y x] < 0
1125 - if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0
1126
1127 When [sort] returns, [a] contains the same elements as before,
1128 reordered in such a way that for all i and j valid indices of [a] :
1129 - [cmp a.(i) a.(j)] >= 0 if i >= j
1130 *)
1131
1132 val stable_sort : cmp:(float -> float -> int) -> t -> unit
1133 (** Same as {!sort}, but the sorting algorithm is stable (i.e.
1134 elements that compare equal are kept in their original order) and
1135 not guaranteed to run in constant heap space.
1136
1137 The current implementation uses Merge Sort. It uses a temporary
1138 floatarray of length [n/2], where [n] is the length of the floatarray.
1139 It is usually faster than the current implementation of {!sort}. *)
1140
1141 val fast_sort : cmp:(float -> float -> int) -> t -> unit
1142 (** Same as {!sort} or {!stable_sort}, whichever is faster
1143 on typical input. *)
1144
1145 val shuffle :
1146 rand: (* thwart tools/sync_stdlib_docs *) (int -> int) -> t -> unit
1147 (** [shuffle ~rand a] randomly permutes [a]'s elements using [rand]
1148 for randomness. The distribution of permutations is uniform.
1149
1150 [rand] must be such that a call to [rand n] returns a uniformly
1151 distributed random number in the range \[[0];[n-1]\].
1152 {!Random.int} can be used for this (do not forget to
1153 {{!Random.self_init}initialize} the generator).
1154
1155 @since 5.2 *)
1156
1157 (** {1 Float arrays and Sequences} *)
1158
1159 val to_seq : t -> float Seq.t
1160 (** Iterate on the floatarray, in increasing order. Modifications of the
1161 floatarray during iteration will be reflected in the sequence. *)
1162
1163 val to_seqi : t -> (int * float) Seq.t
1164 (** Iterate on the floatarray, in increasing order, yielding indices along
1165 elements. Modifications of the floatarray during iteration will be
1166 reflected in the sequence. *)
1167
1168 val of_seq : float Seq.t -> t
1169 (** Create an array from the generator. *)
1170
1171
1172 val map_to_array : f:(float -> 'a) -> t -> 'a array
1173 (** [map_to_array ~f a] applies function [f] to all the elements of [a],
1174 and builds an array with the results returned by [f]:
1175 [[| f a.(0); f a.(1); ...; f a.(length a - 1) |]]. *)
1176
1177 val map_from_array : f:('a -> float) -> 'a array -> t
1178 (** [map_from_array ~f a] applies function [f] to all the elements of [a],
1179 and builds a floatarray with the results returned by [f]. *)
1180
1181 (** {1:floatarray_concurrency Arrays and concurrency safety}
1182
1183 Care must be taken when concurrently accessing float arrays from multiple
1184 domains: accessing an array will never crash a program, but unsynchronized
1185 accesses might yield surprising (non-sequentially-consistent) results.
1186
1187 {2:floatarray_atomicity Atomicity}
1188
1189 Every float array operation that accesses more than one array element is
1190 not atomic. This includes iteration, scanning, sorting, splitting and
1191 combining arrays.
1192
1193 For example, consider the following program:
1194 {[let size = 100_000_000
1195 let a = Float.ArrayLabels.make size 1.
1196 let update a f () =
1197 Float.ArrayLabels.iteri ~f:(fun i x -> Float.Array.set a i (f x)) a
1198 let d1 = Domain.spawn (update a (fun x -> x +. 1.))
1199 let d2 = Domain.spawn (update a (fun x -> 2. *. x +. 1.))
1200 let () = Domain.join d1; Domain.join d2
1201 ]}
1202
1203 After executing this code, each field of the float array [a] is either
1204 [2.], [3.], [4.] or [5.]. If atomicity is required, then the user must
1205 implement their own synchronization (for example, using {!Mutex.t}).
1206
1207 {2:floatarray_data_race Data races}
1208
1209 If two domains only access disjoint parts of the array, then the
1210 observed behaviour is the equivalent to some sequential interleaving of
1211 the operations from the two domains.
1212
1213 A data race is said to occur when two domains access the same array
1214 element without synchronization and at least one of the accesses is a
1215 write. In the absence of data races, the observed behaviour is equivalent
1216 to some sequential interleaving of the operations from different domains.
1217
1218 Whenever possible, data races should be avoided by using synchronization
1219 to mediate the accesses to the array elements.
1220
1221 Indeed, in the presence of data races, programs will not crash but the
1222 observed behaviour may not be equivalent to any sequential interleaving of
1223 operations from different domains. Nevertheless, even in the presence of
1224 data races, a read operation will return the value of some prior write to
1225 that location with a few exceptions.
1226
1227
1228 {2:floatarray_datarace_tearing Tearing }
1229
1230 Float arrays have two supplementary caveats in the presence of data races.
1231
1232 First, the blit operation might copy an array byte-by-byte. Data races
1233 between such a blit operation and another operation might produce
1234 surprising values due to tearing: partial writes interleaved with other
1235 operations can create float values that would not exist with a sequential
1236 execution.
1237
1238 For instance, at the end of
1239 {[let zeros = Float.Array.make size 0.
1240 let max_floats = Float.Array.make size Float.max_float
1241 let res = Float.Array.copy zeros
1242 let d1 = Domain.spawn (fun () -> Float.Array.blit zeros 0 res 0 size)
1243 let d2 = Domain.spawn (fun () -> Float.Array.blit max_floats 0 res 0 size)
1244 let () = Domain.join d1; Domain.join d2
1245 ]}
1246
1247 the [res] float array might contain values that are neither [0.]
1248 nor [max_float].
1249
1250 Second, on 32-bit architectures, getting or setting a field involves two
1251 separate memory accesses. In the presence of data races, the user may
1252 observe tearing on any operation.
1253 *)
1254
1255 (**/**)
1256
1257 (** {1 Undocumented functions} *)
1258
1259 (* These functions are for system use only. Do not call directly. *)
1260 external unsafe_get : t -> int -> float = "%floatarray_unsafe_get"
1261 external unsafe_set : t -> int -> float -> unit = "%floatarray_unsafe_set"
1262
1263end
1264(** Float arrays with packed representation (labeled functions). *)