macro_rules! declare_array_real {
( $name:ident, $N:expr, $T:ty ) => { ... };
}Expand description
This macro implements a type which consists of an array of fixed-point numberts of size N. Complete with the traits shown below.
§Arguments
name- The name of the array type. E.g. Arr4.N- The length of the array. E.g 4.T- The fixed type of the elements.
§Example
Arrays types of fixed size is defined with traits through the macro as follows:
use integer_array as ia;
use integer_array::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
// Declare the type.
integer_array::declare_array_real!( Arr11, 11, FixedI32<U20> );The name of the type for the above array is Arr11. The size of the error is 11 elements, and it has 18 fractional bits.
The implemented traits are documented below. See the source for a complete list.
§Initialization
The array can be initalized with a single value across the array, or by creating a ramp.
§Generate an array of zeros.
zeros is made as separate trait for convenience.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::zeros();
assert_eq!{x.as_array_i32(), [0, 0]};§::new
For creating an array with a specific value.
§Arguments
value- The falue to fill each item with.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::new(FixedI32::<U20>::from_num(200));
assert_eq!{x.as_array_i32(), [200, 200]};To simplify decleration of arrays, float and int types are sypported through the following methods.
::new_from_i32( value ), ::new_from_f32( value ) and ::new_from_f64( value ).
§::ones
ones is made as separate trait for convenience.
It generates an array of ones.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::ones();
assert_eq!{x.as_array_i32(), [1,1]};§::ramp
Generate an array of increasing value.
§Arguments
start- The starting value (of item 0).step- The incrimental value.
§Example
ramp_from_f32( value ) is added for convenience, but using ´ramp( value )´ with a value of the correct fixed type is also supported.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 4, FixedI32<U20> );
let x = Arr4::ramp_from_f32(100.0,20.0);
assert_eq!{x.as_array_i32(), [100, 120, 140, 160] };§::front and ::back:
Access the first element of the array using the .front() trait.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::new(FixedI32::<U20>::from_num(200));
assert_eq!{x.front(), 200};Access the last element of the array using the .back() trait.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr32, 32, FixedI32<U20> );
let x = Arr32::ramp_from_f32(100.0,20.0);
assert_eq!{x.back(), 720};§::at
A specific item can be accessed through either using square bracket notation, or .at( index ).
§Arguments
index- The index of the item, in the range 0..N-1.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::zeros();
assert_eq!{x.at(1), 0};§Bracket indexing
Square bracket indexing can be used both for reading and writing from/to an item.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let x = Arr8::ramp_from_f32(0.0,22.0);
assert_eq!{x[2], 44i32 };use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let mut x = Arr8::ramp_from_f32(0.0,22.0);
x[2] = FixedI32::<U20>::from_num(56);
assert_eq!{x[2], 56i32 };§::bias
The bias trai adds a scalar bias to every element in the array.
§::odd and ::even
Get the items in the odd or even indexes as an array.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let x = Arr8::ramp_from_f32(0.0,22.0);
let y = x.odd();
assert_eq!{y, [22, 66, 110, 154] };use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let x = Arr8::ramp_from_f32(0.0,22.0);
let y = x.even();
assert_eq!{y, [0, 44, 88, 132] };§::bias
The bias trai adds a scalar bias to every element in the array.
§Arguments
value- The bias amount.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::new_from_i32(200);
let y = x.bias_f32(0.25);
assert_eq!{y.front(), 200.25};The bias can also be implemented by adding or subtracting the array with a scalar.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 8, FixedI32<U20> );
let mut x = Arr4::ramp_from_f32(0.0,22.0);
x = x+3;
assert_eq!{x[1], 25i32 };
let mut x = Arr4::ramp_from_f32(0.0,22.0);
x = x-3;
assert_eq!{x[1], 19i32 };§::scale
The scale trait scales every element in the array with a scalar value.
§Arguments
value- The scaling factor.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr2, 2, FixedI32<U20> );
let x = Arr2::new_from_i32(100);
let y = x.scale_f32(5.0);
assert_eq!{y.front(), 500};Scaling can also be used by simply multiplying the array with a scalar value.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let mut x = Arr8::ramp_from_f32(0.0,22.0);
x = x*3;
assert_eq!{x[1], 66i32 };or through a division.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 4, FixedI32<U20> );
let mut x = Arr4::ramp_from_f32(0.0,22.0);
x = 1000/x;
assert_eq!{x.as_array_f32(), [2048.0, 45.454544, 22.727272, 15.151515] };§::sqrt
The sqrt trait finds the item-wise square root of array.
§Argument
error- The gratest allowed error in the numerical method.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 4, FixedI32<U20> );
let x = Arr4::ramp_from_f32(18.0, 10.0);
let y = x.sqrt( FixedI32::<U20>::from_num(0.1) );
assert_eq!{ y[1], 5.300915f32 };§Array operations
Operations can also be performed on an inter-array-basis. The arrays must be of the same size. The operations are written similarly as one would for scalars in Rust.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 4, FixedI32<U20> );
let mut x = Arr4::ramp_from_f32(0.0,22.0);
let y = Arr4::new_from_i32(10);
x = x+y;
assert_eq!{x.as_array_i32(), [10,32,54,76] };
x = x-y;
assert_eq!{x.as_array_i32(), [0,22,44,66] };use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 4, FixedI32<U20> );
let mut x = Arr4::ramp_from_f32(10.0,22.0);
let y = Arr4::new_from_i32(10);
x = x*y;
assert_eq!{x.data, [100,320,540,760] };
x = Arr4::ramp_from_f32(0.0,22.0);
x = x/y;
assert_eq!{x.as_array_i32(), [0,2,4,6] };In a divide-by-zero case, the maximum int value is returned.
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr4, 4, FixedI32<U20> );
let mut x = Arr4::ramp_from_f32(0.0,22.0);
let y = Arr4::new_from_i32(1);
x = y/x;
assert_eq!{x.as_array_f32(), [2048.0, 0.045454025, 0.022727013, 0.015151024] };§::wrap_phase
Wrap array to a fixed-point -π=<x<π range.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let x = Arr8::ramp_from_f32(0.0, 3.1415/3.0);
let y = x.wrap_phase();
assert_eq!{ y.as_array_f32(), [0.0, 1.0471668, 2.0943336, 3.1415005, -2.0945168, -1.0473499, -0.00018310547, 1.0469837] };§::sin
Take the elemtent-wise sine using a Taylor approximation of sine x.
Sin is calculated using the following polynomial:
sin(x) = x -( x^3/6.0 )+( x^5/120.0 )-( x^7/5040.0 )+( x^9/362880.0 )
Self must be wrapped to the -π=<x<π range.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let mut x = Arr8::ramp_from_f32(0.0,3.1415/6.0);
x = x.wrap_phase();
let y = x.sin();
assert_eq!{ y.as_array_f32(), [0.0, 0.49998665, 0.8660097, 1.0000038, 0.86605644, 0.50006676, 0.000091552734, -0.4999075] };Below is the the taylor approximation for sine compared to the Julia native sin function.
The below plot is generated with double presicion floationg point for demonstrative purposes.
In the figure it is apparent that there is greater error in the Taylor approximation further from origo.
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, are used for all values of x.
Resulting in a practically ideal sine function, as can be seen in the frequency domain comparison below.

§::cos
Take the elemtent-wise cosine using a Taylor approximation of cos x.
Cos is calculated using the following polynomial:
cos(x) = 1 -( x^2/2 )+( x^4/24.0 )-( x^6/720.0 )+( x^8/40320.0 )
Self must be wrapped to the -π=<x<π range.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U20> );
let mut x = Arr8::ramp_from_f32(0.0,60.0);
x = x.wrap_phase( );
let y = x.cos();
assert_eq!{ y.as_array_f32(), [1.0, -0.95240974, 0.814167, -0.5984316, 0.3257389, -0.022058487, -0.2837639, 0.56254864] };A first-quarter method as described for the sine implementation is also used on cosine. The pure Taylor approximation is displayed below.
With the first-quarter method, the resulting cosine power spectrum is displayed below.

§::tan
Take the element-wise tan using a Taylor approximation of tan x.
Tan is calculated using the following polynomial:
tan(x) = x+( x^3/3 )+( x^5*2/15.0 )+( x^7*17/315.0 )+( x^9*62/2835.0 )+( x^11*1382/155925.0 )+( x^13*21844/6081075.0 )+( x^15*929569/638512875.0 )
Self must be wrapped to the -π/2=<x<π/2 range. The function is based on a Taylor expansion. Its error increases as |x| approaches π/2.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U4, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U4> );
let x = Arr8::ramp_from_f32(0.0,0.17);
let y = x.tan();
assert_eq!{ y.as_array_f32(), [0.0, 0.1875, 0.375, 0.5625, 0.875, 1.25, 1.6875, 2.5625] };Below is the the taylor approximation for tan compared to the Julia native tan function.
The below plot is generated with double presicion floationg point for demonstrative purposes.

§::atan
Calculate atan(x) using a polynomial approximation. Utilizes the following polynomial to estimate the angle θ [radians].
atan(x) = ((x)+0.372003(x)^3) / (1+0.703384(x)^2 + 0.043562(x)^4)
The method is accurat within 0.003 degrees when |θ|<=π/4.
[1] R. G. Lyons, Streamlining Digital Signal Processing, Second Etition, IEEE Press, 2012.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U4, FixedI32};
ia::declare_array_real!( Arr8, 8, FixedI32<U4> );
let x = Arr8::ramp_from_f32(0.0,0.1);
let y = x.atan();
assert_eq!{ y.as_array_f32(), [0.0, 0.125, 0.25, 0.3125, 0.4375, 0.5, 0.625, 0.6875] };§::max and ::min
The maimum and minimum value in the array can be found through the .max() and .min() traits respectively.
§Examples
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr32, 32, FixedI32<U20> );
let x = Arr32::ramp_from_f32(100.0,20.0);
assert_eq!{x.max(), 720};use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr32, 32, FixedI32<U20> );
let x = Arr32::ramp_from_f32(100.0,20.0);
assert_eq!{x.min(), 100};§::argmax and ::argmin
The index of the maximum and minimum items in the array can be found through the .argmax() and .argmin() traits respectively.
§Example
use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr32, 32, FixedI32<U20> );
let x = Arr32::ramp_from_f32(0.0,1.0);
assert_eq!{x.argmax(), 31};use integer_array as ia;
use ia::trait_definitions::*;
use fixed::{types::extra::U20, FixedI32};
ia::declare_array_real!( Arr32, 32, FixedI32<U20> );
let x = Arr32::ramp_from_f32(100.0,20.0);
assert_eq!{x.argmin(), 0};