This commit is contained in:
Steven Dan
2025-12-11 09:43:42 +08:00
commit d8b2974133
1822 changed files with 280037 additions and 0 deletions

View 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;
}
}

View 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);

View 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);

View 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;
}
}

View 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;
}
}

View 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};
// }

View 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--;
}
}

View 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);

View 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;
}
}

View 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);

View 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})

View 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);

View 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);
}
}

View 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;
}

View 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
}

View 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");
}