diff --git a/dspl/dox/doxyfile_en b/dspl/dox/doxyfile_en index de9a690..367247b 100644 --- a/dspl/dox/doxyfile_en +++ b/dspl/dox/doxyfile_en @@ -2168,7 +2168,7 @@ ENABLE_PREPROCESSING = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -MACRO_EXPANSION = YES +MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then # the macro expansion is limited to the macros specified with the PREDEFINED and @@ -2176,7 +2176,7 @@ MACRO_EXPANSION = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_ONLY_PREDEF = YES +EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. @@ -2209,7 +2209,8 @@ INCLUDE_FILE_PATTERNS = # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = DSPL_API \ - BUILD_LIB + BUILD_LIB \ + DOXYGEN_ENGLISH # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2219,7 +2220,8 @@ PREDEFINED = DSPL_API \ # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. EXPAND_AS_DEFINED = DSPL_API \ - BUILD_LIB + BUILD_LIB \ + DOXYGEN_ENGLISH # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have diff --git a/dspl/dox/doxyfile_ru b/dspl/dox/doxyfile_ru index 7ac3ce4..53af314 100644 --- a/dspl/dox/doxyfile_ru +++ b/dspl/dox/doxyfile_ru @@ -2209,7 +2209,8 @@ INCLUDE_FILE_PATTERNS = # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = DSPL_API \ - BUILD_LIB + BUILD_LIB \ + DOXYGEN_RUSSIAN # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2219,7 +2220,8 @@ PREDEFINED = DSPL_API \ # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. EXPAND_AS_DEFINED = DSPL_API \ - BUILD_LIB + BUILD_LIB \ + DOXYGEN_RUSSIAN # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have diff --git a/dspl/dox/en/array.dox b/dspl/dox/en/array.dox deleted file mode 100644 index cb894fe..0000000 --- a/dspl/dox/en/array.dox +++ /dev/null @@ -1,655 +0,0 @@ -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int array_scale_lin(double* x, int n, - double xmin, double xmax, double dx, - double h, double* y) -\brief Vector `x` linear transformation - -Function transforms values \f$x(i)\f$, \f$i = 0,1,\ldots n\f$ -to the \f$y(i)\f$, accordint to equation: - -\f[ -y(i) = k_x x(i) + d_x, \qquad k_x = -\frac{h}{x_{\textrm{max}} - x_{\textrm{min}}}. -\f] - -All values of the vector `x` between -\f$x_{\textrm{min}}\f$ and \f$x_{\textrm{max}}\f$, transforms to -the vector `y` between \f$d_x\f$ and \f$h + d_x\f$. -Parameter \f$d_x\f$ sets mean shift of the vector `y`. - -This function is convenient for translating values ​​ -of different dimensions. For example it can be used -to transfer the values ​​of the vector `x` -to the graph of the height of` h`, where the height can -be set in the number of pixels, in centimeters, etc. - -\param[in] x -Pointer to the input vector `x`. \n -Vector size is `[n x 1]`. \n -\n - -\param[in] n -Size of vector `x`. \n -\n - -\param[in] xmin -Parameter \f$x_{\textrm{min}}\f$. \n -\n - -\param[in] xmax -Parameter \f$x_{\textrm{min}}\f$. \n -Value `xmax` must be more than `xmin`. \n -\n - -\param[in] dx -Displacement after transformation. \n -This parameter must have output vector `y` -dimensions (pixels, centimeters). \n -\n - -\param[in] h -Height of vector `y` after transforming between `dx` and `h+dx`. \n -\n - -\param[out] y -Pointer to the output vector `y`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n -\note -Pointer `y` can be equal to `x`. -Velues of vector `x` will be rewritten in this case. \n -\n - -\return -`RES_OK` if function returns successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -**************************************************************************** */ - - - -/*! **************************************************************************** -\fn int concat(void* a, size_t na, void* b, size_t nb, void* c) -\brief -Concatenate arrays `a` and `b` - -Let's arrays `a` and `b` are vectors: \n -`a = [a(0), a(1), ... a(na-1)]`, \n -`b = [b(0), b(1), ... b(nb-1)]`, \n -concatenation of these arrays will be array `c` size `na+nb`: \n -`c = [a(0), a(1), ... a(na-1), b(0), b(1), ... b(nb-1)]`. - - -\param[in] a -Pointer to the first array `a`. \n -Array `a` size is `na` bytes. \n -\n - -\param[in] na -Array `a` size (bytes). \n -\n - -\param[in] b -Pointer to the second array `b`. \n -Array `b` size is `nb` bytes. \n -\n - -\param[in] nb -Array `a` size (bytes). \n -\n - -\param[out] c -Pointer to the concatenation result array `c`. \n -Array `c` size is `na + nb` bytes. \n -Memory must be allocated. \n -\n - -\return -`RES_OK` if function returns successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Function uses pointer type `void*` and can be useful for an arrays -concatenation with different types. \n -For example two `double` arrays concatenation: -\code{.cpp} -double a[3] = {1.0, 2.0, 3.0}; -double b[2] = {4.0, 5.0}; -double c[5]; - -concat((void*)a, 3*sizeof(double), (void*)b, 2*sizeof(double), (void*)c); -\endcode -Vector `c` keeps follow data: -\verbatim -c = [1.0, 2.0, 3.0, 4.0, 5.0] -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int decimate(double* x, int n, int d, double* y, int* cnt) -\brief -Real vector decimation - -Function `d` times decimates real vector `x`. \n -Output vector `y` keeps values corresponds to: -`y(k) = x(k*d), k = 0...n/d-1` \n - -\param[in] x -Pointer to the input real vector `x`. \n -Vector `x` size is `[n x 1]`. \n \n - -\param[in] n -Size of input vector `x`. \n \n - -\param[in] d -Decimation coefficient. \n -Each d-th vector will be copy from vector `x` to the -output vector `y`. \n \n - -\param[out] y -Pointer to the output decimated vector `y`. \n -Output vector size is `[n/d x 1]` will be copy -to the address `cnt`. \n - -\param[out] cnt -Address which will keep decimated vector `y` size. \n -Pointer can be `NULL`, vector `y` will not return -in this case. \n \n - -\return -`RES_OK` if function calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Two-times decimation example: -\code{.cpp} -double x[10] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; -double y[5]; -int d = 2; -int cnt; - -decimate(x, 10, d, y, &cnt); -\endcode -As result variable `cnt` will be written value 5 and -vector `y` will keep array: -\verbatim -c = [0.0, 2.0, 4.0, 6.0, 8.0] -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int decimate_cmplx(complex_t* x, int n, int d, complex_t* y, int* cnt) -\brief -Complex vector decimation - -Function `d` times decimates a complex vector `x`. \n -Output vector `y` keeps values corresponds to: -`y(k) = x(k*d), k = 0...n/d-1` \n - -\param[in] x -Pointer to the input complex vector `x`. \n -Vector `x` size is `[n x 1]`. \n \n - -\param[in] n -Size of input vector `x`. \n \n - -\param[in] d -Decimation coefficient. \n -Each d-th vector will be copy from vector `x` to the -output vector `y`. \n \n - -\param[out] y -Pointer to the output decimated vector `y`. \n -Output vector size is `[n/d x 1]` will be copy -to the address `cnt`. \n -Memory must be allocated. \n \n - -\param[out] cnt -Address which will keep decimated vector `y` size. \n -Pointer can be `NULL`, vector `y` will not return -in this case. \n \n - -\return -`RES_OK` if function calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Two-times complex vector decimation example: - -\code{.cpp} -compex_t x[10] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}, -{5.0, 5.0}, {6.0, 6.0}, {7.0, 7.0}, {8.0, 8.0}, {9.0, 9.0}}; -compex_t y[5]; -int d = 2; -int cnt; - -decimate_cmplx(x, 10, d, y, &cnt); -\endcode - -As result variable `cnt` will be written value 5 and -vector `y` will keep array: - -\verbatim -c = [0.0+0.0j, 2.0+2.0j, 4.0+4.0j, 6.0+6.0j, 8.0+8.0j] -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - - - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int flipip(double* x, int n) -\brief -Flip real vector `x` in place - -Function flips real vector `x` length `n` in the memory. \n -For example real vector `x` length 6:\n -\verbatim -x = [0, 1, 2, 3, 4, 5] -\endverbatim -After flipping it will be as follow: -\verbatim -x = [5, 4, 3, 2, 1, 0] -\endverbatim - -\param[in, out] x -Pointer to the real vector `x`. \n -Vector size is `[n x 1]`. \n -Flipped vector will be on the same address. \n -\n - -\param[in] n -Length of the vector `x`. \n -\n - -\return -`RES_OK` if function returns successfully. \n - Else \ref ERROR_CODE_GROUP "error code". - -Example: -\code{.cpp} -double x[5] = {0.0, 1.0, 2.0, 3.0, 4.0}; -int i; -for(i = 0; i < 5; i++) - printf("%6.1f ", x[i]); -flipip(x, 5); -printf("\n"); -for(i = 0; i < 5; i++) - printf("%6.1f ", x[i]); -\endcode -\n -Program result: -\verbatim - 0.0 1.0 2.0 3.0 4.0 - 4.0 3.0 2.0 1.0 0.0 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int flipip_cmplx(complex_t* x, int n) -\brief Flip complex vector `x` in place - -Function flips complex vector `x` length `n` in the memory - \n -For example complex vector `x` length 6: \n -\verbatim -x = [0+0j, 1+1j, 2+2j, 3+3j, 4+4j, 5+5j] -\endverbatim -After flipping it will be as follow: -\verbatim -x = [5+5j, 4+4j, 3+3j, 2+2j, 1+1j, 0+0j] -\endverbatim - -\param[in, out] x -Pointer to the complex vector `x`. \n -Vector size is `[n x 1]`. \n -Flipped vector will be on the same address. \n - -\param[in] n -Length of the vector `x`. \n \n - -\return -`RES_OK` if function returns successfully. \n -Else \ref ERROR_CODE_GROUP "error code". - -Example: -\code{.cpp} -complex_t y[5] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}}; -for(i = 0; i < 5; i++) - printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); -flipip_cmplx(y, 5); -printf("\n"); -for(i = 0; i < 5; i++) - printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); -\endcode - \n -Program result: -\verbatim - 0.0+0.0j 1.0+1.0j 2.0+2.0j 3.0+3.0j 4.0+4.0j - 4.0+4.0j 3.0+3.0j 2.0+2.0j 1.0+1.0j 0.0+0.0j -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int linspace(double x0, double x1, int n, int type, double* x) -\brief Function fills a vector with `n` linearly spaced elements -between `x0` and `x1`. - -Function supports two kinds of filling according to `type` parameter: \n - -Symmetric fill (parameter `type=DSPL_SYMMETRIC`): \n - -\f$x(k) = x_0 + k \cdot dx\f$, -\f$dx = \frac{x_1 - x_0}{n-1}\f$, \f$k = 0 \ldots n-1.\f$ - -Periodic fill (parameter `type=DSPL_PERIODIC`): \n - -\f$x(k) = x_0 + k \cdot dx\f$, -\f$dx = \frac{x_1 - x_0}{n}\f$, \f$k = 0 \ldots n-1.\f$ - -\param[in] x0 -Start point \f$x_0\f$. \n \n - -\param[in] x1 -End point \f$x_1\f$. \n \n - -\param[in] n -Number of points `x` (size of vector `x`). \n \n - -\param[in] type -Fill type: \n -`DSPL_SYMMETRIC` --- symmetric, \n -`DSPL_PERIODIC` --- periodic. \n \n - -\param[in,out] x -Pointer to the output linearly spaced vector `x` . \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if function returns successfully. \n - Else \ref ERROR_CODE_GROUP "error code". - -\note -Difference between symmetric and periodic filling we can -understand from the follow examples. \n -Example 1. Periodic fill. - double x[5]; - linspace(0, 5, 5, DSPL_PERIODIC, x); -\endcode -Values in the vector `x` are: -\verbatim -0, 1, 2, 3, 4 -\endverbatim - \n \n -Example 2. Symmetric fill. -\code{.cpp} - double x[5]; - linspace(0, 5, 5, DSPL_SYMMETRIC, x); -\endcode -Values in the vector `x` are: -\verbatim -0, 1.25, 2.5, 3.75, 5 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int logspace(double x0, double x1, int n, int type, double* x) -\brief Function fills a vector with `n` logarithmically spaced elements -between \f$10^{x_0}\f$ and \f$10^{x_1}\f$. - - -Function supports two kinds of filling according to `type` parameter: \n - -Symmetric fill (parameter `type=DSPL_SYMMETRIC`): \n - -\f$x(k) = 10^{x_0} \cdot dx^k\f$, here \f$dx = \sqrt[n-1]{10^{x_1 - x_0}}\f$, -\f$k = 0 \ldots n-1.\f$ - -Periodic fill (parameter `type=DSPL_PERIODIC`): \n - -\f$x(k) = 10^{x_0} \cdot dx^k\f$, here \f$dx = \sqrt[n]{10^{x_1 - x_0}}\f$, -\f$k = 0 \ldots n-1.\f$ \n - - -\param[in] x0 -Start exponent value \f$x_0\f$. \n \n - -\param[in] x1 -End exponent value \f$x_1\f$. \n \n - -\param[in] n -Number of points `x` (size of vector `x`). \n \n - -\param[in] type -Fill type: \n -`DSPL_SYMMETRIC` --- symmetric, \n -`DSPL_PERIODIC` --- periodic. \n \n - -\param[in,out] x -Pointer to the output logarithmically spaced vector `x` . \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if function returns successfully. \n - Else \ref ERROR_CODE_GROUP "error code". - -\note -Difference between symmetric and periodic filling we can -understand from the follow examples. \n -Example 1. Periodic fill. -\code{.cpp} - double x[5]; - logspace(-2, 3, 5, DSPL_PERIODIC, x); -\endcode - -Values in the vector `x` are: - -\verbatim -0.01, 0.1, 1, 10, 100 -\endverbatim - -\n \n - -Example 2. Symmetric fill. -\code{.cpp} - double x[5]; - logspace(-2, 3, 5, DSPL_SYMMETRIC, x); -\endcode - -Values in the vector `x` are: - -\verbatim -0.01 0.178 3.162 56.234 1000 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int ones(double* x, int n) -\brief Function fills all real vector `x` by ones values. - -\param[in, out] x -Pointer to the vector `x`. \n -Vector size is `[n x 1]`. \n -All elements on this vector will be set to one. \n -\n - -\param[in] n -Size of vector `x`. \n -\n - -\return -`RES_OK` if function returns successfully. \n - Else \ref ERROR_CODE_GROUP "error code". - -Example: -\code{.cpp} -double y[5] = {0}; -int i; -ones(y, 5); -for(i = 0; i < 5; i++) - printf("%6.1f% ", y[i]); -\endcode - \n -Vector `y` values are: -\verbatim - 1.0 1.0 1.0 1.0 1.0 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -**************************************************************************** */ - - - - - - - - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int verif(double* x, double* y, size_t n, double eps, double* err) -\brief Real arrays verification - -Function calculates a maximum relative error between two real arrays `x` -and `y` (both length equals `n`): - -\f[ -e = \max \left( \frac{|x(k) - y(k)| }{ |x(k)|} \right), \quad if \quad |x(k)| > 0, -\f] -or -\f[ -e = \max(|x(k) - y(k)| ), ~\qquad if \quad~|x(k)| = 0, -\f] -Return `DSPL_VERIF_SUCCESS` if maximum relative error \f$ e\f$ less than `eps`. -Else returns `DSPL_VERIF_FAILED`. \n - -This function can be used for algorithms verification if vector `x` is user -algorithm result and vector `y` -- reference vector. - -\param[in] x -Pointer to the first vector `x`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] y -Pointer to the second vector `y`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of vectors `x` and `y`. \n \n - -\param[in] eps -Relative error threshold. \n -If error less than `eps`, then function returns -`DSPL_VERIF_SUCCESS`, else `DSPL_VERIF_FAILED`. \n \n - -\param[in, out] err -Pointer to the variable which keep -maximum relative error. \n -Pointer can be `NULL`, maximum error will not be returned -in this case. \n \n - -\return -`DSPL_VERIF_SUCCESS` if maximum relative error less than `eps`. \n -Otherwise `DSPL_VERIF_FAILED`. - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - - - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int verif_cmplx(complex_t* x, complex_t* y, size_t n, - double eps, double* err) -\brief -Complex arrays verification - -Function calculates a maximum relative error between two complex arrays `x` -and `y` (both length equals `n`): - -\f[ -e = \max \left( \frac{|x(k) - y(k)| }{ |x(k)|} \right), \quad if \quad |x(k)| > 0, -\f] -or -\f[ -e = \max(|x(k) - y(k)| ), ~\qquad if \quad~|x(k)| = 0, -\f] -Return `DSPL_VERIF_SUCCESS` if maximum relative error \f$ e\f$ less than `eps`. -Else returns `DSPL_VERIF_FAILED`. \n - -This function can be used for algorithms verification if vector `x` is user -algorithm result and vector `y` -- reference vector. - -\param[in] x -Pointer to the first vector `x`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] y -Pointer to the second vector `y`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of vectors `x` and `y`. \n \n - -\param[in] eps -Relative error threshold. \n -If error less than `eps`, then function returns -`DSPL_VERIF_SUCCESS`, else `DSPL_VERIF_FAILED`. \n \n - -\param[in, out] err -Pointer to the variable which keep -maximum relative error. \n -Pointer can be `NULL`, maximum error will not be returned -in this case. \n \n - -\return -`DSPL_VERIF_SUCCESS` if maximum relative error less than `eps`. \n -Otherwise `DSPL_VERIF_FAILED`. - -\author -Sergey Bakhurin -www.dsplib.org -****************************************************************************** */ \ No newline at end of file diff --git a/dspl/dox/en/cheby.dox b/dspl/dox/en/cheby.dox deleted file mode 100644 index e26f740..0000000 --- a/dspl/dox/en/cheby.dox +++ /dev/null @@ -1,111 +0,0 @@ - -/*! ***************************************************************************** -\ingroup SPEC_MATH_TRANSCEND -\fn int cheby_poly1(double* x, int n, int ord, double* y) -\brief Chebyshev polynomial of the first kind order `ord` - -Function calculates Chebyshev polynomial \f$ C_ord(x)\f$ of the first kind -order `ord` for the real vector `x` (length `n`) by recurrent equation: -\f[ -C_ord(x) = 2 x C_{ord-1}(x) - C_{ord-2}(x), -\f] -where \f$ C_0(x) = 1 \f$, \f$ C_1(x) = x\f$ - -\param[in] x -Pointer to the real argument vector `x`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of vectors `x` and `y`. \n \n - -\param[in] ord -Chebyshev polynomial order. \n \n - -\param[out] y -Pointer to the Chebyshev polynomial values, corresponds to the argument `x`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if Chebyshev polynomial is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: - -\include cheby_poly1_test.c - - \n \n -Text files will be created in `dat` directory: \n - -
-cheby_poly1_ord1.txt
-cheby_poly1_ord2.txt
-cheby_poly1_ord3.txt
-cheby_poly1_ord4.txt
-
- -GNUPLOT package will create Chebyshev polynomials plot from saved text-files: - -\image html cheby_poly1.png - -GNUPLOT script is follow: -\include cheby_poly1.plt - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ - - -/*! ***************************************************************************** -\ingroup SPEC_MATH_TRANSCEND -\fn int cheby_poly2(double* x, int n, int ord, double* y) -\brief Chebyshev polynomial of the second kind order `ord` - -Function calculates Chebyshev polynomial \f$ U_ord(x)\f$ of the first kind -order `ord` for the real vector `x` (length `n`) by recurrent equation: -\f[ -U_ord(x) = 2 x U_{ord-1}(x) - U_{ord-2}(x), -\f] -where \f$ U_0(x) = 1 \f$, \f$ U_1(x) = 2x\f$ - -\param[in] x -Pointer to the real argument vector `x`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of vectors `x` and `y`. \n \n - -\param[in] ord -Chebyshev polynomial order. \n \n - -\param[out] y -Pointer to the Chebyshev polynomial values, corresponds to the argument `x`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if Chebyshev polynomial is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: - -\include cheby_poly2_test.c - - \n \n -Text files will be created in `dat` directory: \n - -
-cheby_poly2_ord1.txt
-cheby_poly2_ord2.txt
-cheby_poly2_ord3.txt
-cheby_poly2_ord4.txt
-
- -GNUPLOT package will create Chebyshev polynomials plot from saved text-files: - -\image html cheby_poly2.png - -GNUPLOT script is follow: -\include cheby_poly2.plt - -\author Sergey Bakhurin www.dsplib.org -****************************************************************************** */ \ No newline at end of file diff --git a/dspl/dox/en/complex.dox b/dspl/dox/en/complex.dox deleted file mode 100644 index 1965b16..0000000 --- a/dspl/dox/en/complex.dox +++ /dev/null @@ -1,234 +0,0 @@ -/*! **************************************************************************** -\ingroup TYPES_GROUP -\typedef complex_t -\brief Complex data type. - -DSPL-2.0 decribes complex numbers data type as an array -of two `double` elements. -First element sets real part, second --- imaginary part. - -For example: - -\code{.cpp} - complex_t z; - z[0] = 1.0; - z[1] = -2.0; -\endcode - -Variable `z = 1-2j`, here `j` - imaginary unit. - -For the convenience of working with complex numbers implemented -special macros: \ref RE, \ref IM, \ref ABSSQR -***************************************************************************** */ - - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\def ABSSQR(x) -\brief -The macro returns the square of the modulus of a complex number `x`. - -Square of the modulus of a complex number \f$ x = a + j b \f$ equals: - -\f[ - |x|^2 = x x^* = a^2 + b^2. -\f] - -Example: -\code{.cpp} - complex_t z; - double y; - RE(z) = 1.0; - IM(z) = -2.0; - y = ABSSQR(z); -\endcode - -Variable `z = 1-2j`, here `j` - imaginary unit, but variable `y = 5`. -***************************************************************************** */ - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\def IM(x) -\brief Macro sets imaginary part of the complex number. - -Example: -\code{.cpp} - complex_t z; - RE(z) = 1.0; - IM(z) = -2.0; -\endcode - -Variable `z = 1-2j`, here `j` - imaginary unit. - -This macro can be used to return -imaginary part of the complex number: -\code{.cpp} - complex_t z = {3.0, -4.0}; - double r; - r = IM(z); -\endcode -In this example `z = 3-4i`, -but variable `r` will keep -4. -***************************************************************************** */ - - - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\def RE(x) -\brief Macro sets real part of the complex number. - -Example: -\code{.cpp} - complex_t z; - RE(z) = 1.0; - IM(z) = -2.0; -\endcode - -Variable `z = 1-2j`, here `j` - imaginary unit. - -This macro can be used to return -real part of the complex number: - -\code{.cpp} - complex_t z = {3.0, -4.0}; - double r; - r = RE(z); -\endcode -In this example `z = 3-4i`, -but variable `r` will keep 3. -***************************************************************************** */ - - - - - -/*! ***************************************************************************** -\ingroup TYPES_GROUP -\fn int cmplx2re(complex_t* x, int n, double* re, double* im) -\brief Separate complex vector to the real and image vectors - -Function fills `re` and `im` vectors corresponds to real and image -parts of the input complex array `x`. \n - - -\param[in] x -Pointer to the real complex vector. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of the input complex vector `x` and real and image -vectors `re` and `im`. \n \n - -\param[out] re -Pointer to the real part vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[out] im -Pointer to the image part vector. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if function converts complex vector successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: \n -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - double re[3], im[3]; - - cmplx2re(x, 3, re, im); -\endcode - -Vectors `re` and `im` will contains: - -\verbatim -re[0] = 1.0; im[0] = 2.0; -re[1] = 3.0; im[1] = 4.0; -re[2] = 5.0; im[2] = 6.0; -\endverbatim - -\author Sergey Bakhurin. www.dsplib.org -****************************************************************************** */ - - - - - - - - -/*! ***************************************************************************** -\ingroup TYPES_GROUP -\fn int re2cmplx(double* x, int n, complex_t *y) -\brief Convert real array to the complex array. - -Function copies the vector `x` to the real part of vector `y`. -Image part of the vector `y` sets as zero. \n -So complex vector contains data: \n -`y[i] = x[i] + j0, here i = 0,1,2 ... n-1` - - -\param[in] x -Pointer to the real vector `x`. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of the real vector `x` and complex vector `y`. \n \n - -\param[out] y -Pointer to the complex vector `y`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` if function returns successfully. \n -Else \ref ERROR_CODE_GROUP "code error": \n - - - -Example: -\code{.cpp} - double x[3] = {1.0, 2.0, 3.0}; - complex_t y[3]; - - re2cmplx(x, 3, y); -\endcode - -Vector `y` will keep: - -\verbatim - y[0] = 1+0j; - y[1] = 2+0j; - y[2] = 3+0j. -\endverbatim - -\author Sergey Bakhurin. www.dsplib.org -****************************************************************************** */ - - - diff --git a/dspl/dox/en/dft.dox b/dspl/dox/en/dft.dox deleted file mode 100644 index 3498ec6..0000000 --- a/dspl/dox/en/dft.dox +++ /dev/null @@ -1,216 +0,0 @@ - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int dft(double* x, int n, complex_t* y) -\brief Discrete Fourier transform of a real signal. - -The function calculates the \f$ n \f$ -point discrete Fourier transform -real signal \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y (k) = \sum_ {m = 0} ^ {n-1} x (m) - \exp \left (-j \frac {2 \pi} {n} m k \right), -\f] -where \f$ k = 0 \ldots n-1 \f$. - -\param [in] x -Pointer to the vector of the real input signal \f$ x (m) \f$, -\f$ m = 0 \ldots n-1 \f$. \n -The size of the vector is `[n x 1]`. \n \n - -\param [in] n -The size of the DFT \f$ n \f$ -(the size of the vectors of the input signal and the result of the DFT). \n \n - -\param [out] y -Pointer to the complex vector of the DFT result \f$ Y (k) \f$, -\f$ k = 0 \ldots n-1 \f$. -The size of the vector is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` if the DFT is calculated successfully. \n -Otherwise, \ref ERROR_CODE_GROUP "error code". - -An example of using the `dft` function: - -\include dft_test.c - -The result of the program: - -\verbatim -y [0] = 120.000 0.000 -y [1] = -8.000 40.219 -y [2] = -8.000 19.314 -y [3] = -8.000 11.973 -y [4] = -8.000 8.000 -y [5] = -8.000 5.345 -y [6] = -8.000 3.314 -y [7] = -8.000 1.591 -y [8] = -8.000 0.000 -y [9] = -8.000 -1.591 -y [10] = -8.000 -3.314 -y [11] = -8.000 -5.345 -y [12] = -8.000 -8.000 -y [13] = -8.000 -11.973 -y [14] = -8.000 -19.314 -y [15] = -8.000 -40.219 -\endverbatim - -\note -This function performs the DFT calculation using the naive method and requires \f$ n ^ 2 \f$ -complex multiplications. \n -To increase the calculation speed, it is recommended to use -fast Fourier transform algorithms. - -\author -Bakhurin Sergey -www.dsplib.org -**************************************************************************** */ - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int dft_cmplx(complex_t* x, int n, complex_t* y) -\brief Discrete Fourier transform of a complex signal. - -The function calculates the \f$ n \f$ -point discrete Fourier transform -complex signal \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y (k) = \sum_ {m = 0} ^ {n-1} x (m) - \exp \left (-j \frac {2 \pi} {n} m k \right), -\f] -where \f$ k = 0 \ldots n-1 \f$. - -\param [in] x -Pointer to a vector of complex -input signal \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -The size of the vector is `[n x 1]`. \n \n - -\param [in] n -The size of the DFT \f$ n \f$ -(the size of the vectors of the input signal and the result of the DFT). \n \n - -\param [out] y -Integrated Vector Pointer -DFT result \f$ Y (k) \f$, \f$ k = 0 \ldots n-1 \f$. \n -The size of the vector is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` if the DFT is calculated successfully. \n -Otherwise, \ref ERROR_CODE_GROUP "error code". - -An example of using the `dft_cmplx` function: - -\include dft_cmplx_test.c - -The result of the program: - -\verbatim -y [0] = 120.000 0.000 -y [1] = -8.000 40.219 -y [2] = -8.000 19.314 -y [3] = -8.000 11.973 -y [4] = -8.000 8.000 -y [5] = -8.000 5.345 -y [6] = -8.000 3.314 -y [7] = -8.000 1.591 -y [8] = -8.000 0.000 -y [9] = -8.000 -1.591 -y [10] = -8.000 -3.314 -y [11] = -8.000 -5.345 -y [12] = -8.000 -8.000 -y [13] = -8.000 -11.973 -y [14] = -8.000 -19.314 -y [15] = -8.000 -40.219 -\endverbatim - -\note -This function performs the calculation of the DFT by the naive method -and requires \f$ n ^ 2 \f$ complex multiplications. \n -To increase the calculation speed, it is recommended -use fast Fourier transform algorithms. - -\author -Bakhurin Sergey -www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int idft_cmplx(complex_t* x, int n, complex_t* y) -\brief Inverse discrete Fourier transform of the complex spectrum. - -The function calculates the \f$ n \f$ -point inverse discrete transform -Fourier complex spectrum \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - y (k) = \sum_ {m = 0} ^ {n-1} x (m) - \exp \left (j \frac {2 \pi} {n} m k \right), -\f] -where \f$ k = 0 \ldots n-1 \f$. - -\param [in] x -Pointer to the vector of the input complex signal spectrum \f$ x (m) \f$, -\f$ m = 0 \ldots n-1 \f$. \n -The size of the vector is `[n x 1]`. \n \n - -\param [in] n -The size of the ODPF \f$ n \f$ -(the size of the vectors of the input spectrum and the result of the ODPF). \n \n - -\param [out] y -Pointer to the complex vector of the ODPF result \f$ y (k) \f$, -\f$ k = 0 \ldots n-1 \f$. -The size of the vector is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` if the ODPF is calculated successfully. \n -Otherwise, \ref ERROR_CODE_GROUP "error code". - -An example of using the `dft_cmplx` function: - -\include idft_cmplx_test.c - -The result of the program: - -\verbatim -x [0] = 0.000 + 0.000j, z [0] = 0.000 -0.000 -x [1] = 1.000 + 0.000j, z [1] = 1.000 -0.000 -x [2] = 2.000 + 0.000j, z [2] = 2.000 -0.000 -x [3] = 3.000 + 0.000j, z [3] = 3.000 -0.000 -x [4] = 4.000 + 0.000j, z [4] = 4.000 -0.000 -x [5] = 5.000 + 0.000j, z [5] = 5.000 -0.000 -x [6] = 6.000 + 0.000j, z [6] = 6.000 -0.000 -x [7] = 7.000 + 0.000j, z [7] = 7.000 -0.000 -x [8] = 8.000 + 0.000j, z [8] = 8.000 -0.000 -x [9] = 9.000 + 0.000j, z [9] = 9.000 -0.000 -x [10] = 10.000 + 0.000j, z [10] = 10.000 -0.000 -x [11] = 11.000 + 0.000j, z [11] = 11.000 +0.000 -x [12] = 12.000 + 0.000j, z [12] = 12.000 +0.000 -x [13] = 13.000 + 0.000j, z [13] = 13.000 +0.000 -x [14] = 14.000 + 0.000j, z [14] = 14.000 +0.000 -x [15] = 15.000 + 0.000j, z [15] = 15.000 -0.000 -\endverbatim - -\note -This function performs the calculation of the DFT using the naive method. -and requires \f$ n ^ 2 \f$ complex multiplications. \n -To increase the calculation speed, it is recommended -use fast Fourier transform algorithms. - -\author -Bakhurin Sergey -www.dsplib.org -***************************************************************************** */ - - - - diff --git a/dspl/dox/en/ellipj.dox b/dspl/dox/en/ellipj.dox deleted file mode 100644 index c3f7b5a..0000000 --- a/dspl/dox/en/ellipj.dox +++ /dev/null @@ -1,418 +0,0 @@ - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd(double* w, int n, double k, double* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ -of the real vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$ of the real vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ -of complex vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$ of complex vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn(double* w, int n, double k, double* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ -of real vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$ of real vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ -of complex vector argument - -Function calculates inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$ of complex vector `w`. \n - -\param[in] w -Pointer to the argument vector \f$ w \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `w`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] u -Pointer to the vector of inverse Jacobi elliptic function -\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd(double* u, int n, double k, double* y) -\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ -of real vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$ of real vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ -of complex vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$ of complex vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{cd}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_landen(double k, int n, double* y) -\brief Function calculates complete elliptical integral -coefficients \f$ k_i \f$ - -Complete elliptical integral \f$ K(k) \f$ can be described as: - -\f[ -K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), -\f] - -here \f$ k_i \f$ -- coefficients which calculated -iterative from \f$ k_0 = k\f$: - -\f[ -k_i = -\left( -\frac{k_{i-1}} -{ -1+\sqrt{1-k_{i-1}^2} -} -\right)^2 -\f] - -This function calculates `n` fist coefficients \f$ k_i \f$, which can -be used for Complete elliptical integral. - - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, which values can be from 0 to 1. \n \n - - -\param[in] n -Number of \f$ k_i \f$ which need to calculate. \n -Parameter `n` is size of output vector `y`. \n - - -\param[out] y -pointer to the real vector which keep \f$ k_i \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return - `RES_OK` -- successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -Example: - -\include ellip_landen_test.c - -Result: - -\verbatim - i k[i] - - 1 4.625e-01 - 2 6.009e-02 - 3 9.042e-04 - 4 2.044e-07 - 5 1.044e-14 - 6 2.727e-29 - 7 1.859e-58 - 8 8.640e-117 - 9 1.866e-233 -10 0.000e+00 -11 0.000e+00 -12 0.000e+00 -13 0.000e+00 -\endverbatim - -\note Complete elliptical integral converges enough fast - if modulus \f$ k<1 \f$. There are 10 to 20 coefficients \f$ k_i \f$ ​​ - are sufficient for practical applications - to ensure complete elliptic integral precision within EPS. - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn(double* u, int n, double k, double* y) -\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ -of real vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$ of real vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org - ***************************************************************************** */ - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ of complex vector argument - -Function calculates Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$ of complex vector `u` and -elliptical modulus `k`. \n - -\param[in] u -Pointer to the argument vector \f$ u \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\param[in] n -Size of vector `u`. \n - -\param[in] k -Elliptical modulus \f$ k \f$. \n -Elliptical modulus is real parameter, -which values can be from 0 to 1. \n \n - - -\param[out] y -Pointer to the vector of Jacobi elliptic function -\f$ y = \textrm{sn}(u K(k), k)\f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - diff --git a/dspl/dox/en/fft.dox b/dspl/dox/en/fft.dox deleted file mode 100644 index 1ecefb9..0000000 --- a/dspl/dox/en/fft.dox +++ /dev/null @@ -1,435 +0,0 @@ - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\struct fft_t -\brief Fast Fourier Transform Object Data Structure - -The structure stores pointers to twiddle factors and arrays of intermediate -data of the fast Fourier transform algorithm. - -The DSPL library uses an FFT algorithm for composite size. - - -\param n -The size of the FFT vector for which memory is allocated -in the structure arrays. \n -The parameter `n` must be equal to an integer power of two (radix 2). \n \n - - -\param w -Pointer to the vector of twiddle factors. \n -The size of the vector is `[n x 1]`. \n -The memory must be allocated and an array of twiddle factors -must be filled with the \ref fft_create function. \n\n - - -\param t0 -Pointer to the vector of intermediate results of the FFT algorithm. \n -The size of the vector is `[n x 1]`. \n -Memory must be allocated by \ref fft_create function. \n\n - - -\param t1 -Pointer to the vector of intermediate results. \n -The size of the vector is `[n x 1]`. \n -The memory must be allocated with the \ref fft_create function. \n\n -The structure is populated with the \ref fft_create function once -before using the FFT algorithm. \n -A pointer to an object of this structure may be -reused when calling FFT functions. \n -Before exiting the program, dedicated memory for twiddle factors and arrays of -intermediate data must be cleared by the \ref fft_free function. -For example: -\code -fft_t pfft = {0}; /* Structure fft_t and clear all fields */ -int n = 64; /* FFT size */ - -int err; - -/* Create and fill FFT structure for 64-points FFT */ -err = fft_create(&pfft, n); - -/* FFT calculation here */ -/* FFT calculation here one more */ -/* ... */ - -/* Clear fft structure */ -fft_free(&pfft); -\endcode - -\note -It is important to note that if the object `fft_t` was created for the FFT size -equal to` n`, it can only be used for FFT of size `n`. \n \n -It’s also worth noting that the FFT functions independently control the size, -and independently allocate the memory of the FFT object, if necessary. -So if you call any function using the `fft_t` structure with filled -data for the FFT length `k` for calculating the FFT of length`n`, -then the structure arrays will be automatically recreated for the length `n`. - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int ifft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) -\brief Inverse fast Fourier transform - -Function calculates \f$ n \f$-point IFFT of complex data -\f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \frac{1}{N} \sum_{m = 0}^{n-1} x(m) \exp - \left( j \frac{2\pi}{n} m k \right), -\f] -here \f$ k = 0 \ldots n-1 \f$. - - -\param[in] x -Pointer to the input vector \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -IFFT size \f$n\f$. \n -IFFT size can be composite: -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -here \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -simple number less than 46340 -(see \ref fft_create function). \n \n - -\param[in] pfft -Pointer to the `fft_t` object. \n -This pointer cannot be `NULL`. \n -Structure \ref fft_t should be previously once -filled with the \ref fft_create function, and the memory should be -cleared before exiting by the \ref fft_free function. \n \n - -\param[out] y -Pointer to the IFFT result vector \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if IFFT is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - - -IFFT example: - -\include ifft_cmplx_test.c - -Result: - -\verbatim -| x[ 0] = 1.000 0.000 | y[ 0] = -0.517 0.686 | z[ 0] = 1.000 0.000 | -| x[ 1] = 0.540 0.841 | y[ 1] = -0.943 0.879 | z[ 1] = 0.540 0.841 | -| x[ 2] = -0.416 0.909 | y[ 2] = -2.299 1.492 | z[ 2] = -0.416 0.909 | -| x[ 3] = -0.990 0.141 | y[ 3] = 16.078 -6.820 | z[ 3] = -0.990 0.141 | -| x[ 4] = -0.654 -0.757 | y[ 4] = 2.040 -0.470 | z[ 4] = -0.654 -0.757 | -| x[ 5] = 0.284 -0.959 | y[ 5] = 1.130 -0.059 | z[ 5] = 0.284 -0.959 | -| x[ 6] = 0.960 -0.279 | y[ 6] = 0.786 0.097 | z[ 6] = 0.960 -0.279 | -| x[ 7] = 0.754 0.657 | y[ 7] = 0.596 0.183 | z[ 7] = 0.754 0.657 | -| x[ 8] = -0.146 0.989 | y[ 8] = 0.470 0.240 | z[ 8] = -0.146 0.989 | -| x[ 9] = -0.911 0.412 | y[ 9] = 0.375 0.283 | z[ 9] = -0.911 0.412 | -| x[10] = -0.839 -0.544 | y[10] = 0.297 0.318 | z[10] = -0.839 -0.544 | -| x[11] = 0.004 -1.000 | y[11] = 0.227 0.350 | z[11] = 0.004 -1.000 | -| x[12] = 0.844 -0.537 | y[12] = 0.161 0.380 | z[12] = 0.844 -0.537 | -| x[13] = 0.907 0.420 | y[13] = 0.094 0.410 | z[13] = 0.907 0.420 | -| x[14] = 0.137 0.991 | y[14] = 0.023 0.442 | z[14] = 0.137 0.991 | -| x[15] = -0.760 0.650 | y[15] = -0.059 0.479 | z[15] = -0.760 0.650 | -| x[16] = -0.958 -0.288 | y[16] = -0.161 0.525 | z[16] = -0.958 -0.288 | -| x[17] = -0.275 -0.961 | y[17] = -0.300 0.588 | z[17] = -0.275 -0.961 | -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft(double* x, int n, fft_t* pfft, complex_t* y) -\brief Fast Fourier transform for the real vector. - -Function calculated \f$ n \f$-points FFT for the real vector -\f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \sum_{m = 0}^{n-1} x(m) \exp - \left( -j \frac{2\pi}{n} m k \right), -\f] -here \f$ k = 0 \ldots n-1 \f$. - - -\param[in] x -Pointer to the input real vector \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -FFT size \f$n\f$. \n -FFT size can be composite: -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -here \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -simple number less than 46340 -(see \ref fft_create function). \n \n - -\param[in] pfft -Pointer to the `fft_t` object. \n -This pointer cannot be `NULL`. \n -Structure \ref fft_t should be previously once -filled with the \ref fft_create function, and the memory should be -cleared before exiting by the \ref fft_free function. \n \n - -\param[out] y -Pointer to the FFT result complex vector \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if FFT is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - - -Example: - -\include fft_test.c - -Result: - -\verbatim -y[ 0] = 91.000 0.000 -y[ 1] = -7.000 30.669 -y[ 2] = -7.000 14.536 -y[ 3] = -7.000 8.778 -y[ 4] = -7.000 5.582 -y[ 5] = -7.000 3.371 -y[ 6] = -7.000 1.598 -y[ 7] = -7.000 0.000 -y[ 8] = -7.000 -1.598 -y[ 9] = -7.000 -3.371 -y[10] = -7.000 -5.582 -y[11] = -7.000 -8.778 -y[12] = -7.000 -14.536 -y[13] = -7.000 -30.669 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) -\brief Fast Fourier transform for the complex vector. - -Function calculated \f$ n \f$-points FFT for the complex vector -\f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \sum_{m = 0}^{n-1} x(m) \exp - \left( -j \frac{2\pi}{n} m k \right), -\f] -here \f$ k = 0 \ldots n-1 \f$. - -\param[in] x -Pointer to the input complex vector \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -FFT size \f$n\f$. \n -FFT size can be composite: -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -here \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -simple number less than 46340 -(see \ref fft_create function). \n \n - -\param[in] pfft -Pointer to the `fft_t` object. \n -This pointer cannot be `NULL`. \n -Structure \ref fft_t should be previously once -filled with the \ref fft_create function, and the memory should be -cleared before exiting by the \ref fft_free function. \n \n - -\param[out] y -Pointer to the FFT result complex vector \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return -`RES_OK` if FFT is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - - -Example: - -\include fft_cmplx_test.c - -Result: - -\verbatim -y[ 0] = -0.517 0.686 -y[ 1] = -0.943 0.879 -y[ 2] = -2.299 1.492 -y[ 3] = 16.078 -6.820 -y[ 4] = 2.040 -0.470 -y[ 5] = 1.130 -0.059 -y[ 6] = 0.786 0.097 -y[ 7] = 0.596 0.183 -y[ 8] = 0.470 0.240 -y[ 9] = 0.375 0.283 -y[10] = 0.297 0.318 -y[11] = 0.227 0.350 -y[12] = 0.161 0.380 -y[13] = 0.094 0.410 -y[14] = 0.023 0.442 -y[15] = -0.059 0.479 -y[16] = -0.161 0.525 -y[17] = -0.300 0.588 -\endverbatim - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft_create(fft_t* pfft, int n) -\brief Function creates and fill `fft_t` structure. - -The function allocates memory and calculates twiddle factors - of the `n`-point FFT for the structure` fft_t`. - -\param[in,out] pfft -Pointer to the `fft_t` object. \n -Pointer cannot be `NULL`. \n \n - -\param[in] n -FFT size \f$n\f$. \n -FFT size can be composite -\f$n = n_0 \times n_1 \times n_2 \ldots \times n_p \times m\f$, -here \f$n_i = 2,3,5,7\f$, and \f$m \f$ -- - arbitrary prime factor not exceeding 46340. \n -Thus, the FFT algorithm supports arbitrary integer lengths. -degrees of numbers 2,3,5,7, as well as their various combinations. \n -For example, with \f$ n = 725760 \f$ the structure will be successfully filled, -because -\f$ 725760 = 2 \cdot 3 \cdot 4 \cdot 5 \cdot 6 \cdot 7 \cdot 9 \cdot 16 \f$. \n -If \f$ n = 172804 = 43201 \cdot 4 \f$ then the structure will also be -successfully filled, because the simple factor in \f$ n \f$ does not -exceed 46340. \n -For size \f$ n = 13 \cdot 17 \cdot 23 \cdot 13 = 66079 \f$ -the function will return an error since 66079 is greater than 46340 and is -not the result of the product of numbers 2,3,5,7. \n \n - -\return -`RES_OK` if FFT structure is created and filled successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\note -Some compilers do not nullify its contents when creating a structure. -Therefore, it is recommended to reset the structure after its declaration: -\code{.cpp} -fft_t pfft = {0}; /* fill and fields of fft_t as zeros*/ -int n = 64; /* FFT size */ - -int err; - -/* Create fft_t object for 64-points FFT */ - -err = fft_create(&pfft, n); - -/* ................................... */ - -/* Clear fft_t structure */ - -fft_free(&pfft); -\endcode - -Before exiting the program, the memory allocated in the structure -need to clear by \ref fft_free function. \n \n - -\note -The "magic number" 46340 because \f$\sqrt{2^{31}} = 46340.95\f$. \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn void fft_free(fft_t *pfft) -\brief Free `fft_t` structure. - -The function clears the intermediate data memory -and vectors of FFT twiddle factors of the structure `fft_t`. - -\param[in] pfft -Pointer to the `fft_t` object. \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft_shift(double* x, int n, double* y) -\brief Perform a shift of the vector `x`, for use with the `fft` and `ifft` -functions, in order - - to move the frequency 0 to the center - of the vector `y`. - -\param[in] x -Pointer to the input vector (FFT or IFFT result). \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Input and output vector size. \n \n - -\param[out] y -Pointer to the output vector with frequency 0 in the center. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - - -\return -`RES_OK` if function is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ diff --git a/dspl/dox/en/filter_an.dox b/dspl/dox/en/filter_an.dox deleted file mode 100644 index 6e1ded5..0000000 --- a/dspl/dox/en/filter_an.dox +++ /dev/null @@ -1,221 +0,0 @@ - -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) -\brief Analog filter frequency response \f$ H(j \omega) \f$ calculation - -Function calculates analog filter frequaency response \f$ H(j \omega)\f$ -corresponds to transfer function \f$ H(s) \f$: - -\f[ - H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} - {\sum_{m = 0}^{N} a_m s^m}, -\f] -here \f$ N \f$ - filter order (equals to `ord`). - -\param[in] b -Pointer to the transfer function \f$ H(s) \f$ -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the transfer function \f$ H(s) \f$ -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$ H(s) \f$ numerator and denominator -coefficients number equals `ord+1`. \n \n - -\param[in] w -Pointer to the angular frequency \f$ \omega \f$ (rad/s), -which used for frequency response \f$ H(j \omega) \f$ calculation. \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -The size of the angular frequency vector `w`. \n \n - -\param[out] h -Pointer to the frequency response vector \f$ H(j \omega) \f$, -corresponds to angular frequency `w`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if frequency response vector is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, - int flag, double* mag, double* phi, double* tau) - -\brief -Magnitude, phase response and group delay vectors calculation -for digital or analog filter corresponds to \f$H(s)\f$, or \f$H(z)\f$ -transfer function. - - -\param[in] b -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator -and denominator coefficients number equals `ord+1`. \n \n - -\param[in] w -Pointer to the angular frequency \f$ \omega \f$ (rad/s), -which used for analog filter characteristics calculation -(flag sets as `DSPL_FLAG_ANALOG`). \n -For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), - parameter `w` describes normalized frequency of -frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. -Digital filter frequency response is \f$ 2\pi \f$-periodic function, -and vector `w` advisable to set from 0 to \f$ \pi \f$, -or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of frequency vector `w`. \n \n - -\param[in] flag -Binary flags to set calculation rules: \n -\verbatim -DSPL_FLAG_ANALOG Coefficients corresponds to analog filter -DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter -DSPL_FLAG_LOGMAG Calculate magnitude in logarithmic scale (in dB) -DSPL_FLAG_UNWRAP Unwrap radian phases by adding multiples of 2*pi -\endverbatim - -\param[out] mag -Pointer to the filter magnitude vector. \n -Vector size is `[n x 1]`. \n -If pointer is `NULL`, then magnitude will not calculted. \n \n - -\param[out] phi -Pointer to the phase response vector. \n -Vector size is `[n x 1]`. \n -If pointer is `NULL`, then phase response will not calculted. \n \n - -\param[out] tau -Pointer to the group delay vector. \n -Vector size is `[n x 1]`. \n -If pointer is `NULL`, then group delay will not calculted. \n \n - -\return -\return `RES_OK` if function is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Example: - -\include butter_ap_test.c - -Result: - -\verbatim -b[ 0] = 1.002 a[ 0] = 1.002 -b[ 1] = 0.000 a[ 1] = 2.618 -b[ 2] = 0.000 a[ 2] = 3.418 -b[ 3] = 0.000 a[ 3] = 2.615 -b[ 4] = 0.000 a[ 4] = 1.000 -\endverbatim -\n - -In `dat` folder will be created 3 files: \n - -\verbatim -butter_ap_test_mag.txt magnitude -butter_ap_test_phi.txt phase response -butter_ap_test_tau.txt group delay -\endverbatim - -In addition, GNUPLOT will build the following graphs from data stored in files: - -\image html butter_ap_test.png - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ - - - - - - - - - - -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) - -\brief Function calculates the digital filter frequency response -\f$ H \left(e^{j \omega} \right)\f$ corresponds to transfer function \f$H(z)\f$. - -Digital filter transfer function: -\f[ -H(z) = \frac{\sum\limits_{k = 0}^{N} b_k z^{-k}} - {\sum\limits_{m = 0}^{N} a_m z^{-m}}, -\f] -here \f$N\f$ --- filter order (parameter `ord`). \n - -Frequency response \f$ H \left(e^{j \omega} \right)\f$ we can get -if substitude \f$z = e^{j \omega} \f$. \n - - -\param[in] b -Pointer to the \f$ H(z) \f$ transfer function -numerator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] a -Pointer to the \f$H(z)\f$ transfer function -denominator coefficients vector. \n -Vector size is `[ord+1 x 1]`. \n \n - -\param[in] ord -Filter order. \n -Transfer function \f$H(z)\f$ numerator -and denominator coefficients number equals `ord+1`. \n \n - -\param[in] w -Pointer to the normalized frequency of digital filter -frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. \n -Digital filter frequency response is \f$ 2\pi \f$-periodic function, -and vector `w` advisable to set from 0 to \f$ \pi \f$, -or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. -Vector size is `[n x 1]`. \n \n - - -\param[in] n -Size of frequency vector `w`. \n \n - -\param[out] h -Pointer to the frequency response vector -\f$ H \left(\mathrm{e}^{j\omega} \right) \f$, -corresponds to normalized frequency `w`. \n -Vector size is `[n x 1]`. \n -Memory must be allocated. \n \n - -\return `RES_OK` if frequaency response vector is calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ diff --git a/dspl/dox/en/filter_ap.dox b/dspl/dox/en/filter_ap.dox index 23494dd..f76ea5f 100644 --- a/dspl/dox/en/filter_ap.dox +++ b/dspl/dox/en/filter_ap.dox @@ -255,7 +255,7 @@ In addition, GNUPLOT will build the following graphs from data stored in files: /*! **************************************************************************** \ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby1_ap_zp( int ord, double rp, complex_t *z, int* nz, +\fn int cheby1_ap_zp( int ord, double rp, complex_t* z, int* nz, complex_t* p, int* np) \brief Function calculates arrays of zeros and poles for analog normlized lowpass @@ -309,6 +309,33 @@ Else \ref ERROR_CODE_GROUP "code error". Normalized Chebyshev type 1 lowpass filter has no finite zeros. So `z` vector will not changed and in pointer `nz` will write 0 value. \n +Example of normalized Chebyshev type 1 lowpass filter + zeros and poles calculation: +\include cheby1_ap_zp_test.c + +Result: + +\verbatim +Chebyshev type 1 filter zeros: 0 +Chebyshev type 1 filter poles: 7 +p[ 0] = -0.256 +0.000 j +p[ 1] = -0.057 +1.006 j +p[ 2] = -0.057 -1.006 j +p[ 3] = -0.160 +0.807 j +p[ 4] = -0.160 -0.807 j +p[ 5] = -0.231 +0.448 j +p[ 6] = -0.231 -0.448 j +\endverbatim +\n + +In `dat` folder will be created `cheby1_ap_zp.txt` file. \n + +In addition, GNUPLOT will build the following graphs +from data stored in `dat/cheby1_ap_zp.txt` file: + +\image html cheby1_ap_zp_test.png + + \author Sergey Bakhurin www.dsplib.org ***************************************************************************** */ @@ -450,30 +477,39 @@ Pointer cannot be `NULL`. \n Else \ref ERROR_CODE_GROUP "code error". \n -Example: - +Example of normalized Chebyshev type 2 lowpass filter + zeros and poles calculation: \include cheby2_ap_zp_test.c Result: \verbatim - Chebyshev type 2 zeros: - z[ 0] = 0.000 1.026 j - z[ 1] = 0.000 -1.026 j - z[ 2] = 0.000 1.279 j - z[ 3] = 0.000 -1.279 j - z[ 4] = 0.000 2.305 j - z[ 5] = 0.000 -2.305 j - - Chebyshev type 2 poles: - p[ 0] = -1.203 0.000 j - p[ 1] = -0.113 0.772 j - p[ 2] = -0.113 -0.772 j - p[ 3] = -0.398 0.781 j - p[ 4] = -0.398 -0.781 j - p[ 5] = -0.852 0.642 j - p[ 6] = -0.852 -0.642 j +Chebyshev type 2 filter zeros: 6 +z[ 0] = 0.000 +1.026 j +z[ 1] = 0.000 -1.026 j +z[ 2] = 0.000 +1.279 j +z[ 3] = 0.000 -1.279 j +z[ 4] = 0.000 +2.305 j +z[ 5] = 0.000 -2.305 j +Chebyshev type 2 filter poles: 7 +p[ 0] = -1.203 +0.000 j +p[ 1] = -0.113 +0.772 j +p[ 2] = -0.113 -0.772 j +p[ 3] = -0.398 +0.781 j +p[ 4] = -0.398 -0.781 j +p[ 5] = -0.852 +0.642 j +p[ 6] = -0.852 -0.642 j \endverbatim +\n + +In `dat` folder will be created `cheby2_ap_z.txt` and +`cheby2_ap_z.txt` files which keeps zeros and poles vectors. \n + +In addition, GNUPLOT will build the following graphs +from data stored in the files: + +\image html cheby2_ap_zp_test.png + \author Sergey Bakhurin www.dsplib.org ***************************************************************************** */ @@ -562,6 +598,97 @@ In addition, GNUPLOT will build the following graphs from data stored in files: +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ellip_ap_zp(int ord, double rp, double rs, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Function calculates arrays of zeros and poles for analog normlized lowpass +elliptic filter transfer function \f$ H(s) \f$ order `ord` . + +\param[in] ord +Filter order. \n +Number of zeros and poles of filter can be less or equal `ord`. \n +\n + +\param[in] rp +Magnitude ripple in passband (dB). \n +This parameter sets maximum filter distortion from 0 to 1 rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[in] rs +Suppression level in stopband (dB). \n +This parameter sets filter suppression +for \f$\omega \geq 1\f$ rad/s frequency. \n +Parameter must be positive. \n +\n + +\param[out] z +Pointer to the \f$ H(s) \f$ zeros array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] nz +Pointer to the variable which keep number of finite zeros \f$ H(s) \f$. \n +Number of finite zeros which was calculated and saved in vector `z`. \n +Pointer cannot be `NULL`. \n +\n + +\param[out] p +Pointer to the \f$ H(s) \f$ poles array. \n +Maximum vector size is `[ord x 1]`. \n +Memory must be allocated for maximum vector size. \n +\n + +\param[out] np +Pointer to the variable which keep number of +calculated poles of \f$ H(s) \f$. \n +Pointer cannot be `NULL`. \n +\n + +\return +`RES_OK` if zeros and poles is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". +\n + +Example of normalized elliptic lowpass filter zeros and poles calculation: +\include ellip_ap_zp_test.c + +Result: + +\verbatim +Elliptic filter zeros: 6 +z[ 0] = 0.000 +1.053 j +z[ 1] = 0.000 -1.053 j +z[ 2] = 0.000 +1.136 j +z[ 3] = 0.000 -1.136 j +z[ 4] = 0.000 +1.626 j +z[ 5] = 0.000 -1.626 j +Elliptic filter poles: 7 +p[ 0] = -0.358 +0.000 j +p[ 1] = -0.011 +1.000 j +p[ 2] = -0.011 -1.000 j +p[ 3] = -0.060 +0.940 j +p[ 4] = -0.060 -0.940 j +p[ 5] = -0.206 +0.689 j +p[ 6] = -0.206 -0.689 j +\endverbatim +\n + +In `dat` folder will be created `ellip_ap_z.txt` and +`ellip_ap_z.txt` files which keeps zeros and poles vectors. \n + +In addition, GNUPLOT will build the following graphs +from data stored in the files: + +\image html ellip_ap_zp_test.png + + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ diff --git a/dspl/dox/en/groups_define.dox b/dspl/dox/en/groups_define.dox index 85ea3d5..179abd9 100644 --- a/dspl/dox/en/groups_define.dox +++ b/dspl/dox/en/groups_define.dox @@ -30,8 +30,14 @@ groupdelay, impulse response and other. \defgroup RESAMPLING_GROUP Digital samplerate conversion (resampling) + +\defgroup ARRAY_GROUP Basic operations for real and complex arrays. + + \defgroup SPEC_MATH_COMMON_GROUP Basic math functions of the real and complex arguments. +\defgroup SPEC_MATH_POLY_GROUP Polynomial functions and analysis. + \defgroup SPEC_MATH_TRIG_GROUP Trigonometric and hyperbolic of functions the real and complex arguments. \defgroup SPEC_MATH_TRANSCEND Transcendent math functions diff --git a/dspl/dox/en/mainpage.dox b/dspl/dox/en/mainpage.dox index 5ec9d2d..7da482e 100644 --- a/dspl/dox/en/mainpage.dox +++ b/dspl/dox/en/mainpage.dox @@ -42,7 +42,9 @@ Dsplib toolchain includes GCC, GNUPLOT, CodeBlocks IDE, Far file manager and als \subsection sec_doc_content Documentation content Mathematical sections: \n + - \ref ARRAY_GROUP \n - \ref SPEC_MATH_COMMON_GROUP \n + - \ref SPEC_MATH_POLY_GROUP \n - \ref SPEC_MATH_TRIG_GROUP \n - \ref SPEC_MATH_TRANSCEND \n - \ref SPEC_MATH_ELLIP_GROUP \n diff --git a/dspl/dox/en/math.dox b/dspl/dox/en/math.dox index 8420252..3a7a9c0 100644 --- a/dspl/dox/en/math.dox +++ b/dspl/dox/en/math.dox @@ -1,96 +1,395 @@ +/***************************************************************************** +\ingroup SPEC_MATH_TRIG_GROUP +\fn int acos_cmplx(complex_t* x, int n, complex_t *y) +\brief The inverse of the cosine function the complex vector argument `x` + +Function calculates the inverse of the cosine function as: \n + +\f[ +\textrm{Arccos}(x) = \frac{\pi}{2} - \textrm{Arcsin}(x) = +\frac{\pi}{2} -j \textrm{Ln}\left( j x + \sqrt{1 - x^2} \right) +\f] + + +\param[in] x +Pointer to the argument vector `x`. \n +Vector size is `[n x 1]`. \n +\n + +\param[in] n +Input vector `x` and the inverse cosine vector `y` size. \n +\n + + +\param[out] y +Pointer to the output complex vector `y`, +corresponds to the input vector `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + acos_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("acos_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); +\endcode +\n + +Output is: \n +\verbatim +acos_cmplx(1.0+2.0j) = 1.144-1.529j +acos_cmplx(3.0+4.0j) = 0.937-2.306j +acos_cmplx(5.0+6.0j) = 0.880-2.749j +\endverbatim + +\author +Sergey Bakhurin www.dsplib.org +******************************************************************************/ + + + + +/*! **************************************************************************** +\ingroup SPEC_MATH_TRIG_GROUP +\fn int asin_cmplx(complex_t* x, int n, complex_t *y) +\brief The inverse of the sine function the complex vector argument `x` + +Function calculates the inverse of the sine function as: \n + +\f[ +\textrm{Arcsin}(x) = j \textrm{Ln}\left( j x + \sqrt{1 - x^2} \right) +\f] + + +\param[in] x +Pointer to the argument vector `x`. \n +Vector size is `[n x 1]`. \n +\n + +\param[in] n +Input vector `x` and the inverse sine vector `y` size. \n +\n + +\param[out] y +Pointer to the output complex vector `y`, +corresponds to the input vector `x`.\n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if function calculated successfully.\n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + asin_cmplx(x, 3, y); + for(k = 0; k < 3; k++) + printf("asin_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); + +\endcode +\n + +Output is: \n +\verbatim +asin_cmplx(1.0+2.0j) = 0.427+1.529j +asin_cmplx(3.0+4.0j) = 0.634+2.306j +asin_cmplx(5.0+6.0j) = 0.691+2.749j +\endverbatim + +\author +Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + + + + + + /*! **************************************************************************** \ingroup SPEC_MATH_TRANSCEND \fn int bessel_i0(double* x, int n, double* y) \brief -Модифицированная функция Бесселя первого рода \f$ I_0(x)\f$ +Modified Bessel Function of the First Kind – \f$ I_0(x)\f$ [1] -Функция рассчитывает значения функции для вещественного вектора `x`, -который должен принимать неотрицательные значения. \n -\param[in] x -Указатель на вектор переменной \f$ x \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n +\param[in] x +Pointer to the function argument vector \f$ x \f$. \n +Vector size is `[n x 1]`. \n +Input vector must contain nonnegative values. \n \n -\param[in] n -Размер входного вектора `x`. \n +\param[in] n +Input vector size `x`. \n \n \param[out] y -Указатель на вектор значений функции \f$ I_0(x)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n +Pointer to \f$ I_0(x)\f$ function vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n \return -`RES_OK` --- расчёт произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n \note -Используемый алгоритм описа в статье: -Rational Approximations for the Modified Bessel Function -of the First Kind – I0(x) for Computations with Double Precision -by PAVEL HOLOBORODKO on NOVEMBER 11, 2015 +[1] Rational Approximations for the Modified Bessel Function + of the First Kind – I0(x) for Computations with Double Precision + by PAVEL HOLOBORODKO on NOVEMBER 11, 2015 -Пример использования функции `bessel_i0`: +Example: \include bessel_i0.c -Данная программа рассчитывает значения функции \f$ I_0(x)\f$ переменной `x` -в интервале \f$[0 \ 3]\f$. -Рассчитанные данные сохраняются в текстовый файл `dat/dat0.txt` -и выводятся на график `img/bessel_i0.png` +Program calcultes \f$ I_0(x)\f$ function for `x` +in \f$[0 \ 3]\f$ interval. +Data saved if `dat/dat0.txt` file and shows on the plot \image html bessel_i0.png \author -Бахурин Сергей -www.dsplib.org +Sergey Bakhurin www.dsplib.org ***************************************************************************** */ + + +/*! **************************************************************************** +\ingroup SPEC_MATH_TRIG_GROUP +\fn int cos_cmplx(complex_t* x, int n, complex_t *y) +\brief The cosine function the complex vector argument `x` + +Function calculates the cosine function as: \n + +\f[ +\textrm{cos}(x) = \frac{\exp(jx) + \exp(-jx)}{2} +\f] + + +\param[in] x +Pointer to the argument vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Input vector `x` and the cosine vector `y` size. \n \n + + +\param[out] y +Pointer to the output complex vector `y`, +corresponds to the input vector `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + cos_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("cos_cmplx(%.1f%+.1fj) = %9.3f%+9.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); + +\endcode + \n + +Output is: \n +\verbatim +cos_cmplx(1.0+2.0j) = 2.033 -3.052j +cos_cmplx(3.0+4.0j) = -27.035 -3.851j +cos_cmplx(5.0+6.0j) = 57.219 +193.428j +\endverbatim + +\author +Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + + + + + + +/*! **************************************************************************** +\ingroup SPEC_MATH_COMMON_GROUP +\fn int log_cmplx(complex_t* x, int n, complex_t *y) +\brief The logarithm function the complex vector argument `x` + +Function calculates the logarithm function as: \n + +\f[ +\textrm{Ln}(x) = j \varphi + \ln(|x|), +\f] +here \f$\varphi\f$ - the complex number phase. + +\param[in] x +Pointer to the argument vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Input vector `x` and the logarithm vector `y` size. \n \n + + +\param[out] y +Pointer to the output complex vector `y`, +corresponds to the input vector `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + log_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("log_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); +\endcode + \n + +Output is: \n +\verbatim +log_cmplx(1.0+2.0j) = 0.805+1.107j +log_cmplx(3.0+4.0j) = 1.609+0.927j +log_cmplx(5.0+6.0j) = 2.055+0.876j +\endverbatim + +\author +Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + + + + + + + + +/*! **************************************************************************** +\ingroup SPEC_MATH_TRIG_GROUP +\fn int sin_cmplx(complex_t* x, int n, complex_t *y) +\brief The sine function the complex vector argument `x` + +Function calculates the sine function as: \n + +\f[ +\textrm{cos}(x) = \frac{\exp(jx) - \exp(-jx)}{2j} +\f] + + +\param[in] x +Pointer to the argument vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Input vector `x` and the sine vector `y` size. \n \n + + +\param[out] y +Pointer to the output complex vector `y`, +corresponds to the input vector `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + sin_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("sin_cmplx(%.1f%+.1fj) = %9.3f%+9.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); + +\endcode + \n + +Output is: \n +\verbatim +sin_cmplx(1.0+2.0j) = 3.166 +1.960j +sin_cmplx(3.0+4.0j) = 3.854 -27.017j +sin_cmplx(5.0+6.0j) = -193.430 +57.218j +\endverbatim + +\author +Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + + + + /*! **************************************************************************** \ingroup SPEC_MATH_COMMON_GROUP \fn int sinc(double* x, int n, double a, double* y) \brief -Функция \f$ \textrm{sinc}(x,a) = \frac{\sin(ax)}{ax}\f$ +Function \f$ \textrm{sinc}(x,a) = \frac{\sin(ax)}{ax}\f$ +for the real vector `x`. -Функция рассчитывает значения функции для вещественного вектора `x`. - - -\param[in] x -Указатель на вектор переменной \f$ x \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n +\param[in] x +Pointer to the input vector \f$ x \f$. \n +Vector size is `[n x 1]`. \n \n -\param[in] n -Размер входного вектора `x`. \n +\param[in] n +Input and output vectors size. \n \n -\param[in] a -Параметр функции \f$ \textrm{sinc}(x,a) = \frac{\sin(ax)}{ax}\f$. \n +\param[in] a +Function parameter \f$ \textrm{sinc}(x,a) = \frac{\sin(ax)}{ax}\f$. \n \n -\param[out] y -Указатель на вектор значений функции. \n - Размер вектора `[n x 1]`. \n - Память должна быть выделена. \n - \n +\param[out] y +Pointer to the `sinc` function output vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n +\n \return -`RES_OK` --- расчёт произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n \author -Бахурин Сергей -www.dsplib.org +Sergey Bakhurin www.dsplib.org ***************************************************************************** */ @@ -100,52 +399,108 @@ www.dsplib.org \fn int sine_int(double* x, int n, double* si) \brief -Функция интегрального синуса +Sine integral function \f$\textrm{Si}(x)\f$ for the real vector `x`. \f[ \textrm{Si}(x) = \int_{0}^{x} \frac{\sin(x)}{x} \, dx\f] -Функция рассчитывает значения функции для интегрального синуса -для произвольного вещественного вектора `x`. +This function uses + +Padé approximants of the convergent Taylor series. + + \param[in] x -Указатель на вектор переменной \f$ x \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n +Pointer to the input vector \f$ x \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n \param[in] n -Размер входного вектора `x`. \n +Size of input vector `x`. \n \n \param[out] si -Указатель на вектор значений функции интегрального синуса. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n +Pointer to the `Si` function vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n \return -`RES_OK` --- расчёт произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n -Пример использования функции `sine_int`: +Example: \include sine_int_test.c -Данная программа рассчитывает значения функции интегрального синуса и -функции \ref sinc для вектора переменной `x` -в интервале \f$[-6\pi \ 6\pi]\f$. -Рассчитанные данные сохраняются в текстовые файлы -`dat/dat0.txt` и `dat/dat1.txt` - -и выводятся на график `img/sine_int.png` +This program calcultes sine integral \f$\textrm{Si}(x)\f$ and +\f$\textrm{sinc}(x)\f$ functions for input `x` vector in interval +\f$[-6\pi \ 6\pi]\f$. +Functions values saved to th +`dat/dat0.txt` and `dat/dat1.txt` files and showed on the figure: \image html sine_int.png \author -Бахурин Сергей -www.dsplib.org +Sergey Bakhurin www.dsplib.org ***************************************************************************** */ + + + +/*! **************************************************************************** +\ingroup SPEC_MATH_COMMON_GROUP +\fn int sqrt_cmplx(complex_t* x, int n, complex_t *y) +\brief Square root of the complex vector argguument `x`. + +Function calculates square root value of vector `x` length `n`: \n +\f[ +y(k) = \sqrt{x(k)}, \qquad k = 0 \ldots n-1. +\f] + + +\param[in] x +Pointer to the input complex vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of input and output vectors `x` and `y`. \n \n + + +\param[out] y +Pointer to the square root vector `y`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if function is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3] + int k; + + sqrt_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("sqrt_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); + + \endcode + \n + +Результатом работы будет + +\verbatim +sqrt_cmplx(1.0+2.0j) = 1.272+0.786j +sqrt_cmplx(3.0+4.0j) = 2.000+1.000j +sqrt_cmplx(5.0+6.0j) = 2.531+1.185j +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + diff --git a/dspl/dox/ru/array.dox b/dspl/dox/ru/array.dox deleted file mode 100644 index 53072ea..0000000 --- a/dspl/dox/ru/array.dox +++ /dev/null @@ -1,662 +0,0 @@ - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int array_scale_lin(double* x, int n, - double xmin, double xmax, double dx, - double h, double* y) -\brief Линейное растяжение вектора данных `x` -Функция производит преобразование значений \f$x(i)\f$, \f$i = 0,1,\ldots n\f$ -в значения \f$y(i)\f$, в соответствии с формулой: - -\f[ -y(i) = k_x x(i) + d_x, \qquad k_x = -\frac{h}{x_{\textrm{max}} - x_{\textrm{min}}}. -\f] - -Таким образом, все значения входного вектора `x` в диапазоне от -\f$x_{\textrm{min}}\f$ до \f$x_{\textrm{max}}\f$, линейно растягиваются в -значения вектора `y` в диапазоне от \f$d_x\f$ до \f$h + d_x\f$. -Заметим, что \f$d_x\f$ задает линейное смещение значений вектора `y`. - -Данная функция удобна для перевода величин разных размерностей, в частности, -для переноса значений вектора `x` на график высоты `h`, где высота может -быть задана в количестве пикселей, в сантиметрах и т.д. - -\param[in] x -Указатель на вектор входных значений `x`. \n -Размер вектора `[n x 1]`. \n -\n - -\param[in] n -Размер вектора `x`. \n -\n - -\param[in] xmin -Нижняя граница диапазона трансформации. \n -\n - -\param[in] xmax -Верхняя граница диапазона трансформации. \n -Значение `xmax` должно быть строго больше значения `xmin`. \n -\n - -\param[in] dx -Смещение после трансформации. \n -Данный параметр должен иметь размерность выходного вектора `y`. \n -\n - -\param[in] h -Диапазон значений вектора `y` после трансформации от `dx` до `h+dx`. \n -\n - -\param[out] y -Указатель на вектора данных после трансформации. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -\note -Указатель `y` может совпадать с `x`, в этом случае, -данные вектора `x` будут перезаписаны линейно измененными в соответствии -с формулой выше. \n -\n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int concat(void* a, size_t na, void* b, size_t nb, void* c) -\brief Конкатенация двух массивов данных - -Функция производит конкатенацию двух массивов. Пусть массивы `a` и `b` -заданы как векторы: \n -`a = [a(0), a(1), ... a(na-1)]`, \n -`b = [b(0), b(1), ... b(nb-1)]`, \n -тогда результатом конкатенации будет вектор размера `na+nb` вида: \n -`c = [a(0), a(1), ... a(na-1), b(0), b(1), ... b(nb-1)]`. - - -\param[in] a -Указатель на первый вектор `a`. \n -Размер вектора `na` байт. \n \n - -\param[in] na -Размер первого вектора `a` в байт. \n \n - -\param[in] b -Указатель на второй вектор `b`. \n -Размер памяти вектора `nb` байт. \n \n - -\param[in] nb -Размер второго вектора `b` в байт. \n \n - -\param[out] c -Указатель на вектор конкатенации `c`. \n -Размер памяти вектора `na + nb` байт. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\note -Функция использует указатели типа `void*` и может быть использована для -конкатенации данных различного типа. \n -Например конкатенация массивов типа `double`: -\code{.cpp} -double a[3] = {1.0, 2.0, 3.0}; -double b[2] = {4.0, 5.0}; -double c[5]; -concat((void*)a, 3*sizeof(double), (void*)b, 2*sizeof(double), (void*)c); -\endcode -в результате вектор `c` будет хранить массив данных: -\verbatim -c = [1.0, 2.0, 3.0, 4.0, 5.0] -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int decimate(double* x, int n, int d, double* y, int* cnt) -\brief Децимация вещественного вектора данных - -Функция производит децимацию вещественного вектора `x` в `d` раз. \n -В результате выходной вектор `y` содержит значения: -`y(k) = x(k*d), k = 0...n/d-1` \n - -\param[in] x -Указатель на вектор входных данных `x`. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер входного вектора `x`. \n \n - -\param[in] d -Коэффициент децимации. \n -В результате децимации из вектора `x` будет взять каждый -d-й элемент. \n \n - -\param[out] y -Указатель на децимированный вектор `y`. \n -Размер выходного вектора равен `[n/d x 1]` -будет сохранен по адресу `cnt`. \n -Память должна быть выделена. \n \n - -\param[out] cnt -Указатель переменную, в которую будет сохранен -размер выходного вектора после децимации. \n -Указатель может быть `NULL`, в этом случае -размер вектора `y` не возвращается. \n \n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример децимации вещественного массива данных в 2 раза: -\code{.cpp} -double x[10] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; -double y[5]; -int d = 2; -int cnt; -decimate(x, 10, d, y, &cnt); -\endcode -В результате в переменную `cnt` будет записан размер 5, -а вектор `y` будет хранить массив данных: -\verbatim -c = [0.0, 2.0, 4.0, 6.0, 8.0] -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int decimate_cmplx(complex_t* x, int n, int d, complex_t* y, int* cnt) -\brief Децимация комплексного вектора данных - -Функция производит децимацию комплексного вектора `x` в `d` раз. \n -В результате выходной вектор `y` содержит значения: -`y(k) = x(k*d), k = 0...n/d-1` \n - -\param[in] x -Указатель на вектор входных данных `x`. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер входного вектора `x`. \n \n - -\param[in] d -Коэффициент децимации. \n -В результате децимации из вектора `x` будет взять каждый d-й элемент. \n \n - -\param[out] y -Указатель на децимированный вектор `y`. \n -Размер выходного вектора равен `[n/d x 1]` будет сохранен по адресу `cnt`. \n -Память должна быть выделена. \n \n - -\param[out] cnt -Указатель переменную, в которую будет сохранен -размер выходного вектора после децимации. \n -Указатель может быть `NULL`, в этом случае -размер вектора `y` не возвращается. \n \n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример децимации комплексного массива данных в 2 раза: -\code{.cpp} -compex_t x[10] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}, - {5.0, 5.0}, {6.0, 6.0}, {7.0, 7.0}, {8.0, 8.0}, {9.0, 9.0}}; -compex_t y[5]; -int d = 2; -int cnt; -decimate_cmplx(x, 10, d, y, &cnt); -\endcode -В результате в переменную `cnt` будет записан размер 5, а вектор `y` будет -хранить массив данных: -\verbatim -c = [0.0+0.0j, 2.0+2.0j, 4.0+4.0j, 6.0+6.0j, 8.0+8.0j] -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int flipip(double* x, int n) -\brief Функция отражения вещественного вектора `x` - -Функция производит отражение вещественного вектора длины `n` -в памяти данных. \n -Например исходный вектор `x` длины 6: \n -\verbatim -x = [0, 1, 2, 3, 4, 5] -\endverbatim -После отражения вектор `x` будет иметь вид: -\verbatim -x = [5, 4, 3, 2, 1, 0] -\endverbatim - -\param[in, out] x -Указатель на вещественный вектор `x`. \n -Размер вектора `[n x 1]`. \n -Результат отражения будет помещен по этому же адресу. \n - -\param[in] n -Размер вектора `x`. \n \n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример: -\code{.cpp} -double x[5] = {0.0, 1.0, 2.0, 3.0, 4.0}; -int i; -for(i = 0; i < 5; i++) - printf("%6.1f ", x[i]); -flipip(x, 5); -printf("\n"); -for(i = 0; i < 5; i++) - printf("%6.1f ", x[i]); -\endcode -\n -Результат выполнения: -\verbatim - 0.0 1.0 2.0 3.0 4.0 - 4.0 3.0 2.0 1.0 0.0 -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int flipip_cmplx(complex_t* x, int n) -\brief Функция отражения комплексного вектора `x` - -Функция производит отражение комплексного вектора длины `n` -в памяти данных. \n -Например исходный вектор `x` длины 6: \n -\verbatim -x = [0+0j, 1+1j, 2+2j, 3+3j, 4+4j, 5+5j] -\endverbatim -После отражения вектор `x` будет иметь вид: -\verbatim -x = [5+5j, 4+4j, 3+3j, 2+2j, 1+1j, 0+0j] -\endverbatim - -\param[in, out] x -Указатель на комплексный вектор `x`. \n -Размер вектора `[n x 1]`. \n -Результат отражения будет помещен по этому же адресу. \n -\n - -\param[in] n -Размер вектора `x`. \n -\n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример: -\code{.cpp} -complex_t y[5] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}}; -for(i = 0; i < 5; i++) - printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); -flipip_cmplx(y, 5); -printf("\n"); -for(i = 0; i < 5; i++) - printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); -\endcode - \n -Результат выполнения: -\verbatim - 0.0+0.0j 1.0+1.0j 2.0+2.0j 3.0+3.0j 4.0+4.0j - 4.0+4.0j 3.0+3.0j 2.0+2.0j 1.0+1.0j 0.0+0.0j -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int linspace(double x0, double x1, int n, int type, double* x) -\brief Функция заполняет массив линейно-нарастающими, равноотстоящими -значениями от `x0` до `x1` - -Заполняет массив `x` длиной `n` значениями в диапазоне -от \f$x_0\f$ до \f$x_1\f$. Функция поддерживает два типа заполнения -в соответствии с параметром `type`: \n - -Симметричное заполнение согласно выражению (параметр `type=DSPL_SYMMETRIC`): \n - -\f$x(k) = x_0 + k \cdot dx\f$, -\f$dx = \frac{x_1 - x_0}{n-1}\f$, \f$k = 0 \ldots n-1.\f$ - -Периодическое заполнение (параметр `type=DSPL_PERIODIC`) согласно выражению: \n - -\f$x(k) = x_0 + k \cdot dx\f$, -\f$dx = \frac{x_1 - x_0}{n}\f$, \f$k = 0 \ldots n-1.\f$ - -\param[in] x0 -Начальное показателя \f$x_0\f$. \n \n - -\param[in] x1 -Конечное значение \f$x_1\f$. \n \n - -\param[in] n -Количество точек массива `x`. \n \n - -\param[in] type -Тип заполнения: \n - -`DSPL_SYMMETRIC` --- симметричное заполнение, \n -`DSPL_PERIODIC` --- периодическое заполнение. \n \n - -\param[in,out] x -Указатель на вектор равноотстоящих значений . \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` --- функция выполнена успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n - -\note -Отличие периодического и симметричного заполнения можно -понять из следующих примеров. \n -Пример 1. Периодическое заполнение. -\code{.cpp} - double x[5]; - linspace(0, 5, 5, DSPL_PERIODIC, x); -\endcode -В массиве `x` будут лежать значения: -\verbatim -0, 1, 2, 3, 4 -\endverbatim - \n \n -Пример 2. Симметричное заполнение. -\code{.cpp} - double x[5]; - linspace(0, 5, 5, DSPL_SYMMETRIC, x); -\endcode -В массиве `x` будут лежать значения: -\verbatim -0, 1.25, 2.5, 3.75, 5 -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int logspace(double x0, double x1, int n, int type, double* x) -\brief Функция заполняет массив значениями логарифмической шкале - -Заполняет массив `x` длиной `n` значениями в диапазоне -от \f$10^{x_0}\f$ до \f$10^{x_1}\f$. \n -Функция поддерживает два типа заполнения в соответствии с параметром `type`: \n - -Симметричное заполнение согласно выражению: \n - -\f$x(k) = 10^{x_0} \cdot dx^k\f$, где \f$dx = \sqrt[n-1]{10^{x_1 - x_0}}\f$, -\f$k = 0 \ldots n-1.\f$ - -Периодическое заполнение согласно выражению: - -\f$x(k) = 10^{x_0} \cdot dx^k\f$, где \f$dx = \sqrt[n]{10^{x_1 - x_0}}\f$, -\f$k = 0 \ldots n-1.\f$ \n - -\param[in] x0 -Начальное значение показателя \f$x_0\f$. \n \n - -\param[in] x1 -Конечное значение показателя \f$x_1\f$. \n \n - -\param[in] n -Количество точек массива `x`. \n \n - -\param[in] type -Тип заполнения: \n -`DSPL_SYMMETRIC` --- симметричное заполнение, \n -`DSPL_PERIODIC` --- периодическое заполнение. \n \n - -\param[in,out] x -Указатель на вектор значений в логарифмической шкале. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` --- функция выполнена успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\note -Отличие периодического и симметричного заполнения можно -понять из следующих примеров. \n - -Пример 1. Периодическое заполнение. -\code{.cpp} - double x[5]; - logspace(-2, 3, 5, DSPL_PERIODIC, x); -\endcode -В массиве `x` будут лежать значения: -\verbatim -0.01, 0.1, 1, 10, 100 -\endverbatim - -\n \n - -Пример 2. Симметричное заполнение. -\code{.cpp} - double x[5]; - logspace(-2, 3, 5, DSPL_SYMMETRIC, x); -\endcode - -В массиве `x` будут лежать значения: - -\verbatim -0.01 0.178 3.162 56.234 1000 -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int ones(double* x, int n) -\brief Функция заполнения вещественного массива единицами - -\param[in, out] x -Указатель на вещественный вектор `x`. \n -Размер вектора `[n x 1]`. \n -Значения данного вектора будут установлены в единицу. \n -\n - -\param[in] n -Размер вектора `x`. \n -\n - -\return -`RES_OK` если функция выполнена успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример: -\code{.cpp} -double y[5] = {0}; -int i; -ones(y, 5); -for(i = 0; i < 5; i++) - printf("%6.1f% ", y[i]); -\endcode - \n -Результат выполнения: -\verbatim - 1.0 1.0 1.0 1.0 1.0 -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int verif(double* x, double* y, size_t n, double eps, double* err) -\brief Верификация вещественных массивов - -Функция производит расчет максимальной относительной ошибки между вещественными -векторами `x` и `y` равной длины `n`: - -\f[ -e = \max \left( \frac{|x(k) - y(k)| }{ |x(k)|} \right), \quad \quad |x(k)| > 0, -\f] -или -\f[ -e = \max(|x(k) - y(k)| ), ~\qquad \quad~|x(k)| = 0, -\f] -и возвращает `DSPL_VERIF_SUCCESS` если -разница \f$ e\f$ меньше `eps`. -В противном случае возвращает `DSPL_VERIF_FAILED`. \n -Данная функция используется для верификации работы алгоритмов если вектор `x` -результат работы алгоритма пользователя, а `y` -- результат работы этого же -алгоритма сторонней функцией. - -\param[in] x -Указатель на первый вектор `x`. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] y -Указатель на второй вектор `y`. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер векторов `x` и `y`. \n \n - -\param[in] eps -Допустимая относительная ошибка. \n -Если максимальная относительная ошибка меньше `eps`, то функция возвращает -`DSPL_VERIF_SUCCESS`, в противном случае `DSPL_VERIF_FAILED`. \n \n - -\param[in, out] err -Указатель на переменную максимальной относительной ошибки. \n -По данному адресу будет записано значение максимальной относительной ошибки. \n -Указатель может быть `NULL`, значение ошибки в этом случае -не возвращается. \n \n - -\return -`DSPL_VERIF_SUCCESS` если относительная ошибка меньше `eps`. \n - В противном случае `DSPL_VERIF_FAILED`. - -\author Бахурин Сергей www.dsplib.org -**************************************************************************** */ - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int verif_cmplx(complex_t* x, complex_t* y, size_t n, - double eps, double* err) -\brief Верификация комплексных массивов - -Функция производит расчет максимальной относительной ошибки между комплексными -векторами `x` и `y` равной длины `n`: - -\f[ -e = \max \left( \frac{|x(k) - y(k)|}{|x(k)|} \right), \quad \quad |x(k)| > 0, -\f] -или -\f[ -e = \max(|x(k) - y(k)| ), ~\qquad \quad~|x(k)| = 0, -\f] -и возвращает `DSPL_VERIF_SUCCESS` если -разница \f$ e\f$ меньше `eps`. -В противном случае возвращает `DSPL_VERIF_FAILED`. \n -Данная функция используется для верификации работы алгоритмов если вектор `x` -результат работы алгоритма пользователя, а `y` -- результат работы этого же -алгоритма сторонней функцией. - -\param[in] x -Указатель на первый вектор `x`. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] y -Указатель на второй вектор `y`. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер векторов `x` и `y`. \n \n - -\param[in] eps -Допустимая относительная ошибка. \n -Если максимальная относительная ошибка меньше `eps`, то функция возвращает -`DSPL_VERIF_SUCCESS`, в противном случае `DSPL_VERIF_FAILED`. \n \n - -\param[in, out] err -Указатель на переменную максимальной относительной ошибки. \n -По данному адресу будет записано значение максимальной относительной ошибки. \n -Указатель может быть `NULL`, значение ошибки в этом -случае не возвращается. \n \n - -\return -`DSPL_VERIF_SUCCESS` если функция выполнена успешно. \n - В противном случае `DSPL_VERIF_FAILED`. - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - diff --git a/dspl/dox/ru/cheby.dox b/dspl/dox/ru/cheby.dox deleted file mode 100644 index c1e2d25..0000000 --- a/dspl/dox/ru/cheby.dox +++ /dev/null @@ -1,116 +0,0 @@ - -/*! **************************************************************************** -\ingroup SPEC_MATH_TRANSCEND -\fn int cheby_poly1(double* x, int n, int ord, double* y) -\brief Многочлен Чебышева первого рода порядка `ord` - -Функция производит расчет многочлена Чебышева первого рода \f$ C_ord(x)\f$ для -вещественного вектора `x` длины `n`на основе рекуррентной формулы -\f[ -C_ord(x) = 2 x C_{ord-1}(x) - C_{ord-2}(x), -\f] -где \f$ C_0(x) = 1 \f$, \f$ C_1(x) = x\f$ - -\param[in] x -Указатель на вектор `x` аргумента полинома Чебышева первого рода. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер векторов `x` и `y`. \n \n - -\param[in] ord -Порядок полинома Чебышева первого рода. \n \n - -\param[out] y -Указатель на вектор значений полинома Чебышева, -соответствующих аргументу `x`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции: - -\include cheby_poly1_test.c - - \n \n -В каталоге `dat` будут созданы текстовые файлы значений -полиномов порядка 1-4: \n - -
-cheby_poly1_ord1.txt
-cheby_poly1_ord2.txt
-cheby_poly1_ord3.txt
-cheby_poly1_ord4.txt
-
- -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html cheby_poly1.png - -\author -Бахурин Сергей -www.dsplib.org -**************************************************************************** */ - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_TRANSCEND -\fn int cheby_poly2(double* x, int n, int ord, double* y) -\brief Многочлен Чебышева второго рода порядка `ord` - -Функция производит расчет многочлена Чебышева второго рода \f$ U_{ord}(x)\f$ для -вещественного вектора `x` длины `n`на основе рекуррентной формулы -\f[ -U_{ord}(x) = 2 x U_{ord-1}(x) - U_{ord-2}(x), -\f] -где \f$ U_0(x) = 1 \f$, \f$ U_1(x) = 2x\f$ - -\param[in] x -Указатель на вектор `x` аргумента полинома Чебышева второго рода. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер векторов `x` и `y`. \n \n - -\param[in] ord -Порядок полинома Чебышева второго рода. \n \n - -\param[out] y -Указатель на вектор значений полинома Чебышева, -соответствующих аргументу `x`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции: - -\include cheby_poly2_test.c - - \n \n -В каталоге `dat` будут созданы текстовые файлы значений -полиномов порядка 1-4: \n - -
-cheby_poly2_ord1.txt
-cheby_poly2_ord2.txt
-cheby_poly2_ord3.txt
-cheby_poly2_ord4.txt
-
- -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html cheby_poly2.png - -\author Бахурин Сергей www.dsplib.org -**************************************************************************** */ \ No newline at end of file diff --git a/dspl/dox/ru/complex.dox b/dspl/dox/ru/complex.dox deleted file mode 100644 index 4d2c3c6..0000000 --- a/dspl/dox/ru/complex.dox +++ /dev/null @@ -1,252 +0,0 @@ -/*! **************************************************************************** -\ingroup TYPES_GROUP -\typedef complex_t -\brief Описание комплексного типа данных. - -Комплексный тип данных в библиотеке DSPL-2.0 определен как -массив из двух элементов типа `double`. -При этом первый элемент массива определяет реальную часть -комплексного числа, а второй - мнимую. - -Например: - -\code{.cpp} - complex_t z; - z[0] = 1.0; - z[1] = -2.0; -\endcode - -Переменная `z = 1-2j`, где `j` - мнимая единица. - -Для удобства работы с комплексными числами реализованы -специальные макросы: \ref RE, \ref IM, \ref ABSSQR -***************************************************************************** */ - - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\def ABSSQR(x) -\brief Макрос возвращает квадрат модуля комплексного числа `x`. - -Квадрат модуля комплексного числа \f$ x = a + j b \f$ равен: - -\f[ - |x|^2 = x x^* = a^2 + b^2. -\f] - -Например: -\code{.cpp} - complex_t z; - double y; - RE(z) = 1.0; - IM(z) = -2.0; - y = ABSSQR(z); -\endcode - -Переменная `z = 1-2j`, где `j` - мнимая единица, а переменная `y = 5`. -***************************************************************************** */ - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\def IM(x) -\brief Макрос определяющий мнимую часть комплексного числа. - -Например: -\code{.cpp} - complex_t z; - RE(z) = 1.0; - IM(z) = -2.0; -\endcode - -Переменная `z = 1-2j`, где `j` - мнимая единица. - -Аналогично, макрос можно использовать для получения -мнимой части комплексного числа: -\code{.cpp} - complex_t z = {3.0, -4.0}; - double r; - r = IM(z); -\endcode -В данном примере переменная `z = 3-4i`, -а в переменой `r` будет храниться число -4. -***************************************************************************** */ - - - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\def RE(x) -\brief Макрос определяющий реальную часть комплексного числа. - -Например: -\code{.cpp} - complex_t z; - RE(z) = 1.0; - IM(z) = -2.0; -\endcode - -Переменная `z = 1-2j`, где `j` - мнимая единица. - -Аналогично, макрос можно использовать для получения -реальной части комплексного числа: - -\code{.cpp} - complex_t z = {3.0, -4.0}; - double r; - r = RE(z); -\endcode -В данном примере переменная `z = 3-4i`, а в переменой `r` -будет храниться число 3. -***************************************************************************** */ - - - - - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\fn int cmplx2re(complex_t* x, int n, double* re, double* im) -\brief Преобразование массива комплексных данных в два массива - вещественных данных, содержащих реальную и мнимую части - исходного массива - -Функция заполняет реальные массивы `re` и `im` соответствующими значениями -реальной и мнимой частей исходного комплексного массива `x`. \n - - -\param[in] x -Указатель на массив комплексных данных. \n -Размер массива `[n x 1]`. \n \n - -\param[in] n -Размер массивов входных и выходных данных. \n \n - -\param[out] re -Указатель на адрес массива реальной части данных. \n -Размер массива `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[out] im -Указатель на адрес массива мнимой части данных. \n -Размер массива `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если преобразование произведено успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n - -Например при выполнении следующего кода -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - double re[3], im[3]; - - cmplx2re(x, 3, re, im); -\endcode - -Элементам массивов `re` и `im` будут присвоены значения: - -\verbatim -re[0] = 1.0; im[0] = 2.0; -re[1] = 3.0; im[1] = 4.0; -re[2] = 5.0; im[2] = 6.0; -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - - - - - - - - - -/*! **************************************************************************** -\ingroup TYPES_GROUP -\fn int re2cmplx(double* x, int n, complex_t *y) -\brief Преобразование массива вещественных данных в массив комплексных данных. - -Функция заполняет реальные части массива `y` данных соответсвующими значениями -исходного вещественного массива `x`. \n - - -\param[in] x -Указатель на массив вещественных данных. \n -Размер массива `[n x 1]`. \n \n - -\param[in] n -Размер массивов входных и выходных данных. \n \n - -\param[out] y -Указатель на адрес массива комплексных данных. \n -Размер массива `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` если преобразование произведено успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n - - - -Например при выполнении следующего кода -\code{.cpp} - double x[3] = {1.0, 2.0, 3.0}; - complex_t y[3]; - - re2cmplx(x, 3, y); -\endcode - -Значениям `y` будут присвоены значения: - -\verbatim - y[0] = 1+0j; - y[1] = 2+0j; - y[2] = 3+0j. -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - diff --git a/dspl/dox/ru/dft.dox b/dspl/dox/ru/dft.dox deleted file mode 100644 index 736efa1..0000000 --- a/dspl/dox/ru/dft.dox +++ /dev/null @@ -1,213 +0,0 @@ - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int dft(double* x, int n, complex_t* y) -\brief Дискретное преобразование Фурье вещественного сигнала. - -Функция рассчитывает \f$ n \f$-точечное дискретное преобразование Фурье -вещественного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \sum_{m = 0}^{n-1} x(m) - \exp \left( -j \frac{2\pi}{n} m k \right), -\f] -где \f$ k = 0 \ldots n-1 \f$. - -\param[in] x -Указатель на вектор вещественного входного сигнала \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер ДПФ \f$n\f$ (размер векторов входного сигнала и результата ДПФ). \n \n - -\param[out] y -Указатель на комплексный вектор результата ДПФ \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` если ДПФ рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример использования функции `dft`: - -\include dft_test.c - -Результат работы программы: - -\verbatim -y[ 0] = 120.000 0.000 -y[ 1] = -8.000 40.219 -y[ 2] = -8.000 19.314 -y[ 3] = -8.000 11.973 -y[ 4] = -8.000 8.000 -y[ 5] = -8.000 5.345 -y[ 6] = -8.000 3.314 -y[ 7] = -8.000 1.591 -y[ 8] = -8.000 0.000 -y[ 9] = -8.000 -1.591 -y[10] = -8.000 -3.314 -y[11] = -8.000 -5.345 -y[12] = -8.000 -8.000 -y[13] = -8.000 -11.973 -y[14] = -8.000 -19.314 -y[15] = -8.000 -40.219 -\endverbatim - -\note -Данная функция выполняет расчет ДПФ наивным методом и требует \f$ n^2 \f$ -комплексных умножений. \n -Для увеличения скорости расчета рекомендуется использовать -алгоритмы быстрого преобразования Фурье. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int dft_cmplx(complex_t* x, int n, complex_t* y) -\brief Дискретное преобразование Фурье комплексного сигнала. - -Функция рассчитывает \f$ n \f$-точечное дискретное преобразование Фурье -комплексного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \sum_{m = 0}^{n-1} x(m) - \exp \left( -j \frac{2\pi}{n} m k \right), -\f] -где \f$ k = 0 \ldots n-1 \f$. - -\param[in] x -Указатель на вектор комплексного -входного сигнала \f$x(m)\f$, \f$ m = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер ДПФ \f$n\f$ (размер векторов входного сигнала и результата ДПФ). \n \n - -\param[out] y -Указатель на комплексный вектор -результата ДПФ \f$Y(k)\f$, \f$ k = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` если ДПФ рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример использования функции `dft_cmplx`: - -\include dft_cmplx_test.c - -Результат работы программы: - -\verbatim -y[ 0] = 120.000 0.000 -y[ 1] = -8.000 40.219 -y[ 2] = -8.000 19.314 -y[ 3] = -8.000 11.973 -y[ 4] = -8.000 8.000 -y[ 5] = -8.000 5.345 -y[ 6] = -8.000 3.314 -y[ 7] = -8.000 1.591 -y[ 8] = -8.000 0.000 -y[ 9] = -8.000 -1.591 -y[10] = -8.000 -3.314 -y[11] = -8.000 -5.345 -y[12] = -8.000 -8.000 -y[13] = -8.000 -11.973 -y[14] = -8.000 -19.314 -y[15] = -8.000 -40.219 -\endverbatim - -\note -Данная функция выполняет расчет ДПФ наивным методом -и требует \f$ n^2 \f$ комплексных умножений. \n -Для увеличения скорости расчета рекомендуется -использовать алгоритмы быстрого преобразования Фурье. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int idft_cmplx(complex_t* x, int n, complex_t* y) -\brief Обратное дискретное преобразование Фурье комплексного спектра. - -Функция рассчитывает \f$ n \f$-точечное обратное дискретное преобразование -Фурье комплексного спектра \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - y(k) = \sum_{m = 0}^{n-1} x(m) - \exp \left( j \frac{2\pi}{n} m k \right), -\f] -где \f$ k = 0 \ldots n-1 \f$. - -\param[in] x -Указатель на вектор входного комплексного спектра сигнала \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер ОДПФ \f$n\f$ (размер векторов входного спектра и результата ОДПФ). \n \n - -\param[out] y -Указатель на комплексный вектор результата ОДПФ \f$y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` если ОДПФ рассчитана успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример использования функции `dft_cmplx`: - -\include idft_cmplx_test.c - -Результат работы программы: - -\verbatim -x[ 0] = 0.000 +0.000j, z[ 0] = 0.000 -0.000 -x[ 1] = 1.000 +0.000j, z[ 1] = 1.000 -0.000 -x[ 2] = 2.000 +0.000j, z[ 2] = 2.000 -0.000 -x[ 3] = 3.000 +0.000j, z[ 3] = 3.000 -0.000 -x[ 4] = 4.000 +0.000j, z[ 4] = 4.000 -0.000 -x[ 5] = 5.000 +0.000j, z[ 5] = 5.000 -0.000 -x[ 6] = 6.000 +0.000j, z[ 6] = 6.000 -0.000 -x[ 7] = 7.000 +0.000j, z[ 7] = 7.000 -0.000 -x[ 8] = 8.000 +0.000j, z[ 8] = 8.000 -0.000 -x[ 9] = 9.000 +0.000j, z[ 9] = 9.000 -0.000 -x[10] = 10.000 +0.000j, z[10] = 10.000 -0.000 -x[11] = 11.000 +0.000j, z[11] = 11.000 +0.000 -x[12] = 12.000 +0.000j, z[12] = 12.000 +0.000 -x[13] = 13.000 +0.000j, z[13] = 13.000 +0.000 -x[14] = 14.000 +0.000j, z[14] = 14.000 +0.000 -x[15] = 15.000 +0.000j, z[15] = 15.000 -0.000 -\endverbatim - -\note -Данная функция выполняет расчет ОДПФ наивным методом -и требует \f$ n^2 \f$ комплексных умножений. \n -Для увеличения скорости расчета рекомендуется -использовать алгоритмы быстрого преобразования Фурье. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - diff --git a/dspl/dox/ru/ellipj.dox b/dspl/dox/ru/ellipj.dox deleted file mode 100644 index 5857408..0000000 --- a/dspl/dox/ru/ellipj.dox +++ /dev/null @@ -1,464 +0,0 @@ - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd(double* w, int n, double k, double* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{cd}^{-1}(w, k)\f$ вещественного аргумента - -Функция рассчитывает значения обратной эллиптической функции -\f$ u = \textrm{cd}^{-1}(w, k)\f$ для вещественного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n - -\param[in] k Значение эллиптического модуля \f$ k \f$. -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{cd}^{-1}(w, k)\f$ комплексного аргумента - -Функция рассчитывает занчения значения обратной эллиптической функции -\f$ u = \textrm{cd}^{-1}(w, k)\f$ для комплексного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn(double* w, int n, double k, double* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{sn}^{-1}(w, k)\f$ вещественного аргумента - -Функция рассчитывает занчения значения обратной эллиптической функции -\f$ u = \textrm{sn}^{-1}(w, k)\f$ для вещественного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) -\brief Обратная эллиптическая функция Якоби - \f$ u = \textrm{sn}^{-1}(w, k)\f$ комплексного аргумента - -Функция рассчитывает занчения значения обратной эллиптической функции -\f$ u = \textrm{sn}^{-1}(w, k)\f$ для комплексного вектора `w`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - - -\param[in] w -Указатель на массив вектора переменной \f$ w \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `w`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] u -Указатель на вектор значений обратной эллиптической -функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK`Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd(double* u, int n, double k, double* y) -\brief Эллиптическая функция Якоби -\f$ y = \textrm{cd}(u K(k), k)\f$ вещественного аргумента - -Функция рассчитывает занчения значения эллиптической функции -\f$ y = \textrm{cd}(u K(k), k)\f$ для вещественного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Эллиптическая функция Якоби - \f$ y = \textrm{cd}(u K(k), k)\f$ комплексного аргумента - -Функция рассчитывает занчения значения эллиптической функции -\f$ y = \textrm{cd}(u K(k), k)\f$ для комплексного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_landen(double k, int n, double* y) -\brief Расчет коэффициентов \f$ k_i \f$ ряда полного эллиптического интеграла. - -Полный эллиптический интеграл \f$ K(k) \f$ может быть представлен рядом: - -\f[ -K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), -\f] - -где \f$ k_i \f$ вычисляется итерационно при начальных условиях \f$ k_0 = k\f$: - -\f[ -k_i = -\left( -\frac{k_{i-1}} -{ -1+\sqrt{1-k_{i-1}^2} -} -\right)^2 -\f] - -Данная функция рассчитывает ряд первых `n` значений \f$ k_i \f$, которые в -дальнейшем могут быть использованы для расчета эллиптического интеграла и -эллиптических функций. - -\param[in] k -Эллиптический модуль \f$ k \f$. \n - -\param[in] n -Размер вектора `y` соответсвующих коэффициентам \f$ k_i \f$. \n \n - -\param[out] y -Указатель на вектор значений коэффициентов \f$ k_i \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `ellip_landen`: - -\include ellip_landen_test.c - -Результат работы программы: - -\verbatim - i k[i] - - 1 4.625e-01 - 2 6.009e-02 - 3 9.042e-04 - 4 2.044e-07 - 5 1.044e-14 - 6 2.727e-29 - 7 1.859e-58 - 8 8.640e-117 - 9 1.866e-233 -10 0.000e+00 -11 0.000e+00 -12 0.000e+00 -13 0.000e+00 -\endverbatim - -\note -Ряд полного эллиптического интеграла сходится при значениях -эллиптического модуля \f$ k<1 \f$. При этом сходимость ряда достаточно -быстрая и для практический приложений достаточно от 10 до 20 значений -\f$ k_i \f$ для обеспечения погрешности при расчете полного -эллиптического интеграла в пределах машинной точности. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn(double* u, int n, double k, double* y) -\brief Эллиптическая функция Якоби -\f$ y = \textrm{sn}(u K(k), k)\f$ вещественного аргумента - -Функция рассчитывает занчения значения эллиптической функции -\f$ y = \textrm{sn}(u K(k), k)\f$ для вещественного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup SPEC_MATH_ELLIP_GROUP -\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) -\brief Эллиптическая функция Якоби -\f$ y = \textrm{sn}(u K(k), k)\f$ комплексного аргумента - -Функция рассчитывает занчения значения эллиптической функции -\f$ y = \textrm{sn}(u K(k), k)\f$ для комплексного вектора `u` и -эллиптического модуля `k`. \n - -Для расчета используется итерационный алгоритм на основе преобразования -Ландена. \n - -\param[in] u -Указатель на массив вектора переменной \f$ u \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\param[in] n -Размер вектора `u`. \n \n - -\param[in] k -Значение эллиптического модуля \f$ k \f$. \n -Эллиптический модуль -- вещественный параметр, -принимающий значения от 0 до 1. \n \n - -\param[out] y -Указатель на вектор значений эллиптической -функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - diff --git a/dspl/dox/ru/error_list.dox b/dspl/dox/ru/error_list.dox index 8de438b..d0b21db 100644 --- a/dspl/dox/ru/error_list.dox +++ b/dspl/dox/ru/error_list.dox @@ -183,12 +183,6 @@ */ - - - - - - /*! \ingroup ERROR_CODE_GROUP \def ERROR_GNUPLOT_CREATE @@ -208,7 +202,6 @@ */ - /*! \ingroup ERROR_CODE_GROUP \def ERROR_LAPACK @@ -251,7 +244,6 @@ */ - /*! \ingroup ERROR_CODE_GROUP \def ERROR_POLY_AN @@ -262,7 +254,6 @@ */ - /*! \ingroup ERROR_CODE_GROUP \def ERROR_POLY_ORD @@ -271,7 +262,6 @@ */ - /*! \ingroup ERROR_CODE_GROUP \def ERROR_PTR @@ -294,7 +284,6 @@ */ - /*! \ingroup ERROR_CODE_GROUP \def ERROR_RAND_TYPE diff --git a/dspl/dox/ru/fft.dox b/dspl/dox/ru/fft.dox deleted file mode 100644 index b2fb671..0000000 --- a/dspl/dox/ru/fft.dox +++ /dev/null @@ -1,469 +0,0 @@ - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\struct fft_t -\brief Структура данных объекта быстрого преобразования Фурье - -Структура хранит указатели на массивы поворотных коэффициентов -и массивы промежуточных данных алгоритма быстрого преобразования Фурье. - -Библиотека DSPL использует для БПФ алгоритм для составной длины - - -\param n -Размер вектора БПФ, для которого выделена память в массивах структуры. \n -Парметр `n` должен быть равен целой степени двойки. \n \n - - -\param w -Указатель на вектор поворотных коэффициентов алгоритма БПФ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена и массив поворотных коэффициентов -должен быть заполнен функцией \ref fft_create. \n \n - - -\param t0 -Указатель на вектор промежуточных вычислений алгоритма БПФ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена функцией \ref fft_create. \n \n - - -\param t1 -Указатель на вектор промежуточных вычислений алгоритма БПФ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена функцией \ref fft_create. \n \n -Структура заполняется функцией \ref fft_create один раз -до использования алгоритма БПФ. \n -Указатель на объект данной структуры может быть -многократно использован при вызове функций БПФ. \n -Перед выходом из программы выделенную память под поворотные -коэффициенты и массивы промежуточных данных -необходимо очистить функцией \ref fft_free. Например: -\code -fft_t pfft; /* объявляем объект fft_t */ -int n = 64; /* Размер БПФ */ - -/* -обнуляем все поля и указатели. -Данные шаг рекомендуется ввиду того, что некоторые -при создании переменной не инициализируют ее нулем. -*/ - -memset(&pfft, 0, sizeof(fft_t)); - -int err; - -/* создаем объект для 64-точечного БПФ */ -err = fft_create(&pfft, n); - -/* Вызов БПФ функции*/ -/* Еще раз вызов БПФ функции */ -/* ... */ - -/* очистить память объекта БПФ */ -fft_free(&pfft); -\endcode - -\note -Важно отметить, что если объект `fft_t` был создан для размера БПФ равного `n`, -то он может быть использован только для БПФ размера `n`. \n\n -Также необходимо заметить, что функции БПФ самостоятельно контролируют размер, -и самостоятельно выделяют память объекта БПФ при необходимости. -Так если вызвать любую функцию использующую структуру `fft_t` с заполненными -данными для длины БПФ `k` для расчета БПФ длины `n`, -то массивы структуры будут автоматически пересозданы для длины `n`. - -\author -Бахурин Сергей. -www.dsplib.org -***************************************************************************** */ - - - - - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int ifft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) -\brief Обратное быстрое преобразование Фурье - -Функция рассчитывает \f$ n \f$-точечное обратное быстрое преобразование Фурье -от \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \frac{1}{N} \sum_{m = 0}^{n-1} x(m) \exp - \left( j \frac{2\pi}{n} m k \right), -\f] -где \f$ k = 0 \ldots n-1 \f$. - -Для расчета используется алгоритм БПФ составной длины. - -\param[in] x -Указатель на входной комплексный вектор \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер ОБПФ \f$n\f$. \n -Размер ОБПФ может быть составным вида -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -произвольный простой множитель не превосходящий 46340 -(см. описание функции \ref fft_create). \n \n - -\param[in] pfft -Указатель на структуру `fft_t`. \n -Указатель не должен быть `NULL`. \n -Структура \ref fft_t должна быть предварительно однократно -заполнена функцией \ref fft_create, и память должна быть -очищена перед выходом функцией \ref fft_free. \n \n - -\param[out] y -Указатель на вектор результата ОБПФ \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если расчет произведен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n - -Пример использования функции `fft`: - -\include ifft_cmplx_test.c - -Результат работы программы: - -\verbatim -| x[ 0] = 1.000 0.000 | y[ 0] = -0.517 0.686 | z[ 0] = 1.000 0.000 | -| x[ 1] = 0.540 0.841 | y[ 1] = -0.943 0.879 | z[ 1] = 0.540 0.841 | -| x[ 2] = -0.416 0.909 | y[ 2] = -2.299 1.492 | z[ 2] = -0.416 0.909 | -| x[ 3] = -0.990 0.141 | y[ 3] = 16.078 -6.820 | z[ 3] = -0.990 0.141 | -| x[ 4] = -0.654 -0.757 | y[ 4] = 2.040 -0.470 | z[ 4] = -0.654 -0.757 | -| x[ 5] = 0.284 -0.959 | y[ 5] = 1.130 -0.059 | z[ 5] = 0.284 -0.959 | -| x[ 6] = 0.960 -0.279 | y[ 6] = 0.786 0.097 | z[ 6] = 0.960 -0.279 | -| x[ 7] = 0.754 0.657 | y[ 7] = 0.596 0.183 | z[ 7] = 0.754 0.657 | -| x[ 8] = -0.146 0.989 | y[ 8] = 0.470 0.240 | z[ 8] = -0.146 0.989 | -| x[ 9] = -0.911 0.412 | y[ 9] = 0.375 0.283 | z[ 9] = -0.911 0.412 | -| x[10] = -0.839 -0.544 | y[10] = 0.297 0.318 | z[10] = -0.839 -0.544 | -| x[11] = 0.004 -1.000 | y[11] = 0.227 0.350 | z[11] = 0.004 -1.000 | -| x[12] = 0.844 -0.537 | y[12] = 0.161 0.380 | z[12] = 0.844 -0.537 | -| x[13] = 0.907 0.420 | y[13] = 0.094 0.410 | z[13] = 0.907 0.420 | -| x[14] = 0.137 0.991 | y[14] = 0.023 0.442 | z[14] = 0.137 0.991 | -| x[15] = -0.760 0.650 | y[15] = -0.059 0.479 | z[15] = -0.760 0.650 | -| x[16] = -0.958 -0.288 | y[16] = -0.161 0.525 | z[16] = -0.958 -0.288 | -| x[17] = -0.275 -0.961 | y[17] = -0.300 0.588 | z[17] = -0.275 -0.961 | -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft(double* x, int n, fft_t* pfft, complex_t* y) -\brief Быстрое преобразование Фурье вещественного сигнала - -Функция рассчитывает \f$ n \f$-точечное быстрое преобразование Фурье -вещественного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \sum_{m = 0}^{n-1} x(m) \exp - \left( -j \frac{2\pi}{n} m k \right), -\f] -где \f$ k = 0 \ldots n-1 \f$. - -Для расчета используется алгоритм БПФ составной длины. - -\param[in] x -Указатель на вектор вещественного входного сигнала \f$x(m)\f$, -\f$ m = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер БПФ \f$n\f$. \n -Размер БПФ может быть составным вида -\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, -где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -произвольный простой множитель не превосходящий 46340 -(см. описание функции \ref fft_create). \n \n - -\param[in] pfft -Указатель на структуру `fft_t`. \n -Указатель не должен быть `NULL`. \n -Структура \ref fft_t должна быть предварительно однократно -заполнена функцией \ref fft_create, и память должна быть -очищена перед выходом функцией \ref fft_free. \n \n - -\param[out] y -Указатель на комплексный вектор результата БПФ \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если расчет произведен успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n - -Пример использования функции `fft`: - -\include fft_test.c - -Результат работы программы: - -\verbatim -y[ 0] = 91.000 0.000 -y[ 1] = -7.000 30.669 -y[ 2] = -7.000 14.536 -y[ 3] = -7.000 8.778 -y[ 4] = -7.000 5.582 -y[ 5] = -7.000 3.371 -y[ 6] = -7.000 1.598 -y[ 7] = -7.000 0.000 -y[ 8] = -7.000 -1.598 -y[ 9] = -7.000 -3.371 -y[10] = -7.000 -5.582 -y[11] = -7.000 -8.778 -y[12] = -7.000 -14.536 -y[13] = -7.000 -30.669 -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) -\brief Быстрое преобразование Фурье комплексного сигнала - -Функция рассчитывает \f$ n \f$-точечное быстрое преобразование Фурье -комплексного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n -\f[ - Y(k) = \sum_{m = 0}^{n-1} x(m) \exp - \left( -j \frac{2\pi}{n} m k \right), -\f] -где \f$ k = 0 \ldots n-1 \f$. - -Для расчета используется алгоритм БПФ составной длины. - -\param[in] x -Указатель на вектор комплексного -входного сигнала \f$x(m)\f$, \f$ m = 0 \ldots n-1 \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер БПФ \f$n\f$. \n -Размер БПФ может быть составным вида -\f$n = n_0 \times n_1 \times n_2 \times n_3 \times \ldots \times n_p \times m\f$, -где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -произвольный простой множитель не превосходящий 46340 -(см. описание функции \ref fft_create). \n \n - -\param[in] pfft -Указатель на структуру `fft_t`. \n -Указатель не должен быть `NULL`. \n -Структура \ref fft_t должна быть предварительно однократно -заполнена функцией \ref fft_create, и память должна быть -очищена перед выходом функцией \ref fft_free. \n \n - -\param[out] y -Указатель на комплексный вектор -результата БПФ \f$Y(k)\f$, -\f$ k = 0 \ldots n-1 \f$. -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` если расчет произведен успешно. \n - В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n - -Пример использования функции `fft`: - -\include fft_cmplx_test.c - -Результат работы программы: - -\verbatim -y[ 0] = -0.517 0.686 -y[ 1] = -0.943 0.879 -y[ 2] = -2.299 1.492 -y[ 3] = 16.078 -6.820 -y[ 4] = 2.040 -0.470 -y[ 5] = 1.130 -0.059 -y[ 6] = 0.786 0.097 -y[ 7] = 0.596 0.183 -y[ 8] = 0.470 0.240 -y[ 9] = 0.375 0.283 -y[10] = 0.297 0.318 -y[11] = 0.227 0.350 -y[12] = 0.161 0.380 -y[13] = 0.094 0.410 -y[14] = 0.023 0.442 -y[15] = -0.059 0.479 -y[16] = -0.161 0.525 -y[17] = -0.300 0.588 -\endverbatim - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft_create(fft_t* pfft, int n) -\brief Заполнение структуры `fft_t` для алгоритма БПФ - -Функция производит выделение памяти и рассчет векторов -поворотных коэффициентов `n`-точечного БПФ для структуры `fft_t`. - -\param[in,out] pfft -Указатель на структуру `fft_t`. \n -Указатель не должен быть `NULL`. \n \n - -\param[in] n -Размер БПФ \f$n\f$. \n -Размер БПФ может быть составным вида -\f$n = n_0 \times n_1 \times n_2 \ldots \times n_p \times m\f$, -где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- -произвольный простой множитель не превосходящий 46340. \n -Таким образом алгоритм БПФ поддерживает произвольные длины, равные целой -степени чисел 2,3,5,7, а также различные их комбинации. \n -Так например, при \f$ n = 725760 \f$ структура будет успешно заполнена, -потому что -\f$725760 = 2 \cdot 3 \cdot 4 \cdot 5 \cdot 6 \cdot 7 \cdot 9 \cdot 16 \f$, -т.е. получается как произведение множителей 2,3,5,7. \n -При \f$ n = 172804 = 43201 \cdot 4 \f$ структура также будет успешно заполнена, -потому что простой множитель входящий в \f$n\f$ не превосходит 46340. \n -Для размера \f$ n = 13 \cdot 17 \cdot 23 \cdot 13 = 66079 \f$ -функция вернет ошибку, поскольку 66079 больше 46340 и не является результатом -произведения чисел 2,3,5,7. \n \n - -\return -`RES_OK` если структура заполнена успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n - -\note -Некоторые компиляторы при создании структуры не обнуляют ее содержимое. -Поэтому рекомендуется произвести обнуление структуры после ее объявления: -\code{.cpp} -fft_t pfft; /* объявляем объект fft_t */ -int n = 64; /* Размер БПФ */ - -/* -бнуляем все поля и указатели. -Данные шаг рекомендуется ввиду того, что некоторые -компиляторы при создании переменной не инициализируют ее нулем. -*/ - -memset(&pfft, 0, sizeof(fft_t)); - -int err; - -/* создаем объект для 64-точечного БПФ */ - -err = fft_create(&pfft, n); - -/* ................................... */ - -/* очистить память объекта БПФ */ - -fft_free(&pfft); -\endcode - -Перед выходом из программы выделенную в структуре память -необходимо очистить функцией \ref fft_free . \n \n - -\note -Магия числа 46340 заключается в том, что \f$\sqrt{2^{31}} = 46340.95\f$. \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn void fft_free(fft_t *pfft) -\brief Очистить структуру `fft_t` алгоритма БПФ - -Функция производит очищение памяти промежуточных данных -и векторов поворотных коэффициентов структуры `fft_t`. - -\param[in] pfft -Указатель на структуру `fft_t`. \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - - -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fft_shift(double* x, int n, double* y) -\brief Перестановка спектральных отсчетов дискретного преобразования Фурье - -Функция производит - -перестановку спектральных отсчетов ДПФ - и переносит нулевую частоту в центр вектора ДПФ. \n -Данная функция обрабатывает вещественные входные и выходные вектора -и может применяться для перестановки -амплитудного или фазового спектра. - -\param[in] x -Указатель на исходный вектор ДПФ. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер ДПФ \f$n\f$ (размер векторов до и после перестановки). \n \n - -\param[out] y -Указатель на вектор результата перестановки. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` если перестановка произведена успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ diff --git a/dspl/dox/ru/filter_an.dox b/dspl/dox/ru/filter_an.dox deleted file mode 100644 index 0f9e6eb..0000000 --- a/dspl/dox/ru/filter_an.dox +++ /dev/null @@ -1,260 +0,0 @@ - -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) - -\brief Расчет комплексного коэффициента передачи -\f$ H(j \omega) \f$ аналогового фильтра. - -Функция рассчитывает значения комплексного коэффициента передачи -\f$ H(j \omega)\f$ аналогового фильтра, заданного коэффициентами -передаточной функции \f$ H(s) \f$: - -\f[ - H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} - {\sum_{m = 0}^{N} a_m s^m}, -\f] -где \f$ N \f$ - порядок фильтра (параметр `ord`). - -Комплексный коэффициент передачи рассчитывается путем -подстановки \f$ s = j \omega \f$. - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - - -\param[in] ord -Порядок фильтра. Количество коэффициентов числителя и -знаменателя передаточной функции \f$ H(s) \f$ -равно `ord+1`. \n \n - - -\param[in] w -Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), -для которого будет рассчитан комплексный -коэффициент передачи \f$ H(j \omega) \f$. \n -Размер вектора `[n x 1]`. \n \n - - -\param[in] n -Размер вектора циклической частоты `w`. \n \n - - -\param[out] h -Указатель на вектор комплексного коэффициента передачи \f$ H(j \omega) \f$, -рассчитанного для циклической частоты `w`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` Комплексноый коэффициент передачи рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, - int flag, double* mag, double* phi, double* tau) - -\brief -Расчет амплитудно-частотной (АЧХ), фазочастотной характеристик (ФЧХ), а также -группового времени запаздывания (ГВЗ) цифрового или аналогового или фильтра. - -Функция рассчитывает АЧХ, ФЧХ и ГВЗ аналогового или цифрового фильтра, заданного -передаточной характеристикой \f$H(s)\f$, или \f$H(z)\f$ соответственно - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$ H(s) \f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] ord -Порядок фильтра. Количество коэффициентов -числителя и знаменателя передаточной -функции \f$ H(s) \f$ равно `ord+1`. \n \n - -\param[in] w -Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), -для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, -если установлен флаг `DSPL_FLAG_ANALOG`. \n -В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` -используется как нормированная частота комплексного коэффициента передачи -\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n -В этом случае характеристика цифрового фильтра является -\f$ 2\pi \f$-периодической, и вектор частоты может содержать -произвольные значения, однако целесообразно задавать -его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или -от \f$ -\pi \f$ до \f$ \pi \f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора циклической частоты `w`. \n \n - -\param[in] flag -Комбинация флагов, которые задают расчет параметров: \n -\verbatim -DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру -DSPL_FLAG_LOGMAG АЧХ рассчитывать в логарифмическом масштабе -DSPL_FLAG_UNWRAP раскрывать периодичность ФЧХ -\endverbatim - -\param[out] mag -Указатель на вектор АЧХ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -Если указатель `NULL`, то расчет АЧХ не производится. \n \n - -\param[out] phi -Указатель на вектор ФЧХ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -Если указатель `NULL`, то расчет ФЧХ не производится. \n \n - -\param[out] tau -Указатель на вектор ГВЗ. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n -Если указатель `NULL`, то расчет ГВЗ не производится. \n \n - -\return -`RES_OK` Параметры фильтра рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -Пример использования функции `filter_freq_resp`: - -\include butter_ap_test.c - -Результат работы программы: - -\verbatim -b[ 0] = 1.002 a[ 0] = 1.002 -b[ 1] = 0.000 a[ 1] = 2.618 -b[ 2] = 0.000 a[ 2] = 3.418 -b[ 3] = 0.000 a[ 3] = 2.615 -b[ 4] = 0.000 a[ 4] = 1.000 -\endverbatim -\n - -В каталоге `dat` будут созданы три файла: \n - -\verbatim -butter_ap_test_mag.txt АЧХ фильтра -butter_ap_test_phi.txt ФЧХ фильтра -butter_ap_test_tau.txt ГВЗ фильтра -\endverbatim - -Кроме того программа GNUPLOT произведет построение следующих графиков -по сохраненным в файлах данным: - -\image html butter_ap_test.png - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ - - - - - - - - - - -/*! **************************************************************************** -\ingroup FILTER_ANALYSIS_GROUP -\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) - -\brief Расчет комплексного коэффициента передачи - \f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра. - -Функция рассчитывает значения комплексного коэффициента передачи -\f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра, заданного -коэффициентами передаточной функции \f$H(z)\f$: - -\f[ -H(z) = \frac {\sum_{k = 0}^{N} b_k z^{-k}} - {\sum_{m = 0}^{N} a_m z^{-m}}, -\f] - -где \f$N\f$ --- порядок фильтра (параметр `ord`). \n - -Комплексный коэффициент передачи рассчитывается путем -подстановки \f$z = e^{j \omega} \f$. \n - - -\param[in] b -Указатель на вектор коэффициентов числителя -передаточной функции \f$H(z)\f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] a -Указатель на вектор коэффициентов знаменателя -передаточной функции \f$H(z)\f$. \n -Размер вектора `[ord+1 x 1]`. \n \n - -\param[in] ord -Порядок фильтра. Количество коэффициентов числителя и знаменателя -передаточной функции \f$H(z)\f$ равно `ord+1`. \n \n - -\param[in] w -Указатель на вектор значений нормированной циклической частоты \f$\omega\f$, -для которого будет рассчитан комплексный коэффициент передачи -\f$ H \left(e^{j \omega} \right)\f$. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора нормированной циклической частоты `w`. \n \n - -\param[out] h -Указатель на вектор комплексного коэффициента передачи -\f$ H \left(e^{j \omega} \right)\f$, рассчитанного для -циклической частоты `w`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - - -\return -`RES_OK` Комплексный коэффициент передачи расcчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Комплексный коэффициент передачи \f$ H \left(e^{j \omega} \right)\f$ -цифрового фильтра представляет собой \f$ 2 \pi-\f$периодическую функцию -нормированной циклической частоты \f$\omega\f$. -Поэтому анализ цифровых фильтров целесообразно вести на одном периоде -повторения \f$ H \left(e^{j \omega} \right)\f$, т.е. в интервале -\f$\omega\f$ от 0 до \f$2 \pi\f$, или от \f$-\pi\f$ до \f$ \pi\f$. \n -Кроме того известно, что для фильтра с вещественными коэффициентами -\f$ H \left(e^{j \omega} \right) = H^* \left(e^{-j \omega} \right)\f$, -а значит, анализ цифрового фильтра с вещественными коэффициентами -достаточно вести для нормированной частоты \f$\omega\f$ от 0 до \f$\pi\f$. - -\author -Бахурин Сергей -www.dsplib.org -***************************************************************************** */ diff --git a/dspl/dox/ru/filter_ap.dox b/dspl/dox/ru/filter_ap.dox index b1206fa..e1e3834 100644 --- a/dspl/dox/ru/filter_ap.dox +++ b/dspl/dox/ru/filter_ap.dox @@ -276,8 +276,7 @@ www.dsplib.org /*! **************************************************************************** \ingroup IIR_FILTER_DESIGN_GROUP -\fn int cheby1_ap_zp( int ord, double rp, complex_t *z, int* nz, - complex_t* p, int* np) +\fn int cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, complex_t* p, int* np) \brief Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ аналогового нормированного ФНЧ Чебышёва первого рода. @@ -300,7 +299,7 @@ www.dsplib.org \param[out] z Указатель на массив комплексных нулей передаточной характеристики \f$ H(s)\f$. \n -Максимальный размер вектора вектора `[ord x 1]`. \n +Максимальный размер вектора `[ord x 1]`. \n Память должна быть выделена. \n \n @@ -321,8 +320,8 @@ www.dsplib.org \param[out] np Указатель на переменную количества полюсов передаточной функции \f$ H(s)\f$. \n -По данному укащзателю будет записано количество нулей фильтра, которые были -рассчитны и помещены в вектор `p`. \n +По данному указателю будет записано количество нулей фильтра, которые были +рассчитаны и помещены в вектор `p`. \n Память должна быть выделена. \n \n @@ -334,6 +333,35 @@ www.dsplib.org Нормированный ФНЧ Чебышёва первого рода не имеет нулей, поэтому массив нулей `z` не будет изменен, а по указателю `nz` будет записан 0. \n + +Пример программы рассчета нулей и полюсов нормированного +ФНЧ Чебышева первого рода: +\include cheby1_ap_zp_test.c + +Результат выполнения программы: + +\verbatim +Chebyshev type 1 filter zeros: 0 +Chebyshev type 1 filter poles: 7 +p[ 0] = -0.256 +0.000 j +p[ 1] = -0.057 +1.006 j +p[ 2] = -0.057 -1.006 j +p[ 3] = -0.160 +0.807 j +p[ 4] = -0.160 -0.807 j +p[ 5] = -0.231 +0.448 j +p[ 6] = -0.231 -0.448 j +\endverbatim +\n + +В каталоге `dat` будет создан файл `cheby1_ap_zp.txt`. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/cheby1_ap_zp.txt` данным: + +\image html cheby1_ap_zp_test.png + + + \author Бахурин Сергей www.dsplib.org @@ -485,28 +513,39 @@ www.dsplib.org Пример использования функции `cheby2_ap_zp`: +Пример программы рассчета нулей и полюсов нормированного +ФНЧ Чебышева первого рода: \include cheby2_ap_zp_test.c -Результат работы программы: +Результат выполнения программы: \verbatim - Chebyshev type 2 zeros: - z[ 0] = 0.000 1.026 j - z[ 1] = 0.000 -1.026 j - z[ 2] = 0.000 1.279 j - z[ 3] = 0.000 -1.279 j - z[ 4] = 0.000 2.305 j - z[ 5] = 0.000 -2.305 j - - Chebyshev type 2 poles: - p[ 0] = -1.203 0.000 j - p[ 1] = -0.113 0.772 j - p[ 2] = -0.113 -0.772 j - p[ 3] = -0.398 0.781 j - p[ 4] = -0.398 -0.781 j - p[ 5] = -0.852 0.642 j - p[ 6] = -0.852 -0.642 j +Chebyshev type 2 filter zeros: 6 +z[ 0] = 0.000 +1.026 j +z[ 1] = 0.000 -1.026 j +z[ 2] = 0.000 +1.279 j +z[ 3] = 0.000 -1.279 j +z[ 4] = 0.000 +2.305 j +z[ 5] = 0.000 -2.305 j +Chebyshev type 2 filter poles: 7 +p[ 0] = -1.203 +0.000 j +p[ 1] = -0.113 +0.772 j +p[ 2] = -0.113 -0.772 j +p[ 3] = -0.398 +0.781 j +p[ 4] = -0.398 -0.781 j +p[ 5] = -0.852 +0.642 j +p[ 6] = -0.852 -0.642 j \endverbatim +\n + +В каталоге `dat` будет создан файлы `cheby2_ap_z.txt` и `cheby2_ap_z.txt`, +хранящие наборы нулей и полюсов на комплексной плоскости. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/cheby2_ap_z.txt` и `dat/cheby2_ap_p.txt` данным: + +\image html cheby2_ap_zp_test.png + \author Бахурин Сергей @@ -538,7 +577,7 @@ www.dsplib.org Значение должно быть положительным. \n \n -\param[in] Rs +\param[in] rs Уровень подавления в полосе заграждения (дБ). \n Значение должно быть положительным. \n \n @@ -607,6 +646,106 @@ www.dsplib.org +/*! **************************************************************************** +\ingroup IIR_FILTER_DESIGN_GROUP +\fn int ellip_ap_zp(int ord, double rp, double rs, complex_t* z, int* nz, + complex_t* p, int* np) + +\brief +Расчет массивов нулей и полюсов передаточной функции \f$ H(s) \f$ +аналогового нормированного эллиптического ФНЧ. + +\param[in] ord +Порядок фильтра. \n +\n + + +\param[in] rp +Неравномерность АЧХ в полосе пропускания (дБ). \n +Параметр задает уровень искажений в полосе от 0 до 1 рад/с. \n +Значение должно быть положительным. \n +\n + +\param[in] rs +Уровень подавления АЧХ в полосе загражения (дБ). \n +Параметр задает уровень подавления сигнала в полосе частот от 1 рад/с и выше. \n +Значение должно быть положительным. \n +\n + +\param[out] z +Указатель на массив комплексных нулей передаточной функции \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] nz +Указатель на переменную количества нулей передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей фильтра, которые были +рассчитаны и помещены в вектор `z`. \n +Память должна быть выделена. \n +\n + +\param[out] p +Указатель на массив комплексных полюсов передаточной функции \f$H(s)\f$. \n +Максимальный размер вектора вектора `[ord x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] np +Указатель на переменную количества полюсов передаточной функции \f$H(s)\f$. \n +По данному указателю будет записано количество нулей +фильтра, которые были +рассчитаны и помещены в вектор `p`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- массивы нулей и полюсов рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `cheby2_ap_zp`: + +Пример программы рассчета нулей и полюсов нормированного +эллиптического ФНЧ : +\include ellip_ap_zp_test.c + +Результат выполнения программы: + +\verbatim +Elliptic filter zeros: 6 +z[ 0] = 0.000 +1.053 j +z[ 1] = 0.000 -1.053 j +z[ 2] = 0.000 +1.136 j +z[ 3] = 0.000 -1.136 j +z[ 4] = 0.000 +1.626 j +z[ 5] = 0.000 -1.626 j +Elliptic filter poles: 7 +p[ 0] = -0.358 +0.000 j +p[ 1] = -0.011 +1.000 j +p[ 2] = -0.011 -1.000 j +p[ 3] = -0.060 +0.940 j +p[ 4] = -0.060 -0.940 j +p[ 5] = -0.206 +0.689 j +p[ 6] = -0.206 -0.689 j +\endverbatim +\n + +В каталоге `dat` будет создан файлы `ellip_ap_z.txt` и `ellip_ap_z.txt`, +хранящие наборы нулей и полюсов на комплексной плоскости. \n + +Пакет GNUPLOT произведет построение карты полюсов по +сохранненным в `dat/ellip_ap_z.txt` и `dat/ellip_ap_p.txt` данным: + +\image html ellip_ap_zp_test.png + + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ + + + diff --git a/dspl/dox/ru/groups_define.dox b/dspl/dox/ru/groups_define.dox index a514cfd..b35be04 100644 --- a/dspl/dox/ru/groups_define.dox +++ b/dspl/dox/ru/groups_define.dox @@ -32,8 +32,12 @@ \defgroup RESAMPLING_GROUP Цифровая передискретизация сигналов +\defgroup ARRAY_GROUP Базовые функции обработки массивов вещественных и комплексных данных + \defgroup SPEC_MATH_COMMON_GROUP Базовые функции и работа с массивами данных +\defgroup SPEC_MATH_POLY_GROUP Функции полиномов и их анализ. + \defgroup SPEC_MATH_TRIG_GROUP Тригонометрические и гиперболические функции Тригонометрические и гиперболические функции вещественного и комплексного аргумента. diff --git a/dspl/dox/ru/mainpage.dox b/dspl/dox/ru/mainpage.dox index 83882d2..a958fff 100644 --- a/dspl/dox/ru/mainpage.dox +++ b/dspl/dox/ru/mainpage.dox @@ -35,7 +35,9 @@ DSPL-2.0 --- свободная библиотека алгоритмов циф \subsection sec_doc_content Разделы документации Математические функции: \n + - \ref ARRAY_GROUP \n - \ref SPEC_MATH_COMMON_GROUP \n + - \ref SPEC_MATH_POLY_GROUP \n - \ref SPEC_MATH_TRIG_GROUP \n - \ref SPEC_MATH_TRANSCEND \n - \ref SPEC_MATH_ELLIP_GROUP \n diff --git a/dspl/src/array.c b/dspl/src/array.c index 5e559ed..2f3c62b 100644 --- a/dspl/src/array.c +++ b/dspl/src/array.c @@ -5,17 +5,17 @@ * This file is part of libdspl-2.0. * * is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by +* it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ @@ -26,176 +26,839 @@ #include "blas.h" -/****************************************************************************** -Vector linear transformation --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ -int array_scale_lin(double* x, int n, - double xmin, double xmax, double dx, - double h, double* y) +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int array_scale_lin(double* x, int n, + double xmin, double xmax, double dx, + double h, double* y) +\brief Vector `x` linear transformation + +Function transforms values \f$x(i)\f$, \f$i = 0,1,\ldots n\f$ +to the \f$y(i)\f$, accordint to equation: + +\f[ +y(i) = k_x x(i) + d_x, \qquad k_x = +\frac{h}{x_{\textrm{max}} - x_{\textrm{min}}}. +\f] + +All values of the vector `x` between +\f$x_{\textrm{min}}\f$ and \f$x_{\textrm{max}}\f$, transforms to +the vector `y` between \f$d_x\f$ and \f$h + d_x\f$. +Parameter \f$d_x\f$ sets mean shift of the vector `y`. + +This function is convenient for translating values ​​ +of different dimensions. For example it can be used +to transfer the values ​​of the vector `x` +to the graph of the height of` h`, where the height can +be set in the number of pixels, in centimeters, etc. + +\param[in] x +Pointer to the input vector `x`. \n +Vector size is `[n x 1]`. \n +\n + +\param[in] n +Size of vector `x`. \n +\n + +\param[in] xmin +Parameter \f$x_{\textrm{min}}\f$. \n +\n + +\param[in] xmax +Parameter \f$x_{\textrm{min}}\f$. \n +Value `xmax` must be more than `xmin`. \n +\n + +\param[in] dx +Displacement after transformation. \n +This parameter must have output vector `y` +dimensions (pixels, centimeters). \n +\n + +\param[in] h +Height of vector `y` after transforming between `dx` and `h+dx`. \n +\n + +\param[out] y +Pointer to the output vector `y`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n +\note +Pointer `y` can be equal to `x`. +Velues of vector `x` will be rewritten in this case. \n +\n + +\return +`RES_OK` if function returns successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif + +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int array_scale_lin(double* x, int n, + double xmin, double xmax, double dx, + double h, double* y) +\brief Линейное растяжение вектора данных `x` +Функция производит преобразование значений \f$x(i)\f$, \f$i = 0,1,\ldots n\f$ +в значения \f$y(i)\f$, в соответствии с формулой: + +\f[ +y(i) = k_x x(i) + d_x, \qquad k_x = +\frac{h}{x_{\textrm{max}} - x_{\textrm{min}}}. +\f] + +Таким образом, все значения входного вектора `x` в диапазоне от +\f$x_{\textrm{min}}\f$ до \f$x_{\textrm{max}}\f$, линейно растягиваются в +значения вектора `y` в диапазоне от \f$d_x\f$ до \f$h + d_x\f$. +Заметим, что \f$d_x\f$ задает линейное смещение значений вектора `y`. + +Данная функция удобна для перевода величин разных размерностей, в частности, +для переноса значений вектора `x` на график высоты `h`, где высота может +быть задана в количестве пикселей, в сантиметрах и т.д. + +\param[in] x +Указатель на вектор входных значений `x`. \n +Размер вектора `[n x 1]`. \n +\n + +\param[in] n +Размер вектора `x`. \n +\n + +\param[in] xmin +Нижняя граница диапазона трансформации. \n +\n + +\param[in] xmax +Верхняя граница диапазона трансформации. \n +Значение `xmax` должно быть строго больше значения `xmin`. \n +\n + +\param[in] dx +Смещение после трансформации. \n +Данный параметр должен иметь размерность выходного вектора `y`. \n +\n + +\param[in] h +Диапазон значений вектора `y` после трансформации от `dx` до `h+dx`. \n +\n + +\param[out] y +Указатель на вектора данных после трансформации. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +\note +Указатель `y` может совпадать с `x`, в этом случае, +данные вектора `x` будут перезаписаны линейно измененными в соответствии +с формулой выше. \n +\n + +\return +`RES_OK` если функция выполнена успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API array_scale_lin(double* x, int n, + double xmin, double xmax, double dx, + double h, double* y) { - double kx; - int k; - if(!x) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(h<0.0) - return ERROR_NEGATIVE; + double kx; + int k; + if(!x) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(h<0.0) + return ERROR_NEGATIVE; - if(xmin >= xmax) - return ERROR_MIN_MAX; + if(xmin >= xmax) + return ERROR_MIN_MAX; - kx = h / (xmax - xmin); + kx = h / (xmax - xmin); - for(k = 0; k < n; k++) - y[k] = (x[k] - xmin) * kx + dx; + for(k = 0; k < n; k++) + y[k] = (x[k] - xmin) * kx + dx; - return RES_OK; + return RES_OK; } - -/****************************************************************************** +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int concat(void* a, size_t na, void* b, size_t nb, void* c) +\brief Concatenate arrays `a` and `b` --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ + +Let's arrays `a` and `b` are vectors: \n +`a = [a(0), a(1), ... a(na-1)]`, \n +`b = [b(0), b(1), ... b(nb-1)]`, \n +concatenation of these arrays will be array `c` size `na+nb`: \n +`c = [a(0), a(1), ... a(na-1), b(0), b(1), ... b(nb-1)]`. + + +\param[in] a +Pointer to the first array `a`. \n +Array `a` size is `na` bytes. \n +\n + +\param[in] na +Array `a` size (bytes). \n +\n + +\param[in] b +Pointer to the second array `b`. \n +Array `b` size is `nb` bytes. \n +\n + +\param[in] nb +Array `a` size (bytes). \n +\n + +\param[out] c +Pointer to the concatenation result array `c`. \n +Array `c` size is `na + nb` bytes. \n +Memory must be allocated. \n +\n + +\return +`RES_OK` if function returns successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Function uses pointer type `void*` and can be useful for an arrays +concatenation with different types. \n +For example two `double` arrays concatenation: +\code{.cpp} +double a[3] = {1.0, 2.0, 3.0}; +double b[2] = {4.0, 5.0}; +double c[5]; + +concat((void*)a, 3*sizeof(double), (void*)b, 2*sizeof(double), (void*)c); +\endcode +Vector `c` keeps follow data: +\verbatim +c = [1.0, 2.0, 3.0, 4.0, 5.0] +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif + +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int concat(void* a, size_t na, void* b, size_t nb, void* c) +\brief Конкатенация двух массивов данных + +Функция производит конкатенацию двух массивов. Пусть массивы `a` и `b` +заданы как векторы: \n +`a = [a(0), a(1), ... a(na-1)]`, \n +`b = [b(0), b(1), ... b(nb-1)]`, \n +тогда результатом конкатенации будет вектор размера `na+nb` вида: \n +`c = [a(0), a(1), ... a(na-1), b(0), b(1), ... b(nb-1)]`. + + +\param[in] a +Указатель на первый вектор `a`. \n +Размер вектора `na` байт. \n \n + +\param[in] na +Размер первого вектора `a` в байт. \n \n + +\param[in] b +Указатель на второй вектор `b`. \n +Размер памяти вектора `nb` байт. \n \n + +\param[in] nb +Размер второго вектора `b` в байт. \n \n + +\param[out] c +Указатель на вектор конкатенации `c`. \n +Размер памяти вектора `na + nb` байт. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если функция выполнена успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\note +Функция использует указатели типа `void*` и может быть использована для +конкатенации данных различного типа. \n +Например конкатенация массивов типа `double`: +\code{.cpp} +double a[3] = {1.0, 2.0, 3.0}; +double b[2] = {4.0, 5.0}; +double c[5]; +concat((void*)a, 3*sizeof(double), (void*)b, 2*sizeof(double), (void*)c); +\endcode +в результате вектор `c` будет хранить массив данных: +\verbatim +c = [1.0, 2.0, 3.0, 4.0, 5.0] +\endverbatim + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API concat(void* a, size_t na, void* b, size_t nb, void* c) { - if(!a || !b || !c || c == b) - return ERROR_PTR; - if(na < 1 || nb < 1) - return ERROR_SIZE; + if(!a || !b || !c || c == b) + return ERROR_PTR; + if(na < 1 || nb < 1) + return ERROR_SIZE; - if(c != a) - memcpy(c, a, na); + if(c != a) + memcpy(c, a, na); - memcpy((char*)c+na, b, nb); - return RES_OK; + memcpy((char*)c+na, b, nb); + return RES_OK; } -/****************************************************************************** +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int decimate(double* x, int n, int d, double* y, int* cnt) +\brief Real vector decimation --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ + +Function `d` times decimates real vector `x`. \n +Output vector `y` keeps values corresponds to: +`y(k) = x(k*d), k = 0...n/d-1` \n + +\param[in] x +Pointer to the input real vector `x`. \n +Vector `x` size is `[n x 1]`. \n \n + +\param[in] n +Size of input vector `x`. \n \n + +\param[in] d +Decimation coefficient. \n +Each d-th vector will be copy from vector `x` to the +output vector `y`. \n \n + +\param[out] y +Pointer to the output decimated vector `y`. \n +Output vector size is `[n/d x 1]` will be copy +to the address `cnt`. \n + +\param[out] cnt +Address which will keep decimated vector `y` size. \n +Pointer can be `NULL`, vector `y` will not return +in this case. \n \n + +\return +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Two-times decimation example: +\code{.cpp} +double x[10] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; +double y[5]; +int d = 2; +int cnt; + +decimate(x, 10, d, y, &cnt); +\endcode +As result variable `cnt` will be written value 5 and +vector `y` will keep array: +\verbatim +c = [0.0, 2.0, 4.0, 6.0, 8.0] +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int decimate(double* x, int n, int d, double* y, int* cnt) +\brief Децимация вещественного вектора данных + +Функция производит децимацию вещественного вектора `x` в `d` раз. \n +В результате выходной вектор `y` содержит значения: +`y(k) = x(k*d), k = 0...n/d-1` \n + +\param[in] x +Указатель на вектор входных данных `x`. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер входного вектора `x`. \n \n + +\param[in] d +Коэффициент децимации. \n +В результате децимации из вектора `x` будет взять каждый +d-й элемент. \n \n + +\param[out] y +Указатель на децимированный вектор `y`. \n +Размер выходного вектора равен `[n/d x 1]` +будет сохранен по адресу `cnt`. \n +Память должна быть выделена. \n \n + +\param[out] cnt +Указатель переменную, в которую будет сохранен +размер выходного вектора после децимации. \n +Указатель может быть `NULL`, в этом случае +размер вектора `y` не возвращается. \n \n + +\return +`RES_OK` если функция выполнена успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример децимации вещественного массива данных в 2 раза: +\code{.cpp} +double x[10] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; +double y[5]; +int d = 2; +int cnt; +decimate(x, 10, d, y, &cnt); +\endcode +В результате в переменную `cnt` будет записан размер 5, +а вектор `y` будет хранить массив данных: +\verbatim +c = [0.0, 2.0, 4.0, 6.0, 8.0] +\endverbatim + +\author +Бахурин Сергей +www.dsplib.org +**************************************************************************** */ +#endif int DSPL_API decimate(double* x, int n, int d, double* y, int* cnt) { - int k = 0, i = 0; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(d < 1) - return ERROR_NEGATIVE; + int k = 0, i = 0; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(d < 1) + return ERROR_NEGATIVE; - k = i = 0; - while(k + d <= n) - { - y[i] = x[k]; - k+=d; - i++; - } - if(cnt) - *cnt = i; + k = i = 0; + while(k + d <= n) + { + y[i] = x[k]; + k+=d; + i++; + } + if(cnt) + *cnt = i; - return RES_OK; + return RES_OK; } -/****************************************************************************** +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int decimate_cmplx(complex_t* x, int n, int d, complex_t* y, int* cnt) +\brief Complex vector decimation --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ + +Function `d` times decimates a complex vector `x`. \n +Output vector `y` keeps values corresponds to: +`y(k) = x(k*d), k = 0...n/d-1` \n + +\param[in] x +Pointer to the input complex vector `x`. \n +Vector `x` size is `[n x 1]`. \n \n + +\param[in] n +Size of input vector `x`. \n \n + +\param[in] d +Decimation coefficient. \n +Each d-th vector will be copy from vector `x` to the +output vector `y`. \n \n + +\param[out] y +Pointer to the output decimated vector `y`. \n +Output vector size is `[n/d x 1]` will be copy +to the address `cnt`. \n +Memory must be allocated. \n \n + +\param[out] cnt +Address which will keep decimated vector `y` size. \n +Pointer can be `NULL`, vector `y` will not return +in this case. \n \n + +\return +`RES_OK` if function calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Two-times complex vector decimation example: + +\code{.cpp} +compex_t x[10] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}, +{5.0, 5.0}, {6.0, 6.0}, {7.0, 7.0}, {8.0, 8.0}, {9.0, 9.0}}; +compex_t y[5]; +int d = 2; +int cnt; + +decimate_cmplx(x, 10, d, y, &cnt); +\endcode + +As result variable `cnt` will be written value 5 and +vector `y` will keep array: + +\verbatim +c = [0.0+0.0j, 2.0+2.0j, 4.0+4.0j, 6.0+6.0j, 8.0+8.0j] +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int decimate_cmplx(complex_t* x, int n, int d, complex_t* y, int* cnt) +\brief Децимация комплексного вектора данных + +Функция производит децимацию комплексного вектора `x` в `d` раз. \n +В результате выходной вектор `y` содержит значения: +`y(k) = x(k*d), k = 0...n/d-1` \n + +\param[in] x +Указатель на вектор входных данных `x`. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер входного вектора `x`. \n \n + +\param[in] d +Коэффициент децимации. \n +В результате децимации из вектора `x` будет взять каждый d-й элемент. \n \n + +\param[out] y +Указатель на децимированный вектор `y`. \n +Размер выходного вектора равен `[n/d x 1]` будет сохранен по адресу `cnt`. \n +Память должна быть выделена. \n \n + +\param[out] cnt +Указатель переменную, в которую будет сохранен +размер выходного вектора после децимации. \n +Указатель может быть `NULL`, в этом случае +размер вектора `y` не возвращается. \n \n + +\return +`RES_OK` если функция выполнена успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример децимации комплексного массива данных в 2 раза: +\code{.cpp} +compex_t x[10] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}, + {5.0, 5.0}, {6.0, 6.0}, {7.0, 7.0}, {8.0, 8.0}, {9.0, 9.0}}; +compex_t y[5]; +int d = 2; +int cnt; +decimate_cmplx(x, 10, d, y, &cnt); +\endcode +В результате в переменную `cnt` будет записан размер 5, а вектор `y` будет +хранить массив данных: +\verbatim +c = [0.0+0.0j, 2.0+2.0j, 4.0+4.0j, 6.0+6.0j, 8.0+8.0j] +\endverbatim + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API decimate_cmplx(complex_t* x, int n, int d, complex_t* y, int* cnt) { - int k = 0, i = 0; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(d < 1) - return ERROR_NEGATIVE; + int k = 0, i = 0; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(d < 1) + return ERROR_NEGATIVE; - k = i = 0; - while(k + d < n) - { - RE(y[i]) = RE(x[k]); - IM(y[i]) = IM(x[k]); - k+=d; - i++; - } - if(cnt) - *cnt = i; + k = i = 0; + while(k + d < n) + { + RE(y[i]) = RE(x[k]); + IM(y[i]) = IM(x[k]); + k+=d; + i++; + } + if(cnt) + *cnt = i; - return RES_OK; + return RES_OK; } -/****************************************************************************** +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int flipip(double* x, int n) +\brief Flip real vector `x` in place --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ + +Function flips real vector `x` length `n` in the memory. \n +For example real vector `x` length 6:\n +\verbatim +x = [0, 1, 2, 3, 4, 5] +\endverbatim +After flipping it will be as follow: +\verbatim +x = [5, 4, 3, 2, 1, 0] +\endverbatim + +\param[in, out] x +Pointer to the real vector `x`. \n +Vector size is `[n x 1]`. \n +Flipped vector will be on the same address. \n +\n + +\param[in] n +Length of the vector `x`. \n +\n + +\return +`RES_OK` if function returns successfully. \n + Else \ref ERROR_CODE_GROUP "error code". + +Example: +\code{.cpp} +double x[5] = {0.0, 1.0, 2.0, 3.0, 4.0}; +int i; +for(i = 0; i < 5; i++) + printf("%6.1f ", x[i]); +flipip(x, 5); +printf("\n"); +for(i = 0; i < 5; i++) + printf("%6.1f ", x[i]); +\endcode +\n +Program result: +\verbatim + 0.0 1.0 2.0 3.0 4.0 + 4.0 3.0 2.0 1.0 0.0 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int flipip(double* x, int n) +\brief Функция отражения вещественного вектора `x` + +Функция производит отражение вещественного вектора длины `n` +в памяти данных. \n +Например исходный вектор `x` длины 6: \n +\verbatim +x = [0, 1, 2, 3, 4, 5] +\endverbatim +После отражения вектор `x` будет иметь вид: +\verbatim +x = [5, 4, 3, 2, 1, 0] +\endverbatim + +\param[in, out] x +Указатель на вещественный вектор `x`. \n +Размер вектора `[n x 1]`. \n +Результат отражения будет помещен по этому же адресу. \n + +\param[in] n +Размер вектора `x`. \n \n + +\return +`RES_OK` если функция выполнена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример: +\code{.cpp} +double x[5] = {0.0, 1.0, 2.0, 3.0, 4.0}; +int i; +for(i = 0; i < 5; i++) + printf("%6.1f ", x[i]); +flipip(x, 5); +printf("\n"); +for(i = 0; i < 5; i++) + printf("%6.1f ", x[i]); +\endcode +\n +Результат выполнения: +\verbatim + 0.0 1.0 2.0 3.0 4.0 + 4.0 3.0 2.0 1.0 0.0 +\endverbatim + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API flipip(double* x, int n) { - int k; - double tmp; - if(!x) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + int k; + double tmp; + if(!x) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + + for(k = 0; k < n/2; k++) + { + tmp = x[k]; + x[k] = x[n-1-k]; + x[n-1-k] = tmp; + } + return RES_OK; - for(k = 0; k < n/2; k++) - { - tmp = x[k]; - x[k] = x[n-1-k]; - x[n-1-k] = tmp; - } - return RES_OK; - } -/****************************************************************************** -Flip complex vector `x` in place --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int flipip_cmplx(complex_t* x, int n) +\brief Flip complex vector `x` in place + +Function flips complex vector `x` length `n` in the memory + \n +For example complex vector `x` length 6: \n +\verbatim +x = [0+0j, 1+1j, 2+2j, 3+3j, 4+4j, 5+5j] +\endverbatim +After flipping it will be as follow: +\verbatim +x = [5+5j, 4+4j, 3+3j, 2+2j, 1+1j, 0+0j] +\endverbatim + +\param[in, out] x +Pointer to the complex vector `x`. \n +Vector size is `[n x 1]`. \n +Flipped vector will be on the same address. \n + +\param[in] n +Length of the vector `x`. \n \n + +\return +`RES_OK` if function returns successfully. \n +Else \ref ERROR_CODE_GROUP "error code". + +Example: +\code{.cpp} +complex_t y[5] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}}; +for(i = 0; i < 5; i++) + printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); +flipip_cmplx(y, 5); +printf("\n"); +for(i = 0; i < 5; i++) + printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); +\endcode + \n +Program result: +\verbatim +0.0+0.0j 1.0+1.0j 2.0+2.0j 3.0+3.0j 4.0+4.0j +4.0+4.0j 3.0+3.0j 2.0+2.0j 1.0+1.0j 0.0+0.0j +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int flipip_cmplx(complex_t* x, int n) +\brief Функция отражения комплексного вектора `x` + +Функция производит отражение комплексного вектора длины `n` +в памяти данных. \n +Например исходный вектор `x` длины 6: \n +\verbatim +x = [0+0j, 1+1j, 2+2j, 3+3j, 4+4j, 5+5j] +\endverbatim +После отражения вектор `x` будет иметь вид: +\verbatim +x = [5+5j, 4+4j, 3+3j, 2+2j, 1+1j, 0+0j] +\endverbatim + +\param[in, out] x +Указатель на комплексный вектор `x`. \n +Размер вектора `[n x 1]`. \n +Результат отражения будет помещен по этому же адресу. \n +\n + +\param[in] n +Размер вектора `x`. \n +\n + +\return +`RES_OK` если функция выполнена успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример: +\code{.cpp} +complex_t y[5] = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}}; +for(i = 0; i < 5; i++) + printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); +flipip_cmplx(y, 5); +printf("\n"); +for(i = 0; i < 5; i++) + printf("%6.1f%+.1fj ", RE(y[i]), IM(y[i])); +\endcode + \n +Результат выполнения: +\verbatim +0.0+0.0j 1.0+1.0j 2.0+2.0j 3.0+3.0j 4.0+4.0j +4.0+4.0j 3.0+3.0j 2.0+2.0j 1.0+1.0j 0.0+0.0j +\endverbatim + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API flipip_cmplx(complex_t* x, int n) { - int k; - complex_t tmp; - if(!x) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + int k; + complex_t tmp; + if(!x) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; - for(k = 0; k < n/2; k++) - { - RE(tmp) = RE(x[k]); - RE(x[k]) = RE(x[n-1-k]); - RE(x[n-1-k]) = RE(tmp); + for(k = 0; k < n/2; k++) + { + RE(tmp) = RE(x[k]); + RE(x[k]) = RE(x[n-1-k]); + RE(x[n-1-k]) = RE(tmp); - IM(tmp) = IM(x[k]); - IM(x[k]) = IM(x[n-1-k]); - IM(x[n-1-k]) = IM(tmp); - } - return RES_OK; + IM(tmp) = IM(x[k]); + IM(x[k]) = IM(x[n-1-k]); + IM(x[n-1-k]) = IM(tmp); + } + return RES_OK; } @@ -203,186 +866,738 @@ int DSPL_API flipip_cmplx(complex_t* x, int n) -/******************************************************************************* -Linspace array filling --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int linspace(double x0, double x1, int n, int type, double* x) +\brief Function fills a vector with `n` linearly spaced elements +between `x0` and `x1`. + +Function supports two kinds of filling according to `type` parameter: \n + +Symmetric fill (parameter `type=DSPL_SYMMETRIC`): \n + +\f$x(k) = x_0 + k \cdot dx\f$, +\f$dx = \frac{x_1 - x_0}{n-1}\f$, \f$k = 0 \ldots n-1.\f$ + +Periodic fill (parameter `type=DSPL_PERIODIC`): \n + +\f$x(k) = x_0 + k \cdot dx\f$, +\f$dx = \frac{x_1 - x_0}{n}\f$, \f$k = 0 \ldots n-1.\f$ + +\param[in] x0 +Start point \f$x_0\f$. \n \n + +\param[in] x1 +End point \f$x_1\f$. \n \n + +\param[in] n +Number of points `x` (size of vector `x`). \n \n + +\param[in] type +Fill type: \n +`DSPL_SYMMETRIC` --- symmetric, \n +`DSPL_PERIODIC` --- periodic. \n \n + +\param[in,out] x +Pointer to the output linearly spaced vector `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function returns successfully. \n + Else \ref ERROR_CODE_GROUP "error code". + +\note +Difference between symmetric and periodic filling we can +understand from the follow examples. \n +Example 1. Periodic fill. + double x[5]; + linspace(0, 5, 5, DSPL_PERIODIC, x); +\endcode +Values in the vector `x` are: +\verbatim +0, 1, 2, 3, 4 +\endverbatim + \n \n +Example 2. Symmetric fill. +\code{.cpp} + double x[5]; + linspace(0, 5, 5, DSPL_SYMMETRIC, x); +\endcode +Values in the vector `x` are: +\verbatim +0, 1.25, 2.5, 3.75, 5 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int linspace(double x0, double x1, int n, int type, double* x) +\brief Функция заполняет массив линейно-нарастающими, равноотстоящими +значениями от `x0` до `x1` + +Заполняет массив `x` длиной `n` значениями в диапазоне +от \f$x_0\f$ до \f$x_1\f$. Функция поддерживает два типа заполнения +в соответствии с параметром `type`: \n + +Симметричное заполнение согласно выражению (параметр `type=DSPL_SYMMETRIC`): \n + +\f$x(k) = x_0 + k \cdot dx\f$, +\f$dx = \frac{x_1 - x_0}{n-1}\f$, \f$k = 0 \ldots n-1.\f$ + +Периодическое заполнение (параметр `type=DSPL_PERIODIC`) согласно выражению: \n + +\f$x(k) = x_0 + k \cdot dx\f$, +\f$dx = \frac{x_1 - x_0}{n}\f$, \f$k = 0 \ldots n-1.\f$ + +\param[in] x0 +Начальное показателя \f$x_0\f$. \n \n + +\param[in] x1 +Конечное значение \f$x_1\f$. \n \n + +\param[in] n +Количество точек массива `x`. \n \n + +\param[in] type +Тип заполнения: \n + +`DSPL_SYMMETRIC` --- симметричное заполнение, \n +`DSPL_PERIODIC` --- периодическое заполнение. \n \n + +\param[in,out] x +Указатель на вектор равноотстоящих значений . \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` --- функция выполнена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n + +\note +Отличие периодического и симметричного заполнения можно +понять из следующих примеров. \n +Пример 1. Периодическое заполнение. +\code{.cpp} + double x[5]; + linspace(0, 5, 5, DSPL_PERIODIC, x); +\endcode +В массиве `x` будут лежать значения: +\verbatim +0, 1, 2, 3, 4 +\endverbatim + \n \n +Пример 2. Симметричное заполнение. +\code{.cpp} + double x[5]; + linspace(0, 5, 5, DSPL_SYMMETRIC, x); +\endcode +В массиве `x` будут лежать значения: +\verbatim +0, 1.25, 2.5, 3.75, 5 +\endverbatim + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API linspace(double x0, double x1, int n, int type, double* x) { - double dx; - int k; + double dx; + int k; - if(n < 2) - return ERROR_SIZE; - if(!x) - return ERROR_PTR; + if(n < 2) + return ERROR_SIZE; + if(!x) + return ERROR_PTR; - switch (type) - { - case DSPL_SYMMETRIC: - dx = (x1 - x0)/(double)(n-1); - x[0] = x0; - for(k = 1; k < n; k++) - x[k] = x[k-1] + dx; - break; - case DSPL_PERIODIC: - dx = (x1 - x0)/(double)n; - x[0] = x0; - for(k = 1; k < n; k++) - x[k] = x[k-1] + dx; - break; - default: - return ERROR_SYM_TYPE; - } - return RES_OK; + switch (type) + { + case DSPL_SYMMETRIC: + dx = (x1 - x0)/(double)(n-1); + x[0] = x0; + for(k = 1; k < n; k++) + x[k] = x[k-1] + dx; + break; + case DSPL_PERIODIC: + dx = (x1 - x0)/(double)n; + x[0] = x0; + for(k = 1; k < n; k++) + x[k] = x[k-1] + dx; + break; + default: + return ERROR_SYM_TYPE; + } + return RES_OK; } -/******************************************************************************* -Logspace array filling --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int logspace(double x0, double x1, int n, int type, double* x) +\brief Function fills a vector with `n` logarithmically spaced elements +between \f$10^{x_0}\f$ and \f$10^{x_1}\f$. + + +Function supports two kinds of filling according to `type` parameter: \n + +Symmetric fill (parameter `type=DSPL_SYMMETRIC`): \n + +\f$x(k) = 10^{x_0} \cdot dx^k\f$, here \f$dx = \sqrt[n-1]{10^{x_1 - x_0}}\f$, +\f$k = 0 \ldots n-1.\f$ + +Periodic fill (parameter `type=DSPL_PERIODIC`): \n + +\f$x(k) = 10^{x_0} \cdot dx^k\f$, here \f$dx = \sqrt[n]{10^{x_1 - x_0}}\f$, +\f$k = 0 \ldots n-1.\f$ \n + + +\param[in] x0 +Start exponent value \f$x_0\f$. \n \n + +\param[in] x1 +End exponent value \f$x_1\f$. \n \n + +\param[in] n +Number of points `x` (size of vector `x`). \n \n + +\param[in] type +Fill type: \n +`DSPL_SYMMETRIC` --- symmetric, \n +`DSPL_PERIODIC` --- periodic. \n \n + +\param[in,out] x +Pointer to the output logarithmically spaced vector `x` . \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function returns successfully. \n + Else \ref ERROR_CODE_GROUP "error code". + +\note +Difference between symmetric and periodic filling we can +understand from the follow examples. \n +Example 1. Periodic fill. +\code{.cpp} + double x[5]; + logspace(-2, 3, 5, DSPL_PERIODIC, x); +\endcode + +Values in the vector `x` are: + +\verbatim +0.01, 0.1, 1, 10, 100 +\endverbatim + +\n \n + +Example 2. Symmetric fill. +\code{.cpp} + double x[5]; + logspace(-2, 3, 5, DSPL_SYMMETRIC, x); +\endcode + +Values in the vector `x` are: + +\verbatim +0.01 0.178 3.162 56.234 1000 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int logspace(double x0, double x1, int n, int type, double* x) +\brief Функция заполняет массив значениями логарифмической шкале + +Заполняет массив `x` длиной `n` значениями в диапазоне +от \f$10^{x_0}\f$ до \f$10^{x_1}\f$. \n +Функция поддерживает два типа заполнения в соответствии с параметром `type`: \n + +Симметричное заполнение согласно выражению: \n + +\f$x(k) = 10^{x_0} \cdot dx^k\f$, где \f$dx = \sqrt[n-1]{10^{x_1 - x_0}}\f$, +\f$k = 0 \ldots n-1.\f$ + +Периодическое заполнение согласно выражению: + +\f$x(k) = 10^{x_0} \cdot dx^k\f$, где \f$dx = \sqrt[n]{10^{x_1 - x_0}}\f$, +\f$k = 0 \ldots n-1.\f$ \n + +\param[in] x0 +Начальное значение показателя \f$x_0\f$. \n \n + +\param[in] x1 +Конечное значение показателя \f$x_1\f$. \n \n + +\param[in] n +Количество точек массива `x`. \n \n + +\param[in] type +Тип заполнения: \n +`DSPL_SYMMETRIC` --- симметричное заполнение, \n +`DSPL_PERIODIC` --- периодическое заполнение. \n \n + +\param[in,out] x +Указатель на вектор значений в логарифмической шкале. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` --- функция выполнена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\note +Отличие периодического и симметричного заполнения можно +понять из следующих примеров. \n + +Пример 1. Периодическое заполнение. +\code{.cpp} + double x[5]; + logspace(-2, 3, 5, DSPL_PERIODIC, x); +\endcode +В массиве `x` будут лежать значения: +\verbatim +0.01, 0.1, 1, 10, 100 +\endverbatim +\n \n + +Пример 2. Симметричное заполнение. +\code{.cpp} + double x[5]; + logspace(-2, 3, 5, DSPL_SYMMETRIC, x); +\endcode + +В массиве `x` будут лежать значения: + +\verbatim +0.01 0.178 3.162 56.234 1000 +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API logspace(double x0, double x1, int n, int type, double* x) { - double mx, a, b; - int k; + double mx, a, b; + int k; - if(n < 2) - return ERROR_SIZE; - if(!x) - return ERROR_PTR; + if(n < 2) + return ERROR_SIZE; + if(!x) + return ERROR_PTR; - a = pow(10.0, x0); - b = pow(10.0, x1); + a = pow(10.0, x0); + b = pow(10.0, x1); - switch (type) - { - case DSPL_SYMMETRIC: - mx = pow(b/a, 1.0/(double)(n-1)); - x[0] = a; - for(k = 1; k < n; k++) - x[k] = x[k-1] * mx; - break; - case DSPL_PERIODIC: - mx = pow(b/a, 1.0/(double)n); - x[0] = a; - for(k = 1; k < n; k++) - x[k] = x[k-1] * mx; - break; - default: - return ERROR_SYM_TYPE; - } - return RES_OK; + switch (type) + { + case DSPL_SYMMETRIC: + mx = pow(b/a, 1.0/(double)(n-1)); + x[0] = a; + for(k = 1; k < n; k++) + x[k] = x[k-1] * mx; + break; + case DSPL_PERIODIC: + mx = pow(b/a, 1.0/(double)n); + x[0] = a; + for(k = 1; k < n; k++) + x[k] = x[k-1] * mx; + break; + default: + return ERROR_SYM_TYPE; + } + return RES_OK; } -/******************************************************************************* -Ones double array --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int ones(double* x, int n) +\brief Function fills all real vector `x` by ones values. + +\param[in, out] x +Pointer to the vector `x`. \n +Vector size is `[n x 1]`. \n +All elements on this vector will be set to one. \n +\n + +\param[in] n +Size of vector `x`. \n +\n + +\return +`RES_OK` if function returns successfully. \n + Else \ref ERROR_CODE_GROUP "error code". + +Example: +\code{.cpp} +double y[5] = {0}; +int i; +ones(y, 5); +for(i = 0; i < 5; i++) + printf("%6.1f% ", y[i]); +\endcode + \n +Vector `y` values are: +\verbatim + 1.0 1.0 1.0 1.0 1.0 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int ones(double* x, int n) +\brief Функция заполнения вещественного массива единицами + +\param[in, out] x +Указатель на вещественный вектор `x`. \n +Размер вектора `[n x 1]`. \n +Значения данного вектора будут установлены в единицу. \n +\n + +\param[in] n +Размер вектора `x`. \n +\n + +\return +`RES_OK` если функция выполнена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример: +\code{.cpp} +double y[5] = {0}; +int i; +ones(y, 5); +for(i = 0; i < 5; i++) + printf("%6.1f% ", y[i]); +\endcode + \n +Результат выполнения: +\verbatim + 1.0 1.0 1.0 1.0 1.0 +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ones(double* x, int n) { - int i; - if(!x) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - for(i = 0; i < n; i++) - x[i] = 1.0; + int i; + if(!x) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + for(i = 0; i < n; i++) + x[i] = 1.0; return RES_OK; } -/****************************************************************************** -Real arrays verification --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ -int DSPL_API verif(double* x, double* y, size_t n, double eps, double* err) +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int verif(double* x, double* y, size_t n, double eps, double* err) +\brief Real arrays verification + +Function calculates a maximum relative error between two real arrays `x` +and `y` (both length equals `n`): + +\f[ +e = \max \left( \frac{|x(k) - y(k)| }{ |x(k)|} \right), +\quad if \quad |x(k)| > 0, +\f] +or +\f[ +e = \max(|x(k) - y(k)| ), ~\qquad if \quad~|x(k)| = 0, +\f] + +This function can be used for algorithms verification if vector `x` is user +algorithm result and vector `y` -- reference vector. + +\param[in] x +Pointer to the first vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] y +Pointer to the second vector `y`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of vectors `x` and `y`. \n \n + +\param[in] eps +Relative error threshold. \n +If error less than `eps`, then function returns +`DSPL_VERIF_SUCCESS`, else `DSPL_VERIF_FAILED`. \n \n + +\param[in, out] err +Pointer to the variable which keep +maximum relative error. \n +Pointer can be `NULL`, maximum error will not be returned +in this case. \n \n + +\return +`DSPL_VERIF_SUCCESS` if maximum relative error less than `eps`. \n +Otherwise `DSPL_VERIF_FAILED`. + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int verif(double* x, double* y, size_t n, double eps, double* err) +\brief Верификация вещественных массивов + +Функция производит расчет максимальной относительной ошибки между вещественными +векторами `x` и `y` равной длины `n`: + +\f[ +e = \max \left( \frac{|x(k) - y(k)| }{ |x(k)|} \right), \quad \quad |x(k)| > 0, +\f] +или +\f[ +e = \max(|x(k) - y(k)| ), \qquad \quad~|x(k)| = 0, +\f] +и возвращает `DSPL_VERIF_SUCCESS` если +разница \f$ e\f$ меньше `eps`. +В противном случае возвращает `DSPL_VERIF_FAILED`. \n +Данная функция используется для верификации работы алгоритмов если вектор `x` +результат работы алгоритма пользователя, а `y` -- результат работы этого же +алгоритма сторонней функцией. + +\param[in] x +Указатель на первый вектор `x`. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] y +Указатель на второй вектор `y`. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер векторов `x` и `y`. \n \n + +\param[in] eps +Допустимая относительная ошибка. \n +Если максимальная относительная ошибка меньше `eps`, то функция возвращает +`DSPL_VERIF_SUCCESS`, в противном случае `DSPL_VERIF_FAILED`. \n \n + +\param[in, out] err +Указатель на переменную максимальной относительной ошибки. \n +По данному адресу будет записано значение максимальной относительной ошибки. \n +Указатель может быть `NULL`, значение ошибки в этом случае +не возвращается. \n \n + +\return +`DSPL_VERIF_SUCCESS` если относительная ошибка меньше `eps`. \n + В противном случае `DSPL_VERIF_FAILED`. + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API verif(double* x, double* y, size_t n, double eps, double* err) { - double d, maxd; - size_t k; - int res; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(eps <= 0.0 ) - return ERROR_NEGATIVE; - - maxd = -100.0; - - for(k = 0; k < n; k++) - { - d = fabs(x[k] - y[k]); - if(fabs(x[k]) > 0.0) + double d, maxd; + size_t k; + int res; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(eps <= 0.0 ) + return ERROR_NEGATIVE; + + maxd = -100.0; + + for(k = 0; k < n; k++) { - d = d / fabs(x[k]); - if(d > maxd) - maxd = d; + d = fabs(x[k] - y[k]); + if(fabs(x[k]) > 0.0) + { + d = d / fabs(x[k]); + if(d > maxd) + maxd = d; + } } - } - if(err) - *err = maxd; - - if(maxd > eps) - res = DSPL_VERIF_FAILED; - else - res = DSPL_VERIF_SUCCESS; - - return res; + if(err) + *err = maxd; + + if(maxd > eps) + res = DSPL_VERIF_FAILED; + else + res = DSPL_VERIF_SUCCESS; + + return res; } -/****************************************************************************** +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int verif_cmplx(complex_t* x, complex_t* y, size_t n, + double eps, double* err) +\brief Complex arrays verification --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ -int DSPL_API verif_cmplx(complex_t* x, complex_t* y, size_t n, - double eps, double* err) + +Function calculates a maximum relative error between two complex arrays `x` +and `y` (both length equals `n`): + +\f[ +e = \max \left( \frac{|x(k) - y(k)| }{ |x(k)|} \right), +\quad if \quad |x(k)| > 0, +\f] +or +\f[ +e = \max(|x(k) - y(k)| ), ~\qquad if \quad~|x(k)| = 0, +\f] +Return `DSPL_VERIF_SUCCESS` if maximum relative error \f$ e\f$ less than `eps`. +Else returns `DSPL_VERIF_FAILED`. \n + +This function can be used for algorithms verification if vector `x` is user +algorithm result and vector `y` -- reference vector. + +\param[in] x +Pointer to the first vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] y +Pointer to the second vector `y`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of vectors `x` and `y`. \n \n + +\param[in] eps +Relative error threshold. \n +If error less than `eps`, then function returns +`DSPL_VERIF_SUCCESS`, else `DSPL_VERIF_FAILED`. \n \n + +\param[in, out] err +Pointer to the variable which keep +maximum relative error. \n +Pointer can be `NULL`, maximum error will not be returned +in this case. \n \n + +\return +`DSPL_VERIF_SUCCESS` if maximum relative error less than `eps`. \n +Otherwise `DSPL_VERIF_FAILED`. + +\author +Sergey Bakhurin +www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int verif_cmplx(complex_t* x, complex_t* y, size_t n, + double eps, double* err) +\brief Верификация комплексных массивов + +Функция производит расчет максимальной относительной ошибки между комплексными +векторами `x` и `y` равной длины `n`: + +\f[ +e = \max \left( \frac{|x(k) - y(k)|}{|x(k)|} \right), \quad \quad |x(k)| > 0, +\f] +или +\f[ +e = \max(|x(k) - y(k)| ), ~\qquad \quad~|x(k)| = 0, +\f] +и возвращает `DSPL_VERIF_SUCCESS` если +разница \f$ e\f$ меньше `eps`. +В противном случае возвращает `DSPL_VERIF_FAILED`. \n +Данная функция используется для верификации работы алгоритмов если вектор `x` +результат работы алгоритма пользователя, а `y` -- результат работы этого же +алгоритма сторонней функцией. + +\param[in] x +Указатель на первый вектор `x`. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] y +Указатель на второй вектор `y`. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер векторов `x` и `y`. \n \n + +\param[in] eps +Допустимая относительная ошибка. \n +Если максимальная относительная ошибка меньше `eps`, то функция возвращает +`DSPL_VERIF_SUCCESS`, в противном случае `DSPL_VERIF_FAILED`. \n \n + +\param[in, out] err +Указатель на переменную максимальной относительной ошибки. \n +По данному адресу будет записано значение максимальной относительной ошибки. \n +Указатель может быть `NULL`, значение ошибки в этом +случае не возвращается. \n \n + +\return +`DSPL_VERIF_SUCCESS` если функция выполнена успешно. \n + В противном случае `DSPL_VERIF_FAILED`. + +\author +Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API verif_cmplx(complex_t* x, complex_t* y, size_t n, + double eps, double* err) { - - complex_t d; - double mx, md, maxd; - size_t k; - int res; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(eps <= 0.0 ) - return ERROR_NEGATIVE; - - maxd = -100.0; - - for(k = 0; k < n; k++) - { - RE(d) = RE(x[k]) - RE(y[k]); - IM(d) = IM(x[k]) - IM(y[k]); - md = ABS(d); - mx = ABS(x[k]); - if(mx > 0.0) + + complex_t d; + double mx, md, maxd; + size_t k; + int res; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(eps <= 0.0 ) + return ERROR_NEGATIVE; + + maxd = -100.0; + + for(k = 0; k < n; k++) { - md = md / mx; - if(md > maxd) - maxd = md; + RE(d) = RE(x[k]) - RE(y[k]); + IM(d) = IM(x[k]) - IM(y[k]); + md = ABS(d); + mx = ABS(x[k]); + if(mx > 0.0) + { + md = md / mx; + if(md > maxd) + maxd = md; + } } - } - if(err) - *err = maxd; - - if(maxd > eps) - res = DSPL_VERIF_FAILED; - else - res = DSPL_VERIF_SUCCESS; - - return res; + if(err) + *err = maxd; + + if(maxd > eps) + res = DSPL_VERIF_FAILED; + else + res = DSPL_VERIF_SUCCESS; + + return res; } diff --git a/dspl/src/cheby.c b/dspl/src/cheby.c index 1b7d487..6a739bd 100644 --- a/dspl/src/cheby.c +++ b/dspl/src/cheby.c @@ -5,17 +5,17 @@ * This file is part of libdspl-2.0. * * is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by +* it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ #include @@ -24,103 +24,306 @@ #include "dspl.h" -/****************************************************************************** -Chebyshev polynomial of the first kind order `ord` --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int cheby_poly1(double* x, int n, int ord, double* y) +\brief Chebyshev polynomial of the first kind order `ord` + +Function calculates Chebyshev polynomial \f$ C_ord(x)\f$ of the first kind +order `ord` for the real vector `x` (length `n`) by recurrent equation: +\f[ +C_{ord}(x) = 2 x C_{ord-1}(x) - C_{ord-2}(x), +\f] +where \f$ C_0(x) = 1 \f$, \f$ C_1(x) = x\f$ + +\param[in] x +Pointer to the real argument vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of vectors `x` and `y`. \n \n + +\param[in] ord +Chebyshev polynomial order. \n \n + +\param[out] y +Pointer to the Chebyshev polynomial values, corresponds to the argument `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if Chebyshev polynomial is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: + +\include cheby_poly1_test.c + +Text files will be created in `dat` directory: \n + +\verbatim +cheby_poly1_ord1.txt +cheby_poly1_ord2.txt +cheby_poly1_ord3.txt +cheby_poly1_ord4.txt +\endverbatim + +GNUPLOT package will create Chebyshev polynomials plot from saved text-files: + +\image html cheby_poly1.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int cheby_poly1(double* x, int n, int ord, double* y) +\brief Многочлен Чебышева первого рода порядка `ord` + +Функция производит расчет многочлена Чебышева первого рода \f$ C_ord(x)\f$ для +вещественного вектора `x` длины `n`на основе рекуррентной формулы +\f[ +C_{ord}(x) = 2 x C_{ord-1}(x) - C_{ord-2}(x), +\f] +где \f$ C_0(x) = 1 \f$, \f$ C_1(x) = x\f$ + +\param[in] x +Указатель на вектор `x` аргумента полинома Чебышева первого рода. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер векторов `x` и `y`. \n \n + +\param[in] ord +Порядок полинома Чебышева первого рода. \n \n + +\param[out] y +Указатель на вектор значений полинома Чебышева, +соответствующих аргументу `x`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции: + +\include cheby_poly1_test.c + +В каталоге `dat` будут созданы текстовые файлы значений +полиномов порядка 1-4: \n + +\verbatim +cheby_poly1_ord1.txt +cheby_poly1_ord2.txt +cheby_poly1_ord3.txt +cheby_poly1_ord4.txt +\endverbatim + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html cheby_poly1.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API cheby_poly1(double* x, int n, int ord, double* y) { - int k, m; - double t[2]; + int k, m; + double t[2]; + + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(ord<0) + return ERROR_POLY_ORD; + if(ord==0) + { + for(k = 0; k < n; k++) + { + y[k] = 1.0; + } + return RES_OK; + } + + if(ord==1) + { + memcpy(y, x, n*sizeof(double)); + return RES_OK; + } - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(ord<0) - return ERROR_POLY_ORD; - if(ord==0) - { for(k = 0; k < n; k++) { - y[k] = 1.0; + m = 2; + t[1] = x[k]; + t[0] = 1.0; + while(m <= ord) + { + y[k] = 2.0 * x[k] *t[1] - t[0]; + t[0] = t[1]; + t[1] = y[k]; + m++; + } } return RES_OK; - } - - if(ord==1) - { - memcpy(y, x, n*sizeof(double)); - return RES_OK; - } - - for(k = 0; k < n; k++) - { - m = 2; - t[1] = x[k]; - t[0] = 1.0; - while(m <= ord) - { - y[k] = 2.0 * x[k] *t[1] - t[0]; - t[0] = t[1]; - t[1] = y[k]; - m++; - } - } - return RES_OK; } -/****************************************************************************** -Chebyshev polynomial of the second kind order `ord` --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int cheby_poly2(double* x, int n, int ord, double* y) +\brief Chebyshev polynomial of the second kind order `ord` + +Function calculates Chebyshev polynomial \f$ U_ord(x)\f$ of the first kind +order `ord` for the real vector `x` (length `n`) by recurrent equation: +\f[ +U_{ord}(x) = 2 x U_{ord-1}(x) - U_{ord-2}(x), +\f] +where \f$ U_0(x) = 1 \f$, \f$ U_1(x) = 2x\f$ + +\param[in] x +Pointer to the real argument vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of vectors `x` and `y`. \n \n + +\param[in] ord +Chebyshev polynomial order. \n \n + +\param[out] y +Pointer to the Chebyshev polynomial values, corresponds to the argument `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if Chebyshev polynomial is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: +\include cheby_poly2_test.c + +Text files will be created in `dat` directory: \n + +\verbatim +cheby_poly2_ord1.txt +cheby_poly2_ord2.txt +cheby_poly2_ord3.txt +cheby_poly2_ord4.txt +\endverbatim + +GNUPLOT package will create Chebyshev polynomials plot from saved text-files: + +\image html cheby_poly2.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int cheby_poly2(double* x, int n, int ord, double* y) +\brief Многочлен Чебышева второго рода порядка `ord` + +Функция производит расчет многочлена Чебышева второго рода \f$ U_{ord}(x)\f$ +для вещественного вектора `x` длины `n`на основе рекуррентной формулы +\f[ +U_{ord}(x) = 2 x U_{ord-1}(x) - U_{ord-2}(x), +\f] +где \f$ U_0(x) = 1 \f$, \f$ U_1(x) = 2x\f$ + +\param[in] x +Указатель на вектор `x` аргумента полинома Чебышева второго рода. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер векторов `x` и `y`. \n \n + +\param[in] ord +Порядок полинома Чебышева второго рода. \n \n + +\param[out] y +Указатель на вектор значений полинома Чебышева, +соответствующих аргументу `x`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции: + +\include cheby_poly2_test.c + +В каталоге `dat` будут созданы текстовые файлы значений +полиномов порядка 1-4: \n + +\verbatim +cheby_poly2_ord1.txt +cheby_poly2_ord2.txt +cheby_poly2_ord3.txt +cheby_poly2_ord4.txt +\endverbatim + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html cheby_poly2.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API cheby_poly2(double* x, int n, int ord, double* y) { - int k, m; - double t[2]; + int k, m; + double t[2]; + + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(ord<0) + return ERROR_POLY_ORD; + if(ord==0) + { + for(k = 0; k < n; k++) + { + y[k] = 1.0; + } + return RES_OK; + } + + if(ord==1) + { + for(k = 0; k < n; k++) + { + y[k] = 2.0*x[k]; + }; + return RES_OK; + } - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(ord<0) - return ERROR_POLY_ORD; - if(ord==0) - { for(k = 0; k < n; k++) { - y[k] = 1.0; + m = 2; + t[1] = 2.0*x[k]; + t[0] = 1.0; + while(m <= ord) + { + y[k] = 2.0 * x[k] *t[1] - t[0]; + t[0] = t[1]; + t[1] = y[k]; + m++; + } } return RES_OK; - } - - if(ord==1) - { - for(k = 0; k < n; k++) - { - y[k] = 2.0*x[k]; - }; - return RES_OK; - } - - for(k = 0; k < n; k++) - { - m = 2; - t[1] = 2.0*x[k]; - t[0] = 1.0; - while(m <= ord) - { - y[k] = 2.0 * x[k] *t[1] - t[0]; - t[0] = t[1]; - t[1] = y[k]; - m++; - } - } - return RES_OK; } diff --git a/dspl/src/complex.c b/dspl/src/complex.c index df2f916..4e83915 100644 --- a/dspl/src/complex.c +++ b/dspl/src/complex.c @@ -24,57 +24,239 @@ #include "dspl.h" +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup TYPES_GROUP +\fn int cmplx2re(complex_t* x, int n, double* re, double* im) +\brief Separate complex vector to the real and image vectors + +Function fills `re` and `im` vectors corresponds to real and image +parts of the input complex array `x`. \n -/****************************************************************************** -Separate complex vector to the real and image vectors --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +\param[in] x +Pointer to the real complex vector. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of the input complex vector `x` and real and image +vectors `re` and `im`. \n \n + +\param[out] re +Pointer to the real part vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[out] im +Pointer to the image part vector. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function converts complex vector successfully. \n +Else \ref ERROR_CODE_GROUP "code error". \n + +Example: \n +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + double re[3], im[3]; + + cmplx2re(x, 3, re, im); +\endcode + +Vectors `re` and `im` will contains: + +\verbatim +re[0] = 1.0; im[0] = 2.0; +re[1] = 3.0; im[1] = 4.0; +re[2] = 5.0; im[2] = 6.0; +\endverbatim + +\author Sergey Bakhurin. www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\fn int cmplx2re(complex_t* x, int n, double* re, double* im) +\brief Преобразование массива комплексных данных в два массива + вещественных данных, содержащих реальную и мнимую части + исходного массива + +Функция заполняет реальные массивы `re` и `im` соответствующими значениями +реальной и мнимой частей исходного комплексного массива `x`. \n + + +\param[in] x +Указатель на массив комплексных данных. \n +Размер массива `[n x 1]`. \n \n + +\param[in] n +Размер массивов входных и выходных данных. \n \n + +\param[out] re +Указатель на адрес массива реальной части данных. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[out] im +Указатель на адрес массива мнимой части данных. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если преобразование произведено успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n + +Например при выполнении следующего кода +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + double re[3], im[3]; + + cmplx2re(x, 3, re, im); +\endcode + +Элементам массивов `re` и `im` будут присвоены значения: + +\verbatim +re[0] = 1.0; im[0] = 2.0; +re[1] = 3.0; im[1] = 4.0; +re[2] = 5.0; im[2] = 6.0; +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API cmplx2re(complex_t* x, int n, double* re, double* im) { - int k; - if(!x) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + if(!x) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - if(re) - { - for(k = 0; k < n; k++) - re[k] = RE(x[k]); - } - if(im) - { - for(k = 0; k < n; k++) - im[k] = IM(x[k]); - } - return RES_OK; + if(re) + { + for(k = 0; k < n; k++) + re[k] = RE(x[k]); + } + if(im) + { + for(k = 0; k < n; k++) + im[k] = IM(x[k]); + } + return RES_OK; } +#ifdef DOXYGEN_ENGLISH +/*! ***************************************************************************** +\ingroup TYPES_GROUP +\fn int re2cmplx(double* x, int n, complex_t *y) +\brief Convert real array to the complex array. -/****************************************************************************** -Convert real array to the complex array. --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +Function copies the vector `x` to the real part of vector `y`. +Image part of the vector `y` sets as zero. \n +So complex vector contains data: \n +`y[i] = x[i] + j0, here i = 0,1,2 ... n-1` + +\param[in] x +Pointer to the real vector `x`. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of the real vector `x` and complex vector `y`. \n \n + +\param[out] y +Pointer to the complex vector `y`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if function returns successfully. \n +Else \ref ERROR_CODE_GROUP "code error": \n + +Example: +\code{.cpp} + double x[3] = {1.0, 2.0, 3.0}; + complex_t y[3]; + + re2cmplx(x, 3, y); +\endcode + +Vector `y` will keep: + +\verbatim + y[0] = 1+0j; + y[1] = 2+0j; + y[2] = 3+0j. +\endverbatim + +\author Sergey Bakhurin. www.dsplib.org +****************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\fn int re2cmplx(double* x, int n, complex_t *y) +\brief Преобразование массива вещественных данных в массив комплексных данных. + +Функция заполняет реальные части массива `y` данных соответсвующими значениями +исходного вещественного массива `x`. \n + + +\param[in] x +Указатель на массив вещественных данных. \n +Размер массива `[n x 1]`. \n \n + +\param[in] n +Размер массивов входных и выходных данных. \n \n + +\param[out] y +Указатель на адрес массива комплексных данных. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` если преобразование произведено успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n + +Например при выполнении следующего кода +\code{.cpp} + double x[3] = {1.0, 2.0, 3.0}; + complex_t y[3]; + + re2cmplx(x, 3, y); +\endcode + +Значениям `y` будут присвоены значения: + +\verbatim + y[0] = 1+0j; + y[1] = 2+0j; + y[2] = 3+0j. +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API re2cmplx(double* x, int n, complex_t* y) { - int k; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - { - RE(y[k]) = x[k]; - IM(y[k]) = 0.0; - } - return RES_OK; + for(k = 0; k < n; k++) + { + RE(y[k]) = x[k]; + IM(y[k]) = 0.0; + } + return RES_OK; } diff --git a/dspl/src/dft.c b/dspl/src/dft.c index 128d205..e5ef5ab 100644 --- a/dspl/src/dft.c +++ b/dspl/src/dft.c @@ -5,17 +5,17 @@ * This file is part of libdspl-2.0. * * is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by +* it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ @@ -25,117 +25,508 @@ -/****************************************************************************** -`n`-points discrete Fourier transform of the real vector `x`. --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int dft(double* x, int n, complex_t* y) +\brief Discrete Fourier transform of a real signal. + +The function calculates the \f$ n \f$ -point discrete Fourier transform +real signal \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y (k) = \sum_ {m = 0} ^ {n-1} x (m) + \exp \left (-j \frac {2 \pi} {n} m k \right), +\f] +where \f$ k = 0 \ldots n-1 \f$. + +\param [in] x +Pointer to the vector of the real input signal \f$ x (m) \f$, +\f$ m = 0 \ldots n-1 \f$. \n +The size of the vector is `[n x 1]`. \n \n + +\param [in] n +The size of the DFT \f$ n \f$ +(the size of the vectors of the input signal and the result of the DFT). \n \n + +\param [out] y +Pointer to the complex vector of the DFT result \f$ Y (k) \f$, +\f$ k = 0 \ldots n-1 \f$. +The size of the vector is `[n x 1]`. \n +Memory must be allocated. \n \n + + +\return +`RES_OK` if the DFT is calculated successfully. \n +Otherwise, \ref ERROR_CODE_GROUP "error code". + +An example of using the `dft` function: + +\include dft_test.c + +The result of the program: + +\verbatim +y [0] = 120.000 0.000 +y [1] = -8.000 40.219 +y [2] = -8.000 19.314 +y [3] = -8.000 11.973 +y [4] = -8.000 8.000 +y [5] = -8.000 5.345 +y [6] = -8.000 3.314 +y [7] = -8.000 1.591 +y [8] = -8.000 0.000 +y [9] = -8.000 -1.591 +y [10] = -8.000 -3.314 +y [11] = -8.000 -5.345 +y [12] = -8.000 -8.000 +y [13] = -8.000 -11.973 +y [14] = -8.000 -19.314 +y [15] = -8.000 -40.219 +\endverbatim + +\note +This function performs the DFT calculation using the naive method and +requires \f$ n ^ 2 \f$ complex multiplications. \n +To increase the calculation speed, it is recommended to use +fast Fourier transform algorithms. + +\author Bakhurin Sergey www.dsplib.org +**************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int dft(double* x, int n, complex_t* y) +\brief Дискретное преобразование Фурье вещественного сигнала. + +Функция рассчитывает \f$ n \f$-точечное дискретное преобразование Фурье +вещественного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \sum_{m = 0}^{n-1} x(m) + \exp \left( -j \frac{2\pi}{n} m k \right), +\f] +где \f$ k = 0 \ldots n-1 \f$. + +\param[in] x +Указатель на вектор вещественного входного сигнала \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер ДПФ \f$n\f$ (размер векторов входного сигнала и результата ДПФ). \n \n + +\param[out] y +Указатель на комплексный вектор результата ДПФ \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` если ДПФ рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример использования функции `dft`: + +\include dft_test.c + +Результат работы программы: + +\verbatim +y[ 0] = 120.000 0.000 +y[ 1] = -8.000 40.219 +y[ 2] = -8.000 19.314 +y[ 3] = -8.000 11.973 +y[ 4] = -8.000 8.000 +y[ 5] = -8.000 5.345 +y[ 6] = -8.000 3.314 +y[ 7] = -8.000 1.591 +y[ 8] = -8.000 0.000 +y[ 9] = -8.000 -1.591 +y[10] = -8.000 -3.314 +y[11] = -8.000 -5.345 +y[12] = -8.000 -8.000 +y[13] = -8.000 -11.973 +y[14] = -8.000 -19.314 +y[15] = -8.000 -40.219 +\endverbatim + +\note +Данная функция выполняет расчет ДПФ наивным методом и требует \f$ n^2 \f$ +комплексных умножений. \n +Для увеличения скорости расчета рекомендуется использовать +алгоритмы быстрого преобразования Фурье. + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API dft(double* x, int n, complex_t* y) { - int k; - int m; - double divn; - double phi; + int k; + int m; + double divn; + double phi; - if(!x || !y) - return ERROR_PTR; + if(!x || !y) + return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(n<1) + return ERROR_SIZE; - divn = 1.0 / (double)n; + divn = 1.0 / (double)n; - for(k = 0; k < n; k++) - { - RE(y[k]) = IM(y[k]) = 0.0; - for(m = 0; m < n; m++) + for(k = 0; k < n; k++) { - phi = -M_2PI * divn * (double)k * (double)m; - RE(y[k]) += x[m] * cos(phi); - IM(y[k]) += x[m] * sin(phi); + RE(y[k]) = IM(y[k]) = 0.0; + for(m = 0; m < n; m++) + { + phi = -M_2PI * divn * (double)k * (double)m; + RE(y[k]) += x[m] * cos(phi); + IM(y[k]) += x[m] * sin(phi); + } } - } - return RES_OK; + return RES_OK; } -/****************************************************************************** -`n`-points discrete Fourier transform of the complex vector `x`. --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int dft_cmplx(complex_t* x, int n, complex_t* y) +\brief Discrete Fourier transform of a complex signal. + +The function calculates the \f$ n \f$ -point discrete Fourier transform +complex signal \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y (k) = \sum_ {m = 0} ^ {n-1} x (m) + \exp \left (-j \frac {2 \pi} {n} m k \right), +\f] +where \f$ k = 0 \ldots n-1 \f$. + +\param [in] x +Pointer to a vector of complex +input signal \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +The size of the vector is `[n x 1]`. \n \n + +\param [in] n +The size of the DFT \f$ n \f$ +(the size of the vectors of the input signal and the result of the DFT). \n \n + +\param [out] y +Integrated Vector Pointer +DFT result \f$ Y (k) \f$, \f$ k = 0 \ldots n-1 \f$. \n +The size of the vector is `[n x 1]`. \n +Memory must be allocated. \n \n + + +\return +`RES_OK` if the DFT is calculated successfully. \n +Otherwise, \ref ERROR_CODE_GROUP "error code". + +An example of using the `dft_cmplx` function: + +\include dft_cmplx_test.c + +The result of the program: + +\verbatim +y [0] = 120.000 0.000 +y [1] = -8.000 40.219 +y [2] = -8.000 19.314 +y [3] = -8.000 11.973 +y [4] = -8.000 8.000 +y [5] = -8.000 5.345 +y [6] = -8.000 3.314 +y [7] = -8.000 1.591 +y [8] = -8.000 0.000 +y [9] = -8.000 -1.591 +y [10] = -8.000 -3.314 +y [11] = -8.000 -5.345 +y [12] = -8.000 -8.000 +y [13] = -8.000 -11.973 +y [14] = -8.000 -19.314 +y [15] = -8.000 -40.219 +\endverbatim + +\note +This function performs the calculation of the DFT by the naive method +and requires \f$ n ^ 2 \f$ complex multiplications. \n +To increase the calculation speed, it is recommended +use fast Fourier transform algorithms. + +\author Bakhurin Sergey www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int dft_cmplx(complex_t* x, int n, complex_t* y) +\brief Дискретное преобразование Фурье комплексного сигнала. + +Функция рассчитывает \f$ n \f$-точечное дискретное преобразование Фурье +комплексного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \sum_{m = 0}^{n-1} x(m) + \exp \left( -j \frac{2\pi}{n} m k \right), +\f] +где \f$ k = 0 \ldots n-1 \f$. + +\param[in] x +Указатель на вектор комплексного +входного сигнала \f$x(m)\f$, \f$ m = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер ДПФ \f$n\f$ (размер векторов входного сигнала и результата ДПФ). \n \n + +\param[out] y +Указатель на комплексный вектор +результата ДПФ \f$Y(k)\f$, \f$ k = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` если ДПФ рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример использования функции `dft_cmplx`: + +\include dft_cmplx_test.c + +Результат работы программы: + +\verbatim +y[ 0] = 120.000 0.000 +y[ 1] = -8.000 40.219 +y[ 2] = -8.000 19.314 +y[ 3] = -8.000 11.973 +y[ 4] = -8.000 8.000 +y[ 5] = -8.000 5.345 +y[ 6] = -8.000 3.314 +y[ 7] = -8.000 1.591 +y[ 8] = -8.000 0.000 +y[ 9] = -8.000 -1.591 +y[10] = -8.000 -3.314 +y[11] = -8.000 -5.345 +y[12] = -8.000 -8.000 +y[13] = -8.000 -11.973 +y[14] = -8.000 -19.314 +y[15] = -8.000 -40.219 +\endverbatim + +\note +Данная функция выполняет расчет ДПФ наивным методом +и требует \f$ n^2 \f$ комплексных умножений. \n +Для увеличения скорости расчета рекомендуется +использовать алгоритмы быстрого преобразования Фурье. + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API dft_cmplx(complex_t* x, int n, complex_t* y) { - int k; - int m; - double divn; - double phi; - complex_t e; + int k; + int m; + double divn; + double phi; + complex_t e; - if(!x || !y) - return ERROR_PTR; + if(!x || !y) + return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(n<1) + return ERROR_SIZE; - divn = 1.0 / (double)n; + divn = 1.0 / (double)n; - for(k = 0; k < n; k++) - { - RE(y[k]) = IM(y[k]) = 0.0; - for(m = 0; m < n; m++) + for(k = 0; k < n; k++) { - phi = -M_2PI * divn * (double)k * (double)m; - RE(e) = cos(phi); - IM(e) = sin(phi); - RE(y[k]) += CMRE(x[m], e); - IM(y[k]) += CMIM(x[m], e); + RE(y[k]) = IM(y[k]) = 0.0; + for(m = 0; m < n; m++) + { + phi = -M_2PI * divn * (double)k * (double)m; + RE(e) = cos(phi); + IM(e) = sin(phi); + RE(y[k]) += CMRE(x[m], e); + IM(y[k]) += CMIM(x[m], e); + } } - } - return RES_OK; + return RES_OK; } -/****************************************************************************** -`n`-points inverse discrete Fourier transform of the complex vector `x`. --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int idft_cmplx(complex_t* x, int n, complex_t* y) +\brief Inverse discrete Fourier transform of the complex spectrum. + +The function calculates the \f$ n \f$ -point inverse discrete transform +Fourier complex spectrum \f$ x (m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + y (k) = \sum_ {m = 0} ^ {n-1} x (m) + \exp \left (j \frac {2 \pi} {n} m k \right), +\f] +where \f$ k = 0 \ldots n-1 \f$. + +\param [in] x +Pointer to the vector of the input complex signal spectrum \f$ x (m) \f$, +\f$ m = 0 \ldots n-1 \f$. \n +The size of the vector is `[n x 1]`. \n \n + +\param [in] n +The size of the ODPF \f$ n \f$ +(the size of the vectors of the input spectrum and the result of the ODPF). \n +\n + +\param [out] y +Pointer to the complex vector of the ODPF result \f$ y (k) \f$, +\f$ k = 0 \ldots n-1 \f$. +The size of the vector is `[n x 1]`. \n +Memory must be allocated. \n \n + + +\return +`RES_OK` if the ODPF is calculated successfully. \n +Otherwise, \ref ERROR_CODE_GROUP "error code". + +An example of using the `dft_cmplx` function: + +\include idft_cmplx_test.c + +The result of the program: + +\verbatim +x [0] = 0.000 + 0.000j, z [0] = 0.000 -0.000 +x [1] = 1.000 + 0.000j, z [1] = 1.000 -0.000 +x [2] = 2.000 + 0.000j, z [2] = 2.000 -0.000 +x [3] = 3.000 + 0.000j, z [3] = 3.000 -0.000 +x [4] = 4.000 + 0.000j, z [4] = 4.000 -0.000 +x [5] = 5.000 + 0.000j, z [5] = 5.000 -0.000 +x [6] = 6.000 + 0.000j, z [6] = 6.000 -0.000 +x [7] = 7.000 + 0.000j, z [7] = 7.000 -0.000 +x [8] = 8.000 + 0.000j, z [8] = 8.000 -0.000 +x [9] = 9.000 + 0.000j, z [9] = 9.000 -0.000 +x [10] = 10.000 + 0.000j, z [10] = 10.000 -0.000 +x [11] = 11.000 + 0.000j, z [11] = 11.000 +0.000 +x [12] = 12.000 + 0.000j, z [12] = 12.000 +0.000 +x [13] = 13.000 + 0.000j, z [13] = 13.000 +0.000 +x [14] = 14.000 + 0.000j, z [14] = 14.000 +0.000 +x [15] = 15.000 + 0.000j, z [15] = 15.000 -0.000 +\endverbatim + +\note +This function performs the calculation of the DFT using the naive method. +and requires \f$ n ^ 2 \f$ complex multiplications. \n +To increase the calculation speed, it is recommended +use fast Fourier transform algorithms. + +\author Bakhurin Sergey www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int idft_cmplx(complex_t* x, int n, complex_t* y) +\brief Обратное дискретное преобразование Фурье комплексного спектра. + +Функция рассчитывает \f$ n \f$-точечное обратное дискретное преобразование +Фурье комплексного спектра \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + y(k) = \sum_{m = 0}^{n-1} x(m) + \exp \left( j \frac{2\pi}{n} m k \right), +\f] +где \f$ k = 0 \ldots n-1 \f$. + +\param[in] x +Указатель на вектор входного комплексного спектра сигнала \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер ОДПФ \f$n\f$ (размер векторов входного спектра и результата ОДПФ). \n \n + +\param[out] y +Указатель на комплексный вектор результата ОДПФ \f$y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` если ОДПФ рассчитана успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример использования функции `dft_cmplx`: + +\include idft_cmplx_test.c + +Результат работы программы: + +\verbatim +x[ 0] = 0.000 +0.000j, z[ 0] = 0.000 -0.000 +x[ 1] = 1.000 +0.000j, z[ 1] = 1.000 -0.000 +x[ 2] = 2.000 +0.000j, z[ 2] = 2.000 -0.000 +x[ 3] = 3.000 +0.000j, z[ 3] = 3.000 -0.000 +x[ 4] = 4.000 +0.000j, z[ 4] = 4.000 -0.000 +x[ 5] = 5.000 +0.000j, z[ 5] = 5.000 -0.000 +x[ 6] = 6.000 +0.000j, z[ 6] = 6.000 -0.000 +x[ 7] = 7.000 +0.000j, z[ 7] = 7.000 -0.000 +x[ 8] = 8.000 +0.000j, z[ 8] = 8.000 -0.000 +x[ 9] = 9.000 +0.000j, z[ 9] = 9.000 -0.000 +x[10] = 10.000 +0.000j, z[10] = 10.000 -0.000 +x[11] = 11.000 +0.000j, z[11] = 11.000 +0.000 +x[12] = 12.000 +0.000j, z[12] = 12.000 +0.000 +x[13] = 13.000 +0.000j, z[13] = 13.000 +0.000 +x[14] = 14.000 +0.000j, z[14] = 14.000 +0.000 +x[15] = 15.000 +0.000j, z[15] = 15.000 -0.000 +\endverbatim + +\note +Данная функция выполняет расчет ОДПФ наивным методом +и требует \f$ n^2 \f$ комплексных умножений. \n +Для увеличения скорости расчета рекомендуется +использовать алгоритмы быстрого преобразования Фурье. + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API idft_cmplx(complex_t* x, int n, complex_t* y) { - int k; - int m; - double divn; - double phi; - complex_t e; + int k; + int m; + double divn; + double phi; + complex_t e; - if(!x || !y) - return ERROR_PTR; + if(!x || !y) + return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(n<1) + return ERROR_SIZE; - divn = 1.0 / (double)n; + divn = 1.0 / (double)n; - for(k = 0; k < n; k++) - { - RE(y[k]) = IM(y[k]) = 0.0; - for(m = 0; m < n; m++) + for(k = 0; k < n; k++) { - phi = M_2PI * divn * (double)k * (double)m; - RE(e) = cos(phi); - IM(e) = sin(phi); - RE(y[k]) += CMRE(x[m], e); - IM(y[k]) += CMIM(x[m], e); + RE(y[k]) = IM(y[k]) = 0.0; + for(m = 0; m < n; m++) + { + phi = M_2PI * divn * (double)k * (double)m; + RE(e) = cos(phi); + IM(e) = sin(phi); + RE(y[k]) += CMRE(x[m], e); + IM(y[k]) += CMIM(x[m], e); + } + RE(y[k]) /= (double)n; + IM(y[k]) /= (double)n; } - RE(y[k]) /= (double)n; - IM(y[k]) /= (double)n; - } - return RES_OK; + return RES_OK; } diff --git a/dspl/src/ellipj.c b/dspl/src/ellipj.c index e6ff0b2..7c0877b 100644 --- a/dspl/src/ellipj.c +++ b/dspl/src/ellipj.c @@ -11,11 +11,11 @@ * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ @@ -27,39 +27,106 @@ -/***************************************************************************** -Inverse Jacobi elliptic function cd^-1(w, k) for the real argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd(double* w, int n, double k, double* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ +of the real vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$ of the real vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd(double* w, int n, double k, double* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{cd}^{-1}(w, k)\f$ вещественного аргумента + +Функция рассчитывает значения обратной эллиптической функции +\f$ u = \textrm{cd}^{-1}(w, k)\f$ для вещественного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n + +\param[in] k Значение эллиптического модуля \f$ k \f$. +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_acd(double* w, int n, double k, double* u) { - double lnd[ELLIP_ITER], t; - int i, m; + double lnd[ELLIP_ITER], t; + int i, m; - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - u[m] = w[m]; - for(i = 1; i < ELLIP_ITER; i++) + for(m = 0; m < n; m++) { - t = lnd[i-1]*u[m]; - t *= t; - t = 1.0 + sqrt(1.0 - t); - u[m] = 2.0 * u[m] / (t+t*lnd[i]); + u[m] = w[m]; + for(i = 1; i < ELLIP_ITER; i++) + { + t = lnd[i-1]*u[m]; + t *= t; + t = 1.0 + sqrt(1.0 - t); + u[m] = 2.0 * u[m] / (t+t*lnd[i]); + } + u[m] = 2.0 * acos(u[m]) / M_PI; } - u[m] = 2.0 * acos(u[m]) / M_PI; - } - return RES_OK; + return RES_OK; } @@ -67,191 +134,469 @@ int DSPL_API ellip_acd(double* w, int n, double k, double* u) -/***************************************************************************** -Inverse Jacobi elliptic function cd^-1(w, k) for the complex argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{cd}^{-1}(w, k)\f$ +of complex vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$ of complex vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{cd}^{-1}(w, k)\f$ комплексного аргумента + +Функция рассчитывает значения значения обратной эллиптической функции +\f$ u = \textrm{cd}^{-1}(w, k)\f$ для комплексного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{cd}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_acd_cmplx(complex_t* w, int n, double k, complex_t* u) { - double lnd[ELLIP_ITER], t; - complex_t tmp0, tmp1; - int i, m; + double lnd[ELLIP_ITER], t; + complex_t tmp0, tmp1; + int i, m; - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - RE(u[m]) = RE(w[m]); - IM(u[m]) = IM(w[m]); - for(i = 1; i < ELLIP_ITER; i++) + for(m = 0; m < n; m++) { - RE(tmp0) = lnd[i-1]*RE(u[m]); - IM(tmp0) = lnd[i-1]*IM(u[m]); - RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); - IM(tmp1) = - CMIM(tmp0, tmp0); + RE(u[m]) = RE(w[m]); + IM(u[m]) = IM(w[m]); + for(i = 1; i < ELLIP_ITER; i++) + { + RE(tmp0) = lnd[i-1]*RE(u[m]); + IM(tmp0) = lnd[i-1]*IM(u[m]); + RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); + IM(tmp1) = - CMIM(tmp0, tmp0); - sqrt_cmplx(&tmp1, 1, &tmp0); - RE(tmp0) += 1.0; + sqrt_cmplx(&tmp1, 1, &tmp0); + RE(tmp0) += 1.0; - RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); - IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); + RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); + IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); - t = 2.0 / ABSSQR(tmp1); + t = 2.0 / ABSSQR(tmp1); - RE(tmp0) = t * CMCONJRE(u[m], tmp1); - IM(tmp0) = t * CMCONJIM(u[m], tmp1); - - RE(u[m]) = RE(tmp0); - IM(u[m]) = IM(tmp0); + RE(tmp0) = t * CMCONJRE(u[m], tmp1); + IM(tmp0) = t * CMCONJIM(u[m], tmp1); + RE(u[m]) = RE(tmp0); + IM(u[m]) = IM(tmp0); + } + acos_cmplx(&tmp0, 1, u+m); + t = 2.0 / M_PI; + RE(u[m]) *= t; + IM(u[m]) *= t; } - acos_cmplx(&tmp0, 1, u+m); - t = 2.0 / M_PI; - RE(u[m]) *= t; - IM(u[m]) *= t; - } - return RES_OK; + return RES_OK; } -/***************************************************************************** -Inverse Jacobi elliptic function sn^-1(w, k) for the real argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn(double* w, int n, double k, double* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ +of real vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$ of real vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn(double* w, int n, double k, double* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{sn}^{-1}(w, k)\f$ вещественного аргумента + +Функция рассчитывает значения значения обратной эллиптической функции +\f$ u = \textrm{sn}^{-1}(w, k)\f$ для вещественного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_asn(double* w, int n, double k, double* u) { - double lnd[ELLIP_ITER], t; - int i, m; + double lnd[ELLIP_ITER], t; + int i, m; - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - u[m] = w[m]; - for(i = 1; i < ELLIP_ITER; i++) + for(m = 0; m < n; m++) { - t = lnd[i-1]*u[m]; - t *= t; - t = 1.0 + sqrt(1.0 - t); - u[m] = 2.0 * u[m] / (t+t*lnd[i]); + u[m] = w[m]; + for(i = 1; i < ELLIP_ITER; i++) + { + t = lnd[i-1]*u[m]; + t *= t; + t = 1.0 + sqrt(1.0 - t); + u[m] = 2.0 * u[m] / (t+t*lnd[i]); + } + u[m] = 2.0 * asin(u[m]) / M_PI; } - u[m] = 2.0 * asin(u[m]) / M_PI; - } - return RES_OK; + return RES_OK; } -/***************************************************************************** -Inverse Jacobi elliptic function sn^-1(w, k) for the complex argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Inverse Jacobi elliptic function \f$ u = \textrm{sn}^{-1}(w, k)\f$ +of complex vector argument + +Function calculates inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$ of complex vector `w`. \n + +\param[in] w +Pointer to the argument vector \f$ w \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `w`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] u +Pointer to the vector of inverse Jacobi elliptic function +\f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) +\brief Обратная эллиптическая функция Якоби + \f$ u = \textrm{sn}^{-1}(w, k)\f$ комплексного аргумента + +Функция рассчитывает значения значения обратной эллиптической функции +\f$ u = \textrm{sn}^{-1}(w, k)\f$ для комплексного вектора `w`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + + +\param[in] w +Указатель на массив вектора переменной \f$ w \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `w`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] u +Указатель на вектор значений обратной эллиптической +функции \f$ u = \textrm{sn}^{-1}(w, k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK`Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_asn_cmplx(complex_t* w, int n, double k, complex_t* u) { - double lnd[ELLIP_ITER], t; - complex_t tmp0, tmp1; - int i, m; + double lnd[ELLIP_ITER], t; + complex_t tmp0, tmp1; + int i, m; - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - RE(u[m]) = RE(w[m]); - IM(u[m]) = IM(w[m]); - for(i = 1; i < ELLIP_ITER; i++) + for(m = 0; m < n; m++) { - RE(tmp0) = lnd[i-1]*RE(u[m]); - IM(tmp0) = lnd[i-1]*IM(u[m]); - RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); - IM(tmp1) = - CMIM(tmp0, tmp0); + RE(u[m]) = RE(w[m]); + IM(u[m]) = IM(w[m]); + for(i = 1; i < ELLIP_ITER; i++) + { + RE(tmp0) = lnd[i-1]*RE(u[m]); + IM(tmp0) = lnd[i-1]*IM(u[m]); + RE(tmp1) = 1.0 - CMRE(tmp0, tmp0); + IM(tmp1) = - CMIM(tmp0, tmp0); - sqrt_cmplx(&tmp1, 1, &tmp0); - RE(tmp0) += 1.0; + sqrt_cmplx(&tmp1, 1, &tmp0); + RE(tmp0) += 1.0; - RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); - IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); + RE(tmp1) = RE(tmp0) * (1.0 + lnd[i]); + IM(tmp1) = IM(tmp0) * (1.0 + lnd[i]); - t = 2.0 / ABSSQR(tmp1); + t = 2.0 / ABSSQR(tmp1); - RE(tmp0) = t * CMCONJRE(u[m], tmp1); - IM(tmp0) = t * CMCONJIM(u[m], tmp1); - - RE(u[m]) = RE(tmp0); - IM(u[m]) = IM(tmp0); + RE(tmp0) = t * CMCONJRE(u[m], tmp1); + IM(tmp0) = t * CMCONJIM(u[m], tmp1); + RE(u[m]) = RE(tmp0); + IM(u[m]) = IM(tmp0); + } + + asin_cmplx(&tmp0, 1, u+m); + t = 2.0 / M_PI; + RE(u[m]) *= t; + IM(u[m]) *= t; } - asin_cmplx(&tmp0, 1, u+m); - t = 2.0 / M_PI; - RE(u[m]) *= t; - IM(u[m]) *= t; - } - return RES_OK; + return RES_OK; } -/***************************************************************************** -Jacobi elliptic function cd(u*K(k), k) for the real argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd(double* u, int n, double k, double* y) +\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ +of real vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$ of real vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd(double* u, int n, double k, double* y) +\brief Эллиптическая функция Якоби +\f$ y = \textrm{cd}(u K(k), k)\f$ вещественного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{cd}(u K(k), k)\f$ для вещественного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_cd(double* u, int n, double k, double* y) { - double lnd[ELLIP_ITER]; - int i, m; + double lnd[ELLIP_ITER]; + int i, m; - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - y[m] = cos(u[m] * M_PI * 0.5); - for(i = ELLIP_ITER-1; i>0; i--) + for(m = 0; m < n; m++) { - y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); + y[m] = cos(u[m] * M_PI * 0.5); + for(i = ELLIP_ITER-1; i>0; i--) + { + y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); + } } - } - return RES_OK; + return RES_OK; } @@ -260,49 +605,118 @@ int DSPL_API ellip_cd(double* u, int n, double k, double* y) -/***************************************************************************** -Jacobi elliptic function cd(u*K(k), k) for the complex argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Jacobi elliptic function \f$ y = \textrm{cd}(u K(k), k)\f$ +of complex vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$ of complex vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{cd}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Эллиптическая функция Якоби + \f$ y = \textrm{cd}(u K(k), k)\f$ комплексного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{cd}(u K(k), k)\f$ для комплексного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{cd}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) { - double lnd[ELLIP_ITER], t; - int i, m; - complex_t tmp; + double lnd[ELLIP_ITER], t; + int i, m; + complex_t tmp; - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - - for(m = 0; m < n; m++) - { - RE(tmp) = RE(u[m]) * M_PI * 0.5; - IM(tmp) = IM(u[m]) * M_PI * 0.5; - - cos_cmplx(&tmp, 1, y+m); - - for(i = ELLIP_ITER-1; i>0; i--) + for(m = 0; m < n; m++) { - t = 1.0 / ABSSQR(y[m]); + RE(tmp) = RE(u[m]) * M_PI * 0.5; + IM(tmp) = IM(u[m]) * M_PI * 0.5; - RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; - IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; + cos_cmplx(&tmp, 1, y+m); - t = (1.0 + lnd[i]) / ABSSQR(tmp); + for(i = ELLIP_ITER-1; i>0; i--) + { + t = 1.0 / ABSSQR(y[m]); - RE(y[m]) = RE(tmp) * t; - IM(y[m]) = -IM(tmp) * t; + RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; + IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; + t = (1.0 + lnd[i]) / ABSSQR(tmp); + + RE(y[m]) = RE(tmp) * t; + IM(y[m]) = -IM(tmp) * t; + } } - } - return RES_OK; + return RES_OK; } @@ -310,130 +724,270 @@ int DSPL_API ellip_cd_cmplx(complex_t* u, int n, double k, complex_t* y) -/***************************************************************************** - Function calculates complete elliptical integral coefficients \f$ k_i \f$ - by Landen transform --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_landen(double k, int n, double* y) +\brief Function calculates complete elliptical integral +coefficients \f$ k_i \f$ + +Complete elliptical integral \f$ K(k) \f$ can be described as: + +\f[ + K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), +\f] + +here \f$ k_i \f$ -- coefficients which calculated +iterative from \f$ k_0 = k\f$: + +\f[ + k_i = \left( \frac{k_{i-1}}{1+\sqrt{1-k_{i-1}^2}}\right)^2 +\f] + +This function calculates `n` fist coefficients \f$ k_i \f$, which can +be used for Complete elliptical integral. + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, which values can be from 0 to 1. \n \n + +\param[in] n +Number of \f$ k_i \f$ which need to calculate. \n +Parameter `n` is size of output vector `y`. \n + +\param[out] y +pointer to the real vector which keep \f$ k_i \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return + `RES_OK` -- successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +Example: + +\include ellip_landen_test.c + +Result: + +\verbatim + i k[i] + + 1 4.625e-01 + 2 6.009e-02 + 3 9.042e-04 + 4 2.044e-07 + 5 1.044e-14 + 6 2.727e-29 + 7 1.859e-58 + 8 8.640e-117 + 9 1.866e-233 +10 0.000e+00 +11 0.000e+00 +12 0.000e+00 +13 0.000e+00 +\endverbatim + +\note Complete elliptical integral converges enough fast + if modulus \f$ k<1 \f$. There are 10 to 20 coefficients \f$ k_i \f$ ​​ + are sufficient for practical applications + to ensure complete elliptic integral precision within EPS. + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_landen(double k, int n, double* y) +\brief Расчет коэффициентов \f$ k_i \f$ ряда полного эллиптического интеграла. + +Полный эллиптический интеграл \f$ K(k) \f$ может быть представлен рядом: + +\f[ +K(k) = \frac{\pi}{2} \prod_{i = 1}^{\infty}(1+k_i), +\f] + +где \f$ k_i \f$ вычисляется итерационно при начальных условиях \f$ k_0 = k\f$: + +\f[ + k_i = \left( \frac{k_{i-1}}{1+\sqrt{1-k_{i-1}^2}}\right)^2 +\f] + +Данная функция рассчитывает ряд первых `n` значений \f$ k_i \f$, которые в +дальнейшем могут быть использованы для расчета эллиптического интеграла и +эллиптических функций. + +\param[in] k +Эллиптический модуль \f$ k \f$. \n + +\param[in] n +Размер вектора `y` соответствующих коэффициентам \f$ k_i \f$. \n \n + +\param[out] y +Указатель на вектор значений коэффициентов \f$ k_i \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `ellip_landen`: + +\include ellip_landen_test.c + +Результат работы программы: + +\verbatim + i k[i] + + 1 4.625e-01 + 2 6.009e-02 + 3 9.042e-04 + 4 2.044e-07 + 5 1.044e-14 + 6 2.727e-29 + 7 1.859e-58 + 8 8.640e-117 + 9 1.866e-233 +10 0.000e+00 +11 0.000e+00 +12 0.000e+00 +13 0.000e+00 +\endverbatim + +\note +Ряд полного эллиптического интеграла сходится при значениях +эллиптического модуля \f$ k<1 \f$. При этом сходимость ряда достаточно +быстрая и для практический приложений достаточно от 10 до 20 значений +\f$ k_i \f$ для обеспечения погрешности при расчете полного +эллиптического интеграла в пределах машинной точности. + +\author +Бахурин Сергей +www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_landen(double k, int n, double* y) { - int i; - y[0] = k; + int i; + y[0] = k; - if(!y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - for(i = 1; i < n; i++) - { - y[i] = y[i-1] / (1.0 + sqrt(1.0 - y[i-1] * y[i-1])); - y[i] *= y[i]; - } + for(i = 1; i < n; i++) + { + y[i] = y[i-1] / (1.0 + sqrt(1.0 - y[i-1] * y[i-1])); + y[i] *= y[i]; + } - return RES_OK; + return RES_OK; } -/***************************************************************************** - Elliptic modular equation - -------------------------------------------------------------------------------- -Documented: NO, NO -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int DSPL_API ellip_modulareq(double rp, double rs, int ord, double *k) { - double ep, es, ke, kp, t, sn = 0.0; - int i, L, r; + double ep, es, ke, kp, t, sn = 0.0; + int i, L, r; - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(rs < 0 || rs == 0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!k) - return ERROR_PTR; + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(rs < 0 || rs == 0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!k) + return ERROR_PTR; - ep = sqrt(pow(10.0, rp*0.1)-1.0); - es = sqrt(pow(10.0, rs*0.1)-1.0); + ep = sqrt(pow(10.0, rp*0.1)-1.0); + es = sqrt(pow(10.0, rs*0.1)-1.0); - ke = ep/es; + ke = ep/es; - ke = sqrt(1.0 - ke*ke); + ke = sqrt(1.0 - ke*ke); - r = ord % 2; - L = (ord-r)/2; + r = ord % 2; + L = (ord-r)/2; - kp = 1.0; - for(i = 0; i < L; i++) - { - t = (double)(2*i+1) / (double)ord; - ellip_sn(&t, 1, ke, &sn); - sn*=sn; - kp *= sn*sn; - } + kp = 1.0; + for(i = 0; i < L; i++) + { + t = (double)(2*i+1) / (double)ord; + ellip_sn(&t, 1, ke, &sn); + sn*=sn; + kp *= sn*sn; + } - kp *= pow(ke, (double)ord); - *k = sqrt(1.0 - kp*kp); + kp *= pow(ke, (double)ord); + *k = sqrt(1.0 - kp*kp); - return RES_OK; + return RES_OK; } -/***************************************************************************** -Elliptic rational function --------------------------------------------------------------------------------- -Documented: NO, NO -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int DSPL_API ellip_rat(double* w, int n, int ord, double k, double* u) { - double t, xi, w2, xi2, k2; - int i, m, r, L; + double t, xi, w2, xi2, k2; + int i, m, r, L; - if(!u || !w) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !w) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - r = ord%2; - L = (ord-r)/2; + r = ord%2; + L = (ord-r)/2; - if(r) - memcpy(u, w, n*sizeof(double)); - else - { - for(m = 0; m < n; m++) + if(r) + memcpy(u, w, n*sizeof(double)); + else { - u[m] = 1.0; + for(m = 0; m < n; m++) + { + u[m] = 1.0; + } } - } - k2 = k*k; - for(i = 0; i < L; i++) - { - t = (double)(2*i+1) / (double)ord; - ellip_cd(&t, 1, k, &xi); - xi2 = xi*xi; - for(m = 0; m < n; m++) + k2 = k*k; + for(i = 0; i < L; i++) { - w2 = w[m]*w[m]; - u[m] *= (w2 - xi2) / (1.0 - w2 * k2 * xi2); - u[m] *= (1.0 - k2*xi2) / (1.0 - xi2); + t = (double)(2*i+1) / (double)ord; + ellip_cd(&t, 1, k, &xi); + xi2 = xi*xi; + for(m = 0; m < n; m++) + { + w2 = w[m]*w[m]; + u[m] *= (w2 - xi2) / (1.0 - w2 * k2 * xi2); + u[m] *= (1.0 - k2*xi2) / (1.0 - xi2); + } } - } - return RES_OK; + return RES_OK; } @@ -441,82 +995,224 @@ int DSPL_API ellip_rat(double* w, int n, int ord, double k, double* u) -/***************************************************************************** -Jacobi elliptic function sn(u*K(k), k) for the real vector argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn(double* u, int n, double k, double* y) +\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ +of real vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$ of real vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org + **************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn(double* u, int n, double k, double* y) +\brief Эллиптическая функция Якоби +\f$ y = \textrm{sn}(u K(k), k)\f$ вещественного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{sn}(u K(k), k)\f$ для вещественного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_sn(double* u, int n, double k, double* y) { - double lnd[ELLIP_ITER]; - int i, m; + double lnd[ELLIP_ITER]; + int i, m; - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - for(m = 0; m < n; m++) - { - y[m] = sin(u[m] * M_PI * 0.5); - for(i = ELLIP_ITER-1; i>0; i--) + for(m = 0; m < n; m++) { - y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); + y[m] = sin(u[m] * M_PI * 0.5); + for(i = ELLIP_ITER-1; i>0; i--) + { + y[m] = (1.0 + lnd[i]) / (1.0 / y[m] + lnd[i]*y[m]); + } } - } - return RES_OK; + return RES_OK; } -/***************************************************************************** -Jacobi elliptic function sn(u*K(k), k) for the complex vector argument --------------------------------------------------------------------------------- -Documented: RU, EN -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Jacobi elliptic function \f$ y = \textrm{sn}(u K(k), k)\f$ of +complex vector argument + +Function calculates Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$ of complex vector `u` and +elliptical modulus `k`. \n + +\param[in] u +Pointer to the argument vector \f$ u \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\param[in] n +Size of vector `u`. \n + +\param[in] k +Elliptical modulus \f$ k \f$. \n +Elliptical modulus is real parameter, +which values can be from 0 to 1. \n \n + +\param[out] y +Pointer to the vector of Jacobi elliptic function +\f$ y = \textrm{sn}(u K(k), k)\f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` successful exit, else \ref ERROR_CODE_GROUP "error code". \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_ELLIP_GROUP +\fn int ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) +\brief Эллиптическая функция Якоби +\f$ y = \textrm{sn}(u K(k), k)\f$ комплексного аргумента + +Функция рассчитывает значения значения эллиптической функции +\f$ y = \textrm{sn}(u K(k), k)\f$ для комплексного вектора `u` и +эллиптического модуля `k`. \n + +Для расчета используется итерационный алгоритм на основе преобразования +Ландена. \n + +\param[in] u +Указатель на массив вектора переменной \f$ u \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\param[in] n +Размер вектора `u`. \n \n + +\param[in] k +Значение эллиптического модуля \f$ k \f$. \n +Эллиптический модуль -- вещественный параметр, +принимающий значения от 0 до 1. \n \n + +\param[out] y +Указатель на вектор значений эллиптической +функции \f$ y = \textrm{sn}(u K(k), k)\f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ellip_sn_cmplx(complex_t* u, int n, double k, complex_t* y) { - double lnd[ELLIP_ITER], t; - int i, m; - complex_t tmp; + double lnd[ELLIP_ITER], t; + int i, m; + complex_t tmp; - if(!u || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - if(k < 0.0 || k>= 1.0) - return ERROR_ELLIP_MODULE; + if(!u || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + if(k < 0.0 || k>= 1.0) + return ERROR_ELLIP_MODULE; - ellip_landen(k,ELLIP_ITER, lnd); + ellip_landen(k,ELLIP_ITER, lnd); - for(m = 0; m < n; m++) - { - RE(tmp) = RE(u[m]) * M_PI * 0.5; - IM(tmp) = IM(u[m]) * M_PI * 0.5; - - sin_cmplx(&tmp, 1, y+m); - - for(i = ELLIP_ITER-1; i>0; i--) + for(m = 0; m < n; m++) { - t = 1.0 / ABSSQR(y[m]); + RE(tmp) = RE(u[m]) * M_PI * 0.5; + IM(tmp) = IM(u[m]) * M_PI * 0.5; - RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; - IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; + sin_cmplx(&tmp, 1, y+m); - t = (1.0 + lnd[i]) / ABSSQR(tmp); + for(i = ELLIP_ITER-1; i>0; i--) + { + t = 1.0 / ABSSQR(y[m]); - RE(y[m]) = RE(tmp) * t; - IM(y[m]) = -IM(tmp) * t; + RE(tmp) = RE(y[m]) * t + RE(y[m]) * lnd[i]; + IM(tmp) = -IM(y[m]) * t + IM(y[m]) * lnd[i]; + t = (1.0 + lnd[i]) / ABSSQR(tmp); + + RE(y[m]) = RE(tmp) * t; + IM(y[m]) = -IM(tmp) * t; + + } } - } - return RES_OK; + return RES_OK; } diff --git a/dspl/src/fft.c b/dspl/src/fft.c index 5730601..b576141 100644 --- a/dspl/src/fft.c +++ b/dspl/src/fft.c @@ -5,17 +5,17 @@ * This file is part of libdspl-2.0. * * is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by +* it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ #include @@ -24,72 +24,335 @@ #include "dspl.h" #include "dspl_internal.h" -/******************************************************************************* -COMPLEX vector IFFT -*******************************************************************************/ + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int ifft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) +\brief Inverse fast Fourier transform + +Function calculates \f$ n \f$-point IFFT of complex data +\f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \frac{1}{N} \sum_{m = 0}^{n-1} x(m) \exp + \left( j \frac{2\pi}{n} m k \right), +\f] +here \f$ k = 0 \ldots n-1 \f$. + + +\param[in] x +Pointer to the input vector \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +IFFT size \f$n\f$. \n +IFFT size can be composite: +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +here \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +simple number less than 46340 +(see \ref fft_create function). \n \n + +\param[in] pfft +Pointer to the `fft_t` object. \n +This pointer cannot be `NULL`. \n +Structure \ref fft_t should be previously once +filled with the \ref fft_create function, and the memory should be +cleared before exiting by the \ref fft_free function. \n \n + +\param[out] y +Pointer to the IFFT result vector \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if IFFT is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +IFFT example: + +\include ifft_cmplx_test.c + +Result: + +\verbatim +| x[ 0] = 1.000 0.000 | y[ 0] = -0.517 0.686 | z[ 0] = 1.000 0.000 | +| x[ 1] = 0.540 0.841 | y[ 1] = -0.943 0.879 | z[ 1] = 0.540 0.841 | +| x[ 2] = -0.416 0.909 | y[ 2] = -2.299 1.492 | z[ 2] = -0.416 0.909 | +| x[ 3] = -0.990 0.141 | y[ 3] = 16.078 -6.820 | z[ 3] = -0.990 0.141 | +| x[ 4] = -0.654 -0.757 | y[ 4] = 2.040 -0.470 | z[ 4] = -0.654 -0.757 | +| x[ 5] = 0.284 -0.959 | y[ 5] = 1.130 -0.059 | z[ 5] = 0.284 -0.959 | +| x[ 6] = 0.960 -0.279 | y[ 6] = 0.786 0.097 | z[ 6] = 0.960 -0.279 | +| x[ 7] = 0.754 0.657 | y[ 7] = 0.596 0.183 | z[ 7] = 0.754 0.657 | +| x[ 8] = -0.146 0.989 | y[ 8] = 0.470 0.240 | z[ 8] = -0.146 0.989 | +| x[ 9] = -0.911 0.412 | y[ 9] = 0.375 0.283 | z[ 9] = -0.911 0.412 | +| x[10] = -0.839 -0.544 | y[10] = 0.297 0.318 | z[10] = -0.839 -0.544 | +| x[11] = 0.004 -1.000 | y[11] = 0.227 0.350 | z[11] = 0.004 -1.000 | +| x[12] = 0.844 -0.537 | y[12] = 0.161 0.380 | z[12] = 0.844 -0.537 | +| x[13] = 0.907 0.420 | y[13] = 0.094 0.410 | z[13] = 0.907 0.420 | +| x[14] = 0.137 0.991 | y[14] = 0.023 0.442 | z[14] = 0.137 0.991 | +| x[15] = -0.760 0.650 | y[15] = -0.059 0.479 | z[15] = -0.760 0.650 | +| x[16] = -0.958 -0.288 | y[16] = -0.161 0.525 | z[16] = -0.958 -0.288 | +| x[17] = -0.275 -0.961 | y[17] = -0.300 0.588 | z[17] = -0.275 -0.961 | +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int ifft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) +\brief Обратное быстрое преобразование Фурье + +Функция рассчитывает \f$ n \f$-точечное обратное быстрое преобразование Фурье +от \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \frac{1}{N} \sum_{m = 0}^{n-1} x(m) \exp + \left( j \frac{2\pi}{n} m k \right), +\f] +где \f$ k = 0 \ldots n-1 \f$. + +Для расчета используется алгоритм БПФ составной длины. + +\param[in] x +Указатель на входной комплексный вектор \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер ОБПФ \f$n\f$. \n +Размер ОБПФ может быть составным вида +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +произвольный простой множитель не превосходящий 46340 +(см. описание функции \ref fft_create). \n \n + +\param[in] pfft +Указатель на структуру `fft_t`. \n +Указатель не должен быть `NULL`. \n +Структура \ref fft_t должна быть предварительно однократно +заполнена функцией \ref fft_create, и память должна быть +очищена перед выходом функцией \ref fft_free. \n \n + +\param[out] y +Указатель на вектор результата ОБПФ \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если расчет произведен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n + +Пример использования функции `fft`: + +\include ifft_cmplx_test.c + +Результат работы программы: + +\verbatim +| x[ 0] = 1.000 0.000 | y[ 0] = -0.517 0.686 | z[ 0] = 1.000 0.000 | +| x[ 1] = 0.540 0.841 | y[ 1] = -0.943 0.879 | z[ 1] = 0.540 0.841 | +| x[ 2] = -0.416 0.909 | y[ 2] = -2.299 1.492 | z[ 2] = -0.416 0.909 | +| x[ 3] = -0.990 0.141 | y[ 3] = 16.078 -6.820 | z[ 3] = -0.990 0.141 | +| x[ 4] = -0.654 -0.757 | y[ 4] = 2.040 -0.470 | z[ 4] = -0.654 -0.757 | +| x[ 5] = 0.284 -0.959 | y[ 5] = 1.130 -0.059 | z[ 5] = 0.284 -0.959 | +| x[ 6] = 0.960 -0.279 | y[ 6] = 0.786 0.097 | z[ 6] = 0.960 -0.279 | +| x[ 7] = 0.754 0.657 | y[ 7] = 0.596 0.183 | z[ 7] = 0.754 0.657 | +| x[ 8] = -0.146 0.989 | y[ 8] = 0.470 0.240 | z[ 8] = -0.146 0.989 | +| x[ 9] = -0.911 0.412 | y[ 9] = 0.375 0.283 | z[ 9] = -0.911 0.412 | +| x[10] = -0.839 -0.544 | y[10] = 0.297 0.318 | z[10] = -0.839 -0.544 | +| x[11] = 0.004 -1.000 | y[11] = 0.227 0.350 | z[11] = 0.004 -1.000 | +| x[12] = 0.844 -0.537 | y[12] = 0.161 0.380 | z[12] = 0.844 -0.537 | +| x[13] = 0.907 0.420 | y[13] = 0.094 0.410 | z[13] = 0.907 0.420 | +| x[14] = 0.137 0.991 | y[14] = 0.023 0.442 | z[14] = 0.137 0.991 | +| x[15] = -0.760 0.650 | y[15] = -0.059 0.479 | z[15] = -0.760 0.650 | +| x[16] = -0.958 -0.288 | y[16] = -0.161 0.525 | z[16] = -0.958 -0.288 | +| x[17] = -0.275 -0.961 | y[17] = -0.300 0.588 | z[17] = -0.275 -0.961 | +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API ifft_cmplx(complex_t *x, int n, fft_t* pfft, complex_t* y) { - int err, k; - double norm; + int err, k; + double norm; - if(!x || !pfft || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(!x || !pfft || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; - err = fft_create(pfft, n); - if(err != RES_OK) - return err; + err = fft_create(pfft, n); + if(err != RES_OK) + return err; - memcpy(pfft->t1, x, n*sizeof(complex_t)); - for(k = 0; k < n; k++) - IM(pfft->t1[k]) = -IM(pfft->t1[k]); + memcpy(pfft->t1, x, n*sizeof(complex_t)); + for(k = 0; k < n; k++) + IM(pfft->t1[k]) = -IM(pfft->t1[k]); - err = fft_krn(pfft->t1, pfft->t0, pfft, n, 0); + err = fft_krn(pfft->t1, pfft->t0, pfft, n, 0); - if(err!=RES_OK) - return err; + if(err!=RES_OK) + return err; - norm = 1.0 / (double)n; - for(k = 0; k < n; k++) - { - RE(y[k]) = RE(pfft->t0[k])*norm; - IM(y[k]) = -IM(pfft->t0[k])*norm; - } - return RES_OK; + norm = 1.0 / (double)n; + for(k = 0; k < n; k++) + { + RE(y[k]) = RE(pfft->t0[k])*norm; + IM(y[k]) = -IM(pfft->t0[k])*norm; + } + return RES_OK; } -/******************************************************************************* -Real vector FFT -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft(double* x, int n, fft_t* pfft, complex_t* y) +\brief Fast Fourier transform for the real vector. + +Function calculated \f$ n \f$-points FFT for the real vector +\f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \sum_{m = 0}^{n-1} x(m) \exp + \left( -j \frac{2\pi}{n} m k \right), +\f] +here \f$ k = 0 \ldots n-1 \f$. + + +\param[in] x +Pointer to the input real vector \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +FFT size \f$n\f$. \n +FFT size can be composite: +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +here \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +simple number less than 46340 +(see \ref fft_create function). \n \n + +\param[in] pfft +Pointer to the `fft_t` object. \n +This pointer cannot be `NULL`. \n +Structure \ref fft_t should be previously once +filled with the \ref fft_create function, and the memory should be +cleared before exiting by the \ref fft_free function. \n \n + +\param[out] y +Pointer to the FFT result complex vector \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if FFT is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Example: + +\include fft_test.c + +Result: + +\verbatim +y[ 0] = 91.000 0.000 +y[ 1] = -7.000 30.669 +y[ 2] = -7.000 14.536 +y[ 3] = -7.000 8.778 +y[ 4] = -7.000 5.582 +y[ 5] = -7.000 3.371 +y[ 6] = -7.000 1.598 +y[ 7] = -7.000 0.000 +y[ 8] = -7.000 -1.598 +y[ 9] = -7.000 -3.371 +y[10] = -7.000 -5.582 +y[11] = -7.000 -8.778 +y[12] = -7.000 -14.536 +y[13] = -7.000 -30.669 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft(double* x, int n, fft_t* pfft, complex_t* y) +\brief Быстрое преобразование Фурье вещественного сигнала + +Функция рассчитывает \f$ n \f$-точечное быстрое преобразование Фурье +вещественного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \sum_{m = 0}^{n-1} x(m) \exp + \left( -j \frac{2\pi}{n} m k \right), +\f] +где \f$ k = 0 \ldots n-1 \f$. + +Для расчета используется алгоритм БПФ составной длины. + +\param[in] x +Указатель на вектор вещественного входного сигнала \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер БПФ \f$n\f$. \n +Размер БПФ может быть составным вида +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +произвольный простой множитель не превосходящий 46340 +(см. описание функции \ref fft_create). \n \n + +\param[in] pfft +Указатель на структуру `fft_t`. \n +Указатель не должен быть `NULL`. \n +Структура \ref fft_t должна быть предварительно однократно +заполнена функцией \ref fft_create, и память должна быть +очищена перед выходом функцией \ref fft_free. \n \n + +\param[out] y +Указатель на комплексный вектор результата БПФ \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если расчет произведен успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n + +Пример использования функции `fft`: + +\include fft_test.c + +Результат работы программы: + +\verbatim +y[ 0] = 91.000 0.000 +y[ 1] = -7.000 30.669 +y[ 2] = -7.000 14.536 +y[ 3] = -7.000 8.778 +y[ 4] = -7.000 5.582 +y[ 5] = -7.000 3.371 +y[ 6] = -7.000 1.598 +y[ 7] = -7.000 0.000 +y[ 8] = -7.000 -1.598 +y[ 9] = -7.000 -3.371 +y[10] = -7.000 -5.582 +y[11] = -7.000 -8.778 +y[12] = -7.000 -14.536 +y[13] = -7.000 -30.669 +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API fft(double* x, int n, fft_t* pfft, complex_t* y) -{ - int err; - - if(!x || !pfft || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - - - err = fft_create(pfft, n); - if(err != RES_OK) - return err; - - re2cmplx(x, n, pfft->t1); - - return fft_krn(pfft->t1, y, pfft, n, 0); -} - - - - -/******************************************************************************* -COMPLEX vector FFT -*******************************************************************************/ -int DSPL_API fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) { int err; @@ -99,6 +362,177 @@ int DSPL_API fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) return ERROR_SIZE; + err = fft_create(pfft, n); + if(err != RES_OK) + return err; + + re2cmplx(x, n, pfft->t1); + + return fft_krn(pfft->t1, y, pfft, n, 0); +} + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) +\brief Fast Fourier transform for the complex vector. + +Function calculated \f$ n \f$-points FFT for the complex vector +\f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \sum_{m = 0}^{n-1} x(m) \exp \left( -j \frac{2\pi}{n} m k \right), +\f] +here \f$ k = 0 \ldots n-1 \f$. + +\param[in] x +Pointer to the input complex vector \f$x(m)\f$, +\f$ m = 0 \ldots n-1 \f$. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +FFT size \f$n\f$. \n +FFT size can be composite: +\f$n = n_0 \times n_1 \times n_2 \times \ldots \times n_p \times m\f$, +here \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +simple number less than 46340 +(see \ref fft_create function). \n \n + +\param[in] pfft +Pointer to the `fft_t` object. \n +This pointer cannot be `NULL`. \n +Structure \ref fft_t should be previously once +filled with the \ref fft_create function, and the memory should be +cleared before exiting by the \ref fft_free function. \n \n + +\param[out] y +Pointer to the FFT result complex vector \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return +`RES_OK` if FFT is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Example: + +\include fft_cmplx_test.c + +Result: + +\verbatim +y[ 0] = -0.517 0.686 +y[ 1] = -0.943 0.879 +y[ 2] = -2.299 1.492 +y[ 3] = 16.078 -6.820 +y[ 4] = 2.040 -0.470 +y[ 5] = 1.130 -0.059 +y[ 6] = 0.786 0.097 +y[ 7] = 0.596 0.183 +y[ 8] = 0.470 0.240 +y[ 9] = 0.375 0.283 +y[10] = 0.297 0.318 +y[11] = 0.227 0.350 +y[12] = 0.161 0.380 +y[13] = 0.094 0.410 +y[14] = 0.023 0.442 +y[15] = -0.059 0.479 +y[16] = -0.161 0.525 +y[17] = -0.300 0.588 +\endverbatim + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) +\brief Быстрое преобразование Фурье комплексного сигнала + +Функция рассчитывает \f$ n \f$-точечное быстрое преобразование Фурье +комплексного сигнала \f$ x(m) \f$, \f$ m = 0 \ldots n-1 \f$. \n +\f[ + Y(k) = \sum_{m = 0}^{n-1} x(m) \exp \left( -j \frac{2\pi}{n} m k \right), +\f] +где \f$ k = 0 \ldots n-1 \f$. + +Для расчета используется алгоритм БПФ составной длины. + +\param[in] x +Указатель на вектор комплексного +входного сигнала \f$x(m)\f$, \f$ m = 0 \ldots n-1 \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер БПФ \f$n\f$. \n +Размер БПФ может быть составным вида +\f$ n = n_0 \times n_1 \times n_2 \times n_3 \times \ldots +\times n_p \times m \f$, +где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +произвольный простой множитель не превосходящий 46340 +(см. описание функции \ref fft_create). \n \n + +\param[in] pfft +Указатель на структуру `fft_t`. \n +Указатель не должен быть `NULL`. \n +Структура \ref fft_t должна быть предварительно однократно +заполнена функцией \ref fft_create, и память должна быть +очищена перед выходом функцией \ref fft_free. \n \n + +\param[out] y +Указатель на комплексный вектор +результата БПФ \f$Y(k)\f$, +\f$ k = 0 \ldots n-1 \f$. +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если расчет произведен успешно. \n + В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n + +Пример использования функции `fft`: + +\include fft_cmplx_test.c + +Результат работы программы: + +\verbatim +y[ 0] = -0.517 0.686 +y[ 1] = -0.943 0.879 +y[ 2] = -2.299 1.492 +y[ 3] = 16.078 -6.820 +y[ 4] = 2.040 -0.470 +y[ 5] = 1.130 -0.059 +y[ 6] = 0.786 0.097 +y[ 7] = 0.596 0.183 +y[ 8] = 0.470 0.240 +y[ 9] = 0.375 0.283 +y[10] = 0.297 0.318 +y[11] = 0.227 0.350 +y[12] = 0.161 0.380 +y[13] = 0.094 0.410 +y[14] = 0.023 0.442 +y[15] = -0.059 0.479 +y[16] = -0.161 0.525 +y[17] = -0.300 0.588 +\endverbatim + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) +{ + int err; + + if(!x || !pfft || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + err = fft_create(pfft, n); if(err != RES_OK) return err; @@ -110,265 +544,423 @@ int DSPL_API fft_cmplx(complex_t* x, int n, fft_t* pfft, complex_t* y) -/******************************************************************************* -composite FFT kernel -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int fft_krn(complex_t* t0, complex_t* t1, fft_t* p, int n, int addr) { - int n1, n2, k, m, i; - complex_t *pw = p->w+addr; - complex_t tmp; - - n1 = 1; - if(n%16== 0) { n1 = 16; goto label_size; } - if(n%7 == 0) { n1 = 7; goto label_size; } - if(n%8 == 0) { n1 = 8; goto label_size; } - if(n%5 == 0) { n1 = 5; goto label_size; } - if(n%4 == 0) { n1 = 4; goto label_size; } - if(n%3 == 0) { n1 = 3; goto label_size; } - if(n%2 == 0) { n1 = 2; goto label_size; } + int n1, n2, k, m, i; + complex_t *pw = p->w+addr; + complex_t tmp; + + n1 = 1; + if(n%16== 0) { n1 = 16; goto label_size; } + if(n%7 == 0) { n1 = 7; goto label_size; } + if(n%8 == 0) { n1 = 8; goto label_size; } + if(n%5 == 0) { n1 = 5; goto label_size; } + if(n%4 == 0) { n1 = 4; goto label_size; } + if(n%3 == 0) { n1 = 3; goto label_size; } + if(n%2 == 0) { n1 = 2; goto label_size; } label_size: - if(n1 == 1) - { - for(k = 0; k < n; k++) + if(n1 == 1) { - RE(t1[k]) = IM(t1[k]) = 0.0; - for(m = 0; m < n; m++) - { - i = (k*m) % n; - RE(tmp) = CMRE(t0[m], pw[i]); - IM(tmp) = CMIM(t0[m], pw[i]); - RE(t1[k]) += RE(tmp); - IM(t1[k]) += IM(tmp); - } - } - } - else - { - n2 = n / n1; - - if(n2>1) - { - memcpy(t1, t0, n*sizeof(complex_t)); - matrix_transpose_cmplx(t1, n2, n1, t0); - } - - if(n1 == 16) - for(k = 0; k < n2; k++) - dft16(t0+16*k, t1+16*k); - - if(n1 == 7) - for(k = 0; k < n2; k++) - dft7(t0+7*k, t1+7*k); - - if(n1 == 8) - for(k = 0; k < n2; k++) - dft8(t0+8*k, t1+8*k); - - if(n1 == 5) - for(k = 0; k < n2; k++) - dft5(t0+5*k, t1+5*k); - - if(n1 == 4) - for(k = 0; k < n2; k++) - dft4(t0+4*k, t1+4*k); - - if(n1 == 3) - for(k = 0; k < n2; k++) - dft3(t0+3*k, t1+3*k); - - if(n1 == 2) - for(k = 0; k < n2; k++) - dft2(t0+2*k, t1+2*k); - - if(n2 > 1) - { - - for(k =0; k < n; k++) - { - RE(t0[k]) = CMRE(t1[k], pw[k]); - IM(t0[k]) = CMIM(t1[k], pw[k]); - } - - matrix_transpose_cmplx(t0, n1, n2, t1); - - for(k = 0; k < n1; k++) - { - fft_krn(t1+k*n2, t0+k*n2, p, n2, addr+n); - } - matrix_transpose_cmplx(t0, n2, n1, t1); - } - } - return RES_OK; - -} - - - - -/******************************************************************************* -FFT create for composite N -*******************************************************************************/ -int DSPL_API fft_create(fft_t* pfft, int n) -{ - - int n1, n2, addr, s, k, m, nw, err; - double phi; - s = n; - nw = addr = 0; - - if(pfft->n == n) - return RES_OK; - - while(s > 1) - { - n2 = 1; - if(s%16== 0) { n2 = 16; goto label_size; } - if(s%7 == 0) { n2 = 7; goto label_size; } - if(s%8 == 0) { n2 = 8; goto label_size; } - if(s%5 == 0) { n2 = 5; goto label_size; } - if(s%4 == 0) { n2 = 4; goto label_size; } - if(s%3 == 0) { n2 = 3; goto label_size; } - if(s%2 == 0) { n2 = 2; goto label_size; } - - -label_size: - if(n2 == 1) - { - if(s > FFT_COMPOSITE_MAX) - { - err = ERROR_FFT_SIZE; - goto error_proc; - } - - nw += s; - pfft->w = pfft->w ? (complex_t*) realloc(pfft->w, nw*sizeof(complex_t)): - (complex_t*) malloc( nw*sizeof(complex_t)); - for(k = 0; k < s; k++) - { - phi = - M_2PI * (double)k / (double)s; - RE(pfft->w[addr]) = cos(phi); - IM(pfft->w[addr]) = sin(phi); - addr++; - } - s = 1; + for(k = 0; k < n; k++) + { + RE(t1[k]) = IM(t1[k]) = 0.0; + for(m = 0; m < n; m++) + { + i = (k*m) % n; + RE(tmp) = CMRE(t0[m], pw[i]); + IM(tmp) = CMIM(t0[m], pw[i]); + RE(t1[k]) += RE(tmp); + IM(t1[k]) += IM(tmp); + } + } } else { - n1 = s / n2; - nw += s; - pfft->w = pfft->w ? (complex_t*) realloc(pfft->w, nw*sizeof(complex_t)): - (complex_t*) malloc( nw*sizeof(complex_t)); - - for(k = 0; k < n1; k++) - { - for(m = 0; m < n2; m++) + n2 = n / n1; + + if(n2>1) { - phi = - M_2PI * (double)(k*m) / (double)s; - RE(pfft->w[addr]) = cos(phi); - IM(pfft->w[addr]) = sin(phi); - addr++; + memcpy(t1, t0, n*sizeof(complex_t)); + matrix_transpose_cmplx(t1, n2, n1, t0); + } + + if(n1 == 16) + for(k = 0; k < n2; k++) + dft16(t0+16*k, t1+16*k); + + if(n1 == 7) + for(k = 0; k < n2; k++) + dft7(t0+7*k, t1+7*k); + + if(n1 == 8) + for(k = 0; k < n2; k++) + dft8(t0+8*k, t1+8*k); + + if(n1 == 5) + for(k = 0; k < n2; k++) + dft5(t0+5*k, t1+5*k); + + if(n1 == 4) + for(k = 0; k < n2; k++) + dft4(t0+4*k, t1+4*k); + + if(n1 == 3) + for(k = 0; k < n2; k++) + dft3(t0+3*k, t1+3*k); + + if(n1 == 2) + for(k = 0; k < n2; k++) + dft2(t0+2*k, t1+2*k); + + if(n2 > 1) + { + + for(k =0; k < n; k++) + { + RE(t0[k]) = CMRE(t1[k], pw[k]); + IM(t0[k]) = CMIM(t1[k], pw[k]); + } + + matrix_transpose_cmplx(t0, n1, n2, t1); + + for(k = 0; k < n1; k++) + { + fft_krn(t1+k*n2, t0+k*n2, p, n2, addr+n); + } + matrix_transpose_cmplx(t0, n2, n1, t1); } - } } - s /= n2; - } + return RES_OK; +} - pfft->t0 = pfft->t0 ? (complex_t*) realloc(pfft->t0, n*sizeof(complex_t)): - (complex_t*) malloc( n*sizeof(complex_t)); - pfft->t1 = pfft->t1 ? (complex_t*) realloc(pfft->t1, n*sizeof(complex_t)): - (complex_t*) malloc( n*sizeof(complex_t)); - - pfft->n = n; - return RES_OK; + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft_create(fft_t* pfft, int n) +\brief Function creates and fill `fft_t` structure. + +The function allocates memory and calculates twiddle factors + of the `n`-point FFT for the structure` fft_t`. + +\param[in,out] pfft +Pointer to the `fft_t` object. \n +Pointer cannot be `NULL`. \n \n + +\param[in] n +FFT size \f$n\f$. \n +FFT size can be composite +\f$n = n_0 \times n_1 \times n_2 \ldots \times n_p \times m\f$, +here \f$n_i = 2,3,5,7\f$, and \f$m \f$ -- + arbitrary prime factor not exceeding 46340. \n +Thus, the FFT algorithm supports arbitrary integer lengths. +degrees of numbers 2,3,5,7, as well as their various combinations. \n +For example, with \f$ n = 725760 \f$ the structure will be successfully filled, +because +\f$ 725760 = 2 \cdot 3 \cdot 4 \cdot 5 \cdot 6 \cdot 7 \cdot 9 \cdot 16 \f$. \n +If \f$ n = 172804 = 43201 \cdot 4 \f$ then the structure will also be +successfully filled, because the simple factor in \f$ n \f$ does not +exceed 46340. \n +For size \f$ n = 13 \cdot 17 \cdot 23 \cdot 13 = 66079 \f$ +the function will return an error since 66079 is greater than 46340 and is +not the result of the product of numbers 2,3,5,7. \n \n + +\return +`RES_OK` if FFT structure is created and filled successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\note +Some compilers do not nullify its contents when creating a structure. +Therefore, it is recommended to reset the structure after its declaration: +\code{.cpp} +fft_t pfft = {0}; // fill and fields of fft_t as zeros +int n = 64; // FFT size + +int err; + +// Create fft_t object for 64-points FFT + +err = fft_create(&pfft, n); + +// ................................... + +// Clear fft_t structure + +fft_free(&pfft); +\endcode + +Before exiting the program, the memory allocated in the structure +need to clear by \ref fft_free function. \n \n + +\note +The "magic number" 46340 because \f$\sqrt{2^{31}} = 46340.95\f$. \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft_create(fft_t* pfft, int n) +\brief Заполнение структуры `fft_t` для алгоритма БПФ + +Функция производит выделение памяти и рассчет векторов +поворотных коэффициентов `n`-точечного БПФ для структуры `fft_t`. + +\param[in,out] pfft +Указатель на структуру `fft_t`. \n +Указатель не должен быть `NULL`. \n \n + +\param[in] n +Размер БПФ \f$n\f$. \n +Размер БПФ может быть составным вида +\f$n = n_0 \times n_1 \times n_2 \ldots \times n_p \times m\f$, +где \f$n_i = 2,3,5,7\f$, а \f$m \f$ -- +произвольный простой множитель не превосходящий 46340. \n +Таким образом алгоритм БПФ поддерживает произвольные длины, равные целой +степени чисел 2,3,5,7, а также различные их комбинации. \n +Так например, при \f$ n = 725760 \f$ структура будет успешно заполнена, +потому что +\f$725760 = 2 \cdot 3 \cdot 4 \cdot 5 \cdot 6 \cdot 7 \cdot 9 \cdot 16 \f$, +т.е. получается как произведение множителей 2,3,5,7. \n +При \f$ n = 172804 = 43201 \cdot 4 \f$ структура также будет успешно заполнена, +потому что простой множитель входящий в \f$n\f$ не превосходит 46340. \n +Для размера \f$ n = 13 \cdot 17 \cdot 23 \cdot 13 = 66079 \f$ +функция вернет ошибку, поскольку 66079 больше 46340 и не является результатом +произведения чисел 2,3,5,7. \n \n + +\return +`RES_OK` если структура заполнена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n \n + +\note +Некоторые компиляторы при создании структуры не обнуляют ее содержимое. +Поэтому рекомендуется произвести обнуление структуры после ее объявления: +\code{.cpp} +fft_t pfft = {0}; // объявляем объект fft_t +int n = 64; // Размер БПФ + +int err; + +// создаем объект для 64-точечного БПФ + +err = fft_create(&pfft, n); + +// ................................... + +// очистить память объекта БПФ + +fft_free(&pfft); +\endcode + +Перед выходом из программы выделенную в структуре память +необходимо очистить функцией \ref fft_free . \n \n + +\note +Магия числа 46340 заключается в том, что \f$\sqrt{2^{31}} = 46340.95\f$. \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API fft_create(fft_t* pfft, int n) +{ + + int n1, n2, addr, s, k, m, nw, err; + double phi; + s = n; + nw = addr = 0; + + if(pfft->n == n) + return RES_OK; + + while(s > 1) + { + n2 = 1; + if(s%16== 0) { n2 = 16; goto label_size; } + if(s%7 == 0) { n2 = 7; goto label_size; } + if(s%8 == 0) { n2 = 8; goto label_size; } + if(s%5 == 0) { n2 = 5; goto label_size; } + if(s%4 == 0) { n2 = 4; goto label_size; } + if(s%3 == 0) { n2 = 3; goto label_size; } + if(s%2 == 0) { n2 = 2; goto label_size; } + + +label_size: + if(n2 == 1) + { + if(s > FFT_COMPOSITE_MAX) + { + err = ERROR_FFT_SIZE; + goto error_proc; + } + + nw += s; + pfft->w = pfft->w ? + (complex_t*) realloc(pfft->w, nw*sizeof(complex_t)): + (complex_t*) malloc( nw*sizeof(complex_t)); + for(k = 0; k < s; k++) + { + phi = - M_2PI * (double)k / (double)s; + RE(pfft->w[addr]) = cos(phi); + IM(pfft->w[addr]) = sin(phi); + addr++; + } + s = 1; + } + else + { + n1 = s / n2; + nw += s; + pfft->w = pfft->w ? + (complex_t*) realloc(pfft->w, nw*sizeof(complex_t)): + (complex_t*) malloc( nw*sizeof(complex_t)); + + for(k = 0; k < n1; k++) + { + for(m = 0; m < n2; m++) + { + phi = - M_2PI * (double)(k*m) / (double)s; + RE(pfft->w[addr]) = cos(phi); + IM(pfft->w[addr]) = sin(phi); + addr++; + } + } + } + s /= n2; + } + + pfft->t0 = pfft->t0 ? (complex_t*) realloc(pfft->t0, n*sizeof(complex_t)): + (complex_t*) malloc( n*sizeof(complex_t)); + + pfft->t1 = pfft->t1 ? (complex_t*) realloc(pfft->t1, n*sizeof(complex_t)): + (complex_t*) malloc( n*sizeof(complex_t)); + pfft->n = n; + + return RES_OK; error_proc: - if(pfft->t0) free(pfft->t0); - if(pfft->t1) free(pfft->t1); - if(pfft->w) free(pfft->w); - pfft->n = 0; - return err; + if(pfft->t0) free(pfft->t0); + if(pfft->t1) free(pfft->t1); + if(pfft->w) free(pfft->w); + pfft->n = 0; + return err; } -/******************************************************************************* -FFT free -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn void fft_free(fft_t *pfft) +\brief Free `fft_t` structure. + +The function clears the intermediate data memory +and vectors of FFT twiddle factors of the structure `fft_t`. + +\param[in] pfft +Pointer to the `fft_t` object. \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn void fft_free(fft_t *pfft) +\brief Очистить структуру `fft_t` алгоритма БПФ + +Функция производит очищение памяти промежуточных данных +и векторов поворотных коэффициентов структуры `fft_t`. + +\param[in] pfft +Указатель на структуру `fft_t`. \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif void DSPL_API fft_free(fft_t *pfft) { - if(!pfft) - return; - if(pfft->w) - free(pfft->w); - if(pfft->t0) - free(pfft->t0); - if(pfft->t1) - free(pfft->t1); - memset(pfft, 0, sizeof(fft_t)); + if(!pfft) + return; + if(pfft->w) + free(pfft->w); + if(pfft->t0) + free(pfft->t0); + if(pfft->t1) + free(pfft->t1); + memset(pfft, 0, sizeof(fft_t)); } -/******************************************************************************* -FFT magnitude for the real signal -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int DSPL_API fft_mag(double* x, int n, fft_t* pfft, double fs, int flag, double* mag, double* freq) { - int k, err = RES_OK; - complex_t *X = NULL; - - if(!x || !pfft) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - if(mag) - { - X = (complex_t*)malloc(n*sizeof(complex_t)); - err = fft(x, n, pfft, X); - if(err!=RES_OK) - goto error_proc; + int k, err = RES_OK; + complex_t *X = NULL; - if(flag & DSPL_FLAG_LOGMAG) - for(k = 0; k < n; k++) - mag[k] = 10.0*log10(ABSSQR(X[k])); - else - for(k = 0; k < n; k++) - mag[k] = ABS(X[k]); - if(flag & DSPL_FLAG_FFT_SHIFT) - { - err = fft_shift(mag, n, mag); - if(err!=RES_OK) - goto error_proc; + if(!x || !pfft) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + if(mag) + { + X = (complex_t*)malloc(n*sizeof(complex_t)); + err = fft(x, n, pfft, X); + if(err!=RES_OK) + goto error_proc; + + if(flag & DSPL_FLAG_LOGMAG) + for(k = 0; k < n; k++) + mag[k] = 10.0*log10(ABSSQR(X[k])); + else + for(k = 0; k < n; k++) + mag[k] = ABS(X[k]); + if(flag & DSPL_FLAG_FFT_SHIFT) + { + err = fft_shift(mag, n, mag); + if(err!=RES_OK) + goto error_proc; + } } - } - - if(freq) - { - if(flag & DSPL_FLAG_FFT_SHIFT) - if(n%2) - err = linspace(-fs*0.5 + fs*0.5/(double)n, - fs*0.5 - fs*0.5/(double)n, - n, DSPL_SYMMETRIC, freq); - else - err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, freq); - else - err = linspace(0, fs, n, DSPL_PERIODIC, freq); - } - -error_proc: - if(X) - free(X); - return err; + if(freq) + { + if(flag & DSPL_FLAG_FFT_SHIFT) + if(n%2) + err = linspace(-fs*0.5 + fs*0.5/(double)n, + fs*0.5 - fs*0.5/(double)n, + n, DSPL_SYMMETRIC, freq); + else + err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, freq); + else + err = linspace(0, fs, n, DSPL_PERIODIC, freq); + } + +error_proc: + if(X) + free(X); + + return err; } @@ -377,148 +969,214 @@ error_proc: -/******************************************************************************* -FFT magnitude for the complex signal -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int DSPL_API fft_mag_cmplx(complex_t* x, int n, fft_t* pfft, double fs, int flag, double* mag, double* freq) { - int k, err = RES_OK; - complex_t *X = NULL; - - if(!x || !pfft) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - if(mag) - { - X = (complex_t*)malloc(n*sizeof(complex_t)); - err = fft_cmplx(x, n, pfft, X); - if(err!=RES_OK) - goto error_proc; + int k, err = RES_OK; + complex_t *X = NULL; - if(flag & DSPL_FLAG_LOGMAG) - for(k = 0; k < n; k++) - mag[k] = 10.0*log10(ABSSQR(X[k])); - else - for(k = 0; k < n; k++) - mag[k] = ABS(X[k]); - if(flag & DSPL_FLAG_FFT_SHIFT) - { - err = fft_shift(mag, n, mag); - if(err!=RES_OK) - goto error_proc; + if(!x || !pfft) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + if(mag) + { + X = (complex_t*)malloc(n*sizeof(complex_t)); + err = fft_cmplx(x, n, pfft, X); + if(err!=RES_OK) + goto error_proc; + + if(flag & DSPL_FLAG_LOGMAG) + for(k = 0; k < n; k++) + mag[k] = 10.0*log10(ABSSQR(X[k])); + else + for(k = 0; k < n; k++) + mag[k] = ABS(X[k]); + if(flag & DSPL_FLAG_FFT_SHIFT) + { + err = fft_shift(mag, n, mag); + if(err!=RES_OK) + goto error_proc; + } } - } - - if(freq) - { - if(flag & DSPL_FLAG_FFT_SHIFT) - if(n%2) - err = linspace(-fs*0.5 + fs*0.5/(double)n, - fs*0.5 - fs*0.5/(double)n, - n, DSPL_SYMMETRIC, freq); - else - err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, freq); - else - err = linspace(0, fs, n, DSPL_PERIODIC, freq); - } -error_proc: - if(X) - free(X); - return err; + if(freq) + { + if(flag & DSPL_FLAG_FFT_SHIFT) + if(n%2) + err = linspace(-fs*0.5 + fs*0.5/(double)n, + fs*0.5 - fs*0.5/(double)n, + n, DSPL_SYMMETRIC, freq); + else + err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, freq); + else + err = linspace(0, fs, n, DSPL_PERIODIC, freq); + } +error_proc: + if(X) + free(X); + + return err; } -/******************************************************************************* -FFT shifting -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft_shift(double* x, int n, double* y) +\brief Perform a shift of the vector `x`, for use with the `fft` and `ifft` +functions, in order + + to move the frequency 0 to the center + of the vector `y`. + +\param[in] x +Pointer to the input vector (FFT or IFFT result). \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Input and output vector size. \n \n + +\param[out] y +Pointer to the output vector with frequency 0 in the center. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + + +\return +`RES_OK` if function is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fft_shift(double* x, int n, double* y) +\brief Перестановка спектральных отсчетов дискретного преобразования Фурье + +Функция производит + +перестановку спектральных отсчетов ДПФ + и переносит нулевую частоту в центр вектора ДПФ. \n +Данная функция обрабатывает вещественные входные и выходные вектора +и может применяться для перестановки +амплитудного или фазового спектра. + +\param[in] x +Указатель на исходный вектор ДПФ. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер ДПФ \f$n\f$ (размер векторов до и после перестановки). \n \n + +\param[out] y +Указатель на вектор результата перестановки. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если перестановка произведена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API fft_shift(double* x, int n, double* y) { - int n2, r; - int k; - double tmp; - double *buf; + int n2, r; + int k; + double tmp; + double *buf; - if(!x || !y) - return ERROR_PTR; + if(!x || !y) + return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(n<1) + return ERROR_SIZE; - r = n%2; - if(!r) - { - n2 = n>>1; - for(k = 0; k < n2; k++) + r = n%2; + if(!r) { - tmp = x[k]; - y[k] = x[k+n2]; - y[k+n2] = tmp; + n2 = n>>1; + for(k = 0; k < n2; k++) + { + tmp = x[k]; + y[k] = x[k+n2]; + y[k+n2] = tmp; + } } - } - else - { - n2 = (n+1) >> 1; - buf = (double*) malloc(n2*sizeof(double)); - memcpy(buf, x, n2*sizeof(double)); - memcpy(y, x+n2, (n2-1)*sizeof(double)); - memcpy(y+n2-1, buf, n2*sizeof(double)); - free(buf); - } - return RES_OK; + else + { + n2 = (n+1) >> 1; + buf = (double*) malloc(n2*sizeof(double)); + memcpy(buf, x, n2*sizeof(double)); + memcpy(y, x+n2, (n2-1)*sizeof(double)); + memcpy(y+n2-1, buf, n2*sizeof(double)); + free(buf); + } + return RES_OK; } -/******************************************************************************* -FFT shifting for complex vector -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int DSPL_API fft_shift_cmplx(complex_t* x, int n, complex_t* y) { - int n2, r; - int k; - complex_t tmp; - complex_t *buf; + int n2, r; + int k; + complex_t tmp; + complex_t *buf; - if(!x || !y) - return ERROR_PTR; + if(!x || !y) + return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(n<1) + return ERROR_SIZE; - r = n%2; - if(!r) - { - n2 = n>>1; - for(k = 0; k < n2; k++) + r = n%2; + if(!r) { - RE(tmp) = RE(x[k]); - IM(tmp) = IM(x[k]); + n2 = n>>1; + for(k = 0; k < n2; k++) + { + RE(tmp) = RE(x[k]); + IM(tmp) = IM(x[k]); - RE(y[k]) = RE(x[k+n2]); - IM(y[k]) = IM(x[k+n2]); + RE(y[k]) = RE(x[k+n2]); + IM(y[k]) = IM(x[k+n2]); - RE(y[k+n2]) = RE(tmp); - IM(y[k+n2]) = IM(tmp); + RE(y[k+n2]) = RE(tmp); + IM(y[k+n2]) = IM(tmp); + } } - } - else - { - n2 = (n+1) >> 1; - buf = (complex_t*) malloc(n2*sizeof(complex_t)); - memcpy(buf, x, n2*sizeof(complex_t)); - memcpy(y, x+n2, (n2-1)*sizeof(complex_t)); - memcpy(y+n2-1, buf, n2*sizeof(complex_t)); - free(buf); - } - return RES_OK; + else + { + n2 = (n+1) >> 1; + buf = (complex_t*) malloc(n2*sizeof(complex_t)); + memcpy(buf, x, n2*sizeof(complex_t)); + memcpy(y, x+n2, (n2-1)*sizeof(complex_t)); + memcpy(y+n2-1, buf, n2*sizeof(complex_t)); + free(buf); + } + return RES_OK; } diff --git a/dspl/src/filter_an.c b/dspl/src/filter_an.c index 7656352..9fc9b70 100644 --- a/dspl/src/filter_an.c +++ b/dspl/src/filter_an.c @@ -5,17 +5,17 @@ * This file is part of libdspl-2.0. * * is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by +* it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ @@ -28,491 +28,834 @@ -/****************************************************************************** -Magnitude, phase response and group delay of a digital filter H(z) or -analog filter H(s) -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, + int flag, double* mag, double* phi, double* tau) + +\brief +Magnitude, phase response and group delay vectors calculation +for digital or analog filter corresponds to \f$H(s)\f$, or \f$H(z)\f$ +transfer function. + + +\param[in] b +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the \f$ H(s) \f$ or \f$H(z)\f$ transfer function +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$ H(s) \f$ or \f$H(z)\f$ numerator +and denominator coefficients number equals `ord+1`. \n \n + +\param[in] w +Pointer to the angular frequency \f$ \omega \f$ (rad/s), +which used for analog filter characteristics calculation +(flag sets as `DSPL_FLAG_ANALOG`). \n +For digital filter (flag sets as `DSPL_FLAG_DIGITAL`), + parameter `w` describes normalized frequency of +frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. +Digital filter frequency response is \f$ 2\pi \f$-periodic function, +and vector `w` advisable to set from 0 to \f$ \pi \f$, +or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of frequency vector `w`. \n \n + +\param[in] flag +Binary flags to set calculation rules: \n +\verbatim +DSPL_FLAG_ANALOG Coefficients corresponds to analog filter +DSPL_FLAG_DIGITAL Coefficients corresponds to digital filter +DSPL_FLAG_LOGMAG Calculate magnitude in logarithmic scale (in dB) +DSPL_FLAG_UNWRAP Unwrap radian phases by adding multiples of 2*pi +\endverbatim + +\param[out] mag +Pointer to the filter magnitude vector. \n +Vector size is `[n x 1]`. \n +If pointer is `NULL`, then magnitude will not calculted. \n \n + +\param[out] phi +Pointer to the phase response vector. \n +Vector size is `[n x 1]`. \n +If pointer is `NULL`, then phase response will not calculted. \n \n + +\param[out] tau +Pointer to the group delay vector. \n +Vector size is `[n x 1]`. \n +If pointer is `NULL`, then group delay will not calculted. \n \n + +\return +\return `RES_OK` if function is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Example: + +\include butter_ap_test.c + +Result: + +\verbatim +b[ 0] = 1.002 a[ 0] = 1.002 +b[ 1] = 0.000 a[ 1] = 2.618 +b[ 2] = 0.000 a[ 2] = 3.418 +b[ 3] = 0.000 a[ 3] = 2.615 +b[ 4] = 0.000 a[ 4] = 1.000 +\endverbatim +\n + +In `dat` folder will be created 3 files: \n + +\verbatim +butter_ap_test_mag.txt magnitude +butter_ap_test_phi.txt phase response +butter_ap_test_tau.txt group delay +\endverbatim + +In addition, GNUPLOT will build the following graphs from data stored in files: + +\image html butter_ap_test.png + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int filter_freq_resp(double* b, double* a, int ord, double* w, int n, + int flag, double* mag, double* phi, double* tau) + +\brief +Расчет амплитудно-частотной (АЧХ), фазочастотной характеристик (ФЧХ), а также +группового времени запаздывания (ГВЗ) цифрового или аналогового или фильтра. + +Функция рассчитывает АЧХ, ФЧХ и ГВЗ аналогового или цифрового фильтра, заданного +передаточной характеристикой \f$H(s)\f$, или \f$H(z)\f$ соответственно + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] ord +Порядок фильтра. Количество коэффициентов +числителя и знаменателя передаточной +функции \f$ H(s) \f$ равно `ord+1`. \n \n + +\param[in] w +Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), +для которого будет рассчитаны АЧХ, ФЧХ и ГВЗ аналогового фильтра, +если установлен флаг `DSPL_FLAG_ANALOG`. \n +В случае если флаг `DSPL_FLAG_ANALOG` не установлен, то вектор частоты `w` +используется как нормированная частота комплексного коэффициента передачи +\f$ H \left(\mathrm{e}^{j\omega} \right) \f$ цифрового фильтра. \n +В этом случае характеристика цифрового фильтра является +\f$ 2\pi \f$-периодической, и вектор частоты может содержать +произвольные значения, однако целесообразно задавать +его от 0 до \f$ \pi \f$, а такжет от 0 до \f$ 2\pi \f$, или +от \f$ -\pi \f$ до \f$ \pi \f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора циклической частоты `w`. \n \n + +\param[in] flag +Комбинация флагов, которые задают расчет параметров: \n +\verbatim +DSPL_FLAG_ANALOG Коэффициенты относятся к аналоговому фильтру +DSPL_FLAG_LOGMAG АЧХ рассчитывать в логарифмическом масштабе +DSPL_FLAG_UNWRAP раскрывать периодичность ФЧХ +\endverbatim + +\param[out] mag +Указатель на вектор АЧХ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +Если указатель `NULL`, то расчет АЧХ не производится. \n \n + +\param[out] phi +Указатель на вектор ФЧХ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +Если указатель `NULL`, то расчет ФЧХ не производится. \n \n + +\param[out] tau +Указатель на вектор ГВЗ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n +Если указатель `NULL`, то расчет ГВЗ не производится. \n \n + +\return +`RES_OK` Параметры фильтра рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +Пример использования функции `filter_freq_resp`: + +\include butter_ap_test.c + +Результат работы программы: + +\verbatim +b[ 0] = 1.002 a[ 0] = 1.002 +b[ 1] = 0.000 a[ 1] = 2.618 +b[ 2] = 0.000 a[ 2] = 3.418 +b[ 3] = 0.000 a[ 3] = 2.615 +b[ 4] = 0.000 a[ 4] = 1.000 +\endverbatim +\n + +В каталоге `dat` будут созданы три файла: \n + +\verbatim +butter_ap_test_mag.txt АЧХ фильтра +butter_ap_test_phi.txt ФЧХ фильтра +butter_ap_test_tau.txt ГВЗ фильтра +\endverbatim + +Кроме того программа GNUPLOT произведет построение следующих графиков +по сохраненным в файлах данным: + +\image html butter_ap_test.png + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API filter_freq_resp(double* b, double* a, int ord, double* w, int n, int flag, double* mag, double* phi, double* tau) { - int res, k, flag_analog; + int res, k, flag_analog; - complex_t *hc = NULL; - double *phi0 = NULL; - double *phi1 = NULL; - double *w0 = NULL; - double *w1 = NULL; + complex_t *hc = NULL; + double *phi0 = NULL; + double *phi1 = NULL; + double *w0 = NULL; + double *w1 = NULL; - if(!b || !w) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(n < 1) - return ERROR_SIZE; + if(!b || !w) + return ERROR_PTR; + if(ord < 1) + return ERROR_FILTER_ORD; + if(n < 1) + return ERROR_SIZE; - flag_analog = flag & DSPL_FLAG_ANALOG; - - hc = (complex_t*) malloc (n*sizeof(complex_t)); - - res = flag_analog ? freqs(b, a, ord, w, n, hc) : freqz(b, a, ord, w, n, hc); - if(res != RES_OK) - goto exit_label; + flag_analog = flag & DSPL_FLAG_ANALOG; + + hc = (complex_t*) malloc (n*sizeof(complex_t)); + + res = flag_analog ? + freqs(b, a, ord, w, n, hc) : + freqz(b, a, ord, w, n, hc); - - if(mag) - { - if(flag & DSPL_FLAG_LOGMAG) - { - for(k = 0; k < n; k++) - mag[k] = 10.0 * log10(ABSSQR(hc[k])); - } - else - { - for(k = 0; k < n; k++) - mag[k] = sqrt(ABSSQR(hc[k])); - } - } - - - if(phi) - { - for(k = 0; k < n; k++) - phi[k] = atan2(IM(hc[k]), RE(hc[k])); - - if(flag & DSPL_FLAG_UNWRAP) - { - res = unwrap(phi, n, M_2PI, 0.8); - if(res != RES_OK) + if(res != RES_OK) goto exit_label; - } - } - if(tau) - { - phi0 = (double*) malloc(n*sizeof(double)); - phi1 = (double*) malloc(n*sizeof(double)); - w0 = (double*) malloc(n*sizeof(double)); - w1 = (double*) malloc(n*sizeof(double)); - - w0[0] = w[0] - (w[1] - w[0])*0.02; - w1[0] = w[0] + (w[1] - w[0])*0.02; - - for(k = 1; k < n; k++) + if(mag) { - w0[k] = w[k] - (w[k] - w[k-1])*0.02; - w1[k] = w[k] + (w[k] - w[k-1])*0.02; + if(flag & DSPL_FLAG_LOGMAG) + { + for(k = 0; k < n; k++) + mag[k] = 10.0 * log10(ABSSQR(hc[k])); + } + else + { + for(k = 0; k < n; k++) + mag[k] = sqrt(ABSSQR(hc[k])); + } + } + + + if(phi) + { + for(k = 0; k < n; k++) + phi[k] = atan2(IM(hc[k]), RE(hc[k])); + + if(flag & DSPL_FLAG_UNWRAP) + { + res = unwrap(phi, n, M_2PI, 0.8); + if(res != RES_OK) + goto exit_label; + } + } + + + if(tau) + { + phi0 = (double*) malloc(n*sizeof(double)); + phi1 = (double*) malloc(n*sizeof(double)); + w0 = (double*) malloc(n*sizeof(double)); + w1 = (double*) malloc(n*sizeof(double)); + + w0[0] = w[0] - (w[1] - w[0])*0.02; + w1[0] = w[0] + (w[1] - w[0])*0.02; + + for(k = 1; k < n; k++) + { + w0[k] = w[k] - (w[k] - w[k-1])*0.02; + w1[k] = w[k] + (w[k] - w[k-1])*0.02; + } + res = filter_freq_resp(b, a, ord, w0, n, + DSPL_FLAG_UNWRAP | flag_analog, + NULL, phi0, NULL); + if(res != RES_OK) + goto exit_label; + res = filter_freq_resp(b, a, ord, w1, n, + DSPL_FLAG_UNWRAP | flag_analog, + NULL, phi1, NULL); + if(res != RES_OK) + goto exit_label; + + for(k = 0; k < n; k++) + tau[k] = (phi0[k] - phi1[k])/(w1[k] - w0[k]); } - res = filter_freq_resp(b, a, ord, w0, n, - DSPL_FLAG_UNWRAP | flag_analog, NULL, phi0, NULL); - if(res != RES_OK) - goto exit_label; - res = filter_freq_resp(b, a, ord, w1, n, - DSPL_FLAG_UNWRAP | flag_analog, NULL, phi1, NULL); - if(res != RES_OK) - goto exit_label; - for(k = 0; k < n; k++) - tau[k] = (phi0[k] - phi1[k])/(w1[k] - w0[k]); - } exit_label: - if(hc) - free(hc); - if(phi0) - free(phi0); - if(phi1) - free(phi1); - if(w0) - free(w0); - if(w1) - free(w1); - return res; + if(hc) + free(hc); + if(phi0) + free(phi0); + if(phi1) + free(phi1); + if(w0) + free(w0); + if(w1) + free(w1); + return res; } -/****************************************************************************** -Complex frequency response of an analog filter H(s) -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) +\brief Analog filter frequency response \f$ H(j \omega) \f$ calculation + +Function calculates analog filter frequency response \f$ H(j \omega)\f$ +corresponds to transfer function \f$ H(s) \f$: + +\f[ + H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} + {\sum_{m = 0}^{N} a_m s^m}, +\f] +here \f$ N \f$ - filter order (equals to `ord`). + +\param[in] b +Pointer to the transfer function \f$ H(s) \f$ +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the transfer function \f$ H(s) \f$ +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$ H(s) \f$ numerator and denominator +coefficients number equals `ord+1`. \n \n + +\param[in] w +Pointer to the angular frequency \f$ \omega \f$ (rad/s), +which used for frequency response \f$ H(j \omega) \f$ calculation. \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +The size of the angular frequency vector `w`. \n \n + +\param[out] h +Pointer to the frequency response vector \f$ H(j \omega) \f$, +corresponds to angular frequency `w`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if frequency response vector is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ + +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) + +\brief Расчет комплексного коэффициента передачи +\f$ H(j \omega) \f$ аналогового фильтра. + +Функция рассчитывает значения комплексного коэффициента передачи +\f$ H(j \omega)\f$ аналогового фильтра, заданного коэффициентами +передаточной функции \f$ H(s) \f$: + +\f[ + H(s) = \frac {\sum_{k = 0}^{N} b_k s^k} + {\sum_{m = 0}^{N} a_m s^m}, +\f] +где \f$ N \f$ - порядок фильтра (параметр `ord`). + +Комплексный коэффициент передачи рассчитывается путем +подстановки \f$ s = j \omega \f$. + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$ H(s) \f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + + +\param[in] ord +Порядок фильтра. Количество коэффициентов числителя и +знаменателя передаточной функции \f$ H(s) \f$ +равно `ord+1`. \n \n + + +\param[in] w +Указатель на вектор значений циклической частоты \f$ \omega \f$ (рад/с), +для которого будет рассчитан комплексный +коэффициент передачи \f$ H(j \omega) \f$. \n +Размер вектора `[n x 1]`. \n \n + + +\param[in] n +Размер вектора циклической частоты `w`. \n \n + + +\param[out] h +Указатель на вектор комплексного коэффициента передачи \f$ H(j \omega) \f$, +рассчитанного для циклической частоты `w`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` Комплексный коэффициент передачи рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API freqs(double* b, double* a, int ord, double* w, int n, complex_t *h) { - complex_t jw; - complex_t *bc = NULL; - complex_t *ac = NULL; - complex_t num, den; - double mag; - int k; - int res; + complex_t jw; + complex_t *bc = NULL; + complex_t *ac = NULL; + complex_t num, den; + double mag; + int k; + int res; - if(!b || !a || !w || !h) - return ERROR_PTR; - if(ord<0) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; + if(!b || !a || !w || !h) + return ERROR_PTR; + if(ord<0) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; - RE(jw) = 0.0; + RE(jw) = 0.0; - bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(b, ord+1, bc); + bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(b, ord+1, bc); - if( res!=RES_OK ) - goto exit_label; - - ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(a, ord+1, ac); - if( res!=RES_OK ) - goto exit_label; - - for(k = 0; k < n; k++) - { - IM(jw) = w[k]; - res = polyval_cmplx(bc, ord, &jw, 1, &num); - if(res != RES_OK) - goto exit_label; - res = polyval_cmplx(ac, ord, &jw, 1, &den); - if(res != RES_OK) - goto exit_label; - mag = ABSSQR(den); - if(mag == 0.0) - { - res = ERROR_DIV_ZERO; - goto exit_label; - } - mag = 1.0 / mag; - RE(h[k]) = CMCONJRE(num, den) * mag; - IM(h[k]) = CMCONJIM(num, den) * mag; - } - res = RES_OK; -exit_label: - if(bc) - free(bc); - if(ac) - free(ac); - return res; -} - - - - - - -/****************************************************************************** - * Complex frequency response of an analog filter H(s), s is complex variable - ******************************************************************************/ -int DSPL_API freqs_cmplx(double* b, double* a, int ord, - complex_t* s, int n, complex_t *h) -{ - complex_t *bc = NULL; - complex_t *ac = NULL; - complex_t num, den; - double mag; - int k; - int res; - - if(!b || !a || !s || !h) - return ERROR_PTR; - if(ord<0) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - - bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(b, ord+1, bc); - - if( res!=RES_OK ) - goto exit_label; - - ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(a, ord+1, ac); - if( res!=RES_OK ) - goto exit_label; - - for(k = 0; k < n; k++) - { - res = polyval_cmplx(bc, ord, s+k, 1, &num); - if(res != RES_OK) - goto exit_label; - res = polyval_cmplx(ac, ord, s+k, 1, &den); - if(res != RES_OK) - goto exit_label; - mag = ABSSQR(den); - if(mag == 0.0) - { - res = ERROR_DIV_ZERO; - goto exit_label; - } - mag = 1.0 / mag; - RE(h[k]) = CMCONJRE(num, den) * mag; - IM(h[k]) = CMCONJIM(num, den) * mag; - - } - res = RES_OK; - exit_label: - if(bc) - free(bc); - if(ac) - free(ac); - return res; -} - - - - - - - -/****************************************************************************** -impulse response of an analog filter H(s) -*******************************************************************************/ -int DSPL_API freqs2time(double* b, double* a, int ord, double fs, - int n, fft_t* pfft, double *t, double *h) -{ - double *w = NULL; - complex_t *hs = NULL; - complex_t *ht = NULL; - int err, k; - - if(!b || !a || !t || !h) - return ERROR_PTR; - if(ord<1) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - w = (double*)malloc(n*sizeof(double)); - hs = (complex_t*)malloc(n*sizeof(complex_t)); - - - err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, w); - if(err != RES_OK) - goto exit_label; - - err = freqs(b, a, ord, w, n, hs); - if(err != RES_OK) - goto exit_label; - - err = fft_shift_cmplx(hs, n, hs); - if(err != RES_OK) - goto exit_label; - - ht = (complex_t*)malloc(n*sizeof(complex_t)); - - err = ifft_cmplx(hs, n, pfft, ht); - if(err != RES_OK) - { - err = idft_cmplx(hs, n, ht); - if(err != RES_OK) - goto exit_label; - } - - for(k = 0; k < n; k++) - { - t[k] = (double)k/fs; - h[k] = RE(ht[k]) * fs; - } - -exit_label: - if(w) - free(w); - if(hs) - free(hs); - if(ht) - free(ht); - return err; -} - - - - - - -/****************************************************************************** -Magnitude, phase response and group delay of an analog filter H(s) - -int DSPL_API freqs_resp(double* b, double* a, int ord, - double* w, int n, int flag, - double *h, double* phi, double* tau) -{ - int res, k; - - complex_t *hc = NULL; - double *phi0 = NULL; - double *phi1 = NULL; - double *w0 = NULL; - double *w1 = NULL; - - if(!b || !a || !w) - return ERROR_PTR; - if(ord < 1) - return ERROR_FILTER_ORD; - if(n < 1) - return ERROR_SIZE; - - - hc = (complex_t*) malloc (n*sizeof(complex_t)); - res = freqs(b, a, ord, w, n, hc); - if(res != RES_OK) - goto exit_label; - - - if(h) - { - if(flag & DSPL_FLAG_LOG) - { - for(k = 0; k < n; k++) - h[k] = 10.0 * log10(ABSSQR(hc[k])); - } - else - { - for(k = 0; k < n; k++) - h[k] = sqrt(ABSSQR(hc[k])); - } - } - - - if(phi) - { - for(k = 0; k < n; k++) - phi[k] = atan2(IM(hc[k]), RE(hc[k])); - - if(flag & DSPL_FLAG_UNWRAP) - { - res = unwrap(phi, n, M_2PI, 0.8); - if(res != RES_OK) + if( res!=RES_OK ) goto exit_label; - } - } - - if(tau) - { - phi0 = (double*) malloc(n*sizeof(double)); - phi1 = (double*) malloc(n*sizeof(double)); - w0 = (double*) malloc(n*sizeof(double)); - w1 = (double*) malloc(n*sizeof(double)); - - w0[0] = w[0] - (w[1] - w[0])*0.02; - w1[0] = w[0] + (w[1] - w[0])*0.02; - - for(k = 1; k < n; k++) - { - w0[k] = w[k] - (w[k] - w[k-1])*0.02; - w1[k] = w[k] + (w[k] - w[k-1])*0.02; - } - res = freqs_resp(b, a, ord, w0, n, DSPL_FLAG_UNWRAP, NULL, phi0, NULL); - if(res != RES_OK) - goto exit_label; - res = freqs_resp(b, a, ord, w1, n, DSPL_FLAG_UNWRAP, NULL, phi1, NULL); - if(res != RES_OK) - goto exit_label; - for(k = 0; k < n; k++) - tau[k] = (phi0[k] - phi1[k])/(w1[k] - w0[k]); - } - - -exit_label: - if(hc) - free(hc); - if(phi0) - free(phi0); - if(phi1) - free(phi1); - if(w0) - free(w0); - if(w1) - free(w1); - return res; -} - -*******************************************************************************/ - - - - - - - - -/******************************************************************************* -Complex frequency response of a digital filter H(z) -*******************************************************************************/ -int DSPL_API freqz(double* b, double* a, int ord, double* w, - int n, complex_t *h) -{ - complex_t jw; - complex_t *bc = NULL; - complex_t *ac = NULL; - complex_t num, den; - double mag; - int k; - int res; - - if(!b || !w || !h) - return ERROR_PTR; - if(ord<0) - return ERROR_FILTER_ORD; - if(n<1) - return ERROR_SIZE; - - - bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = re2cmplx(b, ord+1, bc); - if( res!=RES_OK ) - goto exit_label; - - if(a) - { - /* IIR filter if a != NULL */ ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); res = re2cmplx(a, ord+1, ac); if( res!=RES_OK ) - goto exit_label; + goto exit_label; + for(k = 0; k < n; k++) { - RE(jw) = cos(w[k]); - IM(jw) = -sin(w[k]); - res = polyval_cmplx(bc, ord, &jw, 1, &num); - if(res != RES_OK) - goto exit_label; - res = polyval_cmplx(ac, ord, &jw, 1, &den); - if(res != RES_OK) - goto exit_label; - mag = ABSSQR(den); - if(mag == 0.0) - { - res = ERROR_DIV_ZERO; - goto exit_label; - } - mag = 1.0 / mag; - RE(h[k]) = CMCONJRE(num, den) * mag; - IM(h[k]) = CMCONJIM(num, den) * mag; + IM(jw) = w[k]; + res = polyval_cmplx(bc, ord, &jw, 1, &num); + if(res != RES_OK) + goto exit_label; + res = polyval_cmplx(ac, ord, &jw, 1, &den); + if(res != RES_OK) + goto exit_label; + mag = ABSSQR(den); + if(mag == 0.0) + { + res = ERROR_DIV_ZERO; + goto exit_label; + } + mag = 1.0 / mag; + RE(h[k]) = CMCONJRE(num, den) * mag; + IM(h[k]) = CMCONJIM(num, den) * mag; } - } - else - { - /* FIR filter if a == NULL */ - for(k = 0; k < n; k++) - { - RE(jw) = cos(w[k]); - IM(jw) = -sin(w[k]); - res = polyval_cmplx(bc, ord, &jw, 1, h+k); - if(res != RES_OK) - goto exit_label; - } - } - res = RES_OK; + res = RES_OK; exit_label: - if(bc) - free(bc); - if(ac) - free(ac); - return res; + if(bc) + free(bc); + if(ac) + free(ac); + return res; +} + + + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API freqs_cmplx(double* b, double* a, int ord, + complex_t* s, int n, complex_t *h) +{ + complex_t *bc = NULL; + complex_t *ac = NULL; + complex_t num, den; + double mag; + int k; + int res; + + if(!b || !a || !s || !h) + return ERROR_PTR; + if(ord<0) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + + bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(b, ord+1, bc); + + if( res!=RES_OK ) + goto exit_label; + + ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(a, ord+1, ac); + if( res!=RES_OK ) + goto exit_label; + + for(k = 0; k < n; k++) + { + res = polyval_cmplx(bc, ord, s+k, 1, &num); + if(res != RES_OK) + goto exit_label; + res = polyval_cmplx(ac, ord, s+k, 1, &den); + if(res != RES_OK) + goto exit_label; + mag = ABSSQR(den); + if(mag == 0.0) + { + res = ERROR_DIV_ZERO; + goto exit_label; + } + mag = 1.0 / mag; + RE(h[k]) = CMCONJRE(num, den) * mag; + IM(h[k]) = CMCONJIM(num, den) * mag; + + } + res = RES_OK; + exit_label: + if(bc) + free(bc); + if(ac) + free(ac); + return res; +} + + + + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API freqs2time(double* b, double* a, int ord, double fs, + int n, fft_t* pfft, double *t, double *h) +{ + double *w = NULL; + complex_t *hs = NULL; + complex_t *ht = NULL; + int err, k; + + if(!b || !a || !t || !h) + return ERROR_PTR; + if(ord<1) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + w = (double*)malloc(n*sizeof(double)); + hs = (complex_t*)malloc(n*sizeof(complex_t)); + + + err = linspace(-fs*0.5, fs*0.5, n, DSPL_PERIODIC, w); + if(err != RES_OK) + goto exit_label; + + err = freqs(b, a, ord, w, n, hs); + if(err != RES_OK) + goto exit_label; + + err = fft_shift_cmplx(hs, n, hs); + if(err != RES_OK) + goto exit_label; + + ht = (complex_t*)malloc(n*sizeof(complex_t)); + + err = ifft_cmplx(hs, n, pfft, ht); + if(err != RES_OK) + { + err = idft_cmplx(hs, n, ht); + if(err != RES_OK) + goto exit_label; + } + + for(k = 0; k < n; k++) + { + t[k] = (double)k/fs; + h[k] = RE(ht[k]) * fs; + } + +exit_label: + if(w) + free(w); + if(hs) + free(hs); + if(ht) + free(ht); + return err; +} + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) + +\brief Function calculates the digital filter frequency response +\f$ H \left(e^{j \omega} \right)\f$ corresponds to transfer function \f$H(z)\f$. + +Digital filter transfer function: +\f[ +H(z) = \frac{\sum\limits_{k = 0}^{N} b_k z^{-k}} + {\sum\limits_{m = 0}^{N} a_m z^{-m}}, +\f] +here \f$N\f$ --- filter order (parameter `ord`). \n + +Frequency response \f$ H \left(e^{j \omega} \right)\f$ we can get +if substitute \f$z = e^{j \omega} \f$. \n + +\param[in] b +Pointer to the \f$ H(z) \f$ transfer function +numerator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] a +Pointer to the \f$H(z)\f$ transfer function +denominator coefficients vector. \n +Vector size is `[ord+1 x 1]`. \n \n + +\param[in] ord +Filter order. \n +Transfer function \f$H(z)\f$ numerator +and denominator coefficients number equals `ord+1`. \n \n + +\param[in] w +Pointer to the normalized frequency of digital filter +frequency response \f$ H \left(\mathrm{e}^{j\omega} \right) \f$. \n +Digital filter frequency response is \f$ 2\pi \f$-periodic function, +and vector `w` advisable to set from 0 to \f$ \pi \f$, +or from 0 to \f$ 2\pi \f$, or from \f$ -\pi \f$ to \f$ \pi \f$. +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of frequency vector `w`. \n \n + +\param[out] h +Pointer to the frequency response vector +\f$ H \left(\mathrm{e}^{j\omega} \right) \f$, +corresponds to normalized frequency `w`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n \n + +\return `RES_OK` if frequaency response vector is calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup FILTER_ANALYSIS_GROUP +\fn int freqz(double* b, double* a, int ord, double* w, int n, complex_t *h) + +\brief Расчет комплексного коэффициента передачи + \f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра. + +Функция рассчитывает значения комплексного коэффициента передачи +\f$ H \left(e^{j \omega} \right)\f$ цифрового фильтра, заданного +коэффициентами передаточной функции \f$H(z)\f$: + +\f[ +H(z) = \frac {\sum_{k = 0}^{N} b_k z^{-k}} + {\sum_{m = 0}^{N} a_m z^{-m}}, +\f] + +где \f$N\f$ --- порядок фильтра (параметр `ord`). \n + +Комплексный коэффициент передачи рассчитывается путем +подстановки \f$z = e^{j \omega} \f$. \n + + +\param[in] b +Указатель на вектор коэффициентов числителя +передаточной функции \f$H(z)\f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] a +Указатель на вектор коэффициентов знаменателя +передаточной функции \f$H(z)\f$. \n +Размер вектора `[ord+1 x 1]`. \n \n + +\param[in] ord +Порядок фильтра. Количество коэффициентов числителя и знаменателя +передаточной функции \f$H(z)\f$ равно `ord+1`. \n \n + +\param[in] w +Указатель на вектор значений нормированной циклической частоты \f$\omega\f$, +для которого будет рассчитан комплексный коэффициент передачи +\f$ H \left(e^{j \omega} \right)\f$. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора нормированной циклической частоты `w`. \n \n + +\param[out] h +Указатель на вектор комплексного коэффициента передачи +\f$ H \left(e^{j \omega} \right)\f$, рассчитанного для +циклической частоты `w`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + + +\return +`RES_OK` Комплексный коэффициент передачи рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Комплексный коэффициент передачи \f$ H \left(e^{j \omega} \right)\f$ +цифрового фильтра представляет собой \f$ 2 \pi-\f$периодическую функцию +нормированной циклической частоты \f$\omega\f$. +Поэтому анализ цифровых фильтров целесообразно вести на одном периоде +повторения \f$ H \left(e^{j \omega} \right)\f$, т.е. в интервале +\f$\omega\f$ от 0 до \f$2 \pi\f$, или от \f$-\pi\f$ до \f$ \pi\f$. \n +Кроме того известно, что для фильтра с вещественными коэффициентами +\f$ H \left(e^{j \omega} \right) = H^* \left(e^{-j \omega} \right)\f$, +а значит, анализ цифрового фильтра с вещественными коэффициентами +достаточно вести для нормированной частоты \f$\omega\f$ от 0 до \f$\pi\f$. + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API freqz(double* b, double* a, int ord, double* w, + int n, complex_t *h) +{ + complex_t jw; + complex_t *bc = NULL; + complex_t *ac = NULL; + complex_t num, den; + double mag; + int k; + int res; + + if(!b || !w || !h) + return ERROR_PTR; + if(ord<0) + return ERROR_FILTER_ORD; + if(n<1) + return ERROR_SIZE; + + + bc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(b, ord+1, bc); + if( res!=RES_OK ) + goto exit_label; + + if(a) + { + /* IIR filter if a != NULL */ + ac = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = re2cmplx(a, ord+1, ac); + if( res!=RES_OK ) + goto exit_label; + for(k = 0; k < n; k++) + { + RE(jw) = cos(w[k]); + IM(jw) = -sin(w[k]); + res = polyval_cmplx(bc, ord, &jw, 1, &num); + if(res != RES_OK) + goto exit_label; + res = polyval_cmplx(ac, ord, &jw, 1, &den); + if(res != RES_OK) + goto exit_label; + mag = ABSSQR(den); + if(mag == 0.0) + { + res = ERROR_DIV_ZERO; + goto exit_label; + } + mag = 1.0 / mag; + RE(h[k]) = CMCONJRE(num, den) * mag; + IM(h[k]) = CMCONJIM(num, den) * mag; + } + } + else + { + /* FIR filter if a == NULL */ + for(k = 0; k < n; k++) + { + RE(jw) = cos(w[k]); + IM(jw) = -sin(w[k]); + res = polyval_cmplx(bc, ord, &jw, 1, h+k); + if(res != RES_OK) + goto exit_label; + } + } + res = RES_OK; +exit_label: + if(bc) + free(bc); + if(ac) + free(ac); + return res; } @@ -522,50 +865,52 @@ exit_label: -/******************************************************************************* -Unwrap function -*******************************************************************************/ +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif int DSPL_API unwrap(double* phi, int n, double lev, double mar) { - double a[2] = {0.0, 0.0}; - double d; - double th; - int k; - int flag = 1; + double a[2] = {0.0, 0.0}; + double d; + double th; + int k; + int flag = 1; + if(!phi) + return ERROR_PTR; - if(!phi) - return ERROR_PTR; + if(n<1) + return ERROR_SIZE; - if(n<1) - return ERROR_SIZE; + if(lev<=0 || mar <=0) + return ERROR_UNWRAP; - if(lev<=0 || mar <=0) - return ERROR_UNWRAP; - - th = mar*lev; - while(flag) - { - flag = 0; - a[0] = a[1] = 0.0; - for(k = 0; k th) - { - a[0] -= lev; - flag = 1; - } - if( d < -th) - { - a[0] += lev; - flag = 1; - } - phi[k]+=a[1]; - a[1] = a[0]; + flag = 0; + a[0] = a[1] = 0.0; + for(k = 0; k th) + { + a[0] -= lev; + flag = 1; + } + if( d < -th) + { + a[0] += lev; + flag = 1; + } + phi[k]+=a[1]; + a[1] = a[0]; + } + phi[n-1]+=a[1]; } - phi[n-1]+=a[1]; - } return RES_OK; } diff --git a/dspl/src/filter_ap.c b/dspl/src/filter_ap.c index 8be290d..b3c9c14 100644 --- a/dspl/src/filter_ap.c +++ b/dspl/src/filter_ap.c @@ -5,17 +5,17 @@ * This file is part of libdspl-2.0. * * is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by +* it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ #include @@ -32,39 +32,39 @@ Analog Normalized Butterworth filter *******************************************************************************/ int DSPL_API butter_ap(double rp, int ord, double* b, double* a) { - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np; + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np; - if(rp < 0.0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; + if(rp < 0.0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); - res = butter_ap_zp(ord, rp, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; + res = butter_ap_zp(ord, rp, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; - b[0] = a[0]; + b[0] = a[0]; exit_label: - if(z) - free(z); - if(p) - free(p); - return res; + if(z) + free(z); + if(p) + free(p); + return res; } @@ -80,42 +80,42 @@ Analog Normalized Butterworth filter zeros and poles int DSPL_API butter_ap_zp(int ord, double rp, complex_t* z, int* nz, complex_t *p, int* np) { - double alpha; - double theta; - double ep; - int r; - int L; - int ind = 0, k; + double alpha; + double theta; + double ep; + int r; + int L; + int ind = 0, k; - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; - ep = sqrt(pow(10.0, rp*0.1) - 1.0); - r = ord % 2; - L = (int)((ord-r)/2); + ep = sqrt(pow(10.0, rp*0.1) - 1.0); + r = ord % 2; + L = (int)((ord-r)/2); - alpha = pow(ep, -1.0/(double)ord); - if(r) - { - RE(p[ind]) = -alpha; - IM(p[ind]) = 0.0; - ind++; - } - for(k = 0; k < L; k++) - { - theta = M_PI*(double)(2*k + 1)/(double)(2*ord); - RE(p[ind]) = RE(p[ind+1]) = -alpha * sin(theta); - IM(p[ind]) = alpha * cos(theta); - IM(p[ind+1]) = -alpha * cos(theta); - ind+=2; - } - *np = ord; - *nz = 0; - return RES_OK; + alpha = pow(ep, -1.0/(double)ord); + if(r) + { + RE(p[ind]) = -alpha; + IM(p[ind]) = 0.0; + ind++; + } + for(k = 0; k < L; k++) + { + theta = M_PI*(double)(2*k + 1)/(double)(2*ord); + RE(p[ind]) = RE(p[ind+1]) = -alpha * sin(theta); + IM(p[ind]) = alpha * cos(theta); + IM(p[ind+1]) = -alpha * cos(theta); + ind+=2; + } + *np = ord; + *nz = 0; + return RES_OK; } @@ -128,52 +128,52 @@ Analog Normalized Chebyshev type 1 filter *******************************************************************************/ int DSPL_API cheby1_ap(double rp, int ord, double* b, double* a) { - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np, k; - complex_t h0 = {1.0, 0.0}; - double tmp; + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np, k; + complex_t h0 = {1.0, 0.0}; + double tmp; - if(rp < 0.0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; + if(rp < 0.0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); - res = cheby1_ap_zp(ord, rp, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; + res = cheby1_ap_zp(ord, rp, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; - if(!(ord % 2)) - RE(h0) = 1.0 / pow(10.0, rp*0.05); + if(!(ord % 2)) + RE(h0) = 1.0 / pow(10.0, rp*0.05); - for(k = 0; k < np; k++) - { - tmp = CMRE(h0, p[k]); - IM(h0) = CMIM(h0, p[k]); - RE(h0) = tmp; - } + for(k = 0; k < np; k++) + { + tmp = CMRE(h0, p[k]); + IM(h0) = CMIM(h0, p[k]); + RE(h0) = tmp; + } - b[0] = fabs(RE(h0)); + b[0] = fabs(RE(h0)); exit_label: - if(z) - free(z); - if(p) - free(p); - return res; + if(z) + free(z); + if(p) + free(p); + return res; } @@ -184,50 +184,50 @@ exit_label: Analog Normalized Chebyshev type 1 filter zeros and poles *******************************************************************************/ int DSPL_API cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, - complex_t *p, int* np) + complex_t* p, int* np) { - double theta; - double ep; - double beta; - double shbeta; - double chbeta; - int r; - int L; - int ind = 0, k; + double theta; + double ep; + double beta; + double shbeta; + double chbeta; + int r; + int L; + int ind = 0, k; - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; - ep = sqrt(pow(10.0, rp*0.1) - 1.0); - r = ord % 2; - L = (int)((ord-r)/2); + ep = sqrt(pow(10.0, rp*0.1) - 1.0); + r = ord % 2; + L = (int)((ord-r)/2); - beta = asinh(1.0/ep)/(double)ord; - chbeta = cosh(beta); - shbeta = sinh(beta); + beta = asinh(1.0/ep)/(double)ord; + chbeta = cosh(beta); + shbeta = sinh(beta); - if(r) - { - RE(p[ind]) = -shbeta; - IM(p[ind]) = 0.0; - ind++; - } - for(k = 0; k < L; k++) - { - theta = M_PI*(double)(2*k + 1)/(double)(2*ord); - RE(p[ind]) = RE(p[ind+1]) = -shbeta * sin(theta); - IM(p[ind]) = chbeta * cos(theta); - IM(p[ind+1]) = -IM(p[ind]); - ind+=2; - } - *np = ord; - *nz = 0; - return RES_OK; + if(r) + { + RE(p[ind]) = -shbeta; + IM(p[ind]) = 0.0; + ind++; + } + for(k = 0; k < L; k++) + { + theta = M_PI*(double)(2*k + 1)/(double)(2*ord); + RE(p[ind]) = RE(p[ind+1]) = -shbeta * sin(theta); + IM(p[ind]) = chbeta * cos(theta); + IM(p[ind+1]) = -IM(p[ind]); + ind+=2; + } + *np = ord; + *nz = 0; + return RES_OK; } @@ -238,43 +238,43 @@ int DSPL_API cheby1_ap_zp(int ord, double rp, complex_t* z, int* nz, ******************************************************************************/ int DSPL_API cheby2_ap(double rs, int ord, double* b, double* a) { - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np; - double norm; + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np; + double norm; - if(rs < 0.0) - return ERROR_FILTER_RP; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; + if(rs < 0.0) + return ERROR_FILTER_RP; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); - res = cheby2_ap_zp(ord, rs, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; + res = cheby2_ap_zp(ord, rs, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; - norm = a[0] / b[0]; + norm = a[0] / b[0]; - for(nz = 0; nz < ord+1; nz++) - b[nz]*=norm; + for(nz = 0; nz < ord+1; nz++) + b[nz]*=norm; exit_label: - if(z) - free(z); - if(p) - free(p); - return res; + if(z) + free(z); + if(p) + free(p); + return res; } @@ -285,27 +285,27 @@ exit_label: ******************************************************************************/ int DSPL_API cheby2_ap_wp1(double rp, double rs, int ord, double* b, double* a) { - int err; - double es, gp, alpha, beta, y, wp; + int err; + double es, gp, alpha, beta, y, wp; - if(rp <= 0) - return ERROR_FILTER_RP; + if(rp <= 0) + return ERROR_FILTER_RP; - err = cheby2_ap(rs, ord, b, a); - if(err!=RES_OK) - goto exit_label; + err = cheby2_ap(rs, ord, b, a); + if(err!=RES_OK) + goto exit_label; - es = sqrt(pow(10.0, rs*0.1) - 1.0); - gp = pow(10.0, -rp*0.05); - alpha = gp * es / sqrt(1.0 - gp*gp); - beta = alpha + sqrt(alpha * alpha - 1.0); - y = log(beta)/ (double)ord; - wp = 2.0 / (exp(y) + exp(-y)); - - err = low2low(b, a, ord, wp, 1.0, b, a); + es = sqrt(pow(10.0, rs*0.1) - 1.0); + gp = pow(10.0, -rp*0.05); + alpha = gp * es / sqrt(1.0 - gp*gp); + beta = alpha + sqrt(alpha * alpha - 1.0); + y = log(beta)/ (double)ord; + wp = 2.0 / (exp(y) + exp(-y)); + + err = low2low(b, a, ord, wp, 1.0, b, a); exit_label: - return err; + return err; } @@ -315,67 +315,67 @@ exit_label: Analog Normalized Chebyshev type 2 filter zeros and poles *******************************************************************************/ int DSPL_API cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, - complex_t *p, int* np) + complex_t *p, int* np) { - double es; - int L, r, k; - double beta; - int iz, ip; + double es; + int L, r, k; + double beta; + int iz, ip; - double alpha; - double chb, shb, sa, ca; - double ssh2, cch2; + double alpha; + double chb, shb, sa, ca; + double ssh2, cch2; - if(rs < 0 || rs == 0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; + if(rs < 0 || rs == 0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; - es = sqrt(pow(10.0, rs*0.1) - 1.0); - r = ord % 2; - L = (int)((ord-r)/2); + es = sqrt(pow(10.0, rs*0.1) - 1.0); + r = ord % 2; + L = (int)((ord-r)/2); - beta = asinh(es)/(double)ord; + beta = asinh(es)/(double)ord; - chb = cosh(beta); - shb = sinh(beta); + chb = cosh(beta); + shb = sinh(beta); - iz = ip = 0; + iz = ip = 0; - if(r) - { - RE(p[0]) = -1.0 / sinh(beta); - IM(p[0]) = 0.0; - ip = 1; - } + if(r) + { + RE(p[0]) = -1.0 / sinh(beta); + IM(p[0]) = 0.0; + ip = 1; + } - for(k = 0; k < L; k++) - { - alpha = M_PI*(double)(2*k + 1)/(double)(2*ord); - sa = sin(alpha); - ca = cos(alpha); - ssh2 = sa*shb; - ssh2 *= ssh2; + for(k = 0; k < L; k++) + { + alpha = M_PI*(double)(2*k + 1)/(double)(2*ord); + sa = sin(alpha); + ca = cos(alpha); + ssh2 = sa*shb; + ssh2 *= ssh2; - cch2 = ca*chb; - cch2 *= cch2; + cch2 = ca*chb; + cch2 *= cch2; - RE(z[iz]) = RE(z[iz+1]) = 0.0; - IM(z[iz]) = 1.0 / ca; - IM(z[iz+1]) = -IM(z[iz]); - iz+=2; + RE(z[iz]) = RE(z[iz+1]) = 0.0; + IM(z[iz]) = 1.0 / ca; + IM(z[iz+1]) = -IM(z[iz]); + iz+=2; - RE(p[ip]) = RE(p[ip+1]) = -sa*shb / (ssh2 + cch2); - IM(p[ip]) = ca*chb / (ssh2 + cch2); - IM(p[ip+1]) = -IM(p[ip]); - ip+=2; - } - *nz = iz; - *np = ip; + RE(p[ip]) = RE(p[ip+1]) = -sa*shb / (ssh2 + cch2); + IM(p[ip]) = ca*chb / (ssh2 + cch2); + IM(p[ip+1]) = -IM(p[ip]); + ip+=2; + } + *nz = iz; + *np = ip; - return RES_OK; + return RES_OK; } @@ -389,53 +389,53 @@ int DSPL_API cheby2_ap_zp(int ord, double rs, complex_t* z, int* nz, *******************************************************************************/ int DSPL_API ellip_ap(double rp, double rs, int ord, double* b, double* a) { - int res; - complex_t *z = NULL; - complex_t *p = NULL; - int nz, np; - double norm, g0; + int res; + complex_t *z = NULL; + complex_t *p = NULL; + int nz, np; + double norm, g0; - if(rp < 0.0) - return ERROR_FILTER_RP; - if(rs < 0.0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!a || !b) - return ERROR_PTR; + if(rp < 0.0) + return ERROR_FILTER_RP; + if(rs < 0.0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!a || !b) + return ERROR_PTR; - z = (complex_t*) malloc(ord*sizeof(complex_t)); - p = (complex_t*) malloc(ord*sizeof(complex_t)); + z = (complex_t*) malloc(ord*sizeof(complex_t)); + p = (complex_t*) malloc(ord*sizeof(complex_t)); - res = ellip_ap_zp(ord, rp, rs, z, &nz, p, &np); - if(res != RES_OK) - goto exit_label; + res = ellip_ap_zp(ord, rp, rs, z, &nz, p, &np); + if(res != RES_OK) + goto exit_label; - res = filter_zp2ab(z, nz, p, np, ord, b, a); - if(res != RES_OK) - goto exit_label; + res = filter_zp2ab(z, nz, p, np, ord, b, a); + if(res != RES_OK) + goto exit_label; - g0 = 1.0; - if(!(ord % 2)) - { - g0 = 1.0 / pow(10.0, rp*0.05); - } + g0 = 1.0; + if(!(ord % 2)) + { + g0 = 1.0 / pow(10.0, rp*0.05); + } - norm = g0 * a[0] / b[0]; + norm = g0 * a[0] / b[0]; - for(nz = 0; nz < ord+1; nz++) - b[nz]*=norm; + for(nz = 0; nz < ord+1; nz++) + b[nz]*=norm; - exit_label: - if(z) - free(z); - if(p) - free(p); - return res; + exit_label: + if(z) + free(z); + if(p) + free(p); + return res; } @@ -447,94 +447,94 @@ int DSPL_API ellip_ap(double rp, double rs, int ord, double* b, double* a) A *nalog Normalized Chebyshev type 2 filter zeros and poles *******************************************************************************/ int DSPL_API ellip_ap_zp(int ord, double rp, double rs, - complex_t* z, int* nz, complex_t* p, int* np) + complex_t* z, int* nz, complex_t* p, int* np) { - double es, ep; - int L, r, n, res; - int iz, ip; - double ke, k, u, t; - complex_t tc, v0, jv0; + double es, ep; + int L, r, n, res; + int iz, ip; + double ke, k, u, t; + complex_t tc, v0, jv0; - if(rp < 0 || rp == 0) - return ERROR_FILTER_RP; - if(rs < 0 || rs == 0) - return ERROR_FILTER_RS; - if(ord < 1) - return ERROR_FILTER_ORD; - if(!z || !p || !nz || !np) - return ERROR_PTR; + if(rp < 0 || rp == 0) + return ERROR_FILTER_RP; + if(rs < 0 || rs == 0) + return ERROR_FILTER_RS; + if(ord < 1) + return ERROR_FILTER_ORD; + if(!z || !p || !nz || !np) + return ERROR_PTR; - es = sqrt(pow(10.0, rs*0.1) - 1.0); - ep = sqrt(pow(10.0, rp*0.1) - 1.0); - ke = ep / es; + es = sqrt(pow(10.0, rs*0.1) - 1.0); + ep = sqrt(pow(10.0, rp*0.1) - 1.0); + ke = ep / es; - r = ord % 2; - L = (int)((ord-r)/2); + r = ord % 2; + L = (int)((ord-r)/2); - res = ellip_modulareq(rp, rs, ord, &k); - if(res != RES_OK) - return res; - // v0 - RE(tc) = 0.0; - IM(tc) = 1.0 / ep; - - ellip_asn_cmplx(&tc, 1, ke, &v0); - - t = RE(v0); - RE(v0) = IM(v0) / (double)ord; - IM(v0) = -t / (double)ord; - - RE(jv0) = -IM(v0); - IM(jv0) = RE(v0); - - - iz = ip = 0; - - if(r) - { - res = ellip_sn_cmplx(&jv0, 1, k, &tc); + res = ellip_modulareq(rp, rs, ord, &k); if(res != RES_OK) - return res; - RE(p[0]) = -IM(tc); - IM(p[0]) = RE(tc); - ip = 1; - } + return res; + // v0 + RE(tc) = 0.0; + IM(tc) = 1.0 / ep; - for(n = 0; n < L; n++) - { - u = (double)(2 * n + 1)/(double)ord; + ellip_asn_cmplx(&tc, 1, ke, &v0); - res = ellip_cd(& u, 1, k, &t); - if(res != RES_OK) - return res; + t = RE(v0); + RE(v0) = IM(v0) / (double)ord; + IM(v0) = -t / (double)ord; - RE(z[iz]) = RE(z[iz+1]) = 0.0; - IM(z[iz]) = 1.0/(k*t); - IM(z[iz+1]) = -1.0/(k*t); - iz+=2; - - RE(tc) = u - RE(jv0); - IM(tc) = - IM(jv0); - - res = ellip_cd_cmplx(&tc, 1, k, p+ip+1); - if(res != RES_OK) - return res; - - RE(p[ip]) = -IM(p[ip+1]); - IM(p[ip]) = RE(p[ip+1]); - - RE(p[ip+1]) = RE(p[ip]); - IM(p[ip+1]) = -IM(p[ip]); - - ip+=2; + RE(jv0) = -IM(v0); + IM(jv0) = RE(v0); - } - *nz = iz; - *np = ip; + iz = ip = 0; - return RES_OK; + if(r) + { + res = ellip_sn_cmplx(&jv0, 1, k, &tc); + if(res != RES_OK) + return res; + RE(p[0]) = -IM(tc); + IM(p[0]) = RE(tc); + ip = 1; + } + + for(n = 0; n < L; n++) + { + u = (double)(2 * n + 1)/(double)ord; + + res = ellip_cd(& u, 1, k, &t); + if(res != RES_OK) + return res; + + RE(z[iz]) = RE(z[iz+1]) = 0.0; + IM(z[iz]) = 1.0/(k*t); + IM(z[iz+1]) = -1.0/(k*t); + iz+=2; + + RE(tc) = u - RE(jv0); + IM(tc) = - IM(jv0); + + res = ellip_cd_cmplx(&tc, 1, k, p+ip+1); + if(res != RES_OK) + return res; + + RE(p[ip]) = -IM(p[ip+1]); + IM(p[ip]) = RE(p[ip+1]); + + RE(p[ip+1]) = RE(p[ip]); + IM(p[ip+1]) = -IM(p[ip]); + + ip+=2; + + + } + *nz = iz; + *np = ip; + + return RES_OK; } @@ -544,41 +544,41 @@ int DSPL_API ellip_ap_zp(int ord, double rp, double rs, Zeros and poles to filter coefficients recalc *******************************************************************************/ int DSPL_API filter_zp2ab(complex_t* z, int nz, complex_t* p, int np, - int ord, double* b, double* a) + int ord, double* b, double* a) { - complex_t *acc = NULL; - int res; + complex_t *acc = NULL; + int res; - if(!z || !p || !b || !a) - return ERROR_PTR; - if(nz < 0 || np < 0) - return ERROR_SIZE; - if(nz > ord || np > ord) - return ERROR_POLY_ORD; + if(!z || !p || !b || !a) + return ERROR_PTR; + if(nz < 0 || np < 0) + return ERROR_SIZE; + if(nz > ord || np > ord) + return ERROR_POLY_ORD; - acc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); - res = poly_z2a_cmplx(z, nz, ord, acc); - if(res != RES_OK) - goto exit_label; + acc = (complex_t*) malloc((ord+1) * sizeof(complex_t)); + res = poly_z2a_cmplx(z, nz, ord, acc); + if(res != RES_OK) + goto exit_label; - res = cmplx2re(acc, ord+1, b, NULL); - if(res != RES_OK) - goto exit_label; + res = cmplx2re(acc, ord+1, b, NULL); + if(res != RES_OK) + goto exit_label; - res = poly_z2a_cmplx(p, np, ord, acc); - if(res != RES_OK) - goto exit_label; + res = poly_z2a_cmplx(p, np, ord, acc); + if(res != RES_OK) + goto exit_label; - res = cmplx2re(acc, ord+1, a, NULL); - if(res != RES_OK) - goto exit_label; + res = cmplx2re(acc, ord+1, a, NULL); + if(res != RES_OK) + goto exit_label; exit_label: - if(acc) - free(acc); - return res; + if(acc) + free(acc); + return res; } diff --git a/dspl/src/math.c b/dspl/src/math.c index 925b3af..0e00b52 100644 --- a/dspl/src/math.c +++ b/dspl/src/math.c @@ -11,11 +11,11 @@ * * DSPL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License -* along with Foobar. If not, see . +* along with Foobar. If not, see . */ @@ -26,48 +26,54 @@ - -/****************************************************************************** +#if DOXYGEN_ENGLISH +/*! **************************************************************************** \ingroup SPEC_MATH_TRIG_GROUP \fn int acos_cmplx(complex_t* x, int n, complex_t *y) -\brief The inverse of the cosine function the complex vector argument `x` +\brief The inverse of the cosine function the complex vector argument `x` Function calculates the inverse of the cosine function as: \n \f[ \textrm{Arccos}(x) = \frac{\pi}{2} - \textrm{Arcsin}(x) = \frac{\pi}{2} -j \textrm{Ln}\left( j x + \sqrt{1 - x^2} \right) -\f] +\f] -\param[in] x Pointer to the argument vector `x`. \n - Vector size is `[n x 1]`. \n \n +\param[in] x +Pointer to the argument vector `x`. \n +Vector size is `[n x 1]`. \n +\n -\param[in] n Input vector `x` and the inverse cosine vector `y` size. \n \n - +\param[in] n +Input vector `x` and the inverse cosine vector `y` size. \n +\n -\param[out] y Pointer to the output complex vector `y`, - corresponds to the input vector `x`. \n - Vector size is `[n x 1]`. \n - Memory must be allocated. \n \n + +\param[out] y +Pointer to the output complex vector `y`, +corresponds to the input vector `x`. \n +Vector size is `[n x 1]`. \n +Memory must be allocated. \n +\n \return -`RES_OK` if function calculated successfully. \n +`RES_OK` if function calculated successfully. \n Else \ref ERROR_CODE_GROUP "code error". \n Example: \n \code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - complex_t y[3]; - int k; - - acos_cmplx(x, 3, y); - - for(k = 0; k < 3; k++) - printf("acos_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", - RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + acos_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("acos_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); \endcode - \n +\n Output is: \n \verbatim @@ -78,99 +84,115 @@ acos_cmplx(5.0+6.0j) = 0.880-2.749j \author Sergey Bakhurin www.dsplib.org -*******************************************************************************/ +***************************************************************************** */ +#endif + +#if DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_TRIG_GROUP +\fn int acos_cmplx(complex_t* x, int n, complex_t *y) +\brief Арккосинус комплексного аргумента `x` + +Функция рассчитывает значения арккосинуса комплексного аргумента, +заданного вектором `x` длины `n`: \n +\f[ +\textrm{Arccos}(x) = \frac{\pi}{2} - \textrm{Arcsin}(x) = +\frac{\pi}{2} -j \textrm{Ln}\left( j x + \sqrt{1 - x^2} \right) +\f] + + +\param[in] x +Указатель на вектор аргумента комплексного арккосинуса. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер входного и выходного векторов `x` и `y`. \n \n + + +\param[out] y +Указатель на вектор значений комплексного арккосинуса, +соответствующего входному вектору `x`. \n +Размер массива `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` если значение функции рассчитано успешно . \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки": \n + +\note +Функция может использоваться для расчета арккосинуса аргумента +большего единицы, когда вещественная функция `acos` не определена. + +Например при выполнении следующего кода +\code{.cpp} + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3]; + int k; + + acos_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("acos_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); +\endcode +\n + +Результатом работы будет + +\verbatim +acos_cmplx(1.0+2.0j) = 1.144-1.529j +acos_cmplx(3.0+4.0j) = 0.937-2.306j +acos_cmplx(5.0+6.0j) = 0.880-2.749j +\endverbatim + +\author +Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif int DSPL_API acos_cmplx(complex_t* x, int n, complex_t *y) { - int k, res; - double pi2 = 0.5 * M_PI; + int k, res; + double pi2 = 0.5 * M_PI; - res = asin_cmplx(x, n, y); - if(res != RES_OK) - return res; + res = asin_cmplx(x, n, y); + if(res != RES_OK) + return res; - for(k = 0; k < n; k++) - { - RE(y[k]) = pi2 - RE(y[k]); - IM(y[k]) = - IM(y[k]); - } - return RES_OK; + for(k = 0; k < n; k++) + { + RE(y[k]) = pi2 - RE(y[k]); + IM(y[k]) = - IM(y[k]); + } + return RES_OK; } /****************************************************************************** -\ingroup SPEC_MATH_TRIG_GROUP -\fn int asin_cmplx(complex_t* x, int n, complex_t *y) -\brief The inverse of the sine function the complex vector argument `x` - -Function calculates the inverse of the sine function as: \n - -\f[ - \textrm{Arcsin}(x) = j \textrm{Ln}\left( j x + \sqrt{1 - x^2} \right) -\f] - - -\param[in] x Pointer to the argument vector `x`. \n - Vector size is `[n x 1]`. \n \n - -\param[in] n Input vector `x` and the inverse sine vector `y` size. \n \n - - -\param[out] y Pointer to the output complex vector `y`, - corresponds to the input vector `x`. \n - Vector size is `[n x 1]`. \n - Memory must be allocated. \n \n - -\return -`RES_OK` if function calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: \n -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - complex_t y[3]; - int k; - - asin_cmplx(x, 3, y); - for(k = 0; k < 3; k++) - printf("asin_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", - RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); - -\endcode - \n - -Output is: \n -\verbatim -asin_cmplx(1.0+2.0j) = 0.427+1.529j -asin_cmplx(3.0+4.0j) = 0.634+2.306j -asin_cmplx(5.0+6.0j) = 0.691+2.749j -\endverbatim - -\author -Sergey Bakhurin www.dsplib.org +The inverse of the sine function the complex vector argument `x` *******************************************************************************/ int DSPL_API asin_cmplx(complex_t* x, int n, complex_t *y) { - int k; - complex_t tmp; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + complex_t tmp; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - { - RE(tmp) = 1.0 - CMRE(x[k], x[k]); /* 1-x[k]^2 */ - IM(tmp) = - CMIM(x[k], x[k]); /* 1-x[k]^2 */ - sqrt_cmplx(&tmp, 1, y+k); /* sqrt(1 - x[k]^2) */ - RE(y[k]) -= IM(x[k]); /* j * x[k] + sqrt(1 - x[k]^2) */ - IM(y[k]) += RE(x[k]); /* j * x[k] + sqrt(1 - x[k]^2) */ - log_cmplx(y+k, 1, &tmp); /* log( j * x[k] + sqrt(1 - x[k]^2) ) */ - RE(y[k]) = IM(tmp); /* -j * log( j * x[k] + sqrt(1 - x[k]^2) ) */ - IM(y[k]) = -RE(tmp); /* -j * log( j * x[k] + sqrt(1 - x[k]^2) ) */ - } - return RES_OK; + for(k = 0; k < n; k++) + { + RE(tmp) = 1.0 - CMRE(x[k], x[k]); /* 1-x[k]^2 */ + IM(tmp) = - CMIM(x[k], x[k]); /* 1-x[k]^2 */ + sqrt_cmplx(&tmp, 1, y+k); /* sqrt(1 - x[k]^2) */ + RE(y[k]) -= IM(x[k]); /* j * x[k] + sqrt(1 - x[k]^2) */ + IM(y[k]) += RE(x[k]); /* j * x[k] + sqrt(1 - x[k]^2) */ + log_cmplx(y+k, 1, &tmp); /* log( j * x[k] + sqrt(1 - x[k]^2) ) */ + RE(y[k]) = IM(tmp); /* -j * log( j * x[k] + sqrt(1 - x[k]^2) ) */ + IM(y[k]) = -RE(tmp); /* -j * log( j * x[k] + sqrt(1 - x[k]^2) ) */ + } + return RES_OK; } @@ -179,83 +201,83 @@ int DSPL_API asin_cmplx(complex_t* x, int n, complex_t *y) /******************************************************************************* Modified Bessel Function of the First Kind – I0(x) [1] -[1] Rational Approximations for the Modified Bessel Function - of the First Kind – I0(x) for Computations with Double Precision - by PAVEL HOLOBORODKO on NOVEMBER 11, 2015 - - https://www.advanpix.com/2015/11/11/ +[1] Rational Approximations for the Modified Bessel Function + of the First Kind – I0(x) for Computations with Double Precision + by PAVEL HOLOBORODKO on NOVEMBER 11, 2015 + + https://www.advanpix.com/2015/11/11/ *******************************************************************************/ int DSPL_API bessel_i0(double* x, int n, double* y) { - double P16[17] = { 1.0000000000000000000000801e+00, - 2.4999999999999999999629693e-01, - 2.7777777777777777805664954e-02, - 1.7361111111111110294015271e-03, - 6.9444444444444568581891535e-05, - 1.9290123456788994104574754e-06, - 3.9367598891475388547279760e-08, - 6.1511873265092916275099070e-10, - 7.5940584360755226536109511e-12, - 7.5940582595094190098755663e-14, - 6.2760839879536225394314453e-16, - 4.3583591008893599099577755e-18, - 2.5791926805873898803749321e-20, - 1.3141332422663039834197910e-22, - 5.9203280572170548134753422e-25, - 2.0732014503197852176921968e-27, - 1.1497640034400735733456400e-29}; + double P16[17] = { 1.0000000000000000000000801e+00, + 2.4999999999999999999629693e-01, + 2.7777777777777777805664954e-02, + 1.7361111111111110294015271e-03, + 6.9444444444444568581891535e-05, + 1.9290123456788994104574754e-06, + 3.9367598891475388547279760e-08, + 6.1511873265092916275099070e-10, + 7.5940584360755226536109511e-12, + 7.5940582595094190098755663e-14, + 6.2760839879536225394314453e-16, + 4.3583591008893599099577755e-18, + 2.5791926805873898803749321e-20, + 1.3141332422663039834197910e-22, + 5.9203280572170548134753422e-25, + 2.0732014503197852176921968e-27, + 1.1497640034400735733456400e-29}; - double P22[23] = { 3.9894228040143265335649948e-01, - 4.9867785050353992900698488e-02, - 2.8050628884163787533196746e-02, - 2.9219501690198775910219311e-02, - 4.4718622769244715693031735e-02, - 9.4085204199017869159183831e-02, - -1.0699095472110916094973951e-01, - 2.2725199603010833194037016e+01, - -1.0026890180180668595066918e+03, - 3.1275740782277570164423916e+04, - -5.9355022509673600842060002e+05, - 2.6092888649549172879282592e+06, - 2.3518420447411254516178388e+08, - -8.9270060370015930749184222e+09, - 1.8592340458074104721496236e+11, - -2.6632742974569782078420204e+12, - 2.7752144774934763122129261e+13, - -2.1323049786724612220362154e+14, - 1.1989242681178569338129044e+15, - -4.8049082153027457378879746e+15, - 1.3012646806421079076251950e+16, - -2.1363029690365351606041265e+16, - 1.6069467093441596329340754e+16}; + double P22[23] = { 3.9894228040143265335649948e-01, + 4.9867785050353992900698488e-02, + 2.8050628884163787533196746e-02, + 2.9219501690198775910219311e-02, + 4.4718622769244715693031735e-02, + 9.4085204199017869159183831e-02, + -1.0699095472110916094973951e-01, + 2.2725199603010833194037016e+01, + -1.0026890180180668595066918e+03, + 3.1275740782277570164423916e+04, + -5.9355022509673600842060002e+05, + 2.6092888649549172879282592e+06, + 2.3518420447411254516178388e+08, + -8.9270060370015930749184222e+09, + 1.8592340458074104721496236e+11, + -2.6632742974569782078420204e+12, + 2.7752144774934763122129261e+13, + -2.1323049786724612220362154e+14, + 1.1989242681178569338129044e+15, + -4.8049082153027457378879746e+15, + 1.3012646806421079076251950e+16, + -2.1363029690365351606041265e+16, + 1.6069467093441596329340754e+16}; - double x2; - int k; - - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - - for(k =0; k < n; k++) - { - if(x[k] < 0.0) - return ERROR_NEGATIVE; - - if(x[k] < 7.75) + double x2; + int k; + + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + + for(k =0; k < n; k++) { - x2 = x[k] * x[k] * 0.25; - polyval(P16, 16, &x2, 1, y+k); - y[k] = x2 * y[k] + 1.0; + if(x[k] < 0.0) + return ERROR_NEGATIVE; + + if(x[k] < 7.75) + { + x2 = x[k] * x[k] * 0.25; + polyval(P16, 16, &x2, 1, y+k); + y[k] = x2 * y[k] + 1.0; + } + else + { + x2 = 1.0 / x[k]; + polyval(P22, 22, &x2, 1, y+k); + y[k] *= exp(x[k]) / sqrt(x[k]); + } } - else - { - x2 = 1.0 / x[k]; - polyval(P22, 22, &x2, 1, y+k); - y[k] *= exp(x[k]) / sqrt(x[k]); - } - } - return RES_OK; + return RES_OK; } @@ -264,155 +286,58 @@ module operator for double *******************************************************************************/ double DSPL_API dmod (double x, double y) { - if(y == 0.0) - return x; - return x - floor(x/y) * y; + if(y == 0.0) + return x; + return x - floor(x/y) * y; } /****************************************************************************** -\ingroup SPEC_MATH_TRIG_GROUP -\fn int cos_cmplx(complex_t* x, int n, complex_t *y) -\brief The cosine function the complex vector argument `x` - -Function calculates the cosine function as: \n - -\f[ -\textrm{cos}(x) = \frac{\exp(jx) + \exp(-jx)}{2} -\f] - - -\param[in] x Pointer to the argument vector `x`. \n - Vector size is `[n x 1]`. \n \n - -\param[in] n Input vector `x` and the cosine vector `y` size. \n \n - - -\param[out] y Pointer to the output complex vector `y`, - corresponds to the input vector `x`. \n - Vector size is `[n x 1]`. \n - Memory must be allocated. \n \n - -\return -`RES_OK` if function calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: \n -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - complex_t y[3]; - int k; - - cos_cmplx(x, 3, y); - - for(k = 0; k < 3; k++) - printf("cos_cmplx(%.1f%+.1fj) = %9.3f%+9.3fj\n", - RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); - -\endcode - \n - -Output is: \n -\verbatim -cos_cmplx(1.0+2.0j) = 2.033 -3.052j -cos_cmplx(3.0+4.0j) = -27.035 -3.851j -cos_cmplx(5.0+6.0j) = 57.219 +193.428j -\endverbatim - -\author -Sergey Bakhurin www.dsplib.org +The cosine function the complex vector argument `x` *******************************************************************************/ int DSPL_API cos_cmplx(complex_t* x, int n, complex_t *y) { - int k; - double ep, em, sx, cx; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + double ep, em, sx, cx; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - { - ep = exp( IM(x[k])); - em = exp(-IM(x[k])); - sx = 0.5 * sin(RE(x[k])); - cx = 0.5 * cos(RE(x[k])); - RE(y[k]) = cx * (em + ep); - IM(y[k]) = sx * (em - ep); - } - return RES_OK; + for(k = 0; k < n; k++) + { + ep = exp( IM(x[k])); + em = exp(-IM(x[k])); + sx = 0.5 * sin(RE(x[k])); + cx = 0.5 * cos(RE(x[k])); + RE(y[k]) = cx * (em + ep); + IM(y[k]) = sx * (em - ep); + } + return RES_OK; } /****************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int log_cmplx(complex_t* x, int n, complex_t *y) -\brief The logarithm function the complex vector argument `x` - -Function calculates the logarithm function as: \n - -\f[ -\textrm{Ln}(x) = j \varphi + \ln(|x|), -\f] -here \f$\varphi\f$ - the complex number phase. - -\param[in] x Pointer to the argument vector `x`. \n - Vector size is `[n x 1]`. \n \n - -\param[in] n Input vector `x` and the logarithm vector `y` size. \n \n - - -\param[out] y Pointer to the output complex vector `y`, - corresponds to the input vector `x`. \n - Vector size is `[n x 1]`. \n - Memory must be allocated. \n \n - -\return -`RES_OK` if function calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: \n -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - complex_t y[3]; - int k; - - log_cmplx(x, 3, y); - - for(k = 0; k < 3; k++) - printf("log_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", - RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); -\endcode - \n - -Output is: \n -\verbatim -log_cmplx(1.0+2.0j) = 0.805+1.107j -log_cmplx(3.0+4.0j) = 1.609+0.927j -log_cmplx(5.0+6.0j) = 2.055+0.876j -\endverbatim - -\author -Sergey Bakhurin www.dsplib.org +The logarithm function the complex vector argument `x` *******************************************************************************/ int DSPL_API log_cmplx(complex_t* x, int n, complex_t *y) { - int k; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - { - RE(y[k]) = 0.5 * log(ABSSQR(x[k])); - IM(y[k]) = atan2(IM(x[k]), RE(x[k])); - } - return RES_OK; + for(k = 0; k < n; k++) + { + RE(y[k]) = 0.5 * log(ABSSQR(x[k])); + IM(y[k]) = atan2(IM(x[k]), RE(x[k])); + } + return RES_OK; } @@ -422,76 +347,27 @@ int DSPL_API log_cmplx(complex_t* x, int n, complex_t *y) /****************************************************************************** -\ingroup SPEC_MATH_TRIG_GROUP -\fn int sin_cmplx(complex_t* x, int n, complex_t *y) -\brief The sine function the complex vector argument `x` - -Function calculates the sine function as: \n - -\f[ -\textrm{cos}(x) = \frac{\exp(jx) - \exp(-jx)}{2j} -\f] - - -\param[in] x Pointer to the argument vector `x`. \n - Vector size is `[n x 1]`. \n \n - -\param[in] n Input vector `x` and the sine vector `y` size. \n \n - - -\param[out] y Pointer to the output complex vector `y`, - corresponds to the input vector `x`. \n - Vector size is `[n x 1]`. \n - Memory must be allocated. \n \n - -\return -`RES_OK` if function calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". \n - -Example: \n -\code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - complex_t y[3]; - int k; - - sin_cmplx(x, 3, y); - - for(k = 0; k < 3; k++) - printf("sin_cmplx(%.1f%+.1fj) = %9.3f%+9.3fj\n", - RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); - -\endcode - \n - -Output is: \n -\verbatim -sin_cmplx(1.0+2.0j) = 3.166 +1.960j -sin_cmplx(3.0+4.0j) = 3.854 -27.017j -sin_cmplx(5.0+6.0j) = -193.430 +57.218j -\endverbatim - -\author -Sergey Bakhurin www.dsplib.org +\brief The sine function the complex vector argument `x` *******************************************************************************/ int DSPL_API sin_cmplx(complex_t* x, int n, complex_t *y) { - int k; - double ep, em, sx, cx; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + double ep, em, sx, cx; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - { - ep = exp( IM(x[k])); - em = exp(-IM(x[k])); - sx = 0.5 * sin(RE(x[k])); - cx = 0.5 * cos(RE(x[k])); - RE(y[k]) = sx * (em + ep); - IM(y[k]) = cx * (ep - em); - } - return RES_OK; + for(k = 0; k < n; k++) + { + ep = exp( IM(x[k])); + em = exp(-IM(x[k])); + sx = 0.5 * sin(RE(x[k])); + cx = 0.5 * cos(RE(x[k])); + RE(y[k]) = sx * (em + ep); + IM(y[k]) = cx * (ep - em); + } + return RES_OK; } @@ -504,17 +380,17 @@ sinc(x) = sin(pi*x)/(pi*x) *******************************************************************************/ int DSPL_API sinc(double* x, int n, double a, double* y) { - int k; + int k; - if(!x || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; + if(!x || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - y[k] = (x[k]==0.0) ? 1.0 : sin(a*x[k])/(a*x[k]); + for(k = 0; k < n; k++) + y[k] = (x[k]==0.0) ? 1.0 : sin(a*x[k])/(a*x[k]); - return RES_OK; + return RES_OK; } @@ -527,159 +403,159 @@ Sine integral This function uses Padé approximants of the convergent Taylor series [1] -[1] +[1] https://www.sciencedirect.com/science/article/pii/S221313371500013X?via%3Dihub *******************************************************************************/ int DSPL_API sine_int(double* x, int n, double* si) { - int k, sgn, p; - double num, den, y, x2, x22, z, f, g; - - double A[8] = {+1.00000000000000000E0 , - -4.54393409816329991E-2 , - +1.15457225751016682E-3 , - -1.41018536821330254E-5 , - +9.43280809438713025E-8 , - -3.53201978997168357E-10 , - +7.08240282274875911E-13 , - -6.05338212010422477E-16 }; - - - - double B[7] = {+1.0 , - +1.01162145739225565E-2 , - +4.99175116169755106E-5 , - +1.55654986308745614E-7 , - +3.28067571055789734E-10 , - +4.50490975753865810E-13 , - +3.21107051193712168E-16 }; - - - - double FA[11] = {+1.000000000000000000000E0, - +7.444370681619367006180E2, - +1.963963728951468698010E5, - +2.377503101254318340340E7, - +1.430734038212746368880E9, - +4.33736238870432522765E10, - +6.40533830574022022911E11, - +4.20968180571076940208E12, - +1.00795182980368574617E13, - +4.94816688199951963482E12, - -4.94701168645415959931E11}; - - double FB[10] = {+1.000000000000000000000E0, - +7.464370681619276780310E2, - +1.978652470315839514500E5, - +2.415356701651268451440E7, - +1.474789521929854649580E9, - +4.58595115847765779830E10, - +7.08501308149515401563E11, - +5.06084464593475076774E12, - +1.43468549171581016479E13, - +1.11535493509914254097E13}; - - - - double GA[11] = {+1.000000000000000000E0, - +8.135952011516861500E2, - +2.352391816264782000E5, - +3.125575707957787310E7, - +2.062975951467633540E9, - +6.83052205423625007E10, - +1.09049528450362786E12, - +7.57664583257834349E12, - +1.81004487464664575E13, - +6.43291613143049485E12, - -1.36517137670871689E12}; - - - double GB[10] = {+1.000000000000000000E0, - +8.195952011514515640E2, - +2.400367528355787770E5, - +3.260266616470908220E7, - +2.233555432780993600E9, - +7.87465017341829930E10, - +1.39866710696414565E12, - +1.17164723371736605E13, - +4.01839087307656620E13, - +3.99653257887490811E13}; - - if(!x || !si) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - - - for(p = 0; p < n; p++) - { - sgn = x[p] > 0.0 ? 0 : 1; - y = x[p] < 0.0 ? -x[p] : x[p]; - - if(y < 4) + int k, sgn, p; + double num, den, y, x2, x22, z, f, g; + + double A[8] = {+1.00000000000000000E0, + -4.54393409816329991E-2, + +1.15457225751016682E-3, + -1.41018536821330254E-5, + +9.43280809438713025E-8, + -3.53201978997168357E-10, + +7.08240282274875911E-13, + -6.05338212010422477E-16}; + + + + double B[7] = {+1.0, + +1.01162145739225565E-2, + +4.99175116169755106E-5, + +1.55654986308745614E-7, + +3.28067571055789734E-10, + +4.50490975753865810E-13, + +3.21107051193712168E-16}; + + + + double FA[11] = {+1.000000000000000000000E0, + +7.444370681619367006180E2, + +1.963963728951468698010E5, + +2.377503101254318340340E7, + +1.430734038212746368880E9, + +4.33736238870432522765E10, + +6.40533830574022022911E11, + +4.20968180571076940208E12, + +1.00795182980368574617E13, + +4.94816688199951963482E12, + -4.94701168645415959931E11}; + + double FB[10] = {+1.000000000000000000000E0, + +7.464370681619276780310E2, + +1.978652470315839514500E5, + +2.415356701651268451440E7, + +1.474789521929854649580E9, + +4.58595115847765779830E10, + +7.08501308149515401563E11, + +5.06084464593475076774E12, + +1.43468549171581016479E13, + +1.11535493509914254097E13}; + + + + double GA[11] = {+1.000000000000000000E0, + +8.135952011516861500E2, + +2.352391816264782000E5, + +3.125575707957787310E7, + +2.062975951467633540E9, + +6.83052205423625007E10, + +1.09049528450362786E12, + +7.57664583257834349E12, + +1.81004487464664575E13, + +6.43291613143049485E12, + -1.36517137670871689E12}; + + + double GB[10] = {+1.000000000000000000E0, + +8.195952011514515640E2, + +2.400367528355787770E5, + +3.260266616470908220E7, + +2.233555432780993600E9, + +7.87465017341829930E10, + +1.39866710696414565E12, + +1.17164723371736605E13, + +4.01839087307656620E13, + +3.99653257887490811E13}; + + if(!x || !si) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + + + for(p = 0; p < n; p++) { - x2 = y * y; - z = 1.0; - num = 0.0; - for(k = 0; k < 8; k++) - { - num += A[k] * z; - z*=x2; - } - z = 1.0; - den = 0.0; - for(k = 0; k < 7; k++) - { - den += B[k]*z; - z*=x2; - } - si[p] = x[p] * num/den; + sgn = x[p] > 0.0 ? 0 : 1; + y = x[p] < 0.0 ? -x[p] : x[p]; + + if(y < 4) + { + x2 = y * y; + z = 1.0; + num = 0.0; + for(k = 0; k < 8; k++) + { + num += A[k] * z; + z*=x2; + } + z = 1.0; + den = 0.0; + for(k = 0; k < 7; k++) + { + den += B[k]*z; + z*=x2; + } + si[p] = x[p] * num/den; + } + else + { + + x2 = 1.0/y; + x22 = x2*x2; + z = 1.0; + num = 0.0; + for(k = 0; k < 11; k++) + { + num += FA[k] * z; + z*=x22; + } + z = 1.0; + den = 0.0; + for(k = 0; k < 10; k++) + { + den += FB[k]*z; + z*=x22; + } + + f = x2 * num / den; + + z = 1.0; + num = 0.0; + for(k = 0; k < 11; k++) + { + num += GA[k] * z; + z*=x22; + } + z = 1.0; + den = 0.0; + for(k = 0; k < 10; k++) + { + den += GB[k]*z; + z*=x22; + } + + g = x22 * num / den; + + si[p] = sgn ? f * cos(y) + g * sin(y) - M_PI * 0.5 : + M_PI * 0.5 - f * cos(y) - g * sin(y); + } } - else - { - - x2 = 1.0/y; - x22 = x2*x2; - z = 1.0; - num = 0.0; - for(k = 0; k < 11; k++) - { - num += FA[k] * z; - z*=x22; - } - z = 1.0; - den = 0.0; - for(k = 0; k < 10; k++) - { - den += FB[k]*z; - z*=x22; - } - - f = x2 * num / den; - - z = 1.0; - num = 0.0; - for(k = 0; k < 11; k++) - { - num += GA[k] * z; - z*=x22; - } - z = 1.0; - den = 0.0; - for(k = 0; k < 10; k++) - { - den += GB[k]*z; - z*=x22; - } - - g = x22 * num / den; - - si[p] = sgn ? f * cos(y) + g * sin(y) - M_PI * 0.5 : - M_PI * 0.5 - f * cos(y) - g * sin(y); - } - } - return RES_OK; + return RES_OK; } @@ -694,38 +570,38 @@ int DSPL_API sine_int(double* x, int n, double* si) \fn int sqrt_cmplx(complex_t* x, int n, complex_t *y) \brief Square root of the complex vector argguument `x`. -Function calculates square root value of vector `x` length `n`: \n +Function calculates square root value of vector `x` length `n`: \n \f[ -y(k) = \sqrt{x(k)}, \qquad k = 0 \ldots n-1. -\f] +y(k) = \sqrt{x(k)}, \qquad k = 0 \ldots n-1. +\f] -\param[in] x Pointer to the input complex vector `x`. \n - Vector size is `[n x 1]`. \n \n +\param[in] x Pointer to the input complex vector `x`. \n + Vector size is `[n x 1]`. \n \n -\param[in] n Size of input and output vectors `x` and `y`. \n \n - +\param[in] n Size of input and output vectors `x` and `y`. \n \n -\param[out] y Pointer to the square root vector `y`. \n - Vector size is `[n x 1]`. \n - Memory must be allocated. \n \n -\return `RES_OK` if function is calculated successfully. \n +\param[out] y Pointer to the square root vector `y`. \n + Vector size is `[n x 1]`. \n + Memory must be allocated. \n \n + +\return `RES_OK` if function is calculated successfully. \n Else \ref ERROR_CODE_GROUP "code error". \n Example \code{.cpp} - complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; - complex_t y[3] - int k; - - sqrt_cmplx(x, 3, y); - - for(k = 0; k < 3; k++) - printf("sqrt_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", - RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); - - \endcode + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; + complex_t y[3] + int k; + + sqrt_cmplx(x, 3, y); + + for(k = 0; k < 3; k++) + printf("sqrt_cmplx(%.1f%+.1fj) = %.3f%+.3fj\n", + RE(x[k]), IM(x[k]), RE(y[k]), IM(y[k])); + + \endcode \n Результатом работы будет @@ -736,44 +612,44 @@ sqrt_cmplx(3.0+4.0j) = 2.000+1.000j sqrt_cmplx(5.0+6.0j) = 2.531+1.185j \endverbatim -\author Sergey Bakhurin www.dsplib.org +\author Sergey Bakhurin www.dsplib.org *******************************************************************************/ int DSPL_API sqrt_cmplx(complex_t* x, int n, complex_t *y) { - int k; - double r, zr, at; - complex_t t; - if(!x || !y) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; + int k; + double r, zr, at; + complex_t t; + if(!x || !y) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; - for(k = 0; k < n; k++) - { - r = ABS(x[k]); - if(r == 0.0) + for(k = 0; k < n; k++) { - RE(y[k]) = 0.0; - IM(y[k]) = 0.0; + r = ABS(x[k]); + if(r == 0.0) + { + RE(y[k]) = 0.0; + IM(y[k]) = 0.0; + } + else + { + RE(t) = RE(x[k]) + r; + IM(t) = IM(x[k]); + at = ABS(t); + if(at == 0.0) + { + RE(y[k]) = 0.0; + IM(y[k]) = sqrt(r); + } + else + { + zr = 1.0 / ABS(t); + r = sqrt(r); + RE(y[k]) = RE(t) * zr * r; + IM(y[k]) = IM(t) * zr * r; + } + } } - else - { - RE(t) = RE(x[k]) + r; - IM(t) = IM(x[k]); - at = ABS(t); - if(at == 0.0) - { - RE(y[k]) = 0.0; - IM(y[k]) = sqrt(r); - } - else - { - zr = 1.0 / ABS(t); - r = sqrt(r); - RE(y[k]) = RE(t) * zr * r; - IM(y[k]) = IM(t) * zr * r; - } - } - } - return RES_OK; + return RES_OK; } \ No newline at end of file diff --git a/examples/src/bilinear_test.c b/examples/src/bilinear_test.c index a02366c..52c55da 100644 --- a/examples/src/bilinear_test.c +++ b/examples/src/bilinear_test.c @@ -10,7 +10,7 @@ int main(int argc, char* argv[]) { void* hdspl; /* DSPL handle */ void* hplot; /* GNUPLOT handle */ - hdspl = dspl_load(); // Load DSPL function + double w[N], h[N]; complex_t hz[N]; @@ -18,7 +18,10 @@ int main(int argc, char* argv[]) double bz[ORD+1], az[ORD+1]; int err, k; - // расчет аналогового фильтра Чебышева первого рода + + hdspl = dspl_load(); /* Load DSPL function */ + + /* normalized analog lowpass filter Chebyshev type 1 */ err = cheby1_ap(1.0, ORD, bs, as); if(err != RES_OK) { @@ -26,7 +29,7 @@ int main(int argc, char* argv[]) return err; } - // Билинейное преобразование + /* Bilinear transform */ err = bilinear(bs, as, ORD, bz, az); if(err != RES_OK) { @@ -34,18 +37,18 @@ int main(int argc, char* argv[]) return err; } - // Печать коэффициентов + /* Print coefficients */ for(k = 0; k < ORD+1; k++) printf("bz[%d] = %7.3f az[%d] = %7.3f\n", k, bz[k], k, az[k]); - // Расчет АЧХ полученного цифрового фильтра + /* Digital filter magnitude */ linspace(0, M_PI, N, DSPL_PERIODIC, w); freqz(bz, az, ORD, w, N, hz); for(k = 0; k < N; k++) { - h[k] = 10.0 * log10 (ABSSQR(hz[k])); // АЧХ в дБ - w[k] /= M_PI; // нормировка частоты от 0 до 1 + h[k] = 10.0 * log10 (ABSSQR(hz[k])); /* Logarithmic scale */ + w[k] /= M_PI; /* frequency from 0 to 1 */ } writetxt(w,h,N,"dat/bilinear.txt"); @@ -60,7 +63,7 @@ int main(int argc, char* argv[]) gnuplot_cmd(hplot, "plot 'dat/bilinear.txt' with lines"); gnuplot_close(hplot); - dspl_free(hdspl); // free dspl handle + dspl_free(hdspl); /* free dspl handle */ return err; } diff --git a/examples/src/cheby_poly1_test.c b/examples/src/cheby_poly1_test.c index 3480f9e..f583cd9 100644 --- a/examples/src/cheby_poly1_test.c +++ b/examples/src/cheby_poly1_test.c @@ -8,13 +8,14 @@ int main(int argc, char* argv[]) { void* hdspl; /* DSPL handle */ - void* hplot; /* GNUPLOT handle */ - hdspl = dspl_load(); // Load DSPL function - + void* hplot; /* GNUPLOT handle */ double x[N], y[N]; int ord; char fn[64]; + + hdspl = dspl_load(); /* Load DSPL function */ + linspace(-1.0, 1.0, N, DSPL_SYMMETRIC, x); for(ord = 1; ord < 5; ord++) { @@ -36,7 +37,7 @@ int main(int argc, char* argv[]) gnuplot_cmd(hplot, " 'dat/cheby_poly1_ord4.txt' with lines"); gnuplot_close(hplot); - dspl_free(hdspl); // free dspl handle + dspl_free(hdspl); /* free dspl handle */ return 0; } \ No newline at end of file diff --git a/examples/src/cheby_poly2_test.c b/examples/src/cheby_poly2_test.c index 3aa6783..8f70d00 100644 --- a/examples/src/cheby_poly2_test.c +++ b/examples/src/cheby_poly2_test.c @@ -9,12 +9,12 @@ int main(int argc, char* argv[]) { void* hdspl; /* DSPL handle */ void* hplot; /* GNUPLOT handle */ - hdspl = dspl_load(); // Load DSPL function + double x[N], y[N]; int ord; char fn[64]; - + hdspl = dspl_load(); /* Load DSPL function */ linspace(-1.0, 1.0, N, DSPL_SYMMETRIC, x); for(ord = 1; ord < 5; ord++) { @@ -36,7 +36,7 @@ int main(int argc, char* argv[]) gnuplot_cmd(hplot, " 'dat/cheby_poly2_ord4.txt' with lines"); gnuplot_close(hplot); - dspl_free(hdspl); // free dspl handle + dspl_free(hdspl); /* free dspl handle */ return 0; } \ No newline at end of file diff --git a/examples/src/complex_test.c b/examples/src/complex_test.c index e780ad3..9f3afa0 100644 --- a/examples/src/complex_test.c +++ b/examples/src/complex_test.c @@ -5,13 +5,15 @@ int main(int argc, char* argv[]) { - void* handle; // DSPL handle - handle = dspl_load(); // Load DSPL function + void* handle; /* DSPL handle */ + complex_t x[3] = {{1.0, 2.0}, {3.0, 4.0}, {5.0, 6.0}}; complex_t y[3]; int k; + handle = dspl_load(); /* Load DSPL function */ + printf("\n\nacos_cmplx\n---------------------------------\n"); acos_cmplx(x, 3, y); for(k = 0; k < 3; k++) @@ -50,7 +52,7 @@ int main(int argc, char* argv[]) - dspl_free(handle); // free dspl handle + dspl_free(handle); /* free dspl handle */ return 0; } diff --git a/examples/src/conv_fft_cmplx_test.c b/examples/src/conv_fft_cmplx_test.c index 3e9f810..e499597 100644 --- a/examples/src/conv_fft_cmplx_test.c +++ b/examples/src/conv_fft_cmplx_test.c @@ -7,8 +7,8 @@ #define M 5 int main() { - void* handle; // DSPL handle - handle = dspl_load(); // Load DSPL function + void* handle; /* DSPL handle */ + handle = dspl_load(); /* Load DSPL function */ complex_t a[N], b[M], c[N+M-1], d[N+M-1]; fft_t pfft; int n; @@ -20,15 +20,15 @@ int main() conv_fft_cmplx(a, N, b, M, &pfft, 8, c); conv_cmplx(a, N, b, M, d); - // print result + /* print result */ for(n = 0; n < N+M-1; n++) { printf("c[%3d] = %9.2f%+9.2fj ", n, RE(c[n]), IM(c[n])); printf("d[%3d] = %9.2f%+9.2fj \n", n, RE(d[n]), IM(d[n])); } - fft_free(&pfft); // free fft structure memory - dspl_free(handle); // free dspl handle + fft_free(&pfft); /* free fft structure memory */ + dspl_free(handle); /* free dspl handle */ return 0; } diff --git a/examples/src/conv_fft_test.c b/examples/src/conv_fft_test.c index 0ae3071..91ccccb 100644 --- a/examples/src/conv_fft_test.c +++ b/examples/src/conv_fft_test.c @@ -7,8 +7,8 @@ #define M 7 int main() { - void* handle; // DSPL handle - handle = dspl_load(); // Load DSPL function + void* handle; /* DSPL handle */ + handle = dspl_load(); /* Load DSPL function */ double a[N], b[M], c[N+M-1], d[N+M-1]; fft_t pfft; int n, err; @@ -23,12 +23,12 @@ int main() err = conv(a, N, b, M, d); printf("conv error: 0x%.8x\n", err); - // print result + /* print result */ for(n = 0; n < N+M-1; n++) printf("c[%3d] = %9.2f d[%3d] = %9.2f\n", n, c[n], n, d[n]); - fft_free(&pfft); // free fft structure memory - dspl_free(handle); // free dspl handle + fft_free(&pfft); /* free fft structure memory */ + dspl_free(handle); /* free dspl handle */ return 0; } diff --git a/examples/src/conv_test.c b/examples/src/conv_test.c index fb3b2ae..aa31769 100644 --- a/examples/src/conv_test.c +++ b/examples/src/conv_test.c @@ -6,8 +6,8 @@ int main() { - void* handle; // DSPL handle - handle = dspl_load(); // Load DSPL function + void* handle; /* DSPL handle */ + handle = dspl_load(); /* Load DSPL function */ complex_t ac[3] = {{0.0, 1.0}, {1.0, 1.0}, {2.0, 2.0}}; complex_t bc[4] = {{3.0, 3.0}, {4.0, 4.0}, {5.0, 5.0}, {6.0, 6.0}}; complex_t cc[6]; diff --git a/examples/src/ellip_landen_test.c b/examples/src/ellip_landen_test.c index 70bdf20..8061179 100644 --- a/examples/src/ellip_landen_test.c +++ b/examples/src/ellip_landen_test.c @@ -6,25 +6,25 @@ int main() { - void* handle; // DSPL handle - handle = dspl_load(); // Load DSPL function - - double k[N]; - int i, err; - - err = ellip_landen(0.93, N, k); - if(err != RES_OK) - { - printf("Error code: %8x\n", err); - return err; - } - - printf(" i%8sk[i]\n\n", ""); - for(i = 1; i < N; i++) - printf("%2d %11.3e\n", i, k[i]); - - dspl_free(handle); // free dspl handle - return 0; + void* handle; // DSPL handle + handle = dspl_load(); // Load DSPL function + + double k[N]; + int i, err; + + err = ellip_landen(0.93, N, k); + if(err != RES_OK) + { + printf("Error code: %8x\n", err); + return err; + } + + printf(" i%8sk[i]\n\n", ""); + for(i = 1; i < N; i++) + printf("%2d %11.3e\n", i, k[i]); + + dspl_free(handle); // free dspl handle + return 0; } diff --git a/include/dspl.h b/include/dspl.h index 20dd97b..f1b3da2 100644 --- a/include/dspl.h +++ b/include/dspl.h @@ -29,20 +29,204 @@ /* math const definition */ #ifndef M_PI - #define M_PI 3.1415926535897932384626433832795 + #define M_PI 3.1415926535897932384626433832795 #endif #ifndef M_2PI - #define M_2PI 6.283185307179586476925286766559 + #define M_2PI 6.283185307179586476925286766559 #endif +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup TYPES_GROUP +\typedef complex_t +\brief Complex data type. + +libdspl-2.0 describes complex numbers data type as an array +of two `double` elements. +First element sets real part, second --- imaginary part. + +For example: + +\code{.cpp} + complex_t z; + z[0] = 1.0; + z[1] = -2.0; +\endcode + +Variable `z = 1-2j`, here `j` - imaginary unit. + +For the convenience of working with complex numbers implemented +special macros: \ref RE, \ref IM, \ref ABSSQR +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\typedef complex_t +\brief Описание комплексного типа данных. + +Комплексный тип данных в библиотеке libdspl-2.0 определен как +массив из двух элементов типа `double`. +При этом первый элемент массива определяет реальную часть +комплексного числа, а второй - мнимую. + +Например: + +\code{.cpp} + complex_t z; + z[0] = 1.0; + z[1] = -2.0; +\endcode + +Переменная `z = 1-2j`, где `j` - мнимая единица. + +Для удобства работы с комплексными числами реализованы +специальные макросы: \ref RE, \ref IM, \ref ABSSQR +***************************************************************************** */ +#endif typedef double complex_t[2]; +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\struct fft_t +\brief Fast Fourier Transform Object Data Structure +The structure stores pointers to twiddle factors and arrays of intermediate +data of the fast Fourier transform algorithm. + +The libdspl-2.0 library uses an FFT algorithm for composite size. + +\param n +The size of the FFT vector for which memory is allocated +in the structure arrays. \n +The parameter `n` must be equal to an integer power of two (radix 2). \n \n + +\param w +Pointer to the vector of twiddle factors. \n +The size of the vector is `[n x 1]`. \n +The memory must be allocated and an array of twiddle factors +must be filled with the \ref fft_create function. \n\n + +\param t0 +Pointer to the vector of intermediate results of the FFT algorithm. \n +The size of the vector is `[n x 1]`. \n +Memory must be allocated by \ref fft_create function. \n\n + +\param t1 +Pointer to the vector of intermediate results. \n +The size of the vector is `[n x 1]`. \n +The memory must be allocated with the \ref fft_create function. \n\n +The structure is populated with the \ref fft_create function once +before using the FFT algorithm. \n +A pointer to an object of this structure may be +reused when calling FFT functions. \n +Before exiting the program, dedicated memory for twiddle factors and arrays of +intermediate data must be cleared by the \ref fft_free function. + +For example: + +\code +fft_t pfft = {0}; // Structure fft_t and clear all fields +int n = 64; // FFT size + +int err; + +// Create and fill FFT structure for 64-points FFT +err = fft_create(&pfft, n); + +// FFT calculation here +// FFT calculation here one more +// ... + +// Clear fft structure +fft_free(&pfft); +\endcode + +\note +It is important to note that if the object `fft_t` was created for the FFT size +equal to` n`, it can only be used for FFT of size `n`. \n \n +It’s also worth noting that the FFT functions independently control the size, +and independently allocate the memory of the FFT object, if necessary. +So if you call any function using the `fft_t` structure with filled +data for the FFT length `k` for calculating the FFT of length`n`, +then the structure arrays will be automatically recreated for the length `n`. + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\struct fft_t +\brief Структура данных объекта быстрого преобразования Фурье + +Структура хранит указатели на массивы поворотных коэффициентов +и массивы промежуточных данных алгоритма быстрого преобразования Фурье. + +Библиотека libdspl-2.0 использует для БПФ алгоритм для составной длины + +\param n +Размер вектора БПФ, для которого выделена память в массивах структуры. \n +Парметр `n` должен быть равен целой степени двойки. \n \n + +\param w +Указатель на вектор поворотных коэффициентов алгоритма БПФ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена и массив поворотных коэффициентов +должен быть заполнен функцией \ref fft_create. \n \n + +\param t0 +Указатель на вектор промежуточных вычислений алгоритма БПФ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена функцией \ref fft_create. \n \n + +\param t1 +Указатель на вектор промежуточных вычислений алгоритма БПФ. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена функцией \ref fft_create. \n \n +Структура заполняется функцией \ref fft_create один раз +до использования алгоритма БПФ. \n +Указатель на объект данной структуры может быть +многократно использован при вызове функций БПФ. \n +Перед выходом из программы выделенную память под поворотные +коэффициенты и массивы промежуточных данных +необходимо очистить функцией \ref fft_free. Например: +\code +fft_t pfft = {0}; // объявляем объект fft_t и обнуляем все поля +int n = 64; // Размер БПФ +int err; + +// создаем объект для 64-точечного БПФ +err = fft_create(&pfft, n); + +// Вызов БПФ функции +// Еще раз вызов БПФ функции +// ... + +// очистить память объекта БПФ +fft_free(&pfft); +\endcode + +\note +Важно отметить, что если объект `fft_t` был создан для размера БПФ равного `n`, +то он может быть использован только для БПФ размера `n`. \n\n +Также необходимо заметить, что функции БПФ самостоятельно контролируют размер, +и самостоятельно выделяют память объекта БПФ при необходимости. +Так если вызвать любую функцию использующую структуру `fft_t` с заполненными +данными для длины БПФ `k` для расчета БПФ длины `n`, +то массивы структуры будут автоматически пересозданы для длины `n`. + +\author +Бахурин Сергей. +www.dsplib.org +***************************************************************************** */ +#endif typedef struct { complex_t* w; @@ -52,6 +236,7 @@ typedef struct } fft_t; + #define RAND_TYPE_MRG32K3A 0x00000001 #define RAND_TYPE_MT19937 0x00000002 #define RAND_MT19937_NN 312 @@ -73,20 +258,194 @@ typedef struct +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup TYPES_GROUP +\def RE(x) +\brief Macro sets real part of the complex number. + +Example: +\code{.cpp} + complex_t z; + RE(z) = 1.0; + IM(z) = -2.0; +\endcode + +Variable `z = 1-2j`, here `j` - imaginary unit. + +This macro can be used to return +real part of the complex number: + +\code{.cpp} + complex_t z = {3.0, -4.0}; + double r; + r = RE(z); +\endcode +In this example `z = 3-4i`, +but variable `r` will keep 3. +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\def RE(x) +\brief Макрос определяющий реальную часть комплексного числа. + +Например: +\code{.cpp} + complex_t z; + RE(z) = 1.0; + IM(z) = -2.0; +\endcode + +Переменная `z = 1-2j`, где `j` --- мнимая единица. + +Аналогично, макрос можно использовать для получения +реальной части комплексного числа: + +\code{.cpp} + complex_t z = {3.0, -4.0}; + double r; + r = RE(z); +\endcode +В данном примере переменная `z = 3-4i`, а в переменой `r` +будет храниться число 3. +***************************************************************************** */ +#endif +#define RE(x) (x[0]) + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup TYPES_GROUP +\def IM(x) +\brief Macro sets imaginary part of the complex number. + +Example: +\code{.cpp} + complex_t z; + RE(z) = 1.0; + IM(z) = -2.0; +\endcode + +Variable `z = 1-2j`, here `j` - imaginary unit. + +This macro can be used to return +imaginary part of the complex number: +\code{.cpp} + complex_t z = {3.0, -4.0}; + double r; + r = IM(z); +\endcode +In this example `z = 3-4i`, +but variable `r` will keep -4. +***************************************************************************** */ + + +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\def IM(x) +\brief Макрос определяющий мнимую часть комплексного числа. + +Например: +\code{.cpp} + complex_t z; + RE(z) = 1.0; + IM(z) = -2.0; +\endcode + +Переменная `z = 1-2j`, где `j` - мнимая единица. + +Аналогично, макрос можно использовать для получения +мнимой части комплексного числа: +\code{.cpp} + complex_t z = {3.0, -4.0}; + double r; + r = IM(z); +\endcode +В данном примере переменная `z = 3-4i`, +а в переменой `r` будет храниться число -4. +***************************************************************************** */ +#endif +#define IM(x) (x[1]) + + + +#define SQR(x) ((x) * (x)) + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup TYPES_GROUP +\def ABSSQR(x) +\brief +The macro returns the square of the modulus of a complex number `x`. + +Square of the modulus of a complex number \f$ x = a + j b \f$ equals: + +\f[ + |x|^2 = x x^* = a^2 + b^2. +\f] + +Example: +\code{.cpp} + complex_t z; + double y; + RE(z) = 1.0; + IM(z) = -2.0; + y = ABSSQR(z); +\endcode + +Variable `z = 1-2j`, here `j` - imaginary unit, but variable `y = 5`. +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup TYPES_GROUP +\def ABSSQR(x) +\brief Макрос возвращает квадрат модуля комплексного числа `x`. + +Квадрат модуля комплексного числа \f$ x = a + j b \f$ равен: + +\f[ + |x|^2 = x x^* = a^2 + b^2. +\f] + +Например: +\code{.cpp} + complex_t z; + double y; + RE(z) = 1.0; + IM(z) = -2.0; + y = ABSSQR(z); +\endcode + +Переменная `z = 1-2j`, где `j` - мнимая единица, а переменная `y = 5`. +***************************************************************************** */ +#endif +#define ABSSQR(x) ((SQR(RE(x))) + (SQR(IM(x)))) + -#define RE(x) (x[0]) -#define IM(x) (x[1]) -#define SQR(x) ((x) * (x)) -#define ABSSQR(x) ((SQR(RE(x))) + (SQR(IM(x)))) #define ABS(x) sqrt((ABSSQR(x))) + + #define ARG(x) atan2(IM(x), RE(x)) + #define CMRE(a,b) ((RE(a)) * (RE(b)) - (IM(a)) * (IM(b))) + + #define CMIM(a,b) ((RE(a)) * (IM(b)) + (IM(a)) * (RE(b))) + #define CMCONJRE(a, b) ((RE(a)) * (RE(b)) + (IM(a)) * (IM(b))) + + #define CMCONJIM(a, b) ((IM(a)) * (RE(b)) - (RE(a)) * (IM(b))) @@ -247,14 +606,14 @@ typedef struct #ifdef BUILD_LIB - #define DECLARE_FUNC(type, fn, param)\ - type DSPL_API fn(param); + #define DECLARE_FUNC(type, fn, param)\ + type DSPL_API fn(param); #endif #ifndef BUILD_LIB - #define DECLARE_FUNC( type, fn, param)\ - typedef type (*p_##fn)(param);\ - extern p_##fn fn; + #define DECLARE_FUNC( type, fn, param)\ + typedef type (*p_##fn)(param);\ + extern p_##fn fn; #endif