Integer-Array
No-STD numeric fixed-size array for Rust.
This is an experimental library for no-std DSP. The library only supports fixed-sized arrays of i32. 32-bit arrays can be handled by most DSP-capable embedded devices and provides 6.02×32>192 dB of dynamic range, which is sufficient for most DSP use. The rationale is that if 64-bit processing is available, then so is an OS, and the Rust standard library.
See the main workings of the library in /src/real/array.rs.
Use example
arrays types of fixed size is defined with traits through a macro as follows:
use integer_array as ia;
use *;
declare_array_real!;
The name of the type for the above array is Arr11
. The size of the error is 11 elements.
Initialization
The array can be initalized with a single value across the array, or by creating a ramp.
!;
let x = new;
assert_eq!;
declare_array_real
Zeros is made as a separate trait for convenience.
!;
let x = zeros;
assert_eq!;
declare_array_real
Indexing
The elements of the array can be indexed using square brackets as normal arrays
!;
let mut x = ramp;
x = -x;
assert_eq!;
declare_array_real
In addition to this, there are utilities such as .front()
and .back()
.
!;
let x = new;
let y = x.bias;
assert_eq!;
declare_array_real
Element-wise arithmetic
Math can then be performed on the array types, like one would expect from a modern language.
let mut x = new;
let y = new;
x = x/y;
assert_eq!;
array-scalar operations
There is also some support for array-scalar operations.
!;
let mut x = ramp;
x = x+3;
assert_eq!;
declare_array_real
Esimator utilities
The arrays are equipped with traits for estimators, such as var, mean, max min and argmax.
!;
let x = ramp;
assert_eq!;
declare_array_real
Sine generation
As this is a no-std library a cusom sine function is implemented. It utilizes a fifth order tailor approximation of sin(x). The trait implementation utilizes floating point multiplications, but returns a fixed point numeric array.
The following polynomial is used:
sin(x) = x-( x^3/6.0 )+( x^5/120.0 )-( x^7/5040.0 )+( x^9/362880.0 )
Below is the taylor approwimation compared to the native sine function, generated in Julia:
The error of the Taylor aproximation is magnified by 100 and showed as well. In the figure it is apparent that there is greater error in the Taylor approximation further from origo.
The error allthough small, introduces strong harmonic components, which can be seen below. These limits the practicality of the resulting signal.
To counter these, the fact that all quarters of the sine(x) function are mirrored versions of each other. Therefore the first quarters, having the least error, which can be seen in the time domain plot above, can be used for all values of x, with the below correction:
The function below is written in Julia, see /src/real/array.rs for the Rust implementation.
function sine( x::Float64 )
if x < -π/2
x = -π/2 + abs(x+π/2);
elseif π/2 < x
x = π/2 - abs(x-π/2);
end
return x-( x^3/6.0 )+( x^5/120.0 )-( x^7/5040.0 )+( x^9/362880.0 );
end
The resulting spectrum is shown below. Note that these plots are generated using 64-bit floating point arithemtic, not integers as in this Rust library.
This is a vast improvement showing close to no reduction in Singal to Noise and Distortion (SiNaD) compared to the native sine function in the Julia language.
The sin(x) function is used as follows:
!;
let mut x = ramp;
x = x.wrap_phase;
assert_eq!;
declare_array_real
The numerical comparison can be found in numerical_verificatons/numerical_verificaton.jl.