kopia lustrzana https://github.com/Dsplib/libdspl-2.0
779 wiersze
20 KiB
C
779 wiersze
20 KiB
C
/*
|
|
* Copyright (c) 2015-2020 Sergey Bakhurin
|
|
* Digital Signal Processing Library [http://dsplib.org]
|
|
*
|
|
* This file is part of DSPL.
|
|
*
|
|
* is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU 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
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "dspl.h"
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
\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
|
|
*******************************************************************************/
|
|
int DSPL_API acos_cmplx(complex_t* x, int n, complex_t *y)
|
|
{
|
|
int k, res;
|
|
double pi2 = 0.5 * M_PI;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
\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
|
|
*******************************************************************************/
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
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/
|
|
*******************************************************************************/
|
|
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 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)
|
|
{
|
|
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]);
|
|
}
|
|
}
|
|
return RES_OK;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
module operator for double
|
|
*******************************************************************************/
|
|
double DSPL_API dmod (double x, double 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
|
|
*******************************************************************************/
|
|
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;
|
|
|
|
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
|
|
*******************************************************************************/
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
\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
|
|
*******************************************************************************/
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
sinc(x) = sin(pi*x)/(pi*x)
|
|
*******************************************************************************/
|
|
int DSPL_API sinc(double* x, int n, double a, double* y)
|
|
{
|
|
int k;
|
|
|
|
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]);
|
|
|
|
return RES_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
Sine integral
|
|
--------------------------------------------------------------------------------
|
|
This function uses Padé approximants of the convergent Taylor series [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)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
return RES_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
\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
|
|
*******************************************************************************/
|
|
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;
|
|
|
|
for(k = 0; k < n; k++)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
return RES_OK;
|
|
} |