Модуль Float.Array
module Array: sig .. end
Массивы с плавающей точкой с упакованным представлением.
type t = floatarray
Тип массивов с плавающей точкой с упакованным представлением.
- Since 4.08.0
val length : t -> int
Возвращает длину (количество элементов) данного floatarray.
val get : t -> int -> float
get a n возвращает элемент с номером n floatarray a.
-
Raises
Invalid_argumentеслиnнаходится вне диапазона от 0 до(length a - 1).
val set : t -> int -> float -> unit
set a n x изменяет floatarray a на месте, заменяя элемент с номером n на x.
-
Raises
Invalid_argumentеслиnнаходится вне диапазона от 0 до(length a - 1).
val make : int -> float -> t
make n x возвращает новый floatarray длины n, инициализированный значением x.
-
Raises
Invalid_argumentеслиn < 0илиn > Sys.max_floatarray_length.
val create : int -> t
create n возвращает новый floatarray длины n, с неинициализированными данными.
-
Raises
Invalid_argumentеслиn < 0илиn > Sys.max_floatarray_length.
val init : int -> (int -> float) -> t
init n f возвращает новый floatarray длины n, с элементом с номером i инициализированным результатом f i. Другими словами, init n f табулирует результаты применения f к целым числам 0 по n-1.
-
Raises
Invalid_argumentеслиn < 0илиn > Sys.max_floatarray_length.
val append : t -> t -> t
append v1 v2 возвращает новый floatarray, содержащий конкатенацию floatarrays v1 и v2.
-
Raises
Invalid_argumentеслиlength v1 + length v2 > Sys.max_floatarray_length.
val concat : t list -> t
То же, что и Float.Array.append, но конкатенирует список floatarrays.
val sub : t -> int -> int -> t
sub a pos len возвращает новый floatarray длины len, содержащий элементы с номерами pos по pos + len - 1 floatarray a.
-
Raises
Invalid_argumentеслиposиlenне обозначают допустимый подмассивa; то есть, еслиpos < 0, илиlen < 0, илиpos + len > length a.
val copy : t -> t
copy a возвращает копию a, то есть новый floatarray, содержащий те же элементы, что и a.
val fill : t -> int -> int -> float -> unit
fill a pos len x изменяет floatarray a на месте, сохраняя x в элементы с номерами pos по pos + len - 1.
-
Raises
Invalid_argumentеслиposиlenне обозначают допустимый подмассивa.
val blit : t -> int -> t -> int -> int -> unit
blit src src_pos dst dst_pos len копирует len элементов из floatarray src, начиная с элемента с номером src_pos, в floatarray dst, начиная с элемента с номером dst_pos. Это работает правильно даже если src и dst являются одним и тем же floatarray, и фрагменты источника и назначения перекрываются.
-
Raises
Invalid_argumentеслиsrc_posиlenне обозначают допустимый подмассивsrc, или еслиdst_posиlenне обозначают допустимый подмассивdst.
val to_list : t -> float list
to_list a возвращает список всех элементов a.
val of_list : float list -> t
of_list l возвращает новый floatarray, содержащий элементы l.
-
Raises
Invalid_argumentесли длинаlбольшеSys.max_floatarray_length.
Итераторы
val iter : (float -> unit) -> t -> unit
iter f a последовательно применяет функцию f ко всем элементам a. Эквивалентно f a.(0); f a.(1); ...; f a.(length a - 1); ().
val iteri : (int -> float -> unit) -> t -> unit
То же, что и Float.Array.iter, но функция применяется к индексу элемента в качестве первого аргумента, а сам элемент - в качестве второго.
val map : (float -> float) -> t -> t
map f a применяет функцию f к всем элементам a, и создаёт floatarray с результатами, возвращаемыми f.
val mapi : (int -> float -> float) -> t -> t
То же, что и Float.Array.map, но функция применяется к индексу элемента в качестве первого аргумента, а сам элемент - в качестве второго.
val fold_left : ('a -> float -> 'a) -> 'a -> t -> 'a
fold_left f x init вычисляет f (... (f (f x init.(0)) init.(1)) ...) init.(n-1), где n - длина floatarray init.
val fold_right : (float -> 'a -> 'a) -> t -> 'a -> 'a
fold_right f a init вычисляет f a.(0) (f a.(1) ( ... (f a.(n-1) init) ...)), где n - длина floatarray a.
Итераторы на двух массивах
val iter2 : (float -> float -> unit) -> t -> t -> unit
Array.iter2 f a b применяет функцию f ко всем элементам a и b.
-
Raises
Invalid_argumentесли floatarrays не имеют одинаковый размер.
val map2 : (float -> float -> float) -> t -> t -> t
map2 f a b применяет функцию f ко всем элементам a и b, и создаёт floatarray с результатами, возвращаемыми f: [| f a.(0) b.(0); ...; f a.(length a - 1) b.(length b - 1)|].
-
Raises
Invalid_argumentесли floatarrays не имеют одинаковый размер.
Сканирование массивов
val for_all : (float -> bool) -> t -> bool
for_all f [|a1; ...; an|] проверяет, удовлетворяют ли все элементы floatarray предикату f. То есть, возвращает (f a1) && (f a2) && ... && (f an).
val exists : (float -> bool) -> t -> bool
exists f [|a1; ...; an|] проверяет, удовлетворяет ли хотя бы один элемент floatarray предикату f. То есть, возвращает (f a1) || (f a2) || ... || (f an).
val mem : float -> t -> bool
mem a set истинно тогда и только тогда, когда существует элемент set структурно равный a, т.е. существует x в set такой, что compare a x = 0.
val mem_ieee : float -> t -> bool
То же, что и Float.Array.mem, но использует IEEE сравнение вместо структурного.
Сортировка
val sort : (float -> float -> int) -> t -> unit
Сортирует floatarray в порядке возрастания согласно функции сравнения. Функция сравнения должна возвращать 0, если её аргументы равны, положительное целое число, если первый больше, и отрицательное целое число, если первый меньше (см. полное описание ниже). Например, compare - подходящая функция сравнения. После вызова sort, массив сортируется на месте в порядке возрастания. sort гарантированно выполняется с постоянным объёмом памяти и (максимум) логарифмическим стеком.
Текущая реализация использует сортировку кучей. Она выполняется с постоянным объёмом стека.
Спецификация функции сравнения: Пусть a - floatarray, а cmp - функция сравнения. Следующее должно быть истинно для всех x, y, z в a :
-
cmp x y> 0 тогда и только тогда, когдаcmp y x< 0 - если
cmp x y>= 0 иcmp y z>= 0, тоcmp x z>= 0
Когда sort завершается, a содержит те же элементы, что и до сортировки, но переупорядоченные так, что для всех i и j - допустимых индексов a:
-
cmp a.(i) a.(j)>= 0 тогда и только тогда, когда i >= j
val stable_sort : (float -> float -> int) -> t -> unit
То же, что и Float.Array.sort, но алгоритм сортировки стабилен (т.е. элементы, которые сравниваются как равные, сохраняются в исходном порядке) и не гарантированно выполняется с постоянным объёмом памяти.
Текущая реализация использует сортировку слиянием. Она использует временный floatarray длиной n/2, где n - длина floatarray. Обычно быстрее текущей реализации Float.Array.sort.
val fast_sort : (float -> float -> int) -> t -> unit
Аналогично Float.Array.sort или Float.Array.stable_sort, что быстрее на типичных входных данных.
Массивы с плавающей запятой и последовательности
val to_seq : t -> float Seq.t
Итерироваться по массиву с плавающей запятой в порядке возрастания. Изменения массива с плавающей запятой во время итерации будут отражены в последовательности.
val to_seqi : t -> (int * float) Seq.t
Итерироваться по массиву с плавающей запятой в порядке возрастания, возвращая индексы элементов. Изменения массива с плавающей запятой во время итерации будут отражены в последовательности.
val of_seq : float Seq.t -> t
Создать массив из генератора.
val map_to_array : (float -> 'a) -> t -> 'a array
map_to_array f a применяет функцию f ко всем элементам a, и создаёт массив с результатами, возвращаемыми f: [| f a.(0); f a.(1); ...; f a.(length a - 1) |].
val map_from_array : ('a -> float) -> 'a array -> t
map_from_array f a применяет функцию f ко всем элементам a, и создаёт массив с плавающей запятой с результатами, возвращаемыми f.
Массивы и безопасность конкурентного доступа
Следует соблюдать осторожность при одновременном доступе к массивам с плавающей запятой из нескольких областей: доступ к массиву никогда не приведёт к аварийному завершению программы, но несинхронизированный доступ может привести к неожиданным (непоследовательным) результатам.
Атомарность
Каждая операция над массивом с плавающей запятой, которая обращается к более чем одному элементу массива, не является атомарной. Это включает итерацию, сканирование, сортировку, разделение и объединение массивов.
Например, рассмотрим следующую программу:
let size = 100_000_000
let a = Float.Array.make size 1.
let update a f () =
Float.Array.iteri (fun i x -> Float.Array.set a i (f x)) a
let d1 = Domain.spawn (update a (fun x -> x +. 1.))
let d2 = Domain.spawn (update a (fun x -> 2. *. x +. 1.))
let () = Domain.join d1; Domain.join d2
После выполнения этого кода каждый элемент массива с плавающей запятой a имеет значение 2., 3., 4. или 5.. Если требуется атомарность, пользователь должен реализовать свою собственную синхронизацию (например, используя Mutex.t).
Конфликты данных
Если две области доступа обращаются только к непересекающимся частям массива, то наблюдаемое поведение эквивалентно некоторому последовательному переплетению операций из двух областей.
Конфликт данных возникает, когда две области доступа обращаются к одному элементу массива без синхронизации, и по крайней мере одна из этих обращений является записью. В отсутствие конфликтов данных наблюдаемое поведение эквивалентно некоторому последовательному переплетению операций из различных областей.
По возможности конфликты данных следует избегать, используя синхронизацию для управления доступом к элементам массива.
Действительно, в случае конфликтов данных программы не завершатся аварийно, но наблюдаемое поведение может не эквивалентно никакому последовательному переплетению операций из разных областей. Тем не менее, даже при наличии конфликтов данных операция чтения вернёт значение некоторой предыдущей записи в эту локацию за некоторыми исключениями.
Разрывы
Массивы с плавающей запятой имеют два дополнительных оговорённых случая при наличии конфликтов данных.
Во-первых, операция копирования может копировать массив байт за байтом. Конфликты данных между такой операцией копирования и другой операцией могут привести к неожиданным значениям из-за разрывов: частичные записи, переплетённые с другими операциями, могут создать значения с плавающей запятой, которые не существовали бы при последовательном выполнении.
Например, в конце
let zeros = Float.Array.make size 0. let max_floats = Float.Array.make size Float.max_float let res = Float.Array.copy zeros let d1 = Domain.spawn (fun () -> Float.Array.blit zeros 0 res 0 size) let d2 = Domain.spawn (fun () -> Float.Array.blit max_floats 0 res 0 size) let () = Domain.join d1; Domain.join d2
массив с плавающей запятой res может содержать значения, которые не являются ни 0., ни max_float.
Во-вторых, на 32-битных архитектурах получение или установка элемента включает два отдельных обращения к памяти. В случае конфликтов данных пользователь может наблюдать разрывы при любой операции.
© 1995-2022 INRIA.
https://v2.ocaml.org/releases/5.0/htmlman/libref/Float.Array.html