My working unpac repository
at opam/upstream/seq 1264 lines 50 kB view raw
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). *)