// 秒寻科技
// 复数运算，包括加减乘除
// 周涛
// 2023-03-04

#include "../includes/includes.h"

// 复数加法
// real1:复数1实部
// imag1:复数1虚部
// real2:复数2实部
// imag2:复数2虚部
// 返回值:复数1的实部和虚部同时为计算结果的返回值
void util_complex_plus(flt32 *real1, flt32 *imag1, flt32 real2, flt32 imag2)
{
    *real1 = *real1 + real2;
    *imag1 = *imag1 + imag2;
}

// 复数减法
// real1:复数1实部
// imag1:复数1虚部
// real2:复数2实部
// imag2:复数2虚部
// 返回值:复数1的实部和虚部同时为计算结果的返回值
void util_complex_minus(flt32 *real1, flt32 *imag1, flt32 real2, flt32 imag2)
{
    *real1 = *real1 - real2;
    *imag1 = *imag1 - imag2;
}

// 复数乘法
// 公式:(a + bi) * (c + di) = (ac - bd) + (ad + bc)i
// real1:复数1实部
// imag1:复数1虚部
// real2:复数2实部
// imag2:复数2虚部
// 返回值:复数1的实部和虚部同时为计算结果的返回值
void util_complex_multiply(flt64 *real1, flt64 *imag1, flt64 real2, flt64 imag2)
{
    flt64 real = *real1 * real2 - (*imag1) * imag2;
    flt64 imag = *real1 * imag2 + real2 * (*imag1);
    *real1 = real;
    *imag1 = imag;
}

// 复数除法
// (a + bi) / (c + di) = ((ac + bd) / (c^2 + d^2)) + ((bc - ad) / (c^2 + d^2))i
// real1:复数1实部
// imag1:复数1虚部
// real2:复数2实部
// imag2:复数2虚部
// 返回值:复数1的实部和虚部同时为计算结果的返回值
void util_complex_divide(flt32 *real1, flt32 *imag1, flt32 real2, flt32 imag2)
{
    flt32 real = (*real1 * real2 + *imag1 * imag2) / (real2 * real2 + imag2 * imag2);
    flt32 imag = (*imag1 * real2 - *real1 * imag2) / (real2 * real2 + imag2 * imag2);
    *real1 = real;
    *imag1 = imag;
}

// 复数取模
// |a + bi| = sqrt(a*a + b*b)
// real:实部
// imag:虚部
// 返回值：复数的模值
flt32 util_complex_modulus(flt32 real, flt32 imag)
{
    return sqrt(real * real + imag * imag);
}

// 复数序列相乘，相乘的结果覆盖序列1
// @param sequence_length 序列长度
// @param [inout]sequence1_real_ptr 序列1实部的数据空间地址，不能是NULL
// @param [inout]sequence1_imag_ptr 序列1虚部的数据空间地址，不能是NULL
// @param sequence2_real_ptr 序列2实部的数据空间地址，不能是NULL
// @param sequence2_imag_ptr 序列2虚部的数据空间地址，为NULL表示序列2为实序列
// @return 操作结果 0失败 1成功
uint8 util_complex_sequence_multiply(int sequence_length, float *sequence1_real_ptr, float *sequence1_imag_ptr, float *sequence2_real_ptr, float *sequence2_imag_ptr)
{
    if (sequence_length == 0 || sequence1_real_ptr == NULL || sequence1_imag_ptr == NULL || sequence2_real_ptr == NULL)
    {
        return RET_FAIL;
    }

    int i = 0;
    float temp_real;
    float temp_imag;

    if (sequence2_imag_ptr != NULL)
    {
        for (i = 0; i < sequence_length; i++)
        {
            // temp_real = sequence1_real_ptr[i] * sequence2_real_ptr[i] - sequence1_imag_ptr[i] * sequence2_imag_ptr[i];
            // temp_imag = sequence1_real_ptr[i] * sequence2_imag_ptr[i] + sequence2_real_ptr[i] * sequence1_imag_ptr[i];
            // sequence1_real_ptr[i] = temp_real;
            // sequence1_imag_ptr[i] = temp_imag;

            temp_real = (*sequence1_real_ptr) * (*sequence2_real_ptr) - (*sequence1_imag_ptr) * (*sequence2_imag_ptr);
            temp_imag = (*sequence1_real_ptr) * (*sequence2_imag_ptr) + (*sequence2_real_ptr) * (*sequence1_imag_ptr);
            *sequence1_real_ptr = temp_real;
            *sequence1_imag_ptr = temp_imag;

            sequence1_real_ptr++;
            sequence1_imag_ptr++;

            sequence2_real_ptr++;
            sequence2_imag_ptr++;
        }
    }
    else
    {
        for (i = 0; i < sequence_length; i++)
        {
            // temp_real = sequence1_real_ptr[i] * sequence2_real_ptr[i];
            // temp_imag = sequence2_real_ptr[i] * sequence1_imag_ptr[i];
            // sequence1_real_ptr[i] = temp_real;
            // sequence1_imag_ptr[i] = temp_imag;

            temp_real = (*sequence1_real_ptr) * (*sequence2_real_ptr);
            temp_imag = (*sequence2_real_ptr) * (*sequence1_imag_ptr);
            *sequence1_real_ptr = temp_real;
            *sequence1_imag_ptr = temp_imag;

            sequence1_real_ptr++;
            sequence1_imag_ptr++;

            sequence2_real_ptr++;
        }
    }

    return RET_OK;
}

// 复数序列计算模值
// @param sequence_length 序列长度
// @param sequence_real_ptr 序列实部的数据空间地址，不能是NULL
// @param sequence_imag_ptr 序列虚部的数据空间地址，不能是NULL
// @param sequence_modulus_ptr 序列模值的数据空间地址，不能是NULL
// @return 操作结果 0失败 1成功
uint8 util_complex_sequence_modulus(int sequence_length, float *sequence_real_ptr, float *sequence_imag_ptr, flt32 *sequence_modulus_ptr)
{
    flt32 fTmp = 0;

    if (sequence_length == 0 || sequence_real_ptr == NULL || sequence_imag_ptr == NULL || sequence_modulus_ptr == NULL)
    {
        return RET_FAIL;
    }

    int i = 0;

    for (i = 0; i < sequence_length; i++)
    {
        fTmp = sqrt((*sequence_real_ptr) * (*sequence_real_ptr) + (*sequence_imag_ptr) * (*sequence_imag_ptr));
        *sequence_modulus_ptr = fTmp;

        sequence_real_ptr++;
        sequence_imag_ptr++;
        sequence_modulus_ptr++;
    }

    return RET_OK;
}