add oversampler

This commit is contained in:
2024-05-24 13:28:31 +02:00
parent e4a4a661a0
commit 989dba5a6b
484 changed files with 313937 additions and 0 deletions

View 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 */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

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

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