Модуль Float.Array
module Array: sig .. end
Массивы чисел с плавающей точкой с упакованным представлением.
type t = floatarray
Тип массивов чисел с плавающей точкой с упакованным представлением.
- С тех пор как 4.08
val length : t -> int
Возвращает длину (количество элементов) заданного массива floatarray.
val get : t -> int -> float
get a n возвращает номер элемента n массива floatarray a.
-
Возвышает
Invalid_argumentеслиnнаходится вне диапазона от 0 до(length a - 1).
val set : t -> int -> float -> unit
set a n x изменяет массив floatarray a на месте, заменяя элемент с номером n на x.
-
Возвышает
Invalid_argumentеслиnнаходится вне диапазона от 0 до(length a - 1).
val make : int -> float -> t
make n x возвращает новый массив floatarray длиной n, инициализированный значением x.
-
Возвышает
Invalid_argumentеслиn < 0илиn > Sys.max_floatarray_length.
val create : int -> t
create n возвращает новый массив floatarray длиной n, с неинициализированными данными.
-
Возвышает
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.
-
Возвышает
Invalid_argumentеслиn < 0илиn > Sys.max_floatarray_length.
val make_matrix : int -> int -> float -> t array
make_matrix dimx dimy e возвращает двумерный массив (массив массивов) с первым измерением dimx и вторым измерением dimy, где все элементы инициализированы значением e.
- С тех пор как 5.2
-
Возвышает
Invalid_argumentеслиdimxилиdimyотрицательные или больше, чемSys.max_floatarray_length.
val init_matrix : int -> int -> (int -> int -> float) -> t array
init_matrix dimx dimy f возвращает двумерный массив (массив массивов) с первым измерением dimx и вторым измерением dimy, где элемент с индексом (x,y) инициализирован значением f x y.
- С тех пор как 5.2
-
Возвышает
Invalid_argumentеслиdimxилиdimyотрицательные или больше, чемSys.max_floatarray_length.
val append : t -> t -> t
append v1 v2 возвращает новый массив floatarray, содержащий конкатенацию массивов floatarrays v1 и v2.
-
Возвышает
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.
-
Возвышает
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.
-
Возвышает
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, и блоки источника и назначения перекрываются.
-
Возвышает
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.
-
Возвышает
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 map_inplace : (float -> float) -> t -> unit
map_inplace f a применяет функцию f к каждому элементу a и изменяет их значения на месте.
- С тех пор как 5.1
val mapi : (int -> float -> float) -> t -> t
То же, что и Float.Array.map, но функция применяется к индексу элемента в качестве первого аргумента, а сам элемент — как второй аргумент.
val mapi_inplace : (int -> float -> float) -> t -> unit
То же, что и Float.Array.map_inplace, но функция применяется к индексу элемента в качестве первого аргумента, а сам элемент — как второй аргумент.
- С тех пор как 5.1
val fold_left : ('acc -> float -> 'acc) -> 'acc -> t -> 'acc
fold_left f x init вычисляет f (... (f (f x init.(0)) init.(1)) ...) init.(n-1), где n — длина массива floatarray init.
val fold_right : (float -> 'acc -> 'acc) -> t -> 'acc -> 'acc
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.
-
Возвышает
Invalid_argumentесли массивы floatarray имеют разную длину.
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)|].
-
Возвышает
Invalid_argumentесли массивы floatarray имеют разную длину.
Сканирование массивов
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 find_opt : (float -> bool) -> t -> float option
val find_index : (float -> bool) -> t -> int option
find_index f a возвращает Some i, где i — индекс первого элемента массива a, удовлетворяющего условию f x, если такой элемент существует.
В противном случае возвращает None.
- Since 5.1
val find_map : (float -> 'a option) -> t -> 'a option
val find_mapi : (int -> float -> 'a option) -> t -> 'a option
Аналогично find_map, но предикат применяется к индексу элемента (считая с 0) в качестве первого аргумента и к самому элементу — как второму аргументу.
- Since 5.1
Сортировка и перемешивание
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 shuffle : rand:(int -> int) -> t -> unit
shuffle rand a случайным образом переупорядочивает элементы a с использованием rand для генерации случайности. Распределение перестановок равномерное.
rand должно обеспечивать, чтобы вызов rand n возвращал равномерно распределённое случайное число в диапазоне [0;n-1]. Можно использовать Random.int (не забудьте инициализировать генератор).
- Since 5.2
Массивы float и последовательности
val to_seq : t -> float Seq.t
Итерируется по floatarray в порядке возрастания индексов. Изменения в floatarray во время итерации будут отражены в последовательности.
val to_seqi : t -> (int * float) Seq.t
Итерируется по floatarray в порядке возрастания индексов, возвращая индексы вместе с элементами. Изменения в floatarray во время итерации будут отражены в последовательности.
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 и строит массив floatarray с результатами, возвращёнными функцией f.
Массивы и безопасность потоков
При одновременном доступе к массивам float из нескольких доменов необходимо соблюдать осторожность: доступ к массиву никогда не приведёт к аварийному завершению программы, но несинхронизированные обращения могут привести к неожиданным (непоследовательным) результатам.
Атомарность
Каждая операция с float array, которая обращается к большему количеству, чем одному элементу массива, не является атомарной. Это включает итерацию, сканирование, сортировку, разделение и объединение массивов.
Например, рассмотрим следующую программу:
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
После выполнения этого кода каждый элемент float array a будет либо 2., либо 3., либо 4., либо 5.. Если требуется атомарность, то пользователь должен реализовать свою собственную синхронизацию (например, используя Mutex.t).
Конфликты данных
Если два домена обращаются только к непересекающимся частям массива, то наблюдаемое поведение эквивалентно некоторому последовательному переплетению операций из двух доменов.
Конфликт данных возникает, когда два домена обращаются к одному и тому же элементу массива без синхронизации, и по крайней мере одно из обращений является записью. При отсутствии конфликтов данных наблюдаемое поведение эквивалентно некоторому последовательному переплетению операций из разных доменов.
По возможности следует избегать конфликтов данных, используя синхронизацию для управления доступом к элементам массива.
Действительно, при наличии конфликтов данных программы не завершатся аварийно, но наблюдаемое поведение может не эквивалентно никакому последовательному переплетению операций из разных доменов. Тем не менее, даже при наличии конфликтов данных операция чтения вернёт значение некоторой предыдущей записи в это место с некоторыми исключениями.
Разрывы
Массивы float имеют два дополнительных замечания в случае конфликтов данных.
Во-первых, операция blit может копировать массив байт за байтом. Конфликты данных между такой операцией blit и другой операцией могут привести к неожиданным значениям из-за разрыва: частичные записи, переплетённые с другими операциями, могут создать значения float, которые не существовали бы при последовательном выполнении.
Например, в конце
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 float может содержать значения, которые не являются ни 0., ни max_float.
Во-вторых, на 32-разрядных архитектурах получение или установка поля включает в себя два отдельных обращения к памяти. В случае конфликтов данных пользователь может наблюдать разрывы в любой операции.
© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/api/Float.Array.html