Spec-Zone.ru › OCaml

Модуль 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API