add oversampler
This commit is contained in:
75
oversampling/WDL/cmath/bessel_polynomial.h
Normal file
75
oversampling/WDL/cmath/bessel_polynomial.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
bessel_polynomial.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
algorithm to calculate coefficients for a bessel polynomial from krall & fink
|
||||
series.
|
||||
*/
|
||||
|
||||
#ifndef _BESSEL_POLYNOMIAL_H_
|
||||
#define _BESSEL_POLYNOMIAL_H_
|
||||
|
||||
#include "custom_math.h"
|
||||
#include "factorial.h"
|
||||
|
||||
#ifdef _BESSEL_USE_INLINE_
|
||||
#define _BESSEL_INLINE _CMATH_INLINE
|
||||
#else
|
||||
#define _BESSEL_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef _CMATH_ANSI
|
||||
#define _BESSEL_MAX_ORDER 10
|
||||
#else
|
||||
#define _BESSEL_MAX_ORDER 3
|
||||
#endif
|
||||
|
||||
/* return a coefficient */
|
||||
_BESSEL_INLINE cmath_std_int_t
|
||||
bessel_coefficient(const cmath_uint16_t k, const cmath_uint16_t n)
|
||||
{
|
||||
register cmath_std_int_t c;
|
||||
const cmath_uint16_t nmk = (cmath_uint16_t)(n - k);
|
||||
c = factorial(2*n - k);
|
||||
c /= (factorial(nmk)*factorial(k)) * (1 << nmk);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* calculate all coefficients for n-th order polynomial */
|
||||
_BESSEL_INLINE
|
||||
void bessel_polynomial( cmath_std_int_t *coeff,
|
||||
const cmath_uint16_t order,
|
||||
const cmath_uint16_t reverse )
|
||||
{
|
||||
register cmath_uint16_t i = (cmath_uint16_t)(order + 1);
|
||||
if (reverse)
|
||||
{
|
||||
while (i--)
|
||||
coeff[order-i] = bessel_coefficient(i, order);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i--)
|
||||
coeff[i] = bessel_coefficient(i, order);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _BESSEL_POLYNOMIAL_H */
|
||||
368
oversampling/WDL/cmath/complex_number.h
Normal file
368
oversampling/WDL/cmath/complex_number.h
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
complex_number.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
portable complex number operations
|
||||
*/
|
||||
|
||||
#ifndef _COMPLEX_NUMBER_H_
|
||||
#define _COMPLEX_NUMBER_H_
|
||||
|
||||
#include "custom_math.h"
|
||||
|
||||
/* settings */
|
||||
#ifndef _CNUM_NO_INLINE
|
||||
#define _CNUM_INLINE _CMATH_INLINE
|
||||
#else
|
||||
#define _CNUM_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef _CNUM_NO_ALIAS
|
||||
#define _CNUM_ALIAS _CMATH_MAY_ALIAS
|
||||
#else
|
||||
#define _CNUM_ALIAS
|
||||
#endif
|
||||
|
||||
/* types & constants */
|
||||
#ifndef cnum_t
|
||||
#define cnum_t cmath_t
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cnum_t r _CMATH_ALIGN(8);
|
||||
cnum_t i _CMATH_ALIGN(8);
|
||||
} _CNUM_ALIAS cnum_s;
|
||||
|
||||
const cnum_s cnum_zero = {0, 0};
|
||||
const cnum_s cnum_i1 = {0, 1};
|
||||
const cnum_s cnum_r1 = {1, 0};
|
||||
const cnum_s cnum_r2 = {2, 0};
|
||||
|
||||
/* methods */
|
||||
#define _CNUM(r, i) cnum_new(r, i)
|
||||
#define _CNUMD(x, r, i) cnum_s x = {r, i}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_set(cnum_s *x, const cnum_t r, const cnum_t i)
|
||||
{
|
||||
x->r = r;
|
||||
x->i = i;
|
||||
return *x;
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_from(cnum_s *x, const cnum_s y)
|
||||
{
|
||||
x->r = y.r;
|
||||
x->i = y.i;
|
||||
return *x;
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_new(const cnum_t r, const cnum_t i)
|
||||
{
|
||||
cnum_s x;
|
||||
x.r = r;
|
||||
x.i = i;
|
||||
return x;
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_cartesian(const cnum_s x)
|
||||
{
|
||||
return cnum_new(x.r * cmath_cos(x.i), x.r * cmath_sin(x.i));
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_polar(const cnum_s x)
|
||||
{
|
||||
return cnum_new(cmath_cabs(x.r, x.i), cmath_carg(x.r, x.i));
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_conjugate(const cnum_s x)
|
||||
{
|
||||
return cnum_new(x.r, -x.i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_negative(const cnum_s x)
|
||||
{
|
||||
return cnum_new(-x.r, -x.i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_swap(const cnum_s x)
|
||||
{
|
||||
return cnum_new(x.i, x.r);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_add(const cnum_s x, const cnum_s y)
|
||||
{
|
||||
return cnum_new(x.r + y.r, x.i + y.i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_add_r(const cnum_s x, const cnum_t y)
|
||||
{
|
||||
return cnum_new(x.r + y, x.i + y);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_sub(const cnum_s x, const cnum_s y)
|
||||
{
|
||||
return cnum_new(x.r - y.r, x.i - y.i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_sub_r(register cnum_s x, const cnum_t y)
|
||||
{
|
||||
return cnum_new(x.r - y, x.i - y);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_r_sub(const cnum_t x, register cnum_s y)
|
||||
{
|
||||
return cnum_new(x - y.r, x - y.i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_mul(const cnum_s x, const cnum_s y)
|
||||
{
|
||||
return cnum_new(x.r*y.r - x.i*y.i, x.r*y.i + x.i*y.r);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_mul_r(const cnum_s x, const cnum_t y)
|
||||
{
|
||||
return cnum_new(x.r*y, x.i*y);
|
||||
}
|
||||
|
||||
#define cnum_sqr(x) \
|
||||
cnum_mul(x, x)
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_div_r(const cnum_s x, const cnum_t y)
|
||||
{
|
||||
return cnum_new(x.r/y, x.i/y);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_r_div(const cnum_t x, const cnum_s y)
|
||||
{
|
||||
return cnum_new(x/y.r, x/y.i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_div(const cnum_s x, const cnum_s y)
|
||||
{
|
||||
return cnum_div_r(cnum_mul(x, cnum_conjugate(y)),
|
||||
(y.r*y.r + cmath_abs(y.i*y.i)));
|
||||
}
|
||||
|
||||
#define cnum_inv(x) \
|
||||
cnum_div(cnum_r1, x)
|
||||
|
||||
#define _CNUM_CHECK_EXP_D_ \
|
||||
cmath_abs(deg - cmath_round(deg)) == 0
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_exp(const cnum_s x)
|
||||
{
|
||||
cnum_t sin_i = cmath_sin(x.i);
|
||||
cnum_t cos_i = cmath_cos(x.i);
|
||||
const cnum_t exp_r = cmath_exp(x.r);
|
||||
|
||||
#ifndef _CNUM_NO_CHECK_EXP_
|
||||
register cnum_t deg;
|
||||
|
||||
if (x.r == 0)
|
||||
return cnum_zero;
|
||||
deg = x.i / cmath_pi;
|
||||
if (_CNUM_CHECK_EXP_D_)
|
||||
sin_i = 0;
|
||||
deg += 0.5;
|
||||
if (_CNUM_CHECK_EXP_D_)
|
||||
cos_i = 0;
|
||||
deg = x.i / cmath_pi2;
|
||||
if (_CNUM_CHECK_EXP_D_)
|
||||
cos_i = 1;
|
||||
#endif
|
||||
|
||||
return cnum_new(exp_r*cos_i, exp_r*sin_i);
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_log_k(const cnum_s x, const cmath_int32_t k)
|
||||
{
|
||||
return cnum_new(cmath_log(cmath_cabs(x.r, x.i)),
|
||||
(cmath_carg(x.r, x.i) + (cmath_pi2*k)));
|
||||
}
|
||||
|
||||
#define cnum_log(x) \
|
||||
cnum_log_k(x, 0)
|
||||
|
||||
#define cnum_log_b_k(x, b, k) \
|
||||
cnum_div(cnum_log_k(x, k), cnum_log_k(b, k))
|
||||
|
||||
#define cnum_log_b(b, x) \
|
||||
cnum_div(cnum_log(x), cnum_log(b))
|
||||
|
||||
#define cnum_log2(x) \
|
||||
cnum_log_b(x, 2)
|
||||
|
||||
#define cnum_log2_k(x, k) \
|
||||
cnum_log_b_k(x, 2, k)
|
||||
|
||||
#define cnum_log10(x) \
|
||||
cnum_log_b(x, 2)
|
||||
|
||||
#define cnum_log10_k(x, k) \
|
||||
cnum_log_b_k(x, 10, k)
|
||||
|
||||
#define _CNUM_CHECK_POW_C_ \
|
||||
if (x.r == 0 && x.i == 0) \
|
||||
return cnum_zero; \
|
||||
if (y.r == 0 && y.i == 0) \
|
||||
return cnum_r1 \
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_pow_c_k(const cnum_s x, const cnum_s y, const cmath_int32_t k)
|
||||
{
|
||||
_CNUM_CHECK_POW_C_;
|
||||
return cnum_exp(cnum_mul(cnum_log_k(x, k), y));
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_pow_c(const cnum_s x, const cnum_s y)
|
||||
{
|
||||
_CNUM_CHECK_POW_C_;
|
||||
return cnum_exp(cnum_mul(cnum_log(x), y));
|
||||
}
|
||||
|
||||
_CNUM_INLINE
|
||||
cnum_s cnum_pow(const cnum_s x, const cnum_t n)
|
||||
{
|
||||
const cnum_t r_pow_n = cmath_pow(cmath_cabs(x.r, x.i), n);
|
||||
const cnum_t theta_n = cmath_carg(x.r, x.i) * n;
|
||||
if (n == 0)
|
||||
return cnum_new(1, 0);
|
||||
if (n == 1)
|
||||
return x;
|
||||
return cnum_new(r_pow_n * cmath_cos(theta_n), r_pow_n * cmath_sin(theta_n));
|
||||
}
|
||||
|
||||
#define cnum_root_c_k(x, y, k) \
|
||||
cnum_exp(cnum_div(cnum_log_k(x, k), y))
|
||||
|
||||
#define cnum_root_c(x, y) \
|
||||
cnum_exp(cnum_div(cnum_log(x), y))
|
||||
|
||||
#define cnum_root(x, n) \
|
||||
cnum_pow(x, 1/n)
|
||||
|
||||
#define cnum_sqrt(x) \
|
||||
cnum_pow(x, 0.5)
|
||||
|
||||
#define cnum_sin(x) \
|
||||
cnum_new(cmath_sin((x).r)*cmath_cosh((x).i), \
|
||||
cmath_cos((x).r)*cmath_sinh((x).i))
|
||||
|
||||
#define cnum_sinh(x) \
|
||||
cnum_new(cmath_sinh(x.r)*cmath_cos(x.i), cmath_cosh(x.r)*sin(x.i))
|
||||
|
||||
#define cnum_cos(x) \
|
||||
cnum_new(cmath_cos(x.r)*cmath_cosh(x.i), -cmath_sin(x.r)*cmath_sinh(x.i))
|
||||
|
||||
#define cnum_cosh(x) \
|
||||
cnum_new(cmath_cosh(x.r)*cmath_cos(x.i), cmath_sinh(x.r)*cmath_sin(x.i))
|
||||
|
||||
#define cnum_tan(x) \
|
||||
cnum_div(cnum_sin(x), cnum_cos(x))
|
||||
|
||||
#define cnum_tanh(x) \
|
||||
cnum_div(cnum_sinh(x), cnum_cosh(x))
|
||||
|
||||
#define cnum_csc(x) \
|
||||
cnum_inv(cnum_sin(x))
|
||||
|
||||
#define cnum_sec(x) \
|
||||
cnum_inv(cnum_cos(x))
|
||||
|
||||
#define cnum_cotan(x) \
|
||||
cnum_inv(cnum_tan(x))
|
||||
|
||||
#define cnum_asin(x) \
|
||||
cnum_negative(cnum_mul(cnum_i1, cnum_log(cnum_add(cnum_mul(cnum_i1, x), \
|
||||
cnum_sqrt(cnum_sub(cnum_r1, cnum_sqr(x)))))))
|
||||
|
||||
#define cnum_acos(x) \
|
||||
cnum_negative(cnum_mul(cnum_i1, cnum_log(cnum_add(x, cnum_mul(cnum_i1, \
|
||||
cnum_sqrt(cnum_sub(cnum_r1, cnum_sqr(x))))))))
|
||||
|
||||
#define cnum_atan(x) \
|
||||
cnum_div(cnum_mul(cnum_i1, cnum_log(cnum_div(cnum_sub(cnum_r1, \
|
||||
cnum_mul(cnum_i1, x)), cnum_add(cnum_r1, cnum_mul(cnum_i1, x))))), cnum_r2)
|
||||
|
||||
#define cnum_acsc(x) \
|
||||
cnum_asin(cnum_inv(x))
|
||||
|
||||
#define cnum_asec(x) \
|
||||
cnum_acos(cnum_inv(x))
|
||||
|
||||
#define cnum_acot(x) \
|
||||
cnum_atan(cnum_inv(x))
|
||||
|
||||
#define cnum_csch(x) \
|
||||
cnum_inv(cnum_sinh(x))
|
||||
|
||||
#define cnum_sech(x) \
|
||||
cnum_inv(cnum_cosh(x))
|
||||
|
||||
#define cnum_coth(x) \
|
||||
cnum_inv(cnum_tanh(x))
|
||||
|
||||
#define cnum_asinh(x) \
|
||||
cnum_log(cnum_add(x, cnum_sqrt(cnum_add(cnum_r1, cnum_sqr(x)))))
|
||||
|
||||
#define cnum_acosh(x) \
|
||||
cnum_log(cnum_add(x, cnum_mul(cnum_sqrt(cnum_add(x, cnum_r1)), \
|
||||
cnum_sqrt(cnum_sub(x, cnum_r1)))))
|
||||
|
||||
#define cnum_atanh(x) \
|
||||
cnum_div(cnum_sub(cnum_log(cnum_add(cnum_r1, x)), \
|
||||
cnum_log(cnum_sub(cnum_r1, x))), cnum_r2)
|
||||
|
||||
#define cnum_acsch(x) \
|
||||
cnum_asinh(cnum_inv(x))
|
||||
|
||||
#define cnum_asech(x) \
|
||||
cnum_acosh(cnum_inv(x))
|
||||
|
||||
#define cnum_asech(x) \
|
||||
cnum_acosh(cnum_inv(x))
|
||||
|
||||
#define cnum_acoth(x) \
|
||||
cnum_atanh(cnum_inv(x))
|
||||
|
||||
#endif /* _COMPLEX_NUMBER_H_ */
|
||||
209
oversampling/WDL/cmath/custom_math.h
Normal file
209
oversampling/WDL/cmath/custom_math.h
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
custom_math.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
portable definitions for ansi c and cross compiler compatibility.
|
||||
contains: numeric constants, custom math functions, macros & other.
|
||||
*/
|
||||
|
||||
#ifndef _CUSTOM_MATH_H_
|
||||
#define _CUSTOM_MATH_H_
|
||||
|
||||
#include "math.h"
|
||||
|
||||
/* check for "c89" mode */
|
||||
#if (defined _MSC_VER && defined __STDC__) || \
|
||||
(defined __GNUC__ && defined __STRICT_ANSI__)
|
||||
#define _CMATH_ANSI
|
||||
#endif
|
||||
|
||||
/* enable inline */
|
||||
#if defined __cplusplus || (!defined _CMATH_ANSI && defined _CMATH_USE_INLINE)
|
||||
#ifdef _MSC_VER
|
||||
#define _CMATH_INLINE __inline
|
||||
#else
|
||||
#define _CMATH_INLINE inline
|
||||
#endif
|
||||
#else
|
||||
#define _CMATH_INLINE
|
||||
#endif
|
||||
|
||||
/* align type to size of type */
|
||||
#if defined __GNUC__ || defined __TINYC__
|
||||
#define _CMATH_ALIGN(x) __attribute__ ((aligned(x)))
|
||||
#define _CMATH_ALIGN_T(x) __attribute__ ((aligned(sizeof(x))))
|
||||
#else
|
||||
#define _CMATH_ALIGN(x)
|
||||
#define _CMATH_ALIGN_T(x)
|
||||
#endif
|
||||
|
||||
/* printf max integer */
|
||||
#ifndef _CMATH_ANSI
|
||||
#ifdef _WIN32
|
||||
#define _CMATH_PR_STD_UINT "I64u"
|
||||
#define _CMATH_PR_STD_INT "I64i"
|
||||
#define _CMATH_PR_STD_HEX "I64x"
|
||||
#else
|
||||
#define _CMATH_PR_STD_UINT "llu"
|
||||
#define _CMATH_PR_STD_INT "lli"
|
||||
#define _CMATH_PR_STD_HEX "llx"
|
||||
#endif
|
||||
#else
|
||||
#define _CMATH_PR_STD_UINT "u"
|
||||
#define _CMATH_PR_STD_INT "d"
|
||||
#define _CMATH_PR_STD_HEX "x"
|
||||
#endif
|
||||
|
||||
/* msvc specifics */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4514)
|
||||
|
||||
#define MK_L(x) (x)
|
||||
#define MK_UL(x) (x)
|
||||
#define MK_LL(x) (x)
|
||||
#define MK_ULL(x) (x)
|
||||
#else
|
||||
#define MK_L(x) (x##L)
|
||||
#define MK_UL(x) (x##UL)
|
||||
#ifdef _CMATH_ANSI
|
||||
#define MK_LL(x) (x##L)
|
||||
#define MK_ULL(x) (x##UL)
|
||||
#else
|
||||
#define MK_LL(x) (x##LL)
|
||||
#define MK_ULL(x) (x##ULL)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* definitions depending on c standard */
|
||||
#ifdef _CMATH_ANSI
|
||||
#define cmath_std_signbit MK_UL(0x7fffffff)
|
||||
#define cmath_std_float_t float
|
||||
#define cmath_std_int_t int
|
||||
#else
|
||||
#define cmath_std_signbit MK_ULL(0x7fffffffffffffff)
|
||||
#define cmath_std_float_t double
|
||||
#ifdef _MSC_VER
|
||||
#define cmath_std_int_t __int64
|
||||
#else
|
||||
#define cmath_std_int_t long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* types and constants */
|
||||
#ifndef cmath_t
|
||||
#define cmath_t double
|
||||
#endif
|
||||
|
||||
#define cmath_std_uint_t unsigned cmath_std_int_t
|
||||
|
||||
#define cmath_pi 3.1415926535897932384626433832795
|
||||
#define cmath_pi2 6.2831853071795864769252867665590
|
||||
#define cmath_pi_2 1.5707963267948966192313216916398
|
||||
#define cmath_e 2.7182818284590452353602874713526
|
||||
#define cmath_sqrt2 1.4142135623730950488016887242097
|
||||
#define cmath_pi_180 0.0174532925199432957692369076848
|
||||
#define cmath_180_pi 57.295779513082320876798154814105
|
||||
|
||||
#define cmath_int8_t char
|
||||
#define cmath_uint8_t unsigned char
|
||||
#define cmath_int16_t short
|
||||
#define cmath_uint16_t unsigned short
|
||||
#define cmath_int32_t int
|
||||
#define cmath_uint32_t unsigned int
|
||||
|
||||
/* aliased types */
|
||||
#ifdef __GNUC__
|
||||
#define _CMATH_MAY_ALIAS __attribute__((__may_alias__))
|
||||
#else
|
||||
#define _CMATH_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
typedef cmath_t _CMATH_MAY_ALIAS cmath_t_a;
|
||||
|
||||
/* possible approximations */
|
||||
#define cmath_sin sin
|
||||
#define cmath_cos cos
|
||||
#define cmath_tan tan
|
||||
#define cmath_asin asin
|
||||
#define cmath_acos acos
|
||||
#define cmath_atan atan
|
||||
#define cmath_atan2 atan2
|
||||
#define cmath_sinh sinh
|
||||
#define cmath_cosh cosh
|
||||
#define cmath_tanh tanh
|
||||
#define cmath_exp exp
|
||||
#define cmath_pow pow
|
||||
#define cmath_sqrt sqrt
|
||||
#define cmath_log log
|
||||
#define cmath_log2 log2
|
||||
#define cmath_log10 log10
|
||||
|
||||
/* methods */
|
||||
#define cmath_array_size(x) \
|
||||
(sizeof(x) / sizeof(*(x)))
|
||||
|
||||
#define poly_order(x) \
|
||||
(sizeof(x) / sizeof(*(x)) - 1)
|
||||
|
||||
#define cmath_cabs(a, b) \
|
||||
cmath_sqrt((a)*(a) + (b)*(b))
|
||||
|
||||
#define cmath_carg(a, b) \
|
||||
cmath_atan2((b), (a))
|
||||
|
||||
#define cmath_radians(x) \
|
||||
((x)*cmath_pi_180)
|
||||
|
||||
#define cmath_degrees(x) \
|
||||
((x)*cmath_180_pi)
|
||||
|
||||
_CMATH_INLINE
|
||||
cmath_t cmath_powi(const cmath_t x, register cmath_uint16_t n)
|
||||
{
|
||||
register cmath_t result = 1;
|
||||
while (n--)
|
||||
result *= x;
|
||||
return result;
|
||||
}
|
||||
|
||||
_CMATH_INLINE
|
||||
cmath_t cmath_abs(const cmath_t x)
|
||||
{
|
||||
register union
|
||||
{
|
||||
cmath_std_int_t i;
|
||||
cmath_std_float_t j;
|
||||
} u;
|
||||
u.j = (cmath_std_float_t)x;
|
||||
u.i &= cmath_std_signbit;
|
||||
return u.j;
|
||||
}
|
||||
|
||||
_CMATH_INLINE
|
||||
cmath_t cmath_round(const cmath_t x)
|
||||
{
|
||||
if (x < 0.0)
|
||||
return (cmath_t)(cmath_std_int_t)(x - 0.5);
|
||||
else
|
||||
return (cmath_t)(cmath_std_int_t)(x + 0.5);
|
||||
}
|
||||
|
||||
#endif /* _CUSTOM_MATH_H_ */
|
||||
117
oversampling/WDL/cmath/durand_kerner.h
Normal file
117
oversampling/WDL/cmath/durand_kerner.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
durand_kerner.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
durand-kerner (weierstrass) algorithm for finding complex roots
|
||||
of polynomials.
|
||||
accuracy depends a lot on data type precision.
|
||||
*/
|
||||
|
||||
#ifndef _DURAND_KERNER_H_
|
||||
#define _DURAND_KERNER_H_
|
||||
|
||||
#include "horner.h"
|
||||
#include "custom_math.h"
|
||||
#include "complex_number.h"
|
||||
|
||||
/* settings */
|
||||
#ifdef _DURAND_KERNER_USE_INLINE_
|
||||
#define _DURAND_KERNER_INLINE _CMATH_INLINE
|
||||
#else
|
||||
#define _DURAND_KERNER_INLINE
|
||||
#endif
|
||||
|
||||
#define DK_EPSILON 1E-16
|
||||
#define DK_MAX_ITR 1E+3
|
||||
#define DK_MAX_N 256
|
||||
|
||||
const cnum_s dk_demoivre_c = {0.4, 0.9};
|
||||
|
||||
/* accepts an array of complex numbers */
|
||||
_DURAND_KERNER_INLINE
|
||||
void durand_kerner_c
|
||||
(const cnum_s *coeff, cnum_s *roots, const cmath_uint16_t order)
|
||||
{
|
||||
register cmath_uint16_t i, j;
|
||||
register cmath_uint32_t itr;
|
||||
cnum_s coeff_sc[DK_MAX_N];
|
||||
cnum_s x;
|
||||
cnum_s hor; /* needs an address or breaks g++ 4.x */
|
||||
|
||||
i = 0;
|
||||
while(i < order)
|
||||
{
|
||||
cnum_from(&roots[i], cnum_pow(dk_demoivre_c, i));
|
||||
i++;
|
||||
}
|
||||
|
||||
cnum_from(&coeff_sc[0], cnum_r1);
|
||||
i = 1;
|
||||
while(i < order+1)
|
||||
{
|
||||
cnum_from(&coeff_sc[i], cnum_div(coeff[i], coeff[0]));
|
||||
i++;
|
||||
}
|
||||
|
||||
itr = 0;
|
||||
while(itr < DK_MAX_ITR)
|
||||
{
|
||||
i = 0;
|
||||
while(i < order)
|
||||
{
|
||||
j = 0;
|
||||
x = cnum_r1;
|
||||
while (j < order)
|
||||
{
|
||||
if (i != j)
|
||||
x = cnum_mul(cnum_sub(roots[i], roots[j]), x);
|
||||
j++;
|
||||
}
|
||||
hor = horner_eval_c(coeff_sc, roots[i], order);
|
||||
x = cnum_div(hor, x);
|
||||
x = cnum_sub(roots[i], x);
|
||||
if (cmath_abs(cmath_abs(x.r) - cmath_abs(roots[i].r)) < DK_EPSILON &&
|
||||
cmath_abs(cmath_abs(x.i) - cmath_abs(roots[i].i)) < DK_EPSILON)
|
||||
return;
|
||||
cnum_from(&roots[i], x);
|
||||
i++;
|
||||
}
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* accepts an array of real numbers */
|
||||
_DURAND_KERNER_INLINE
|
||||
void durand_kerner
|
||||
(const cmath_t *coeff, cnum_s *roots, const cmath_uint16_t order)
|
||||
{
|
||||
register cmath_uint16_t i;
|
||||
cnum_s coeff_c[DK_MAX_N];
|
||||
i = 0;
|
||||
while(i < (order+1))
|
||||
{
|
||||
cnum_set(&coeff_c[i], coeff[i], 0);
|
||||
i++;
|
||||
}
|
||||
durand_kerner_c(coeff_c, roots, order);
|
||||
}
|
||||
|
||||
#endif /* _DURAND_KERNER_H_ */
|
||||
114
oversampling/WDL/cmath/factorial.h
Normal file
114
oversampling/WDL/cmath/factorial.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
factorial.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
methods to return low-order factorials depending on allowed data types.
|
||||
|
||||
20! = 2432902008176640000 is the maximum factorial to be held
|
||||
in a unsigned 64bit integer.
|
||||
13! = 479001600 is the maximum factorial to be held in a unsigned
|
||||
32bit integer.
|
||||
*/
|
||||
|
||||
#ifndef _FACTORIAL_H_
|
||||
#define _FACTORIAL_H_
|
||||
|
||||
#include "custom_math.h"
|
||||
|
||||
#define FACTORIAL_LOWER \
|
||||
MK_ULL(1), \
|
||||
MK_ULL(1), \
|
||||
MK_ULL(2), \
|
||||
MK_ULL(6), \
|
||||
MK_ULL(24), \
|
||||
MK_ULL(120), \
|
||||
MK_ULL(720), \
|
||||
MK_ULL(5040), \
|
||||
MK_ULL(40320), \
|
||||
MK_ULL(362880), \
|
||||
MK_ULL(3628800), \
|
||||
MK_ULL(39916800), \
|
||||
MK_ULL(479001600)
|
||||
|
||||
#define FACTORIAL_HIGHER \
|
||||
MK_ULL(6227020800), \
|
||||
MK_ULL(87178291200), \
|
||||
MK_ULL(1307674368000), \
|
||||
MK_ULL(20922789888000), \
|
||||
MK_ULL(355687428096000), \
|
||||
MK_ULL(6402373705728000), \
|
||||
MK_ULL(121645100408832000), \
|
||||
MK_ULL(2432902008176640000)
|
||||
|
||||
static const cmath_std_uint_t _factorials[] =
|
||||
{
|
||||
#ifdef _CMATH_ANSI
|
||||
FACTORIAL_LOWER
|
||||
#else
|
||||
FACTORIAL_LOWER,
|
||||
FACTORIAL_HIGHER
|
||||
#endif
|
||||
};
|
||||
|
||||
static const cmath_t _inv_factorials[] =
|
||||
{
|
||||
1.00000000000000000000000000000000,
|
||||
1.00000000000000000000000000000000,
|
||||
0.50000000000000000000000000000000,
|
||||
0.16666666666666666666666666666667,
|
||||
0.04166666666666666666666666666666,
|
||||
0.00833333333333333333333333333333,
|
||||
0.00138888888888888888888888888888,
|
||||
0.00019841269841269841269841269841,
|
||||
0.00002480158730158730158730158730,
|
||||
0.00000275573192239858906525573192,
|
||||
0.00000027557319223985890652557319,
|
||||
0.00000002505210838544171877505210,
|
||||
0.00000000208767569878680989792100,
|
||||
0.00000000016059043836821614599390,
|
||||
0.00000000001147074559772972471385,
|
||||
0.00000000000076471637318198164750,
|
||||
0.00000000000004779477332387385297,
|
||||
0.00000000000000281145725434552076,
|
||||
0.00000000000000015619206968586225,
|
||||
0.00000000000000000822063524662433,
|
||||
0.00000000000000000041103176233122
|
||||
};
|
||||
|
||||
_CMATH_INLINE
|
||||
cmath_std_uint_t factorial(const cmath_uint32_t x)
|
||||
{
|
||||
if(x >= cmath_array_size(_factorials))
|
||||
return 0;
|
||||
else
|
||||
return _factorials[x];
|
||||
}
|
||||
|
||||
_CMATH_INLINE
|
||||
cmath_t inv_factorial(const cmath_uint32_t x)
|
||||
{
|
||||
if(x >= cmath_array_size(_inv_factorials))
|
||||
return 0;
|
||||
else
|
||||
return _inv_factorials[x];
|
||||
}
|
||||
|
||||
#endif /* _FACTORIAL_H_ */
|
||||
71
oversampling/WDL/cmath/horner.h
Normal file
71
oversampling/WDL/cmath/horner.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
horner.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
algorithm to evaluate integer order polynomials using horner's scheme.
|
||||
*/
|
||||
|
||||
#ifndef _HORNER_H_
|
||||
#define _HORNER_H_
|
||||
|
||||
#include "custom_math.h"
|
||||
#include "complex_number.h"
|
||||
|
||||
/* settings */
|
||||
#ifndef _HORNER_INLINE
|
||||
#define _HORNER_INLINE _CMATH_INLINE
|
||||
#else
|
||||
#define _HORNER_INLINE
|
||||
#endif
|
||||
|
||||
/* real */
|
||||
_HORNER_INLINE
|
||||
cmath_t horner_eval
|
||||
(const cmath_t *coeff, const cmath_t x, cmath_uint16_t order)
|
||||
{
|
||||
register cmath_t y = coeff[0];
|
||||
register cmath_uint16_t n = 1;
|
||||
order += 1;
|
||||
while(n < order)
|
||||
{
|
||||
y = y*x + coeff[n];
|
||||
n++;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/* complex */
|
||||
_HORNER_INLINE
|
||||
cnum_s horner_eval_c
|
||||
(const cnum_s *coeff, const cnum_s x, cmath_uint16_t order)
|
||||
{
|
||||
register cmath_uint16_t n = 1;
|
||||
cnum_s y = coeff[0];
|
||||
order += 1;
|
||||
while(n < order)
|
||||
{
|
||||
y = cnum_add(cnum_mul(y, x), coeff[n]);
|
||||
n++;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
#endif /* _HORNER_H_ */
|
||||
119
oversampling/WDL/cmath/test_bessel.c
Normal file
119
oversampling/WDL/cmath/test_bessel.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
test_bessel.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
test bessel_polynomial.h and other related headers
|
||||
|
||||
gcc -W -Wall -Wextra -ansi pedantic
|
||||
cl /W4 /Za
|
||||
|
||||
reduced precisions for ansi c
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
#include "custom_math.h"
|
||||
#include "bessel_polynomial.h"
|
||||
#include "durand_kerner.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
register cmath_uint16_t i = 0;
|
||||
register cmath_int16_t diff = 0;
|
||||
|
||||
cmath_uint32_t in_order = _BESSEL_MAX_ORDER + 1;
|
||||
cmath_uint16_t order;
|
||||
const cmath_uint16_t reverse = 1;
|
||||
|
||||
cmath_std_int_t coeff[_BESSEL_MAX_ORDER + 1];
|
||||
|
||||
cnum_t dk_coeff[_BESSEL_MAX_ORDER + 1];
|
||||
cnum_s dk_roots[_BESSEL_MAX_ORDER];
|
||||
|
||||
/* */
|
||||
#ifdef _CMATH_ANSI
|
||||
puts("\n\nansi c is: on");
|
||||
#else
|
||||
puts("\n\nansi c is: off");
|
||||
#endif
|
||||
|
||||
/* */
|
||||
while (in_order > _BESSEL_MAX_ORDER)
|
||||
{
|
||||
printf("\nenter order of bessel polynomial (0 - %d): ", _BESSEL_MAX_ORDER);
|
||||
scanf("%u", &in_order);
|
||||
}
|
||||
|
||||
order = (cmath_uint16_t)in_order;
|
||||
bessel_polynomial(coeff, order, reverse);
|
||||
|
||||
printf("\norder [N]: %d", order);
|
||||
printf("\nreversed bessel: %d\n\n", reverse);
|
||||
printf("list of coefficients:\n");
|
||||
while (i <= order)
|
||||
{
|
||||
printf("order[%2d]: ", (order - i));
|
||||
printf("%"_CMATH_PR_STD_INT"\n", coeff[i]);
|
||||
i++;
|
||||
}
|
||||
puts("\npolynomial:");
|
||||
printf("y(x) = ");
|
||||
|
||||
i = 0;
|
||||
while (i <= order)
|
||||
{
|
||||
diff = (cmath_int16_t)(order - i);
|
||||
if (diff > 0)
|
||||
if (coeff[i] > 1)
|
||||
{
|
||||
printf("%"_CMATH_PR_STD_INT, coeff[i]);
|
||||
if (diff > 1)
|
||||
printf("*x^%d + ", diff);
|
||||
else
|
||||
printf("*x + ");
|
||||
}
|
||||
else
|
||||
printf("x^%d + ", diff);
|
||||
else
|
||||
printf("%"_CMATH_PR_STD_INT"", coeff[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* */
|
||||
puts("\n\nlist roots:");
|
||||
i = 0;
|
||||
while (i < order+1)
|
||||
{
|
||||
dk_coeff[i] = (cnum_t)coeff[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
durand_kerner(dk_coeff, dk_roots, order);
|
||||
|
||||
i = 0;
|
||||
while (i < order)
|
||||
{
|
||||
printf("root[%2d]: %.15f \t % .15f*i\n",
|
||||
i+1, (double)dk_roots[i].r, (double)dk_roots[i].i);
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
87
oversampling/WDL/cmath/test_eval.c
Normal file
87
oversampling/WDL/cmath/test_eval.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
test_eval.h
|
||||
Copyright (C) 2011 and later Lubomir I. Ivanov (neolit123 [at] gmail)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
test horner.h for complex numbers and other related headers
|
||||
|
||||
gcc -W -Wall -Wextra -ansi pedantic
|
||||
cl /W4 /Za
|
||||
|
||||
reduced precisions for ansi c
|
||||
*/
|
||||
|
||||
#include "stdio.h"
|
||||
#include "complex_number.h"
|
||||
#include "horner.h"
|
||||
#include "durand_kerner.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
cmath_uint16_t i = 0;
|
||||
|
||||
cnum_t y[] = {2, -6, 2, -1};
|
||||
cnum_s cy[] = {{2, 0}, {-6, 0}, {2, 0}, {-1, 0}};
|
||||
|
||||
cnum_t fx = horner_eval(y, 5, poly_order(y));
|
||||
cnum_s fcx = horner_eval_c(cy, _CNUM(5, 0), poly_order(y));
|
||||
|
||||
cnum_t dk_coeff[] = {12, -7, 0.001, 0, 3, -5};
|
||||
cnum_s dk_roots[5];
|
||||
|
||||
cnum_s dk_coeff_c[] = {{12, 0}, {-7, 0}, {0.001, 0}, {0, 0}, {3, 0}, {-5, 0}};
|
||||
cnum_s dk_roots_c[5];
|
||||
|
||||
durand_kerner(dk_coeff, dk_roots, poly_order(dk_coeff));
|
||||
durand_kerner_c(dk_coeff_c, dk_roots_c, poly_order(dk_coeff_c));
|
||||
|
||||
/* */
|
||||
#ifdef _CMATH_ANSI
|
||||
puts("\n\nansi c is: on");
|
||||
#else
|
||||
puts("\n\nansi c is: off");
|
||||
#endif
|
||||
|
||||
/* */
|
||||
puts("\n\nevaluate polynomials:\n");
|
||||
printf("* y[]: %.15f\n", (double)fx);
|
||||
printf("* cy[]: %.15f \t %.15f*i\n", (double)fcx.r, (double)fcx.i);
|
||||
|
||||
/* */
|
||||
puts("\nfind roots:");
|
||||
puts("\n* dk_coeff[]:");
|
||||
i = 0;
|
||||
while (i < poly_order(dk_coeff))
|
||||
{
|
||||
printf("root[%2d]: %.15f \t % .15f*i\n",
|
||||
i+1, (double)dk_roots[i].r, (double)dk_roots[i].i);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
puts("\n* dk_coeff_c[]:");
|
||||
while (i < poly_order(dk_coeff_c))
|
||||
{
|
||||
printf("root[%2d]: %.15f \t % .15f*i\n",
|
||||
i+1, (double)dk_roots_c[i].r, (double)dk_roots_c[i].i);
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user