1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! SIMD-vectorized implementations of operations used in neural networks.
//!
//! These implementations are used as kernels for operations in the
//! [rten](https://crates.io/crates/rten) crate.
//!
//! ## Constructing and dispatching operations
//!
//! The operations are implemented by structs which implement the SIMD operation
//! traits from [rten-simd](rten_simd). To apply an operation to data, first
//! construct the operation using the struct from this crate, then use a
//! dispatch method from the [`SimdOp`](rten_simd::SimdOp) or
//! [`SimdUnaryOp`](rten_simd::SimdUnaryOp) traits to execute
//! the operation.
//!
//! ## In-place and non in-place operations
//!
//! Some operations support both updating data in place or reading input from
//! one slice and writing to another. For unary operations this is controlled by
//! dispatching with either [`map`](rten_simd::SimdUnaryOp::map) or
//! [`map_mut`](rten_simd::SimdUnaryOp::map_mut). For other operations
//! this is handled by exposing different constructors for the in-place and
//! mutating cases, such as [`Softmax::new`] and [`Softmax::new_mut`].
//!
//! For operations which use a separate source and destination, the destination
//! is expected to be an uninitialized slice (`[MaybeUninit<T>]`). This allows
//! the caller to control allocation of the buffer and avoid the overhead of
//! initializing elements which the operation will overwrite. The [`ExtendInit`]
//! trait provides a safe API for the common task of filling a new `Vec` with
//! the result of the operation.
//!
//! ## Examples
//!
//! ### Applying a vectorized unary function
//!
//! ```
//! use std::mem::MaybeUninit;
//!
//! use rten_simd::SimdUnaryOp;
//! use rten_vecmath::Erf;
//!
//! // Apply the error function to each element of `data`.
//! let mut data = [1., 0.5, 2.0];
//! let erf_op = Erf {};
//! erf_op.map_mut(&mut data);
//!
//! // Apply the error function to each element of `src`, writing to `dest`.
//! let src = [1., 0.5, 2.0];
//! let mut dest = [MaybeUninit::uninit(); 3];
//! erf_op.map(&src, &mut dest);
//! ```
//!
//! ### Applying softmax in place
//!
//! This example applies the softmax function in-place to a mutable slice.
//!
//! ```
//! use rten_simd::SimdOp;
//! use rten_vecmath::Softmax;
//!
//! let mut data = [1., 0.5, 2.0];
//! Softmax::new_mut(&mut data).dispatch();
//! ```
//!
//! ### Applying softmax with separate input and output buffers
//!
//! This example reads data from an input and writes to an uninitialized output
//! buffer (`&mut [MaybeUninit<f32>]`), obtained from the uninitialized portion
//! of a `Vec<f32>`. To update the length of the `Vec<f32>` after it is
//! initialized, the helper `ExtendInit` trait is used.
//!
//! ```
//! use rten_simd::SimdOp;
//! use rten_vecmath::{Softmax, ExtendInit};
//!
//! let data = [1., 0.5, 2.0];
//! let mut output = Vec::with_capacity(data.len());
//! output.extend_init(|output_uninit| {
//! // `output_uninit` is the uninitialized part of `output`, as returned by
//! // `output.spare_capacity_mut()`.
//! //
//! // The `dispatch` call initializes it and returns the initialized slice.
//! Softmax::new(&data, output_uninit).dispatch()
//! });
//! assert_eq!(output.len(), 3);
//! ```
//!
//! ### Computing the sum of a list of floats
//!
//! ```
//! use rten_simd::SimdOp;
//! use rten_vecmath::Sum;
//!
//! let data = [1., 0.5, 2.0];
//! let sum = Sum::new(&data).dispatch();
//! ```
// Unary functions.
pub use ;
pub use ;
pub use Quantize;
pub use LeakyRelu;
pub use ;
pub use Tanh;
// Normalization and reduction functions.
pub use ;
pub use ;
pub use Softmax;
pub use ;
// Utilities
pub use ExtendInit;