init
This commit is contained in:
72
lib_xcore_math/tests/shared/floating_fft/floating_dct.c
Normal file
72
lib_xcore_math/tests/shared/floating_fft/floating_dct.c
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
|
||||
#include "floating_dct.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void flt_dct_forward(
|
||||
float output[],
|
||||
float input[],
|
||||
const unsigned DCT_N)
|
||||
{
|
||||
for(unsigned int k = 0; k < DCT_N; k++){
|
||||
output[k] = 0.0;
|
||||
for(unsigned int n = 0; n < DCT_N; n++){
|
||||
float c = cosf( k * ((float) M_PI) * (2*n + 1) / (2.0f * DCT_N));
|
||||
output[k] += input[n] * c;
|
||||
}
|
||||
output[k] *= 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void flt_dct_inverse(
|
||||
float output[],
|
||||
float input[],
|
||||
const unsigned DCT_N)
|
||||
{
|
||||
for(unsigned int k = 0; k < DCT_N; k++){
|
||||
output[k] = input[0]/2.0f;
|
||||
for(unsigned int n = 1; n < DCT_N; n++){
|
||||
float c = cosf( n * ((float) M_PI) * (2*k + 1) / (2.0f * DCT_N));
|
||||
output[k] += input[n] * c;
|
||||
}
|
||||
output[k] /= DCT_N;
|
||||
}
|
||||
}
|
||||
|
||||
void dbl_dct_forward(
|
||||
double output[],
|
||||
double input[],
|
||||
const unsigned DCT_N)
|
||||
{
|
||||
for(unsigned int k = 0; k < DCT_N; k++){
|
||||
output[k] = 0.0;
|
||||
for(unsigned int n = 0; n < DCT_N; n++){
|
||||
double c = cos( k * M_PI * (2*n + 1) / (2.0 * DCT_N));
|
||||
output[k] += input[n] * c;
|
||||
}
|
||||
output[k] *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void dbl_dct_inverse(
|
||||
double output[],
|
||||
double input[],
|
||||
const unsigned DCT_N)
|
||||
{
|
||||
for(unsigned int k = 0; k < DCT_N; k++){
|
||||
output[k] = input[0]/2.0;
|
||||
for(unsigned int n = 1; n < DCT_N; n++){
|
||||
double c = cos( n * (M_PI) * (2*k + 1) / (2.0 * DCT_N));
|
||||
output[k] += input[n] * c;
|
||||
}
|
||||
output[k] /= DCT_N;
|
||||
}
|
||||
}
|
||||
62
lib_xcore_math/tests/shared/floating_fft/floating_dct.h
Normal file
62
lib_xcore_math/tests/shared/floating_fft/floating_dct.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmath/xmath.h"
|
||||
|
||||
/**
|
||||
* Forward DCT (type II)
|
||||
*
|
||||
* This is a naive implementation intended to minimize chances of errors, and should be
|
||||
* used only for testing purposes.
|
||||
*
|
||||
* Compared against SciPy DCT implementation.
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_dct_forward(
|
||||
float output[],
|
||||
float input[],
|
||||
const unsigned DCT_N);
|
||||
|
||||
/**
|
||||
* Inverse DCT (type II)
|
||||
*
|
||||
* This is a naive implementation intended to minimize chances of errors, and should be
|
||||
* used only for testing purposes.
|
||||
*
|
||||
* Compared against SciPy DCT implementation.
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_dct_inverse(
|
||||
float output[],
|
||||
float input[],
|
||||
const unsigned DCT_N);
|
||||
|
||||
/**
|
||||
* Forward DCT (type II)
|
||||
*
|
||||
* This is a naive implementation intended to minimize chances of errors, and should be
|
||||
* used only for testing purposes.
|
||||
*
|
||||
* Compared against SciPy DCT implementation.
|
||||
*/
|
||||
EXTERN_C
|
||||
void dbl_dct_forward(
|
||||
double output[],
|
||||
double input[],
|
||||
const unsigned DCT_N);
|
||||
|
||||
/**
|
||||
* Inverse DCT (type II)
|
||||
*
|
||||
* This is a naive implementation intended to minimize chances of errors, and should be
|
||||
* used only for testing purposes.
|
||||
*
|
||||
* Compared against SciPy DCT implementation.
|
||||
*/
|
||||
EXTERN_C
|
||||
void dbl_dct_inverse(
|
||||
double output[],
|
||||
double input[],
|
||||
const unsigned DCT_N);
|
||||
115
lib_xcore_math/tests/shared/floating_fft/floating_fft.h
Normal file
115
lib_xcore_math/tests/shared/floating_fft/floating_fft.h
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmath/xmath.h"
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
unsigned flt_bitrev(
|
||||
const unsigned index,
|
||||
const size_t bit_width);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_bit_reverse_indexes_float(
|
||||
complex_float_t a[],
|
||||
const unsigned length);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_bit_reverse_indexes_double(
|
||||
complex_double_t a[],
|
||||
const unsigned length);
|
||||
|
||||
/**
|
||||
* sine_lut must have a length of `N/4 + 1`
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_make_sine_table_float(
|
||||
float sine_lut[],
|
||||
const unsigned N);
|
||||
|
||||
/**
|
||||
* sine_lut must have a length of `N/4 + 1`
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_make_sine_table_double(
|
||||
double sine_lut[],
|
||||
const unsigned N);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_forward_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N,
|
||||
const float sine_table[]);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_forward_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N,
|
||||
const double sine_table[]);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_inverse_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N,
|
||||
const float sine_table[]);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_inverse_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N,
|
||||
const double sine_table[]);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_split_spectrum_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_split_spectrum_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_merge_spectra_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
EXTERN_C
|
||||
void flt_fft_merge_spectra_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N);
|
||||
250
lib_xcore_math/tests/shared/floating_fft/floating_fft_double.c
Normal file
250
lib_xcore_math/tests/shared/floating_fft/floating_fft_double.c
Normal file
@@ -0,0 +1,250 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
|
||||
#include "floating_fft.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void flt_bit_reverse_indexes_double(
|
||||
complex_double_t a[],
|
||||
const unsigned length)
|
||||
{
|
||||
size_t logn = u32_ceil_log2(length);
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
unsigned rev = flt_bitrev(i, logn);
|
||||
if(rev < i) continue;
|
||||
|
||||
complex_double_t tmp = a[i];
|
||||
|
||||
a[i] = a[rev];
|
||||
a[rev] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_make_sine_table_double(
|
||||
double sine_lut[],
|
||||
const unsigned N)
|
||||
{
|
||||
for(unsigned i = 0; i < (N/4) + 1; i++){
|
||||
sine_lut[i] = (double) sin( 2.0 * M_PI * (double)i / (double)N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_forward_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N,
|
||||
const double sine_table[])
|
||||
{
|
||||
uint32_t shift = 30 - cls(N);
|
||||
|
||||
for(uint32_t step = 2; step <= N; step = 2*step, shift--) {
|
||||
uint32_t step2 = step >> 1;
|
||||
uint32_t step4 = step2 >> 1;
|
||||
uint32_t k;
|
||||
|
||||
for(k = 0; k < (step4 + (step2 & 0x1)); k++)
|
||||
{
|
||||
double rRe = sine_table[(N>>2)-(k<<shift)];
|
||||
double rIm = sine_table[k<<shift];
|
||||
for(int32_t block = k+N-step; block >= 0; block-=step) {
|
||||
double tRe = pts[block].re;
|
||||
double tIm = pts[block].im;
|
||||
double tRe2 = pts[block + step2].re;
|
||||
double tIm2 = pts[block + step2].im;
|
||||
|
||||
double sRe2 = (tRe2*rRe) + (tIm2*rIm);
|
||||
double sIm2 = (tIm2*rRe) - (tRe2*rIm);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
|
||||
for(k = (step2 & 1); k < step4; k++)
|
||||
{
|
||||
double rRe = -sine_table[k<<shift];
|
||||
double rIm = sine_table[(N>>2)-(k<<shift)];
|
||||
for(int32_t block = k+step4+N-step; block >= 0; block-=step) {
|
||||
double tRe = pts[block].re;
|
||||
double tIm = pts[block].im;
|
||||
double tRe2 = pts[block + step2].re;
|
||||
double tIm2 = pts[block + step2].im;
|
||||
|
||||
double sRe2 = (tRe2 * rRe) + (tIm2 * rIm);
|
||||
double sIm2 = (tIm2 * rRe) - (tRe2 * rIm);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_inverse_double (
|
||||
complex_double_t pts[],
|
||||
const unsigned N,
|
||||
const double sine_table[] )
|
||||
{
|
||||
uint32_t shift = 30-cls(N);
|
||||
|
||||
for(uint32_t step = 2; step <= N; step = 2*step, shift--) {
|
||||
uint32_t step2 = step >> 1;
|
||||
uint32_t step4 = step2 >> 1;
|
||||
uint32_t k;
|
||||
|
||||
for(k = 0; k < (step4 + (step2 & 0x1)); k++) {
|
||||
double rRe = sine_table[(N>>2)-(k<<shift)];
|
||||
double rIm = sine_table[k<<shift];
|
||||
|
||||
for(unsigned block = k; block < k+N; block+=step) {
|
||||
double tRe = pts[block].re;
|
||||
double tIm = pts[block].im;
|
||||
double tRe2 = pts[block + step2].re;
|
||||
double tIm2 = pts[block + step2].im;
|
||||
|
||||
double sRe2 = (tRe2*rRe)-(tIm2*rIm);
|
||||
double sIm2 = (tRe2*rIm)+(tIm2*rRe);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
|
||||
for(k=(step2 & 1); k < (step2-step4); k++) {
|
||||
double rRe = -sine_table[k<<shift];
|
||||
double rIm = sine_table[(N>>2)-(k<<shift)];
|
||||
|
||||
for(unsigned block = k+step4; block < k+step4+N; block+=step) {
|
||||
double tRe = pts[block].re;
|
||||
double tIm = pts[block].im;
|
||||
double tRe2 = pts[block + step2].re;
|
||||
double tIm2 = pts[block + step2].im;
|
||||
|
||||
double sRe2 = (tRe2*rRe)-(tIm2*rIm);
|
||||
double sIm2 = (tRe2*rIm)+(tIm2*rRe);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned log2_N = 31-cls(N);
|
||||
|
||||
for(unsigned i=0;i<N;i++){
|
||||
pts[i].re = ldexp(pts[i].re, (int)-(int)log2_N);
|
||||
pts[i].im = ldexp(pts[i].im, (int)-(int)log2_N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_split_spectrum_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N)
|
||||
{
|
||||
|
||||
//pts[0:N] is the combined spectrum X[f]
|
||||
//output pts[0:N/2] is A[f]
|
||||
//output pts[N/2:N] is B[f]
|
||||
|
||||
for(uint32_t i = 1; i < N/2; i++){
|
||||
|
||||
double a_re = ldexp(( pts[i].re + pts[N-i].re), -1);
|
||||
double a_im = ldexp(( pts[i].im - pts[N-i].im), -1);
|
||||
double b_re = ldexp(( pts[i].im + pts[N-i].im), -1);
|
||||
double b_im = ldexp((-pts[i].re + pts[N-i].re), -1);
|
||||
|
||||
//A[i].re = ( X[i].re + X[N-i].im ) / 2
|
||||
pts[ i].re = a_re;
|
||||
|
||||
//A[i].im = ( X[i].im - X[N-i].im ) / 2
|
||||
pts[ i].im = a_im;
|
||||
|
||||
// pts[N-i] = Z[N/2 - i]
|
||||
|
||||
// Z[N/2 - i].re = ( X[i].im + X[N-i].im ) / 2
|
||||
pts[N-i].re = b_re;
|
||||
|
||||
// Z[N/2 - i].im = (-X[i].re + X[N-i].re ) / 2
|
||||
pts[N-i].im = b_im;
|
||||
}
|
||||
|
||||
double re = pts[N/2].re;
|
||||
double im = pts[N/2].im;
|
||||
|
||||
pts[N/2].re = pts[0].im;
|
||||
pts[N/2].im = im;
|
||||
pts[ 0].im = re;
|
||||
|
||||
// B[1:N/2] = Z[N/2:1:-1]
|
||||
for(uint32_t i = 1; i < N/4; i++){
|
||||
complex_double_t a = pts[N/2 + i];
|
||||
complex_double_t b = pts[N - i];
|
||||
|
||||
pts[N/2 + i] = b;
|
||||
pts[N - i] = a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_merge_spectra_double(
|
||||
complex_double_t pts[],
|
||||
const unsigned N)
|
||||
{
|
||||
//pts[0:N/2] is a spectrum A[f] of a real signal a[n]
|
||||
//pts[N/2:N] is a spectrum B[f] of a real signal b[n]
|
||||
//output spectrum X[f] is pts[0:N]
|
||||
|
||||
//Reverses the order of pts[N/2+1:N]
|
||||
// pts[N/2+k] = pts[N-k] --> B[k] = B[N/2 - k]
|
||||
for(uint32_t i=1; i < (N/4); i++){
|
||||
complex_double_t a = pts[N/2 + i];
|
||||
complex_double_t b = pts[ N - i];
|
||||
pts[N/2 + i] = b;
|
||||
pts[ N - i] = a;
|
||||
}
|
||||
|
||||
//X[N/2].re = A[0].im (the Nyquist rate for A[])
|
||||
//X[0].im = B[0].re (the DC value for B[])
|
||||
double t = pts[ 0].im;
|
||||
pts[ 0].im = pts[N/2].re;
|
||||
pts[N/2].re = t;
|
||||
//Note that X[0].re and X[N/2].im are already in their correct places.
|
||||
|
||||
for(uint32_t i = 1; i< (N/2); i++)
|
||||
{
|
||||
//Because of the reversal above:
|
||||
// pts[N-i] = pts[N/2 + i] = B[i]
|
||||
|
||||
double a_re = pts[ i].re;
|
||||
double a_im = pts[ i].im;
|
||||
double b_re = pts[N-i].re;
|
||||
double b_im = pts[N-i].im;
|
||||
|
||||
//X[i].re = A[i].re - B[i].im
|
||||
pts[ i].re = a_re - b_im;
|
||||
//X[i].im = A[i].im + B[i].re
|
||||
pts[ i].im = a_im + b_re;
|
||||
//X[N-i].re = A[i].re + B[i].im
|
||||
pts[N-i].re = b_im + a_re;
|
||||
//X[N-i].re = -A[i].im + B[i].re
|
||||
pts[N-i].im = b_re - a_im;
|
||||
}
|
||||
}
|
||||
219
lib_xcore_math/tests/shared/floating_fft/floating_fft_float.c
Normal file
219
lib_xcore_math/tests/shared/floating_fft/floating_fft_float.c
Normal file
@@ -0,0 +1,219 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
|
||||
#include "floating_fft.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void flt_bit_reverse_indexes_float(
|
||||
complex_float_t a[],
|
||||
const unsigned length)
|
||||
{
|
||||
size_t logn = u32_ceil_log2(length);
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
unsigned rev = flt_bitrev(i, logn);
|
||||
if(rev < i) continue;
|
||||
|
||||
complex_float_t tmp = a[i];
|
||||
|
||||
a[i] = a[rev];
|
||||
a[rev] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void flt_make_sine_table_float(
|
||||
float sine_lut[],
|
||||
const unsigned N)
|
||||
{
|
||||
for(unsigned i = 0; i < (N/4) + 1; i++){
|
||||
sine_lut[i] = (float) sin( 2.0 * M_PI * (double)i / (double)N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_forward_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N,
|
||||
const float sine_table[])
|
||||
{
|
||||
uint32_t shift = 30 - cls(N);
|
||||
|
||||
for(uint32_t step = 2; step <= N; step = 2*step, shift--) {
|
||||
uint32_t step2 = step >> 1;
|
||||
uint32_t step4 = step2 >> 1;
|
||||
uint32_t k;
|
||||
|
||||
for(k = 0; k < (step4 + (step2 & 0x1)); k++)
|
||||
{
|
||||
float rRe = sine_table[(N>>2)-(k<<shift)];
|
||||
float rIm = sine_table[k<<shift];
|
||||
for(int32_t block = k+N-step; block >= 0; block-=step) {
|
||||
float tRe = pts[block].re;
|
||||
float tIm = pts[block].im;
|
||||
float tRe2 = pts[block + step2].re;
|
||||
float tIm2 = pts[block + step2].im;
|
||||
|
||||
float sRe2 = (tRe2*rRe) + (tIm2*rIm);
|
||||
float sIm2 = (tIm2*rRe) - (tRe2*rIm);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
|
||||
for(k = (step2 & 1); k < step4; k++)
|
||||
{
|
||||
float rRe = -sine_table[k<<shift];
|
||||
float rIm = sine_table[(N>>2)-(k<<shift)];
|
||||
for(int32_t block = k+step4+N-step; block >= 0; block-=step) {
|
||||
float tRe = pts[block].re;
|
||||
float tIm = pts[block].im;
|
||||
float tRe2 = pts[block + step2].re;
|
||||
float tIm2 = pts[block + step2].im;
|
||||
|
||||
float sRe2 = (tRe2 * rRe) + (tIm2 * rIm);
|
||||
float sIm2 = (tIm2 * rRe) - (tRe2 * rIm);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_inverse_float (
|
||||
complex_float_t pts[],
|
||||
const unsigned N,
|
||||
const float sine_table[])
|
||||
{
|
||||
uint32_t shift = 30-cls(N);
|
||||
|
||||
for(uint32_t step = 2; step <= N; step = 2*step, shift--) {
|
||||
uint32_t step2 = step >> 1;
|
||||
uint32_t step4 = step2 >> 1;
|
||||
uint32_t k;
|
||||
|
||||
for(k = 0; k < (step4 + (step2 & 0x1)); k++) {
|
||||
float rRe = sine_table[(N>>2)-(k<<shift)];
|
||||
float rIm = sine_table[k<<shift];
|
||||
|
||||
for(unsigned block = k; block < k+N; block+=step) {
|
||||
float tRe = pts[block].re;
|
||||
float tIm = pts[block].im;
|
||||
float tRe2 = pts[block + step2].re;
|
||||
float tIm2 = pts[block + step2].im;
|
||||
|
||||
float sRe2 = (tRe2*rRe)-(tIm2*rIm);
|
||||
float sIm2 = (tRe2*rIm)+(tIm2*rRe);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
|
||||
for(k=(step2 & 1); k < (step2-step4); k++) {
|
||||
float rRe = -sine_table[k<<shift];
|
||||
float rIm = sine_table[(N>>2)-(k<<shift)];
|
||||
|
||||
for(unsigned block = k+step4; block < k+step4+N; block+=step) {
|
||||
float tRe = pts[block].re;
|
||||
float tIm = pts[block].im;
|
||||
float tRe2 = pts[block + step2].re;
|
||||
float tIm2 = pts[block + step2].im;
|
||||
|
||||
float sRe2 = (tRe2*rRe)-(tIm2*rIm);
|
||||
float sIm2 = (tRe2*rIm)+(tIm2*rRe);
|
||||
|
||||
pts[block].re = tRe + sRe2;
|
||||
pts[block].im = tIm + sIm2;
|
||||
pts[block+step2].re = tRe - sRe2;
|
||||
pts[block+step2].im = tIm - sIm2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned log2_N = 31-cls(N);
|
||||
|
||||
for(unsigned i=0;i<N;i++){
|
||||
pts[i].re = ldexpf(pts[i].re, -(int)log2_N);
|
||||
pts[i].im = ldexpf(pts[i].im, -(int)log2_N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_split_spectrum_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N)
|
||||
{
|
||||
|
||||
for(uint32_t i=1;i<N/2;i++){
|
||||
float a_re = ldexpf(( pts[i].re + pts[N-i].re), -1);
|
||||
float a_im = ldexpf(( pts[i].im - pts[N-i].im), -1);
|
||||
float b_re = ldexpf(( pts[i].im + pts[N-i].im), -1);
|
||||
float b_im = ldexpf((-pts[i].re + pts[N-i].re), -1);
|
||||
|
||||
pts[ i].re = a_re;
|
||||
pts[ i].im = a_im;
|
||||
pts[N-i].re = b_re;
|
||||
pts[N-i].im = b_im;
|
||||
}
|
||||
|
||||
float re = pts[N/2].re;
|
||||
float im = pts[N/2].im;
|
||||
|
||||
pts[N/2].re = pts[0].im;
|
||||
pts[N/2].im = im;
|
||||
pts[ 0].im = re;
|
||||
|
||||
|
||||
for(uint32_t i=1;i<N/4;i++){
|
||||
complex_float_t a = pts[N/2 + i];
|
||||
complex_float_t b = pts[ N - i];
|
||||
pts[N/2 + i] = b;
|
||||
pts[ N - i] = a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flt_fft_merge_spectra_float(
|
||||
complex_float_t pts[],
|
||||
const unsigned N)
|
||||
{
|
||||
for(uint32_t i=1; i < (N/4); i++){
|
||||
complex_float_t a = pts[N/2 + i];
|
||||
complex_float_t b = pts[ N - i];
|
||||
pts[N/2 + i] = b;
|
||||
pts[ N - i] = a;
|
||||
}
|
||||
|
||||
float t = pts[ 0].im;
|
||||
pts[ 0].im = pts[N/2].re;
|
||||
pts[N/2].re = t;
|
||||
|
||||
for(uint32_t i = 1; i< (N/2); i++)
|
||||
{
|
||||
float a_re = pts[ i].re;
|
||||
float a_im = pts[ i].im;
|
||||
float b_re = pts[N-i].re;
|
||||
float b_im = pts[N-i].im;
|
||||
|
||||
pts[ i].re = a_re - b_im;
|
||||
pts[ i].im = a_im + b_re;
|
||||
pts[N-i].re = b_im + a_re;
|
||||
pts[N-i].im = b_re - a_im;
|
||||
}
|
||||
}
|
||||
|
||||
33
lib_xcore_math/tests/shared/floating_fft/floating_fft_util.c
Normal file
33
lib_xcore_math/tests/shared/floating_fft/floating_fft_util.c
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
|
||||
#include "floating_fft.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
unsigned flt_bitrev(
|
||||
const unsigned index,
|
||||
const size_t bit_width)
|
||||
{
|
||||
unsigned inp = index;
|
||||
unsigned res = 0;
|
||||
|
||||
for(unsigned int i = 0; i < bit_width; i++, inp >>= 1){
|
||||
res = ((res<<1) | (inp & 0x1));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// {double, double} dsp_poly_interpolate(double left, double peak, double right, double center_bin){
|
||||
// double bin_offset = (left - right) / (2. * (2. * peak - left -right));
|
||||
// double new_peak = peak - 0.25 * (left - right) * bin_offset;
|
||||
|
||||
// return {center_bin + bin_offset, new_peak};
|
||||
// }
|
||||
120
lib_xcore_math/tests/shared/pseudo_rand/pseudo_rand.c
Normal file
120
lib_xcore_math/tests/shared/pseudo_rand/pseudo_rand.c
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
// XMOS Public License: Version 1
|
||||
|
||||
#include "pseudo_rand.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// int pseudo_rand(int* state)
|
||||
// {
|
||||
// const int a = 1664525;
|
||||
// const int c = 1013904223;
|
||||
// *state = (int)((long long)a * (*state) + c);
|
||||
// return *state;
|
||||
// }
|
||||
|
||||
int pseudo_rand(int* state)
|
||||
{
|
||||
srand((unsigned) *state);
|
||||
int res = (rand() << 16) ^ rand();
|
||||
*state = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int8_t pseudo_rand_int8(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
return (int8_t)*r;
|
||||
}
|
||||
|
||||
uint8_t pseudo_rand_uint8(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
return (uint8_t)*r;
|
||||
}
|
||||
|
||||
int16_t pseudo_rand_int16(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
return (int16_t)*r;
|
||||
}
|
||||
|
||||
uint16_t pseudo_rand_uint16(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
return (uint16_t)*r;
|
||||
}
|
||||
|
||||
int32_t pseudo_rand_int32(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
return (int32_t)*r;
|
||||
}
|
||||
|
||||
uint32_t pseudo_rand_uint32(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
return (uint32_t)*r;
|
||||
}
|
||||
|
||||
int64_t pseudo_rand_int64(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
int64_t a = (int64_t)*r;
|
||||
pseudo_rand((int*)r);
|
||||
int64_t b = (int64_t)*r;
|
||||
return (int64_t)(a + (b<<32));
|
||||
}
|
||||
|
||||
uint64_t pseudo_rand_uint64(unsigned *r){
|
||||
pseudo_rand((int*)r);
|
||||
int64_t a = (int64_t)*r;
|
||||
pseudo_rand((int*)r);
|
||||
int64_t b = (int64_t)*r;
|
||||
return (uint64_t)(a + (b<<32));
|
||||
}
|
||||
|
||||
|
||||
int32_t pseudo_rand_int(
|
||||
unsigned *r,
|
||||
int32_t min,
|
||||
int32_t max)
|
||||
{
|
||||
uint32_t delta = max - min;
|
||||
uint32_t d = pseudo_rand_uint32(r) % delta;
|
||||
return min + d;
|
||||
}
|
||||
|
||||
uint32_t pseudo_rand_uint(
|
||||
unsigned *r,
|
||||
uint32_t min,
|
||||
uint32_t max)
|
||||
{
|
||||
uint32_t delta = max - min;
|
||||
uint32_t d = pseudo_rand_uint32(r) % delta;
|
||||
return min + d;
|
||||
}
|
||||
|
||||
|
||||
void pseudo_rand_bytes(unsigned *r, char* buffer, unsigned size){
|
||||
#ifdef __xcore__
|
||||
assert((((unsigned)buffer) & 0x3) == 0);
|
||||
#endif
|
||||
|
||||
unsigned b = 0;
|
||||
|
||||
while(size >= sizeof(unsigned)){
|
||||
pseudo_rand((int*)r);
|
||||
|
||||
char* rch = (char*) r;
|
||||
|
||||
for(int i = 0; i < sizeof(unsigned); i++)
|
||||
buffer[b++] = rch[i];
|
||||
|
||||
size -= sizeof(unsigned);
|
||||
}
|
||||
|
||||
pseudo_rand((int*)r);
|
||||
unsigned tmp = *r;
|
||||
while(size){
|
||||
buffer[b++] = (char) (tmp & 0xFF);
|
||||
tmp >>= 8;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
22
lib_xcore_math/tests/shared/pseudo_rand/pseudo_rand.h
Normal file
22
lib_xcore_math/tests/shared/pseudo_rand/pseudo_rand.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2021-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int pseudo_rand(int* state);
|
||||
|
||||
|
||||
int8_t pseudo_rand_int8(unsigned *r);
|
||||
uint8_t pseudo_rand_uint8(unsigned *r);
|
||||
int16_t pseudo_rand_int16(unsigned *r);
|
||||
uint16_t pseudo_rand_uint16(unsigned *r);
|
||||
int32_t pseudo_rand_int32(unsigned *r);
|
||||
uint32_t pseudo_rand_uint32(unsigned *r);
|
||||
int64_t pseudo_rand_int64(unsigned *r);
|
||||
uint64_t pseudo_rand_uint64(unsigned *r);
|
||||
|
||||
int32_t pseudo_rand_int(unsigned *r, int32_t min, int32_t max);
|
||||
uint32_t pseudo_rand_uint(unsigned *r, uint32_t min, uint32_t max);
|
||||
|
||||
void pseudo_rand_bytes(unsigned *r, char* buffer, unsigned size);
|
||||
330
lib_xcore_math/tests/shared/pseudo_rand/rand_frame.c
Normal file
330
lib_xcore_math/tests/shared/pseudo_rand/rand_frame.c
Normal file
@@ -0,0 +1,330 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include "rand_frame.h"
|
||||
|
||||
#include "pseudo_rand.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
unsigned test_random_vect_s16(
|
||||
int16_t vect[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom)
|
||||
{
|
||||
unsigned length = pseudo_rand_uint(seed, min_length, max_length+1);
|
||||
right_shift_t shr = pseudo_rand_uint(seed, min_headroom, max_headroom+1);
|
||||
|
||||
for(unsigned int k = 0; k < length; k++){
|
||||
vect[k] = pseudo_rand_int16(seed) >> shr;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned test_random_vect_s32(
|
||||
int32_t vect[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom)
|
||||
{
|
||||
unsigned length = pseudo_rand_uint(seed, min_length, max_length+1);
|
||||
right_shift_t shr = pseudo_rand_uint(seed, min_headroom, max_headroom+1);
|
||||
|
||||
for(unsigned int k = 0; k < length; k++){
|
||||
vect[k] = pseudo_rand_int32(seed) >> shr;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned test_random_vect_complex_s16(
|
||||
int16_t vect_re[],
|
||||
int16_t vect_im[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom)
|
||||
{
|
||||
unsigned length = pseudo_rand_uint(seed, min_length, max_length+1);
|
||||
right_shift_t shr = pseudo_rand_uint(seed, min_headroom, max_headroom+1);
|
||||
|
||||
for(unsigned int k = 0; k < length; k++){
|
||||
vect_re[k] = pseudo_rand_int16(seed) >> shr;
|
||||
vect_im[k] = pseudo_rand_int16(seed) >> shr;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned test_random_vect_complex_s32(
|
||||
complex_s32_t vect[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom)
|
||||
{
|
||||
unsigned length = pseudo_rand_uint(seed, min_length, max_length+1);
|
||||
right_shift_t shr = pseudo_rand_uint(seed, min_headroom, max_headroom+1);
|
||||
|
||||
for(unsigned int k = 0; k < length; k++){
|
||||
vect[k].re = pseudo_rand_int32(seed) >> shr;
|
||||
vect[k].im = pseudo_rand_int32(seed) >> shr;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void test_random_bfp_s16(
|
||||
bfp_s16_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_s16_t* A,
|
||||
unsigned int length)
|
||||
{
|
||||
if(length <= 0){
|
||||
if(max_len != 1)
|
||||
length = (pseudo_rand_uint32(seed) % (max_len-1)) + 1;
|
||||
else
|
||||
length = 1;
|
||||
}
|
||||
|
||||
exponent_t exponent = (pseudo_rand_int32(seed) % 40) - 20;
|
||||
|
||||
int shr = (pseudo_rand_uint32(seed) % 10) + 1;
|
||||
|
||||
for(unsigned int i = 0; i < length; i++)
|
||||
B->data[i] = pseudo_rand_int16(seed) >> shr;
|
||||
|
||||
bfp_s16_init(B, B->data, exponent, length, 1);
|
||||
|
||||
if(A != NULL){
|
||||
A->length = B->length;
|
||||
}
|
||||
}
|
||||
|
||||
void test_random_bfp_s32(
|
||||
bfp_s32_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_s32_t* A,
|
||||
unsigned int length)
|
||||
{
|
||||
if(length <= 0){
|
||||
if(max_len != 1)
|
||||
length = (pseudo_rand_uint32(seed) % (max_len-1)) + 1;
|
||||
else
|
||||
length = 1;
|
||||
}
|
||||
|
||||
exponent_t exponent = (pseudo_rand_int32(seed) % 40) - 20;
|
||||
|
||||
int shr = (pseudo_rand_uint32(seed) % 10) + 1;
|
||||
|
||||
for(unsigned int i = 0; i < length; i++)
|
||||
B->data[i] = pseudo_rand_int32(seed) >> shr;
|
||||
|
||||
bfp_s32_init(B, B->data, exponent, length, 1);
|
||||
|
||||
if(A != NULL){
|
||||
A->length = B->length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_random_bfp_complex_s16(
|
||||
bfp_complex_s16_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_complex_s16_t* A,
|
||||
unsigned int length)
|
||||
{
|
||||
if(length <= 0){
|
||||
if(max_len != 1) length = (pseudo_rand_uint32(seed) % (max_len-1)) + 1;
|
||||
else length = 1;
|
||||
}
|
||||
|
||||
exponent_t exponent = (pseudo_rand_int32(seed) % 40) - 20;
|
||||
|
||||
int shr = (pseudo_rand_uint32(seed) % 10) + 1;
|
||||
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
B->real[i] = pseudo_rand_int16(seed) >> shr;
|
||||
B->imag[i] = pseudo_rand_int16(seed) >> shr;
|
||||
}
|
||||
|
||||
bfp_complex_s16_init(B, B->real, B->imag, exponent, length, 1);
|
||||
|
||||
if(A != NULL){
|
||||
A->length = B->length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_random_bfp_complex_s32(
|
||||
bfp_complex_s32_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_complex_s32_t* A,
|
||||
unsigned int length)
|
||||
{
|
||||
if(length <= 0){
|
||||
if(max_len != 1)
|
||||
length = (pseudo_rand_uint32(seed) % (max_len-1)) + 1;
|
||||
else
|
||||
length = 1;
|
||||
}
|
||||
|
||||
exponent_t exponent = (pseudo_rand_int32(seed) % 40) - 20;
|
||||
|
||||
int shr = (pseudo_rand_uint32(seed) % 10) + 1;
|
||||
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
B->data[i].re = pseudo_rand_int32(seed) >> shr;
|
||||
B->data[i].im = pseudo_rand_int32(seed) >> shr;
|
||||
}
|
||||
|
||||
bfp_complex_s32_init(B, B->data, exponent, length, 1);
|
||||
|
||||
if(A != NULL){
|
||||
A->length = B->length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void test_double_from_s16(
|
||||
double* d_out,
|
||||
bfp_s16_t* d_in)
|
||||
{
|
||||
for(unsigned int i = 0; i < d_in->length; i++){
|
||||
d_out[i] = ldexp(d_in->data[i], d_in->exp);
|
||||
}
|
||||
}
|
||||
|
||||
void test_double_from_s32(
|
||||
double* d_out,
|
||||
bfp_s32_t* d_in)
|
||||
{
|
||||
for(unsigned int i = 0; i < d_in->length; i++){
|
||||
d_out[i] = ldexp(d_in->data[i], d_in->exp);
|
||||
}
|
||||
}
|
||||
|
||||
void test_double_from_complex_s16(
|
||||
double* d_out_real,
|
||||
double* d_out_imag,
|
||||
bfp_complex_s16_t* d_in)
|
||||
{
|
||||
for(unsigned int i = 0; i < d_in->length; i++){
|
||||
// printf("## %d\t%d\t%d\n", d_in->real[i], d_in->imag[i], d_in->exp);
|
||||
d_out_real[i] = ldexp(d_in->real[i], d_in->exp);
|
||||
d_out_imag[i] = ldexp(d_in->imag[i], d_in->exp);
|
||||
}
|
||||
}
|
||||
|
||||
void test_double_from_complex_s32(
|
||||
double* d_out_real,
|
||||
double* d_out_imag,
|
||||
bfp_complex_s32_t* d_in)
|
||||
{
|
||||
for(unsigned int i = 0; i < d_in->length; i++){
|
||||
d_out_real[i] = ldexp(d_in->data[i].re, d_in->exp);
|
||||
d_out_imag[i] = ldexp(d_in->data[i].im, d_in->exp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_s16_from_double(
|
||||
int16_t* d_out,
|
||||
double* d_in,
|
||||
unsigned length,
|
||||
exponent_t use_exp)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
int exp;
|
||||
double mant = frexp(d_in[i], &exp);
|
||||
mant = mant * ldexp(1, exp - use_exp);
|
||||
d_out[i] = (int16_t) mant;
|
||||
if(mant > 0 && d_out[i] == INT16_MIN)
|
||||
d_out[i] = INT16_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
void test_s32_from_double(
|
||||
int32_t* d_out,
|
||||
double* d_in,
|
||||
unsigned length,
|
||||
exponent_t use_exp)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
int exp;
|
||||
double mant = frexp(d_in[i], &exp);
|
||||
mant = mant * ldexp(1, exp - use_exp);
|
||||
d_out[i] = (int32_t) mant;
|
||||
if(mant > 0 && d_out[i] == INT32_MIN)
|
||||
d_out[i] = INT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_complex_s16_from_double(
|
||||
int16_t* d_out_real,
|
||||
int16_t* d_out_imag,
|
||||
double* d_in_real,
|
||||
double* d_in_imag,
|
||||
unsigned length,
|
||||
exponent_t use_exp)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
int exp;
|
||||
double mant;
|
||||
|
||||
mant = frexp(d_in_real[i], &exp);
|
||||
mant = mant * ldexp(1, exp - use_exp);
|
||||
|
||||
if(((int32_t)mant) == -INT16_MIN)
|
||||
d_out_real[i] = INT16_MAX;
|
||||
else
|
||||
d_out_real[i] = (int16_t) mant;
|
||||
|
||||
mant = frexp(d_in_imag[i], &exp);
|
||||
mant = mant * ldexp(1, exp - use_exp);
|
||||
|
||||
if(((int32_t)mant) == -INT16_MIN)
|
||||
d_out_imag[i] = INT16_MAX;
|
||||
else
|
||||
d_out_imag[i] = (int16_t) mant;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_complex_s32_from_double(
|
||||
complex_s32_t* d_out,
|
||||
double* d_in_real,
|
||||
double* d_in_imag,
|
||||
unsigned length,
|
||||
exponent_t use_exp)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
int exp;
|
||||
double mant;
|
||||
|
||||
mant = frexp(d_in_real[i], &exp);
|
||||
mant = mant * ldexp(1, exp - use_exp);
|
||||
d_out[i].re = (int32_t) mant;
|
||||
|
||||
mant = frexp(d_in_imag[i], &exp);
|
||||
mant = mant * ldexp(1, exp - use_exp);
|
||||
d_out[i].im = (int32_t) mant;
|
||||
}
|
||||
}
|
||||
|
||||
135
lib_xcore_math/tests/shared/pseudo_rand/rand_frame.h
Normal file
135
lib_xcore_math/tests/shared/pseudo_rand/rand_frame.h
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
// XMOS Public License: Version 1
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmath/xmath.h"
|
||||
|
||||
|
||||
EXTERN_C
|
||||
unsigned test_random_vect_s16(
|
||||
int16_t vect[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom);
|
||||
|
||||
EXTERN_C
|
||||
unsigned test_random_vect_s32(
|
||||
int32_t vect[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom);
|
||||
|
||||
EXTERN_C
|
||||
unsigned test_random_vect_complex_s32(
|
||||
complex_s32_t vect[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom);
|
||||
|
||||
EXTERN_C
|
||||
unsigned test_random_vect_complex_s16(
|
||||
int16_t vect_re[],
|
||||
int16_t vect_im[],
|
||||
unsigned* seed,
|
||||
const unsigned min_length,
|
||||
const unsigned max_length,
|
||||
const unsigned min_headroom,
|
||||
const unsigned max_headroom);
|
||||
|
||||
EXTERN_C
|
||||
void test_random_bfp_s16(
|
||||
bfp_s16_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_s16_t* A,
|
||||
unsigned int length);
|
||||
|
||||
|
||||
EXTERN_C
|
||||
void test_random_bfp_s32(
|
||||
bfp_s32_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_s32_t* A,
|
||||
unsigned int length);
|
||||
|
||||
EXTERN_C
|
||||
void test_random_bfp_complex_s16(
|
||||
bfp_complex_s16_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_complex_s16_t* A,
|
||||
unsigned int length);
|
||||
|
||||
EXTERN_C
|
||||
void test_random_bfp_complex_s32(
|
||||
bfp_complex_s32_t* B,
|
||||
unsigned max_len,
|
||||
unsigned* seed,
|
||||
bfp_complex_s32_t* A,
|
||||
unsigned int length);
|
||||
|
||||
EXTERN_C
|
||||
void test_double_from_s16(
|
||||
double* d_out,
|
||||
bfp_s16_t* d_in);
|
||||
|
||||
EXTERN_C
|
||||
void test_double_from_s32(
|
||||
double* d_out,
|
||||
bfp_s32_t* d_in);
|
||||
|
||||
EXTERN_C
|
||||
void test_double_from_complex_s16(
|
||||
double* d_out_real,
|
||||
double* d_out_imag,
|
||||
bfp_complex_s16_t* d_in);
|
||||
|
||||
EXTERN_C
|
||||
void test_double_from_complex_s32(
|
||||
double* d_out_real,
|
||||
double* d_out_imag,
|
||||
bfp_complex_s32_t* d_in);
|
||||
|
||||
|
||||
EXTERN_C
|
||||
void test_s16_from_double(
|
||||
int16_t* d_out,
|
||||
double* d_in,
|
||||
unsigned length,
|
||||
exponent_t use_exp);
|
||||
|
||||
|
||||
EXTERN_C
|
||||
void test_s32_from_double(
|
||||
int32_t* d_out,
|
||||
double* d_in,
|
||||
unsigned length,
|
||||
exponent_t use_exp);
|
||||
|
||||
|
||||
EXTERN_C
|
||||
void test_complex_s16_from_double(
|
||||
int16_t* d_out_real,
|
||||
int16_t* d_out_imag,
|
||||
double* d_in_real,
|
||||
double* d_in_imag,
|
||||
unsigned length,
|
||||
exponent_t use_exp);
|
||||
|
||||
|
||||
EXTERN_C
|
||||
void test_complex_s32_from_double(
|
||||
complex_s32_t* d_out,
|
||||
double* d_in_real,
|
||||
double* d_in_imag,
|
||||
unsigned length,
|
||||
exponent_t use_exp);
|
||||
8
lib_xcore_math/tests/shared/shared.cmake
Normal file
8
lib_xcore_math/tests/shared/shared.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
option(XMATH_SMOKE_TEST "Build unit tests in 'smoke test' mode. This mostly just reduces the number of repetitions to reduce simulation time." OFF)
|
||||
|
||||
set(SHARED_INCLUDES floating_fft pseudo_rand testing)
|
||||
list(TRANSFORM SHARED_INCLUDES PREPEND ${CMAKE_CURRENT_LIST_DIR}/)
|
||||
list(APPEND APP_INCLUDES ${SHARED_INCLUDES})
|
||||
|
||||
file(GLOB_RECURSE SHARED_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_LIST_DIR}/**/*.c)
|
||||
list(APPEND APP_C_SRCS ${SHARED_SOURCES})
|
||||
127
lib_xcore_math/tests/shared/testing/testing.h
Normal file
127
lib_xcore_math/tests/shared/testing/testing.h
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#pragma once
|
||||
|
||||
#include "xmath/xmath_conf.h"
|
||||
#include "xmath/api.h"
|
||||
#include "xmath/types.h"
|
||||
|
||||
|
||||
/**
|
||||
* xCore: Get 100MHz reference clock timestamp
|
||||
* x86: Return 0
|
||||
*/
|
||||
C_API
|
||||
unsigned getTimestamp();
|
||||
|
||||
|
||||
/*
|
||||
* Type conversion
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
|
||||
//In trying to convert to a integer type the exponent of the float forces
|
||||
//the mantissa of the integer type to not fit in its storage type.
|
||||
CANNOT_FIT_MANTISSA=1,
|
||||
|
||||
//In trying to convert to a unsinged type the float contains a negative number.
|
||||
NEGATIVE_TO_UNSIGNED=2,
|
||||
|
||||
//In trying to convert to a float type the exponent of the integer is out of range.
|
||||
CANNOT_FIT_EXPONENT=4,
|
||||
|
||||
} conv_error_e;
|
||||
|
||||
C_API double conv_s8_to_double (const int8_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_u8_to_double(const uint8_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_s16_to_double(const int16_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_u16_to_double(const uint16_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_s32_to_double (const int32_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_u32_to_double(const uint32_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_s64_to_double (const int64_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API double conv_u64_to_double(const uint64_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
|
||||
|
||||
C_API int8_t conv_double_to_s8 (double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API uint8_t conv_double_to_u8(double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API int16_t conv_double_to_s16 (double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API uint16_t conv_double_to_u16(double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API int32_t conv_double_to_s32 (double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API uint32_t conv_double_to_u32(double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API int64_t conv_double_to_s64 (double d, const exponent_t d_exp, conv_error_e *error);
|
||||
C_API uint64_t conv_double_to_u64(double d, const exponent_t d_exp, conv_error_e *error);
|
||||
|
||||
|
||||
C_API complex_double_t conv_complex_s16_to_complex_double(complex_s16_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API complex_double_t conv_complex_s32_to_complex_double(complex_s32_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API complex_s16_t conv_complex_double_to_complex_s16(complex_double_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API complex_s32_t conv_complex_double_to_complex_s32(complex_double_t x, const exponent_t x_exp, conv_error_e *error);
|
||||
C_API complex_s64_t conv_complex_double_to_complex_s64(complex_double_t x, const exponent_t x_exp, conv_error_e* error);
|
||||
|
||||
|
||||
C_API void conv_vect_s16_to_double(double output[], const int16_t input[], const unsigned length, const exponent_t input_exp, conv_error_e *error);
|
||||
C_API void conv_vect_s32_to_double(double output[], const int32_t input[], const unsigned length, const exponent_t input_exp, conv_error_e *error);
|
||||
C_API void conv_vect_complex_s16_to_complex_double(complex_double_t output[], const complex_s16_t input[], const unsigned length, const exponent_t input_exp, conv_error_e *error);
|
||||
C_API void conv_vect_complex_s32_to_complex_double(complex_double_t output[], const complex_s32_t input[], const unsigned length, const exponent_t input_exp, conv_error_e *error);
|
||||
C_API void conv_vect_complex_s32_to_complex_double_v2(double out_real[], double out_imag[], const complex_s32_t input[], const unsigned length, const exponent_t input_exp, conv_error_e *error);
|
||||
|
||||
|
||||
/*
|
||||
* Float/Fixed comparision
|
||||
*/
|
||||
C_API unsigned abs_diff_complex_s16(complex_s16_t B, const exponent_t B_exp, complex_double_t f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_complex_s32(complex_s32_t B, const exponent_t B_exp, complex_double_t f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_s8(int8_t B, const exponent_t B_exp, double f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_s16( int16_t B, const exponent_t B_exp, double f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_s32(int32_t B, const exponent_t B_exp, double f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_u8(uint8_t B, const exponent_t B_exp, double f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_u16(uint16_t B, const exponent_t B_exp, double f, conv_error_e* error);
|
||||
C_API unsigned abs_diff_u32(uint32_t B, const exponent_t B_exp, double f, conv_error_e* error);
|
||||
|
||||
|
||||
/*
|
||||
* Float/Fixed vector comparision
|
||||
*/
|
||||
C_API unsigned abs_diff_vect_complex_s16(complex_s16_t * B, const exponent_t B_exp, complex_double_t * f, unsigned length, conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_complex_s32(complex_s32_t * B, const exponent_t B_exp, complex_double_t * f, unsigned length, conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_s8( int8_t * B, const exponent_t B_exp, double * f, unsigned length,conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_s16( int16_t * B, const exponent_t B_exp, double * f, unsigned length,conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_s32( int32_t * B, const exponent_t B_exp, double * f, unsigned length,conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_u8(uint8_t * B, const exponent_t B_exp, double * f, unsigned length,conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_u16(uint16_t * B, const exponent_t B_exp, double * f, unsigned length,conv_error_e* error);
|
||||
C_API unsigned abs_diff_vect_u32(uint32_t * B, const exponent_t B_exp, double * f, unsigned length,conv_error_e* error);
|
||||
|
||||
|
||||
#define TESTING_FLOAT_NUM_DIGITS 22
|
||||
|
||||
#define PRINT_VAR(VAR, THING) do{ printf("%s = ", VAR); THING; } while(0)
|
||||
|
||||
C_API void print_vect_complex_s16(complex_s16_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_complex_s16_fft(complex_s16_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_complex_s32(complex_s32_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_complex_s32_fft(complex_s32_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_complex_s32_raw(complex_s32_t * B, unsigned length);
|
||||
C_API void print_vect_complex_s32_fft_raw(complex_s32_t * B, unsigned length);
|
||||
C_API void print_vect_complex_double(complex_double_t * B, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_complex_double_fft(complex_double_t * B, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_s8(int8_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_s16(int16_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_s32(int32_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_s64(int64_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_u8(uint8_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_u16(uint16_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_u32(uint32_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_u64(uint64_t * B, const exponent_t B_exp, unsigned length, conv_error_e* error);
|
||||
C_API void print_vect_double(double * B, unsigned length, conv_error_e* error);
|
||||
|
||||
#define PRINT_PLOT_DIFF_COMPLEX(A, B) \
|
||||
do{ printf("[(plt.plot(np.real(qwer),label='real'),plt.plot(np.imag(qwer),label='imag')) for qwer in [\n"); \
|
||||
A; printf(" - \n"); B; printf("]]\n"); } while(0)
|
||||
|
||||
|
||||
// Get a (weakly) pseudo-random unsigned integer derived from the name of
|
||||
// the containing function. This is intended to provide a unique random seed
|
||||
// for each test case.
|
||||
#define SEED_FROM_FUNC_NAME() get_seed(__func__, sizeof(__func__))
|
||||
C_API unsigned get_seed(const char* str, const unsigned len);
|
||||
358
lib_xcore_math/tests/shared/testing/testing_conv.c
Normal file
358
lib_xcore_math/tests/shared/testing/testing_conv.c
Normal file
@@ -0,0 +1,358 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include "testing.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/*
|
||||
* Type conversion
|
||||
*/
|
||||
double conv_s8_to_double (
|
||||
const int8_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
//TODO check for errors
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_u8_to_double(
|
||||
const uint8_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_s16_to_double(
|
||||
const int16_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
//TODO check for errors
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_u16_to_double(
|
||||
const uint16_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_s32_to_double (
|
||||
const int32_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_u32_to_double(
|
||||
const uint32_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_s64_to_double (
|
||||
const int64_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
double conv_u64_to_double(
|
||||
const uint64_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
return (double) ldexp((double)x, x_exp);
|
||||
}
|
||||
|
||||
|
||||
int8_t conv_double_to_s8 (
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = (double)frexp (d, &m_exp);
|
||||
|
||||
double r = (double) ldexp(m, m_exp - d_exp);
|
||||
exponent_t output_exponent;
|
||||
frexp(r, &output_exponent);
|
||||
|
||||
if(output_exponent>7){
|
||||
*error |= CANNOT_FIT_MANTISSA;
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
return (int8_t) r;
|
||||
}
|
||||
|
||||
uint8_t conv_double_to_u8(
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = (double)frexp (d, &m_exp);
|
||||
|
||||
if(m<0.0){
|
||||
*error |= NEGATIVE_TO_UNSIGNED;
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
return (uint8_t) ldexp(m, m_exp - d_exp);
|
||||
}
|
||||
|
||||
int16_t conv_double_to_s16 (
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = (double)frexp (d, &m_exp);
|
||||
|
||||
double r = (double) ldexp(m, m_exp - d_exp);
|
||||
exponent_t output_exponent;
|
||||
frexp(r, &output_exponent);
|
||||
|
||||
if(output_exponent>15){
|
||||
*error |= CANNOT_FIT_MANTISSA;
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
return (int16_t) r;
|
||||
}
|
||||
|
||||
uint16_t conv_double_to_u16(
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = (double)frexp (d, &m_exp);
|
||||
|
||||
if(m<0.0){
|
||||
*error |= NEGATIVE_TO_UNSIGNED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
return (uint16_t) ldexp(m, m_exp - d_exp);
|
||||
}
|
||||
|
||||
int32_t conv_double_to_s32 (
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = frexp (d, &m_exp);
|
||||
|
||||
double r = ldexp(m, m_exp - d_exp);
|
||||
exponent_t output_exponent;
|
||||
frexp(r, &output_exponent);
|
||||
|
||||
if(output_exponent>31){
|
||||
*error |= CANNOT_FIT_MANTISSA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
return (int32_t) r;
|
||||
}
|
||||
|
||||
uint32_t conv_double_to_u32(
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = frexp (d, &m_exp);
|
||||
|
||||
if(m<0.0){
|
||||
*error |= NEGATIVE_TO_UNSIGNED;
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
|
||||
return (uint32_t) ldexp(m, m_exp - d_exp);
|
||||
}
|
||||
|
||||
int64_t conv_double_to_s64 (
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = frexp (d, &m_exp);
|
||||
|
||||
double r = ldexp(m, m_exp - d_exp);
|
||||
int output_exponent;
|
||||
frexp(r, &output_exponent);
|
||||
|
||||
if(output_exponent>63){
|
||||
*error |= CANNOT_FIT_MANTISSA;
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
|
||||
return (int64_t) r;
|
||||
}
|
||||
|
||||
uint64_t conv_double_to_u64(
|
||||
double d,
|
||||
const exponent_t d_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
exponent_t m_exp;
|
||||
double m = frexp (d, &m_exp);
|
||||
|
||||
if(m<0.0){
|
||||
*error |= NEGATIVE_TO_UNSIGNED;
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
|
||||
return (uint64_t) ldexp(m, m_exp - d_exp);
|
||||
}
|
||||
|
||||
complex_double_t conv_complex_s16_to_complex_double(
|
||||
complex_s16_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
complex_double_t r;
|
||||
r.re = conv_s16_to_double(x.re, x_exp, error);
|
||||
r.im = conv_s16_to_double(x.im, x_exp, error);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
complex_double_t conv_complex_s32_to_complex_double(
|
||||
complex_s32_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
complex_double_t r;
|
||||
r.re = conv_s32_to_double(x.re, x_exp, error);
|
||||
r.im = conv_s32_to_double(x.im, x_exp, error);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
complex_s16_t conv_complex_double_to_complex_s16(
|
||||
complex_double_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
complex_s16_t r;
|
||||
r.re = conv_double_to_s16(x.re, x_exp, error);
|
||||
r.im = conv_double_to_s16(x.im, x_exp, error);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
complex_s32_t conv_complex_double_to_complex_s32(
|
||||
complex_double_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
complex_s32_t r;
|
||||
r.re = conv_double_to_s32(x.re, x_exp, error);
|
||||
r.im = conv_double_to_s32(x.im, x_exp, error);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
complex_s64_t conv_complex_double_to_complex_s64(
|
||||
complex_double_t x,
|
||||
const exponent_t x_exp,
|
||||
conv_error_e* error)
|
||||
{
|
||||
complex_s64_t r;
|
||||
r.re = conv_double_to_s64(x.re, x_exp, error);
|
||||
r.im = conv_double_to_s64(x.im, x_exp, error);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Vector conversions
|
||||
*/
|
||||
|
||||
|
||||
void conv_vect_s16_to_double(
|
||||
double output[],
|
||||
const int16_t input[],
|
||||
const unsigned length,
|
||||
const exponent_t input_exp,
|
||||
conv_error_e *error)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
output[i] = conv_s16_to_double(input[i], input_exp, error);
|
||||
}
|
||||
}
|
||||
|
||||
void conv_vect_s32_to_double(
|
||||
double output[],
|
||||
const int32_t input[],
|
||||
const unsigned length,
|
||||
const exponent_t input_exp,
|
||||
conv_error_e *error)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
output[i] = conv_s32_to_double(input[i], input_exp, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void conv_vect_complex_s16_to_complex_double(
|
||||
complex_double_t output[],
|
||||
const complex_s16_t input[],
|
||||
const unsigned length,
|
||||
const exponent_t input_exp,
|
||||
conv_error_e *error)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
output[i].re = conv_s16_to_double(input[i].re, input_exp, error);
|
||||
output[i].im = conv_s16_to_double(input[i].im, input_exp, error);
|
||||
}
|
||||
}
|
||||
|
||||
void conv_vect_complex_s32_to_complex_double(
|
||||
complex_double_t output[],
|
||||
const complex_s32_t input[],
|
||||
const unsigned length,
|
||||
const exponent_t input_exp,
|
||||
conv_error_e *error)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
output[i].re = conv_s32_to_double(input[i].re, input_exp, error);
|
||||
output[i].im = conv_s32_to_double(input[i].im, input_exp, error);
|
||||
}
|
||||
}
|
||||
|
||||
void conv_vect_complex_s32_to_complex_double_v2(
|
||||
double out_real[],
|
||||
double out_imag[],
|
||||
const complex_s32_t input[],
|
||||
const unsigned length,
|
||||
const exponent_t input_exp,
|
||||
conv_error_e *error)
|
||||
{
|
||||
for(unsigned int i = 0; i < length; i++){
|
||||
out_real[i] = conv_s32_to_double(input[i].re, input_exp, error);
|
||||
out_imag[i] = conv_s32_to_double(input[i].im, input_exp, error);
|
||||
}
|
||||
}
|
||||
265
lib_xcore_math/tests/shared/testing/testing_diff.c
Normal file
265
lib_xcore_math/tests/shared/testing/testing_diff.c
Normal file
@@ -0,0 +1,265 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include "testing.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/*
|
||||
* Float/Fixed comparision
|
||||
*/
|
||||
unsigned abs_diff_complex_s16(
|
||||
complex_s16_t B,
|
||||
const exponent_t B_exp,
|
||||
complex_double_t f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned re_diff = abs_diff_s16(B.re, B_exp, f.re, error);
|
||||
unsigned im_diff = abs_diff_s16(B.im, B_exp, f.im, error);
|
||||
if(re_diff > im_diff){
|
||||
return re_diff;
|
||||
} else {
|
||||
return im_diff;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned abs_diff_complex_s32(
|
||||
complex_s32_t B,
|
||||
const exponent_t B_exp,
|
||||
complex_double_t f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned re_diff = abs_diff_s32(B.re, B_exp, f.re, error);
|
||||
unsigned im_diff = abs_diff_s32(B.im, B_exp, f.im, error);
|
||||
if(re_diff > im_diff){
|
||||
return re_diff;
|
||||
} else {
|
||||
return im_diff;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned abs_diff_s8 (
|
||||
int8_t B,
|
||||
const exponent_t B_exp,
|
||||
double f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
int8_t v = conv_double_to_s8(f, B_exp, error);
|
||||
int diff = v - B;
|
||||
if (diff < 0 ) diff = -diff;
|
||||
return (unsigned)diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_s16 (
|
||||
int16_t B,
|
||||
const exponent_t B_exp,
|
||||
double f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
int16_t v = conv_double_to_s16(f, B_exp, error);
|
||||
int diff = v - B;
|
||||
if (diff < 0 ) diff = -diff;
|
||||
return (unsigned)diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_s32 (
|
||||
int32_t B,
|
||||
const exponent_t B_exp,
|
||||
double f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
int32_t v = conv_double_to_s32(f, B_exp, error);
|
||||
int diff = v - B;
|
||||
if (diff < 0 ) diff = -diff;
|
||||
return (unsigned)diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_u8(
|
||||
uint8_t B,
|
||||
const exponent_t B_exp,
|
||||
double f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
uint8_t v = conv_double_to_u8(f, B_exp, error);
|
||||
int diff = v - B;
|
||||
if (diff < 0 ) diff = -diff;
|
||||
return (unsigned)diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_u16(
|
||||
uint16_t B,
|
||||
const exponent_t B_exp,
|
||||
double f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
uint16_t v = conv_double_to_u16(f, B_exp, error);
|
||||
int diff = v - B;
|
||||
if (diff < 0 ) diff = -diff;
|
||||
return (unsigned)diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_u32(
|
||||
uint32_t B,
|
||||
const exponent_t B_exp,
|
||||
double f,
|
||||
conv_error_e* error)
|
||||
{
|
||||
if ((B == 0) && (f != 0.0)){
|
||||
*error = 1;
|
||||
return 0;
|
||||
}
|
||||
uint32_t v = conv_double_to_u32(f, B_exp, error);
|
||||
int diff = v - B;
|
||||
if (diff < 0 ) diff = -diff;
|
||||
return (unsigned)diff;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Float/Fixed vector comparision
|
||||
*/
|
||||
|
||||
unsigned abs_diff_vect_complex_s16(
|
||||
complex_s16_t * B,
|
||||
const exponent_t B_exp,
|
||||
complex_double_t * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_complex_s16(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_complex_s32(
|
||||
complex_s32_t * B,
|
||||
const exponent_t B_exp,
|
||||
complex_double_t * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_complex_s32(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_s8 (
|
||||
int8_t * B,
|
||||
const exponent_t B_exp,
|
||||
double * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_s8(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_s16 (
|
||||
int16_t * B,
|
||||
const exponent_t B_exp,
|
||||
double * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_s16(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_s32 (
|
||||
int32_t * B,
|
||||
const exponent_t B_exp,
|
||||
double * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_s32(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_u8(
|
||||
uint8_t * B,
|
||||
const exponent_t B_exp,
|
||||
double * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_u8(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_u16(
|
||||
uint16_t * B,
|
||||
const exponent_t B_exp,
|
||||
double * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_u16(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
unsigned abs_diff_vect_u32(
|
||||
uint32_t * B,
|
||||
const exponent_t B_exp,
|
||||
double * f,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
unsigned max_diff = 0;
|
||||
|
||||
for(unsigned i=0;i<length;i++){
|
||||
unsigned diff = abs_diff_u32(B[i], B_exp, f[i], error);
|
||||
if( diff > max_diff) {
|
||||
max_diff = diff;
|
||||
}
|
||||
}
|
||||
return max_diff;
|
||||
}
|
||||
39
lib_xcore_math/tests/shared/testing/testing_misc.c
Normal file
39
lib_xcore_math/tests/shared/testing/testing_misc.c
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
// XMOS Public License: Version 1
|
||||
|
||||
#include "testing.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __xcore__
|
||||
#include "xcore/hwtimer.h"
|
||||
#endif
|
||||
|
||||
|
||||
unsigned get_seed(
|
||||
const char* str,
|
||||
const unsigned len)
|
||||
{
|
||||
unsigned seed = 0;
|
||||
int left = len;
|
||||
|
||||
while(left > 0){
|
||||
unsigned v = ((unsigned*)str)[0];
|
||||
seed = seed ^ v;
|
||||
left -= 4;
|
||||
str = &str[4];
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
unsigned getTimestamp()
|
||||
{
|
||||
#if __xcore__
|
||||
return get_reference_time();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
224
lib_xcore_math/tests/shared/testing/testing_print.c
Normal file
224
lib_xcore_math/tests/shared/testing/testing_print.c
Normal file
@@ -0,0 +1,224 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include "testing.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void print_vect_complex_s16(
|
||||
complex_s16_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++){
|
||||
double re = conv_s16_to_double( B[i].re, B_exp, error);
|
||||
double im = conv_s16_to_double( B[i].im, B_exp, error);
|
||||
printf("%.*f + %.*fj, ", TESTING_FLOAT_NUM_DIGITS, re, TESTING_FLOAT_NUM_DIGITS, im);
|
||||
}
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_complex_s16_fft(
|
||||
complex_s16_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_s16_to_double( B[0].re, B_exp, error));
|
||||
for(unsigned i=1;i<length;i++){
|
||||
double re = conv_s16_to_double( B[i].re, B_exp, error);
|
||||
double im = conv_s16_to_double( B[i].im, B_exp, error);
|
||||
printf("%.*f + %.*fj, ", TESTING_FLOAT_NUM_DIGITS, re, TESTING_FLOAT_NUM_DIGITS, im);
|
||||
}
|
||||
printf("%.*f])\n", TESTING_FLOAT_NUM_DIGITS, conv_s16_to_double( B[0].im, B_exp, error));
|
||||
}
|
||||
|
||||
void print_vect_complex_s32(
|
||||
complex_s32_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++){
|
||||
double re = conv_s32_to_double( B[i].re, B_exp, error);
|
||||
double im = conv_s32_to_double( B[i].im, B_exp, error);
|
||||
printf("%.*f + %.*fj, ", TESTING_FLOAT_NUM_DIGITS, re, TESTING_FLOAT_NUM_DIGITS, im);
|
||||
}
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_complex_s32_fft(
|
||||
complex_s32_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_s32_to_double( B[0].re, B_exp, error));
|
||||
for(unsigned i=1;i<length;i++){
|
||||
double re = conv_s32_to_double( B[i].re, B_exp, error);
|
||||
double im = conv_s32_to_double( B[i].im, B_exp, error);
|
||||
printf("%.*f + %.*fj, ", TESTING_FLOAT_NUM_DIGITS, re, TESTING_FLOAT_NUM_DIGITS, im);
|
||||
}
|
||||
printf("%.*f])\n", TESTING_FLOAT_NUM_DIGITS, conv_s32_to_double(B[0].im, B_exp, error));
|
||||
}
|
||||
|
||||
void print_vect_complex_s32_raw(
|
||||
complex_s32_t * B,
|
||||
unsigned length)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i = 0; i < length; i++){
|
||||
printf("%ld + %ldj, ", (long int)B[i].re, (long int)B[i].im);
|
||||
}
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_complex_s32_fft_raw(
|
||||
complex_s32_t * B,
|
||||
unsigned length)
|
||||
{
|
||||
printf("np.asarray([%ld, ", (long int)B[0].re);
|
||||
for(unsigned i = 1; i < length; i++){
|
||||
printf("%ld + %ldj, ", (long int)B[i].re, (long int)B[i].im);
|
||||
}
|
||||
printf("%ld])\n", (long int)B[0].im);
|
||||
}
|
||||
|
||||
void print_vect_complex_double(
|
||||
complex_double_t * B,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++){
|
||||
printf("%.*f + %.*fj, ", TESTING_FLOAT_NUM_DIGITS, B[i].re, TESTING_FLOAT_NUM_DIGITS, B[i].im);
|
||||
}
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_complex_double_fft(
|
||||
complex_double_t * B,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([%.*f, ", TESTING_FLOAT_NUM_DIGITS, B[0].re);
|
||||
for(unsigned i=1;i<length;i++){
|
||||
printf("%.*f + %.*fj, ", TESTING_FLOAT_NUM_DIGITS, B[i].re, TESTING_FLOAT_NUM_DIGITS, B[i].im);
|
||||
}
|
||||
printf("%.*f])\n", TESTING_FLOAT_NUM_DIGITS, B[0].im);
|
||||
}
|
||||
|
||||
void print_vect_s8 (
|
||||
int8_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_s8_to_double( B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_s16 (
|
||||
int16_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_s16_to_double( B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_s32 (
|
||||
int32_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_s32_to_double(B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_s64 (
|
||||
int64_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_s64_to_double(B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_u8(
|
||||
uint8_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_u8_to_double(B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_u16(
|
||||
uint16_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_u16_to_double(B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_u32(
|
||||
uint32_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_u32_to_double(B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_u64(
|
||||
uint64_t * B,
|
||||
const exponent_t B_exp,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, conv_u64_to_double(B[i], B_exp, error));
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
void print_vect_double (
|
||||
double * B,
|
||||
unsigned length,
|
||||
conv_error_e* error)
|
||||
|
||||
{
|
||||
printf("np.asarray([");
|
||||
for(unsigned i=0;i<length;i++)
|
||||
printf("%.*f, ", TESTING_FLOAT_NUM_DIGITS, B[i]);
|
||||
printf("])\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user