From c76bd63aceda946887f0fc0eced6f4fb03cbe100 Mon Sep 17 00:00:00 2001 From: Dsplib Date: Wed, 29 Dec 2021 14:33:52 +0300 Subject: [PATCH] New Structure is beginning Changes to be committed: deleted: _release/.gitignore deleted: _release/Makefile modified: _release/dspl.c modified: _release/dspl.h deleted: _release/test.c modified: dspl/Makefile modified: dspl/src/array.c new file: dspl/src/array/array_scale_lin.c new file: dspl/src/array/concat.c new file: dspl/src/array/decimate.c new file: dspl/src/array/decimate_cmplx.c new file: dspl/src/array/find_nearest.c new file: dspl/src/array/flipip.c new file: dspl/src/array/flipip_cmplx.c new file: dspl/src/array/linspace.c new file: dspl/src/array/logspace.c new file: dspl/src/array/ones.c new file: dspl/src/array/sum.c new file: dspl/src/array/sum_sqr.c modified: dspl/src/dft.c new file: dspl/src/dft/dft.c new file: dspl/src/dft/dft_cmplx.c new file: dspl/src/dft/fft.c new file: dspl/src/dft/fft_abs.c new file: dspl/src/dft/fft_abs_cmplx.c new file: dspl/src/dft/fft_cmplx.c new file: dspl/src/dft/fft_create.c new file: dspl/src/dft/fft_free.c new file: dspl/src/dft/fft_krn.c new file: dspl/src/dft/fft_mag.c new file: dspl/src/dft/fft_mag_cmplx.c new file: dspl/src/dft/fft_shift.c new file: dspl/src/dft/fft_shift_cmplx.c renamed: dspl/src/fft_subkernel.c -> dspl/src/dft/fft_subkernel.c new file: dspl/src/dft/fourier_integral_cmplx.c new file: dspl/src/dft/fourier_series_dec.c new file: dspl/src/dft/fourier_series_dec_cmplx.c new file: dspl/src/dft/fourier_series_rec.c new file: dspl/src/dft/goertzel.c renamed: dspl/src/goertzel.c -> dspl/src/dft/goertzel_cmplx.c new file: dspl/src/dft/idft_cmplx.c new file: dspl/src/dft/ifft_cmplx.c deleted: dspl/src/fft.c deleted: dspl/src/fourier_series.c new file: dspl/src/math_poly.c new file: dspl/src/math_poly/cheby_poly1.c renamed: dspl/src/cheby.c -> dspl/src/math_poly/cheby_poly2.c new file: dspl/src/math_poly/poly_z2a_cmplx.c renamed: dspl/src/polyval.c -> dspl/src/math_poly/polyroots.c new file: dspl/src/math_poly/polyval.c new file: dspl/src/math_poly/polyval_cmplx.c modified: make.inc --- _release/.gitignore | 4 - _release/Makefile | 37 - _release/dspl.c | 922 +++++------ _release/dspl.h | 18 +- _release/test.c | 30 - dspl/Makefile | 5 +- dspl/src/array.c | 1425 +--------------- dspl/src/array/array_scale_lin.c | 193 +++ dspl/src/array/concat.c | 160 ++ dspl/src/array/decimate.c | 162 ++ dspl/src/array/decimate_cmplx.c | 167 ++ dspl/src/array/find_nearest.c | 58 + dspl/src/array/flipip.c | 151 ++ dspl/src/array/flipip_cmplx.c | 155 ++ dspl/src/array/linspace.c | 199 +++ dspl/src/array/logspace.c | 211 +++ dspl/src/array/ones.c | 113 ++ dspl/src/array/sum.c | 56 + dspl/src/array/sum_sqr.c | 55 + dspl/src/dft.c | 545 +------ dspl/src/dft/dft.c | 192 +++ dspl/src/dft/dft_cmplx.c | 194 +++ dspl/src/dft/fft.c | 192 +++ dspl/src/dft/fft_abs.c | 87 + dspl/src/dft/fft_abs_cmplx.c | 85 + dspl/src/dft/fft_cmplx.c | 201 +++ dspl/src/dft/fft_create.c | 367 +++++ dspl/src/dft/fft_free.c | 85 + dspl/src/dft/fft_krn.c | 170 ++ dspl/src/dft/fft_mag.c | 68 + dspl/src/dft/fft_mag_cmplx.c | 74 + dspl/src/dft/fft_shift.c | 129 ++ dspl/src/dft/fft_shift_cmplx.c | 76 + dspl/src/{ => dft}/fft_subkernel.c | 0 dspl/src/dft/fourier_integral_cmplx.c | 69 + dspl/src/dft/fourier_series_dec.c | 190 +++ dspl/src/dft/fourier_series_dec_cmplx.c | 76 + dspl/src/dft/fourier_series_rec.c | 185 +++ dspl/src/dft/goertzel.c | 157 ++ dspl/src/{goertzel.c => dft/goertzel_cmplx.c} | 468 ++---- dspl/src/dft/idft_cmplx.c | 195 +++ dspl/src/dft/ifft_cmplx.c | 209 +++ dspl/src/fft.c | 1441 ----------------- dspl/src/fourier_series.c | 442 ----- dspl/src/math_poly.c | 10 + dspl/src/math_poly/cheby_poly1.c | 177 ++ dspl/src/{cheby.c => math_poly/cheby_poly2.c} | 506 ++---- dspl/src/math_poly/poly_z2a_cmplx.c | 65 + dspl/src/{polyval.c => math_poly/polyroots.c} | 570 +++---- dspl/src/math_poly/polyval.c | 96 ++ dspl/src/math_poly/polyval_cmplx.c | 107 ++ make.inc | 2 + 52 files changed, 6197 insertions(+), 5354 deletions(-) delete mode 100644 _release/.gitignore delete mode 100644 _release/Makefile delete mode 100644 _release/test.c create mode 100644 dspl/src/array/array_scale_lin.c create mode 100644 dspl/src/array/concat.c create mode 100644 dspl/src/array/decimate.c create mode 100644 dspl/src/array/decimate_cmplx.c create mode 100644 dspl/src/array/find_nearest.c create mode 100644 dspl/src/array/flipip.c create mode 100644 dspl/src/array/flipip_cmplx.c create mode 100644 dspl/src/array/linspace.c create mode 100644 dspl/src/array/logspace.c create mode 100644 dspl/src/array/ones.c create mode 100644 dspl/src/array/sum.c create mode 100644 dspl/src/array/sum_sqr.c create mode 100644 dspl/src/dft/dft.c create mode 100644 dspl/src/dft/dft_cmplx.c create mode 100644 dspl/src/dft/fft.c create mode 100644 dspl/src/dft/fft_abs.c create mode 100644 dspl/src/dft/fft_abs_cmplx.c create mode 100644 dspl/src/dft/fft_cmplx.c create mode 100644 dspl/src/dft/fft_create.c create mode 100644 dspl/src/dft/fft_free.c create mode 100644 dspl/src/dft/fft_krn.c create mode 100644 dspl/src/dft/fft_mag.c create mode 100644 dspl/src/dft/fft_mag_cmplx.c create mode 100644 dspl/src/dft/fft_shift.c create mode 100644 dspl/src/dft/fft_shift_cmplx.c rename dspl/src/{ => dft}/fft_subkernel.c (100%) create mode 100644 dspl/src/dft/fourier_integral_cmplx.c create mode 100644 dspl/src/dft/fourier_series_dec.c create mode 100644 dspl/src/dft/fourier_series_dec_cmplx.c create mode 100644 dspl/src/dft/fourier_series_rec.c create mode 100644 dspl/src/dft/goertzel.c rename dspl/src/{goertzel.c => dft/goertzel_cmplx.c} (54%) create mode 100644 dspl/src/dft/idft_cmplx.c create mode 100644 dspl/src/dft/ifft_cmplx.c delete mode 100644 dspl/src/fft.c delete mode 100644 dspl/src/fourier_series.c create mode 100644 dspl/src/math_poly.c create mode 100644 dspl/src/math_poly/cheby_poly1.c rename dspl/src/{cheby.c => math_poly/cheby_poly2.c} (54%) create mode 100644 dspl/src/math_poly/poly_z2a_cmplx.c rename dspl/src/{polyval.c => math_poly/polyroots.c} (52%) create mode 100644 dspl/src/math_poly/polyval.c create mode 100644 dspl/src/math_poly/polyval_cmplx.c diff --git a/_release/.gitignore b/_release/.gitignore deleted file mode 100644 index 2f5acf7..0000000 --- a/_release/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.o -*.so -*.dll -*.exe diff --git a/_release/Makefile b/_release/Makefile deleted file mode 100644 index 2dae482..0000000 --- a/_release/Makefile +++ /dev/null @@ -1,37 +0,0 @@ - -CC = gcc - -# Define OS -ifeq ($(OS),Windows_NT) - DSPL_LIBNAME = libdspl.dll - DEF_OS = WIN_OS - LFLAGS = -lm -else - UNAME_S := $(shell uname -s) - UNAME_P := $(shell uname -p) - ifeq ($(UNAME_S),Linux) - DSPL_LIBNAME = libdspl.so - DEF_OS = LINUX_OS - LFLAGS = -lm -ldl - else ifeq ($(UNAME_S),Darwin) - DSPL_LIBNAME = libdspl.so - DEF_OS = LINUX_OS - LFLAGS = -lm -ldl - endif -endif - -# C-compiler flags -CFLAGS = -c -O3 -D$(DEF_OS) - -OBJFILES = test.o dspl.o - -all: test.exe clean - -test.exe: $(OBJFILES) - $(CC) $(OBJFILES) -o $@ $(LFLAGS) - -%.o:%.c - $(CC) $(CFLAGS) $< -o $@ $(LFLAGS) - -clean: - rm -f *.o \ No newline at end of file diff --git a/_release/dspl.c b/_release/dspl.c index 253d23b..68c384a 100644 --- a/_release/dspl.c +++ b/_release/dspl.c @@ -1,458 +1,464 @@ -/* -* Copyright (c) 2015-2020 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - - - -#ifdef WIN_OS -#include -#endif /* WIN_OS */ - -#ifdef LINUX_OS -#include -#endif /* LINUX_OS */ - - -#include -#include "dspl.h" - - -#ifndef BUILD_LIB - -p_acos_cmplx acos_cmplx ; -p_addlog addlog ; -p_array_scale_lin array_scale_lin ; -p_asin_cmplx asin_cmplx ; - -p_butter_ap butter_ap ; -p_bessel_i0 bessel_i0 ; -p_bilinear bilinear ; -p_butter_ap_zp butter_ap_zp ; - -p_cheby_poly1 cheby_poly1 ; -p_cheby_poly2 cheby_poly2 ; -p_cheby1_ap cheby1_ap ; -p_cheby1_ap_zp cheby1_ap_zp ; -p_cheby2_ap cheby2_ap ; -p_cheby2_ap_wp1 cheby2_ap_wp1 ; -p_cheby2_ap_zp cheby2_ap_zp ; -p_cmplx2re cmplx2re ; -p_concat concat ; -p_conv conv ; -p_conv_cmplx conv_cmplx ; -p_conv_fft conv_fft ; -p_conv_fft_cmplx conv_fft_cmplx ; -p_cos_cmplx cos_cmplx ; - -p_decimate decimate ; -p_decimate_cmplx decimate_cmplx ; -p_dft dft ; -p_dft_cmplx dft_cmplx ; -p_dmod dmod ; -p_dspl_info dspl_info ; - -p_ellip_acd ellip_acd ; -p_ellip_acd_cmplx ellip_acd_cmplx ; -p_ellip_ap ellip_ap ; -p_ellip_ap_zp ellip_ap_zp ; -p_ellip_asn ellip_asn ; -p_ellip_asn_cmplx ellip_asn_cmplx ; -p_ellip_cd ellip_cd ; -p_ellip_cd_cmplx ellip_cd_cmplx ; -p_ellip_landen ellip_landen ; -p_ellip_modulareq ellip_modulareq ; -p_ellip_rat ellip_rat ; -p_ellip_sn ellip_sn ; -p_ellip_sn_cmplx ellip_sn_cmplx ; - -p_farrow_lagrange farrow_lagrange ; -p_farrow_spline farrow_spline ; -p_fft fft ; -p_fft_abs fft_abs ; -p_fft_abs_cmplx fft_abs_cmplx ; -p_fft_cmplx fft_cmplx ; -p_fft_create fft_create ; -p_fft_free fft_free ; -p_fft_mag fft_mag ; -p_fft_mag_cmplx fft_mag_cmplx ; -p_fft_shift fft_shift ; -p_fft_shift_cmplx fft_shift_cmplx ; -p_filter_freq_resp filter_freq_resp ; -p_filter_iir filter_iir ; -p_filter_ws1 filter_ws1 ; -p_filter_zp2ab filter_zp2ab ; -p_find_max_abs find_max_abs ; -p_fir_linphase fir_linphase ; -p_flipip flipip ; -p_flipip_cmplx flipip_cmplx ; -p_fourier_integral_cmplx fourier_integral_cmplx ; -p_fourier_series_dec fourier_series_dec ; -p_fourier_series_dec_cmplx fourier_series_dec_cmplx ; -p_fourier_series_rec fourier_series_rec ; -p_freqs freqs ; -p_freqs_cmplx freqs_cmplx ; -p_freqs2time freqs2time ; -p_freqz freqz ; - -p_gnuplot_close gnuplot_close ; -p_gnuplot_cmd gnuplot_cmd ; -p_gnuplot_create gnuplot_create ; -p_gnuplot_open gnuplot_open ; -p_goertzel goertzel ; -p_goertzel_cmplx goertzel_cmplx ; -p_group_delay group_delay ; - -p_histogram histogram ; -p_histogram_norm histogram_norm ; - -p_idft_cmplx idft_cmplx ; -p_ifft_cmplx ifft_cmplx ; -p_iir iir ; - -p_linspace linspace ; -p_log_cmplx log_cmplx ; -p_logspace logspace ; -p_low2bp low2bp ; -p_low2bs low2bs ; -p_low2high low2high ; -p_low2low low2low ; - -p_matrix_eig_cmplx matrix_eig_cmplx ; -p_matrix_eye matrix_eye ; -p_matrix_eye_cmplx matrix_eye_cmplx ; -p_matrix_mul matrix_mul ; -p_matrix_pinv matrix_pinv ; -p_matrix_print matrix_print ; -p_matrix_print_cmplx matrix_print_cmplx ; -p_matrix_svd matrix_svd ; -p_matrix_transpose matrix_transpose ; -p_matrix_transpose_cmplx matrix_transpose_cmplx ; -p_matrix_transpose_hermite matrix_transpose_hermite ; -p_mean mean ; -p_mean_cmplx mean_cmplx ; -p_minmax minmax ; - -p_ones ones ; - -p_phase_delay phase_delay ; -p_poly_z2a_cmplx poly_z2a_cmplx ; -p_polyroots polyroots ; -p_polyval polyval ; -p_polyval_cmplx polyval_cmplx ; -p_psd_bartlett psd_bartlett ; -p_psd_bartlett_cmplx psd_bartlett_cmplx ; -p_psd_periodogram psd_periodogram ; -p_psd_periodogram_cmplx psd_periodogram_cmplx ; -p_psd_welch psd_welch ; -p_psd_welch_cmplx psd_welch_cmplx ; - -p_randb randb ; -p_randb2 randb2 ; -p_randi randi ; -p_randn randn ; -p_randn_cmplx randn_cmplx ; -p_random_init random_init ; -p_randu randu ; -p_ratcompos ratcompos ; -p_re2cmplx re2cmplx ; -p_readbin readbin ; - -p_signal_pimp signal_pimp ; -p_signal_saw signal_saw ; -p_sin_cmplx sin_cmplx ; -p_sinc sinc ; -p_sine_int sine_int ; -p_sqrt_cmplx sqrt_cmplx ; -p_std std ; -p_std_cmplx std_cmplx ; - -p_trapint trapint ; -p_trapint_cmplx trapint_cmplx ; - -p_unwrap unwrap ; - -p_vector_dot vector_dot ; -p_verif verif ; -p_verif_data_gen verif_data_gen ; -p_verif_cmplx verif_cmplx ; -p_verif_str verif_str ; -p_verif_str_cmplx verif_str_cmplx ; - -p_window window ; -p_writebin writebin ; -p_writetxt writetxt ; -p_writetxt_3d writetxt_3d ; -p_writetxt_3dline writetxt_3dline ; -p_writetxt_cmplx writetxt_cmplx ; -p_writetxt_cmplx_im writetxt_cmplx_im ; -p_writetxt_cmplx_re writetxt_cmplx_re ; -p_writetxt_int writetxt_int ; - -p_xcorr xcorr ; -p_xcorr_cmplx xcorr_cmplx ; - - -#ifdef WIN_OS -#define LOAD_FUNC(fn) \ - fname = #fn;\ - fn = (p_##fn)GetProcAddress(handle, fname);\ - if(! fn) goto exit_label; -#endif - - - -#ifdef LINUX_OS -#define LOAD_FUNC(fn) \ - fname = #fn;\ - fn = (p_##fn)dlsym(handle, fname);\ - if ((error = dlerror()) != NULL) goto exit_label -#endif - - -void* dspl_load() -{ - char* fname; - #ifdef WIN_OS - HINSTANCE handle; - handle = LoadLibrary(TEXT("libdspl.dll")); - if (!handle) - { - printf("libdspl.dll loading ERROR!\n"); - return NULL; - } - #endif /* WIN_OS */ - - - #ifdef LINUX_OS - char* error; - void *handle; - /* open the *.so */ - handle = dlopen ("./libdspl.so", RTLD_LAZY); - if (!handle) - { - printf("libdspl.so loading ERROR!\n"); - return NULL; - } - #endif /* LINUX_OS */ - - LOAD_FUNC(acos_cmplx); - LOAD_FUNC(addlog); - LOAD_FUNC(array_scale_lin); - LOAD_FUNC(asin_cmplx); - - LOAD_FUNC(bessel_i0); - LOAD_FUNC(bilinear); - LOAD_FUNC(butter_ap); - LOAD_FUNC(butter_ap_zp); - - LOAD_FUNC(cheby_poly1); - LOAD_FUNC(cheby_poly2); - LOAD_FUNC(cheby1_ap); - LOAD_FUNC(cheby1_ap_zp); - LOAD_FUNC(cheby2_ap); - LOAD_FUNC(cheby2_ap_wp1); - LOAD_FUNC(cheby2_ap_zp); - LOAD_FUNC(cmplx2re); - LOAD_FUNC(concat); - LOAD_FUNC(conv); - LOAD_FUNC(conv_cmplx); - LOAD_FUNC(conv_fft); - LOAD_FUNC(conv_fft_cmplx); - LOAD_FUNC(cos_cmplx); - - LOAD_FUNC(decimate); - LOAD_FUNC(decimate_cmplx); - LOAD_FUNC(dft); - LOAD_FUNC(dft_cmplx); - LOAD_FUNC(dmod); - LOAD_FUNC(dspl_info); - - LOAD_FUNC(ellip_acd); - LOAD_FUNC(ellip_acd_cmplx); - LOAD_FUNC(ellip_ap); - LOAD_FUNC(ellip_ap_zp); - LOAD_FUNC(ellip_asn); - LOAD_FUNC(ellip_asn_cmplx); - LOAD_FUNC(ellip_cd); - LOAD_FUNC(ellip_cd_cmplx); - LOAD_FUNC(ellip_landen); - LOAD_FUNC(ellip_modulareq); - LOAD_FUNC(ellip_rat); - LOAD_FUNC(ellip_sn); - LOAD_FUNC(ellip_sn_cmplx); - - LOAD_FUNC(farrow_lagrange); - LOAD_FUNC(farrow_spline); - LOAD_FUNC(fft); - LOAD_FUNC(fft_cmplx); - LOAD_FUNC(fft_create); - LOAD_FUNC(fft_free); - LOAD_FUNC(fft_mag); - LOAD_FUNC(fft_mag_cmplx); - LOAD_FUNC(fft_shift); - LOAD_FUNC(fft_shift_cmplx); - LOAD_FUNC(filter_freq_resp); - LOAD_FUNC(filter_iir); - LOAD_FUNC(filter_ws1); - LOAD_FUNC(filter_zp2ab); - LOAD_FUNC(find_max_abs); - LOAD_FUNC(fir_linphase); - LOAD_FUNC(flipip); - LOAD_FUNC(flipip_cmplx); - LOAD_FUNC(fourier_integral_cmplx); - LOAD_FUNC(fourier_series_dec); - LOAD_FUNC(fourier_series_dec_cmplx); - LOAD_FUNC(fourier_series_rec); - LOAD_FUNC(freqz); - LOAD_FUNC(freqs); - LOAD_FUNC(freqs_cmplx); - LOAD_FUNC(freqs2time); - - LOAD_FUNC(gnuplot_close); - LOAD_FUNC(gnuplot_cmd); - LOAD_FUNC(gnuplot_create); - LOAD_FUNC(gnuplot_open); - LOAD_FUNC(goertzel); - LOAD_FUNC(goertzel_cmplx); - LOAD_FUNC(group_delay); - - LOAD_FUNC(histogram); - LOAD_FUNC(histogram_norm); - - LOAD_FUNC(idft_cmplx); - LOAD_FUNC(ifft_cmplx); - LOAD_FUNC(iir); - - LOAD_FUNC(linspace); - LOAD_FUNC(log_cmplx); - LOAD_FUNC(logspace); - LOAD_FUNC(low2bp); - LOAD_FUNC(low2bs); - LOAD_FUNC(low2high); - LOAD_FUNC(low2low); - - LOAD_FUNC(matrix_eig_cmplx); - LOAD_FUNC(matrix_eye); - LOAD_FUNC(matrix_eye_cmplx); - LOAD_FUNC(matrix_mul); - LOAD_FUNC(matrix_pinv); - LOAD_FUNC(matrix_print); - LOAD_FUNC(matrix_print_cmplx); - LOAD_FUNC(matrix_svd); - LOAD_FUNC(matrix_transpose); - LOAD_FUNC(matrix_transpose_cmplx); - LOAD_FUNC(matrix_transpose_hermite); - LOAD_FUNC(mean); - LOAD_FUNC(mean_cmplx); - LOAD_FUNC(minmax); - - LOAD_FUNC(ones); - - LOAD_FUNC(phase_delay); - LOAD_FUNC(poly_z2a_cmplx); - LOAD_FUNC(polyroots); - LOAD_FUNC(polyval); - LOAD_FUNC(polyval_cmplx); - LOAD_FUNC(psd_bartlett); - LOAD_FUNC(psd_bartlett_cmplx); - LOAD_FUNC(psd_periodogram); - LOAD_FUNC(psd_periodogram_cmplx); - LOAD_FUNC(psd_welch); - LOAD_FUNC(psd_welch_cmplx); - - LOAD_FUNC(randi); - LOAD_FUNC(randb); - LOAD_FUNC(randb2); - LOAD_FUNC(randn); - LOAD_FUNC(randn_cmplx); - LOAD_FUNC(random_init); - LOAD_FUNC(randu); - LOAD_FUNC(ratcompos); - LOAD_FUNC(re2cmplx); - LOAD_FUNC(readbin); - - LOAD_FUNC(signal_pimp); - LOAD_FUNC(signal_saw); - LOAD_FUNC(sin_cmplx); - LOAD_FUNC(sinc); - LOAD_FUNC(sine_int); - LOAD_FUNC(sqrt_cmplx); - LOAD_FUNC(std); - LOAD_FUNC(std_cmplx); - - LOAD_FUNC(trapint); - LOAD_FUNC(trapint_cmplx); - - LOAD_FUNC(unwrap); - - LOAD_FUNC(vector_dot); - LOAD_FUNC(verif); - LOAD_FUNC(verif_data_gen); - LOAD_FUNC(verif_cmplx); - LOAD_FUNC(verif_str); - LOAD_FUNC(verif_str_cmplx); - - LOAD_FUNC(window); - LOAD_FUNC(writebin); - LOAD_FUNC(writetxt); - LOAD_FUNC(writetxt_3d); - LOAD_FUNC(writetxt_3dline); - LOAD_FUNC(writetxt_cmplx); - LOAD_FUNC(writetxt_cmplx_im); - LOAD_FUNC(writetxt_cmplx_re); - LOAD_FUNC(writetxt_int); - - LOAD_FUNC(xcorr); - LOAD_FUNC(xcorr_cmplx); - - - #ifdef WIN_OS - return (void*)handle; - exit_label: - printf("function %s loading ERROR!\n", fname); - if(handle) - FreeLibrary(handle); - return NULL; - #endif /* WIN_OS */ - - - #ifdef LINUX_OS - return handle; - exit_label: - printf("function %s loading ERROR!\n", fname); - if(handle) - dlclose(handle); - return NULL; - #endif /* LINUX_OS */ -} - - - -void dspl_free(void* handle) -{ - #ifdef WIN_OS - FreeLibrary((HINSTANCE)handle); - #endif /* WIN_OS */ - - #ifdef LINUX_OS - dlclose(handle); - #endif /* LINUX_OS */ -} - -#endif /* BUILD_LIB */ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + + +#ifdef WIN_OS +#include +#endif /* WIN_OS */ + +#ifdef LINUX_OS +#include +#endif /* LINUX_OS */ + + +#include +#include "dspl.h" + + +#ifndef BUILD_LIB + +p_acos_cmplx acos_cmplx ; +p_addlog addlog ; +p_array_scale_lin array_scale_lin ; +p_asin_cmplx asin_cmplx ; + +p_butter_ap butter_ap ; +p_bessel_i0 bessel_i0 ; +p_bilinear bilinear ; +p_butter_ap_zp butter_ap_zp ; + +p_cheby_poly1 cheby_poly1 ; +p_cheby_poly2 cheby_poly2 ; +p_cheby1_ap cheby1_ap ; +p_cheby1_ap_zp cheby1_ap_zp ; +p_cheby2_ap cheby2_ap ; +p_cheby2_ap_wp1 cheby2_ap_wp1 ; +p_cheby2_ap_zp cheby2_ap_zp ; +p_cmplx2re cmplx2re ; +p_concat concat ; +p_conv conv ; +p_conv_cmplx conv_cmplx ; +p_conv_fft conv_fft ; +p_conv_fft_cmplx conv_fft_cmplx ; +p_cos_cmplx cos_cmplx ; + +p_decimate decimate ; +p_decimate_cmplx decimate_cmplx ; +p_dft dft ; +p_dft_cmplx dft_cmplx ; +p_dmod dmod ; +p_dspl_info dspl_info ; + +p_ellip_acd ellip_acd ; +p_ellip_acd_cmplx ellip_acd_cmplx ; +p_ellip_ap ellip_ap ; +p_ellip_ap_zp ellip_ap_zp ; +p_ellip_asn ellip_asn ; +p_ellip_asn_cmplx ellip_asn_cmplx ; +p_ellip_cd ellip_cd ; +p_ellip_cd_cmplx ellip_cd_cmplx ; +p_ellip_landen ellip_landen ; +p_ellip_modulareq ellip_modulareq ; +p_ellip_rat ellip_rat ; +p_ellip_sn ellip_sn ; +p_ellip_sn_cmplx ellip_sn_cmplx ; + +p_farrow_lagrange farrow_lagrange ; +p_farrow_spline farrow_spline ; +p_fft fft ; +p_fft_abs fft_abs ; +p_fft_abs_cmplx fft_abs_cmplx ; +p_fft_cmplx fft_cmplx ; +p_fft_create fft_create ; +p_fft_free fft_free ; +p_fft_mag fft_mag ; +p_fft_mag_cmplx fft_mag_cmplx ; +p_fft_shift fft_shift ; +p_fft_shift_cmplx fft_shift_cmplx ; +p_filter_freq_resp filter_freq_resp ; +p_filter_iir filter_iir ; +p_filter_ws1 filter_ws1 ; +p_filter_zp2ab filter_zp2ab ; +p_find_max_abs find_max_abs ; +p_find_nearest find_nearest ; +p_fir_linphase fir_linphase ; +p_flipip flipip ; +p_flipip_cmplx flipip_cmplx ; +p_fourier_integral_cmplx fourier_integral_cmplx ; +p_fourier_series_dec fourier_series_dec ; +p_fourier_series_dec_cmplx fourier_series_dec_cmplx ; +p_fourier_series_rec fourier_series_rec ; +p_freqs freqs ; +p_freqs_cmplx freqs_cmplx ; +p_freqs2time freqs2time ; +p_freqz freqz ; + +p_gnuplot_close gnuplot_close ; +p_gnuplot_cmd gnuplot_cmd ; +p_gnuplot_create gnuplot_create ; +p_gnuplot_open gnuplot_open ; +p_goertzel goertzel ; +p_goertzel_cmplx goertzel_cmplx ; +p_group_delay group_delay ; + +p_histogram histogram ; +p_histogram_norm histogram_norm ; + +p_idft_cmplx idft_cmplx ; +p_ifft_cmplx ifft_cmplx ; +p_iir iir ; + +p_linspace linspace ; +p_log_cmplx log_cmplx ; +p_logspace logspace ; +p_low2bp low2bp ; +p_low2bs low2bs ; +p_low2high low2high ; +p_low2low low2low ; + +p_matrix_eig_cmplx matrix_eig_cmplx ; +p_matrix_eye matrix_eye ; +p_matrix_eye_cmplx matrix_eye_cmplx ; +p_matrix_mul matrix_mul ; +p_matrix_pinv matrix_pinv ; +p_matrix_print matrix_print ; +p_matrix_print_cmplx matrix_print_cmplx ; +p_matrix_svd matrix_svd ; +p_matrix_transpose matrix_transpose ; +p_matrix_transpose_cmplx matrix_transpose_cmplx ; +p_matrix_transpose_hermite matrix_transpose_hermite ; +p_mean mean ; +p_mean_cmplx mean_cmplx ; +p_minmax minmax ; + +p_ones ones ; + +p_phase_delay phase_delay ; +p_poly_z2a_cmplx poly_z2a_cmplx ; +p_polyroots polyroots ; +p_polyval polyval ; +p_polyval_cmplx polyval_cmplx ; +p_psd_bartlett psd_bartlett ; +p_psd_bartlett_cmplx psd_bartlett_cmplx ; +p_psd_periodogram psd_periodogram ; +p_psd_periodogram_cmplx psd_periodogram_cmplx ; +p_psd_welch psd_welch ; +p_psd_welch_cmplx psd_welch_cmplx ; + +p_randb randb ; +p_randb2 randb2 ; +p_randi randi ; +p_randn randn ; +p_randn_cmplx randn_cmplx ; +p_random_init random_init ; +p_randu randu ; +p_ratcompos ratcompos ; +p_re2cmplx re2cmplx ; +p_readbin readbin ; + +p_signal_pimp signal_pimp ; +p_signal_saw signal_saw ; +p_sin_cmplx sin_cmplx ; +p_sinc sinc ; +p_sine_int sine_int ; +p_sqrt_cmplx sqrt_cmplx ; +p_stat_std stat_std ; +p_stat_std_cmplx stat_std_cmplx ; +p_sum sum ; +p_sum_sqr sum_sqr ; + +p_trapint trapint ; +p_trapint_cmplx trapint_cmplx ; + +p_unwrap unwrap ; + +p_vector_dot vector_dot ; +p_verif verif ; +p_verif_data_gen verif_data_gen ; +p_verif_cmplx verif_cmplx ; +p_verif_str verif_str ; +p_verif_str_cmplx verif_str_cmplx ; + +p_window window ; +p_writebin writebin ; +p_writetxt writetxt ; +p_writetxt_3d writetxt_3d ; +p_writetxt_3dline writetxt_3dline ; +p_writetxt_cmplx writetxt_cmplx ; +p_writetxt_cmplx_im writetxt_cmplx_im ; +p_writetxt_cmplx_re writetxt_cmplx_re ; +p_writetxt_int writetxt_int ; + +p_xcorr xcorr ; +p_xcorr_cmplx xcorr_cmplx ; + + +#ifdef WIN_OS +#define LOAD_FUNC(fn) \ + fname = #fn;\ + fn = (p_##fn)GetProcAddress(handle, fname);\ + if(! fn) goto exit_label; +#endif + + + +#ifdef LINUX_OS +#define LOAD_FUNC(fn) \ + fname = #fn;\ + fn = (p_##fn)dlsym(handle, fname);\ + if ((error = dlerror()) != NULL) goto exit_label +#endif + + +void* dspl_load() +{ + char* fname; + #ifdef WIN_OS + HINSTANCE handle; + handle = LoadLibrary(TEXT("libdspl.dll")); + if (!handle) + { + printf("libdspl.dll loading ERROR!\n"); + return NULL; + } + #endif /* WIN_OS */ + + + #ifdef LINUX_OS + char* error; + void *handle; + /* open the *.so */ + handle = dlopen ("./libdspl.so", RTLD_LAZY); + if (!handle) + { + printf("libdspl.so loading ERROR!\n"); + return NULL; + } + #endif /* LINUX_OS */ + + LOAD_FUNC(acos_cmplx); + LOAD_FUNC(addlog); + LOAD_FUNC(array_scale_lin); + LOAD_FUNC(asin_cmplx); + + LOAD_FUNC(bessel_i0); + LOAD_FUNC(bilinear); + LOAD_FUNC(butter_ap); + LOAD_FUNC(butter_ap_zp); + + LOAD_FUNC(cheby_poly1); + LOAD_FUNC(cheby_poly2); + LOAD_FUNC(cheby1_ap); + LOAD_FUNC(cheby1_ap_zp); + LOAD_FUNC(cheby2_ap); + LOAD_FUNC(cheby2_ap_wp1); + LOAD_FUNC(cheby2_ap_zp); + LOAD_FUNC(cmplx2re); + LOAD_FUNC(concat); + LOAD_FUNC(conv); + LOAD_FUNC(conv_cmplx); + LOAD_FUNC(conv_fft); + LOAD_FUNC(conv_fft_cmplx); + LOAD_FUNC(cos_cmplx); + + LOAD_FUNC(decimate); + LOAD_FUNC(decimate_cmplx); + LOAD_FUNC(dft); + LOAD_FUNC(dft_cmplx); + LOAD_FUNC(dmod); + LOAD_FUNC(dspl_info); + + LOAD_FUNC(ellip_acd); + LOAD_FUNC(ellip_acd_cmplx); + LOAD_FUNC(ellip_ap); + LOAD_FUNC(ellip_ap_zp); + LOAD_FUNC(ellip_asn); + LOAD_FUNC(ellip_asn_cmplx); + LOAD_FUNC(ellip_cd); + LOAD_FUNC(ellip_cd_cmplx); + LOAD_FUNC(ellip_landen); + LOAD_FUNC(ellip_modulareq); + LOAD_FUNC(ellip_rat); + LOAD_FUNC(ellip_sn); + LOAD_FUNC(ellip_sn_cmplx); + + LOAD_FUNC(farrow_lagrange); + LOAD_FUNC(farrow_spline); + LOAD_FUNC(fft); + LOAD_FUNC(fft_cmplx); + LOAD_FUNC(fft_create); + LOAD_FUNC(fft_free); + LOAD_FUNC(fft_mag); + LOAD_FUNC(fft_mag_cmplx); + LOAD_FUNC(fft_shift); + LOAD_FUNC(fft_shift_cmplx); + LOAD_FUNC(filter_freq_resp); + LOAD_FUNC(filter_iir); + LOAD_FUNC(filter_ws1); + LOAD_FUNC(filter_zp2ab); + LOAD_FUNC(find_max_abs); + LOAD_FUNC(find_nearest); + LOAD_FUNC(fir_linphase); + LOAD_FUNC(flipip); + LOAD_FUNC(flipip_cmplx); + LOAD_FUNC(fourier_integral_cmplx); + LOAD_FUNC(fourier_series_dec); + LOAD_FUNC(fourier_series_dec_cmplx); + LOAD_FUNC(fourier_series_rec); + LOAD_FUNC(freqz); + LOAD_FUNC(freqs); + LOAD_FUNC(freqs_cmplx); + LOAD_FUNC(freqs2time); + + LOAD_FUNC(gnuplot_close); + LOAD_FUNC(gnuplot_cmd); + LOAD_FUNC(gnuplot_create); + LOAD_FUNC(gnuplot_open); + LOAD_FUNC(goertzel); + LOAD_FUNC(goertzel_cmplx); + LOAD_FUNC(group_delay); + + LOAD_FUNC(histogram); + LOAD_FUNC(histogram_norm); + + LOAD_FUNC(idft_cmplx); + LOAD_FUNC(ifft_cmplx); + LOAD_FUNC(iir); + + LOAD_FUNC(linspace); + LOAD_FUNC(log_cmplx); + LOAD_FUNC(logspace); + LOAD_FUNC(low2bp); + LOAD_FUNC(low2bs); + LOAD_FUNC(low2high); + LOAD_FUNC(low2low); + + LOAD_FUNC(matrix_eig_cmplx); + LOAD_FUNC(matrix_eye); + LOAD_FUNC(matrix_eye_cmplx); + LOAD_FUNC(matrix_mul); + LOAD_FUNC(matrix_pinv); + LOAD_FUNC(matrix_print); + LOAD_FUNC(matrix_print_cmplx); + LOAD_FUNC(matrix_svd); + LOAD_FUNC(matrix_transpose); + LOAD_FUNC(matrix_transpose_cmplx); + LOAD_FUNC(matrix_transpose_hermite); + LOAD_FUNC(mean); + LOAD_FUNC(mean_cmplx); + LOAD_FUNC(minmax); + + LOAD_FUNC(ones); + + LOAD_FUNC(phase_delay); + LOAD_FUNC(poly_z2a_cmplx); + LOAD_FUNC(polyroots); + LOAD_FUNC(polyval); + LOAD_FUNC(polyval_cmplx); + LOAD_FUNC(psd_bartlett); + LOAD_FUNC(psd_bartlett_cmplx); + LOAD_FUNC(psd_periodogram); + LOAD_FUNC(psd_periodogram_cmplx); + LOAD_FUNC(psd_welch); + LOAD_FUNC(psd_welch_cmplx); + + LOAD_FUNC(randi); + LOAD_FUNC(randb); + LOAD_FUNC(randb2); + LOAD_FUNC(randn); + LOAD_FUNC(randn_cmplx); + LOAD_FUNC(random_init); + LOAD_FUNC(randu); + LOAD_FUNC(ratcompos); + LOAD_FUNC(re2cmplx); + LOAD_FUNC(readbin); + + LOAD_FUNC(signal_pimp); + LOAD_FUNC(signal_saw); + LOAD_FUNC(sin_cmplx); + LOAD_FUNC(sinc); + LOAD_FUNC(sine_int); + LOAD_FUNC(sqrt_cmplx); + LOAD_FUNC(stat_std); + LOAD_FUNC(stat_std_cmplx); + LOAD_FUNC(sum); + LOAD_FUNC(sum_sqr); + + LOAD_FUNC(trapint); + LOAD_FUNC(trapint_cmplx); + + LOAD_FUNC(unwrap); + + LOAD_FUNC(vector_dot); + LOAD_FUNC(verif); + LOAD_FUNC(verif_data_gen); + LOAD_FUNC(verif_cmplx); + LOAD_FUNC(verif_str); + LOAD_FUNC(verif_str_cmplx); + + LOAD_FUNC(window); + LOAD_FUNC(writebin); + LOAD_FUNC(writetxt); + LOAD_FUNC(writetxt_3d); + LOAD_FUNC(writetxt_3dline); + LOAD_FUNC(writetxt_cmplx); + LOAD_FUNC(writetxt_cmplx_im); + LOAD_FUNC(writetxt_cmplx_re); + LOAD_FUNC(writetxt_int); + + LOAD_FUNC(xcorr); + LOAD_FUNC(xcorr_cmplx); + + + #ifdef WIN_OS + return (void*)handle; + exit_label: + printf("function %s loading ERROR!\n", fname); + if(handle) + FreeLibrary(handle); + return NULL; + #endif /* WIN_OS */ + + + #ifdef LINUX_OS + return handle; + exit_label: + printf("function %s loading ERROR!\n", fname); + if(handle) + dlclose(handle); + return NULL; + #endif /* LINUX_OS */ +} + + + +void dspl_free(void* handle) +{ + #ifdef WIN_OS + FreeLibrary((HINSTANCE)handle); + #endif /* WIN_OS */ + + #ifdef LINUX_OS + dlclose(handle); + #endif /* LINUX_OS */ +} + +#endif /* BUILD_LIB */ diff --git a/_release/dspl.h b/_release/dspl.h index 9673989..534247c 100644 --- a/_release/dspl.h +++ b/_release/dspl.h @@ -1068,6 +1068,12 @@ DECLARE_FUNC(int, find_max_abs, double* a COMMA double* m COMMA int* ind); /*----------------------------------------------------------------------------*/ +DECLARE_FUNC(int, find_nearest, double* x + COMMA int n + COMMA double val + COMMA int* idx + COMMA double* dist); +/*----------------------------------------------------------------------------*/ DECLARE_FUNC(int, fir_linphase, int ord COMMA double w0 COMMA double w1 @@ -1511,11 +1517,19 @@ DECLARE_FUNC(int, sqrt_cmplx, complex_t* COMMA int COMMA complex_t*); /*----------------------------------------------------------------------------*/ -DECLARE_FUNC(int, std, double* x +DECLARE_FUNC(int, stat_std, double* x COMMA int n COMMA double* s); /*----------------------------------------------------------------------------*/ -DECLARE_FUNC(int, std_cmplx, complex_t* x +DECLARE_FUNC(int, stat_std_cmplx, complex_t* x + COMMA int n + COMMA double* s); +/*----------------------------------------------------------------------------*/ +DECLARE_FUNC(int, sum, double* x + COMMA int n + COMMA double* s); +/*----------------------------------------------------------------------------*/ +DECLARE_FUNC(int, sum_sqr, double* x COMMA int n COMMA double* s); /*----------------------------------------------------------------------------*/ diff --git a/_release/test.c b/_release/test.c deleted file mode 100644 index 5209033..0000000 --- a/_release/test.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include "dspl.h" - - -int main(int argc, char* argv[]) -{ - /* libdspl handle */ - void* hdspl; - - /* Load libdspl functions */ - hdspl = dspl_load(); - - /* Check libdspl handle. */ - /* If hdspl == NULL means problem with libdspl loading */ - if(!hdspl) - { - printf("libdspl loading error!\n"); - return -1; - } - - /* Print libdspl info */ - dspl_info(); - - - /* free dspl handle */ - dspl_free(hdspl); - return 0; -} - diff --git a/dspl/Makefile b/dspl/Makefile index 93dac4a..2113580 100644 --- a/dspl/Makefile +++ b/dspl/Makefile @@ -2,13 +2,12 @@ include ../make.inc # C-compiler flags -CFLAGS = -c -fPIC -Wall -O3 -I$(INC_DIR) -DBUILD_LIB -D$(DEF_OS) +CFLAGS = -c -fPIC -Wall -O3 -I$(INC_DIR) -Isrc -DBUILD_LIB -D$(DEF_OS) # DSPL src and obj files list DSPL_SRC_FILES = $(wildcard $(DSPL_SRC_DIR)/*.c) DSPL_OBJ_FILES = $(addprefix $(DSPL_OBJ_DIR)/,$(notdir $(DSPL_SRC_FILES:.c=.o))) - all: $(RELEASE_DIR)/$(LIB_NAME)\ $(EXAMPLE_BIN_DIR)/$(LIB_NAME)\ $(PERFORMANCE_BIN_DIR)/$(LIB_NAME)\ @@ -18,7 +17,7 @@ all: $(RELEASE_DIR)/$(LIB_NAME)\ #Build libdspl.dll or libdspl.so $(RELEASE_DIR)/$(LIB_NAME): $(DSPL_OBJ_FILES) $(BLAS_LIB_NAME) $(LAPACK_DOUBLE_LIB_NAME) $(LAPACK_COMPLEX_LIB_NAME) - $(CC) -shared -o $(RELEASE_DIR)/$(LIB_NAME) $(DSPL_OBJ_FILES) -lm -L$(LAPACK_RELEASE_DIR) -llapack_complex -llapack_double -L$(BLAS_RELEASE_DIR) -lblas -lgfortran -lquadmath + $(CC) -shared -o $(RELEASE_DIR)/$(LIB_NAME) $(DSPL_OBJ_FILES) -lm -L$(LAPACK_RELEASE_DIR) -llapack_complex -llapack_double -L$(BLAS_RELEASE_DIR) -lblas -lgfortran -lquadmath #Compile libdspl obj files from c sources $(DSPL_OBJ_DIR)/%.o:$(DSPL_SRC_DIR)/%.c diff --git a/dspl/src/array.c b/dspl/src/array.c index d5c573f..ccef1e1 100644 --- a/dspl/src/array.c +++ b/dspl/src/array.c @@ -1,1410 +1,15 @@ -/* -* Copyright (c) 2015-2020 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - - - - -#include -#include -#include -#include "dspl.h" -#include "blas.h" - - -#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; - - if(xmin >= xmax) - return ERROR_MIN_MAX; - - kx = h / (xmax - xmin); - - for(k = 0; k < n; k++) - y[k] = (x[k] - xmin) * kx + dx; - - 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` - -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(c != a) - memcpy(c, a, na); - - 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 - -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; - - k = i = 0; - while(k + d <= n) - { - y[i] = x[k]; - k+=d; - i++; - } - if(cnt) - *cnt = i; - - 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 - -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; - - 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; -} - - - - -int DSPL_API find_nearest(double* x, int n, double val, int *idx, double* dist) -{ - double mind, dv; - int iv, i; - - if(!x) - return ERROR_PTR; - if(n < 1) - return ERROR_SIZE; - - mind = fabs(x[0] - val); - iv = 0; - for(i = 1; i < n; i++) - { - dv = fabs(x[i] - val); - if( dv < mind) - { - mind = dv; - iv = i; - } - } - - if(idx) - *idx = iv; - if(dist) - *dist = fabs(x[iv] - val); - - return RES_OK; - -} - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup ARRAY_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 -***************************************************************************** */ -#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; - - for(k = 0; k < n/2; k++) - { - tmp = x[k]; - x[k] = x[n-1-k]; - x[n-1-k] = tmp; - } - return RES_OK; - -} - - - -#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; - - 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; -} - - - - - - -#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; - - 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; -} - - - - - -#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; - - if(n < 2) - return ERROR_SIZE; - if(!x) - return ERROR_PTR; - - 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; -} - - - - -#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; - return RES_OK; -} - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup ARRAY_GROUP -\fn int sum(double* x, int n, double* s) -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup ARRAY_GROUP -\fn int sum(double* x, int n, double* s) -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API sum(double* x, int n, double* s) -{ - int i; - double z = 0.0; - if(!x || !s) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - - for(i = 0; i < n; i++) - z += x[i]; - *s = z; - return RES_OK; -} - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup ARRAY_GROUP -\fn int sum(double* x, int n, double* s) -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup ARRAY_GROUP -\fn int sum(double* x, int n, double* s) -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API sum_sqr(double* x, int n, double* s) -{ - int i; - double z = 0.0; - if(!x || !s) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - - for(i = 0; i < n; i++) - z += x[i]*x[i]; - *s = z; - return RES_OK; -} - - - - - +#include "array/array_scale_lin.c" +#include "array/concat.c" +#include "array/decimate.c" +#include "array/decimate_cmplx.c" +#include "array/find_nearest.c" +#include "array/flipip.c" +#include "array/flipip_cmplx.c" +#include "array/linspace.c" +#include "array/logspace.c" +#include "array/ones.c" +#include "array/sum.c" +#include "array/sum_sqr.c" + + + diff --git a/dspl/src/array/array_scale_lin.c b/dspl/src/array/array_scale_lin.c new file mode 100644 index 0000000..c4e009e --- /dev/null +++ b/dspl/src/array/array_scale_lin.c @@ -0,0 +1,193 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#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; + + if(xmin >= xmax) + return ERROR_MIN_MAX; + + kx = h / (xmax - xmin); + + for(k = 0; k < n; k++) + y[k] = (x[k] - xmin) * kx + dx; + + return RES_OK; +} diff --git a/dspl/src/array/concat.c b/dspl/src/array/concat.c new file mode 100644 index 0000000..9e69666 --- /dev/null +++ b/dspl/src/array/concat.c @@ -0,0 +1,160 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#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` + +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(c != a) + memcpy(c, a, na); + + memcpy((char*)c+na, b, nb); + return RES_OK; +} + + diff --git a/dspl/src/array/decimate.c b/dspl/src/array/decimate.c new file mode 100644 index 0000000..6670147 --- /dev/null +++ b/dspl/src/array/decimate.c @@ -0,0 +1,162 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_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 +***************************************************************************** */ +#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; + + k = i = 0; + while(k + d <= n) + { + y[i] = x[k]; + k+=d; + i++; + } + if(cnt) + *cnt = i; + + return RES_OK; +} + diff --git a/dspl/src/array/decimate_cmplx.c b/dspl/src/array/decimate_cmplx.c new file mode 100644 index 0000000..8e86770 --- /dev/null +++ b/dspl/src/array/decimate_cmplx.c @@ -0,0 +1,167 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#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 + +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; + + 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; +} + diff --git a/dspl/src/array/find_nearest.c b/dspl/src/array/find_nearest.c new file mode 100644 index 0000000..f5fb3e5 --- /dev/null +++ b/dspl/src/array/find_nearest.c @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +int DSPL_API find_nearest(double* x, int n, double val, int *idx, double* dist) +{ + double mind, dv; + int iv, i; + + if(!x) + return ERROR_PTR; + if(n < 1) + return ERROR_SIZE; + + mind = fabs(x[0] - val); + iv = 0; + for(i = 1; i < n; i++) + { + dv = fabs(x[i] - val); + if( dv < mind) + { + mind = dv; + iv = i; + } + } + + if(idx) + *idx = iv; + if(dist) + *dist = fabs(x[iv] - val); + + return RES_OK; + +} \ No newline at end of file diff --git a/dspl/src/array/flipip.c b/dspl/src/array/flipip.c new file mode 100644 index 0000000..4b778b0 --- /dev/null +++ b/dspl/src/array/flipip.c @@ -0,0 +1,151 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_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 +***************************************************************************** */ +#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; + + for(k = 0; k < n/2; k++) + { + tmp = x[k]; + x[k] = x[n-1-k]; + x[n-1-k] = tmp; + } + return RES_OK; + +} + diff --git a/dspl/src/array/flipip_cmplx.c b/dspl/src/array/flipip_cmplx.c new file mode 100644 index 0000000..6926600 --- /dev/null +++ b/dspl/src/array/flipip_cmplx.c @@ -0,0 +1,155 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + +#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; + + 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; +} + + + diff --git a/dspl/src/array/linspace.c b/dspl/src/array/linspace.c new file mode 100644 index 0000000..4791a83 --- /dev/null +++ b/dspl/src/array/linspace.c @@ -0,0 +1,199 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#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; + + 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; +} + + diff --git a/dspl/src/array/logspace.c b/dspl/src/array/logspace.c new file mode 100644 index 0000000..9b95bf9 --- /dev/null +++ b/dspl/src/array/logspace.c @@ -0,0 +1,211 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#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; + + if(n < 2) + return ERROR_SIZE; + if(!x) + return ERROR_PTR; + + 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; +} + + diff --git a/dspl/src/array/ones.c b/dspl/src/array/ones.c new file mode 100644 index 0000000..7e78b9b --- /dev/null +++ b/dspl/src/array/ones.c @@ -0,0 +1,113 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#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; + return RES_OK; +} diff --git a/dspl/src/array/sum.c b/dspl/src/array/sum.c new file mode 100644 index 0000000..b7296d0 --- /dev/null +++ b/dspl/src/array/sum.c @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int sum(double* x, int n, double* s) +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int sum(double* x, int n, double* s) +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API sum(double* x, int n, double* s) +{ + int i; + double z = 0.0; + if(!x || !s) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + + for(i = 0; i < n; i++) + z += x[i]; + *s = z; + return RES_OK; +} \ No newline at end of file diff --git a/dspl/src/array/sum_sqr.c b/dspl/src/array/sum_sqr.c new file mode 100644 index 0000000..3cf00c3 --- /dev/null +++ b/dspl/src/array/sum_sqr.c @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2015-2020 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int sum(double* x, int n, double* s) +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup ARRAY_GROUP +\fn int sum(double* x, int n, double* s) +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API sum_sqr(double* x, int n, double* s) +{ + int i; + double z = 0.0; + if(!x || !s) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + + for(i = 0; i < n; i++) + z += x[i]*x[i]; + *s = z; + return RES_OK; +} \ No newline at end of file diff --git a/dspl/src/dft.c b/dspl/src/dft.c index e5ef5ab..759b74e 100644 --- a/dspl/src/dft.c +++ b/dspl/src/dft.c @@ -1,532 +1,53 @@ + /* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . +Discrete Fourier Transform Algorithms */ +#include "dft/dft.c" +#include "dft/dft_cmplx.c" +#include "dft/idft_cmplx.c" +/* +Fast Fourier Transform Algrithms +*/ +#include "dft/fft.c" +#include "dft/fft_abs.c" +#include "dft/fft_abs_cmplx.c" +#include "dft/fft_cmplx.c" +#include "dft/fft_create.c" +#include "dft/fft_free.c" +#include "dft/fft_krn.c" +#include "dft/fft_mag.c" +#include "dft/fft_mag_cmplx.c" +#include "dft/fft_shift.c" +#include "dft/fft_shift_cmplx.c" +#include "dft/fft_subkernel.c" +#include "dft/ifft_cmplx.c" -#include -#include -#include "dspl.h" +/* +Goertzel Algorithm +*/ +#include "dft/goertzel.c" +#include "dft/goertzel_cmplx.c" -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int dft(double* x, int n, complex_t* y) -\brief Discrete Fourier transform of a real signal. +/* +Fourier Series and Fourier Intergral +*/ +#include "dft/fourier_series_dec.c" +#include "dft/fourier_series_dec_cmplx.c" +#include "dft/fourier_integral_cmplx.c" +#include "dft/fourier_series_rec.c" -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; - - - if(!x || !y) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - 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++) - { - 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; -} - - - -#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; - - if(!x || !y) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - 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++) - { - 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; -} - - - - - -#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; - - if(!x || !y) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - 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++) - { - 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; - } - return RES_OK; -} diff --git a/dspl/src/dft/dft.c b/dspl/src/dft/dft.c new file mode 100644 index 0000000..b356718 --- /dev/null +++ b/dspl/src/dft/dft.c @@ -0,0 +1,192 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include "dspl.h" + + + +#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; + + + if(!x || !y) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + 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++) + { + 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; +} + + diff --git a/dspl/src/dft/dft_cmplx.c b/dspl/src/dft/dft_cmplx.c new file mode 100644 index 0000000..93aec27 --- /dev/null +++ b/dspl/src/dft/dft_cmplx.c @@ -0,0 +1,194 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include "dspl.h" + + + +#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; + + if(!x || !y) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + 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++) + { + 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; +} + + diff --git a/dspl/src/dft/fft.c b/dspl/src/dft/fft.c new file mode 100644 index 0000000..6b4167e --- /dev/null +++ b/dspl/src/dft/fft.c @@ -0,0 +1,192 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + +#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); +} \ No newline at end of file diff --git a/dspl/src/dft/fft_abs.c b/dspl/src/dft/fft_abs.c new file mode 100644 index 0000000..86362c4 --- /dev/null +++ b/dspl/src/dft/fft_abs.c @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API fft_abs(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; + + + 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; +} + diff --git a/dspl/src/dft/fft_abs_cmplx.c b/dspl/src/dft/fft_abs_cmplx.c new file mode 100644 index 0000000..621e9b6 --- /dev/null +++ b/dspl/src/dft/fft_abs_cmplx.c @@ -0,0 +1,85 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API fft_abs_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; + + + 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; +} diff --git a/dspl/src/dft/fft_cmplx.c b/dspl/src/dft/fft_cmplx.c new file mode 100644 index 0000000..cd92bbb --- /dev/null +++ b/dspl/src/dft/fft_cmplx.c @@ -0,0 +1,201 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + + + +#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; + + memcpy(pfft->t1, x, n*sizeof(complex_t)); + + return fft_krn(pfft->t1, y, pfft, n, 0); +} + diff --git a/dspl/src/dft/fft_create.c b/dspl/src/dft/fft_create.c new file mode 100644 index 0000000..3f44765 --- /dev/null +++ b/dspl/src/dft/fft_create.c @@ -0,0 +1,367 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + + +#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%4096 == 0) { n2 = 4096; goto label_size; } + if(s%2048 == 0) { n2 = 2048; goto label_size; } + if(s%1024 == 0) { n2 = 1024; goto label_size; } + if(s%512 == 0) { n2 = 512; goto label_size; } + if(s%256 == 0) { n2 = 256; goto label_size; } + if(s%128 == 0) { n2 = 128; goto label_size; } + if(s% 64 == 0) { n2 = 64; goto label_size; } + if(s% 32 == 0) { n2 = 32; goto label_size; } + 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; + + /* w32 fill */ + addr = 0; + for(k = 0; k < 4; k++) + { + for(m = 0; m < 8; m++) + { + phi = - M_2PI * (double)(k*m) / 32.0; + RE(pfft->w32[addr]) = cos(phi); + IM(pfft->w32[addr]) = sin(phi); + addr++; + } + } + + + /* w64 fill */ + addr = 0; + for(k = 0; k < 8; k++) + { + for(m = 0; m < 8; m++) + { + phi = - M_2PI * (double)(k*m) / 64.0; + RE(pfft->w64[addr]) = cos(phi); + IM(pfft->w64[addr]) = sin(phi); + addr++; + } + } + + /* w128 fill */ + addr = 0; + for(k = 0; k < 8; k++) + { + for(m = 0; m < 16; m++) + { + phi = - M_2PI * (double)(k*m) / 128.0; + RE(pfft->w128[addr]) = cos(phi); + IM(pfft->w128[addr]) = sin(phi); + addr++; + } + } + + /* w256 fill */ + addr = 0; + for(k = 0; k < 16; k++) + { + for(m = 0; m < 16; m++) + { + phi = - M_2PI * (double)(k*m) / 256.0; + RE(pfft->w256[addr]) = cos(phi); + IM(pfft->w256[addr]) = sin(phi); + addr++; + } + } + + /* w512 fill */ + addr = 0; + for(k = 0; k < 16; k++) + { + for(m = 0; m < 32; m++) + { + phi = - M_2PI * (double)(k*m) / 512.0; + RE(pfft->w512[addr]) = cos(phi); + IM(pfft->w512[addr]) = sin(phi); + addr++; + } + } + + /* w1024 fill */ + if(pfft->w1024 == NULL) + { + pfft->w1024 = (complex_t*) malloc(1024 * sizeof(complex_t)); + addr = 0; + for(k = 0; k < 32; k++) + { + for(m = 0; m < 32; m++) + { + phi = - M_2PI * (double)(k*m) / 1024.0; + RE(pfft->w1024[addr]) = cos(phi); + IM(pfft->w1024[addr]) = sin(phi); + addr++; + } + } + } + + /* w2048 fill */ + if(pfft->w2048 == NULL) + { + pfft->w2048= (complex_t*) malloc(2048 * sizeof(complex_t)); + addr = 0; + for(k = 0; k < 32; k++) + { + for(m = 0; m < 64; m++) + { + phi = - M_2PI * (double)(k*m) / 2048.0; + RE(pfft->w2048[addr]) = cos(phi); + IM(pfft->w2048[addr]) = sin(phi); + addr++; + } + } + } + + /* w4096 fill */ + if(pfft->w4096 == NULL) + { + pfft->w4096= (complex_t*) malloc(4096 * sizeof(complex_t)); + addr = 0; + for(k = 0; k < 16; k++) + { + for(m = 0; m < 256; m++) + { + phi = - M_2PI * (double)(k*m) / 4096.0; + RE(pfft->w4096[addr]) = cos(phi); + IM(pfft->w4096[addr]) = sin(phi); + addr++; + } + } + } + + 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; +} diff --git a/dspl/src/dft/fft_free.c b/dspl/src/dft/fft_free.c new file mode 100644 index 0000000..e81a841 --- /dev/null +++ b/dspl/src/dft/fft_free.c @@ -0,0 +1,85 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + + +#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); + + if(pfft->w1024) + free(pfft->w1024); + + if(pfft->w2048) + free(pfft->w2048); + + if(pfft->w4096) + free(pfft->w4096); + + memset(pfft, 0, sizeof(fft_t)); +} + diff --git a/dspl/src/dft/fft_krn.c b/dspl/src/dft/fft_krn.c new file mode 100644 index 0000000..e601d77 --- /dev/null +++ b/dspl/src/dft/fft_krn.c @@ -0,0 +1,170 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + +#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 % 4096 == 0) { n1 = 4096; goto label_size; } + if(n % 2048 == 0) { n1 = 2048; goto label_size; } + if(n % 1024 == 0) { n1 = 1024; goto label_size; } + if(n % 512 == 0) { n1 = 512; goto label_size; } + if(n % 256 == 0) { n1 = 256; goto label_size; } + if(n % 128 == 0) { n1 = 128; goto label_size; } + if(n % 64 == 0) { n1 = 64; goto label_size; } + if(n % 32 == 0) { n1 = 32; goto label_size; } + 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++) + { + 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 == 4096) + for(k = 0; k < n2; k++) + dft4096(t0+4096*k, t1+4096*k, p->w4096, p->w256); + + if(n1 == 2048) + for(k = 0; k < n2; k++) + dft2048(t0+2048*k, t1+2048*k, p->w2048, p->w32, p->w64); + + if(n1 == 1024) + for(k = 0; k < n2; k++) + dft1024(t0+1024*k, t1+1024*k, p->w1024, p->w32); + + if(n1 == 512) + for(k = 0; k < n2; k++) + dft512(t0+512*k, t1+512*k, p->w512, p->w32); + + if(n1 == 256) + for(k = 0; k < n2; k++) + dft256(t0+256*k, t1+256*k, p->w256); + + if(n1 == 128) + for(k = 0; k < n2; k++) + dft128(t0+128*k, t1+128*k, p->w128); + + if(n1 == 64) + for(k = 0; k < n2; k++) + dft64(t0+64*k, t1+64*k, p->w64); + + if(n1 == 32) + for(k = 0; k < n2; k++) + dft32(t0+32*k, t1+32*k, p->w32); + + 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; +} + + diff --git a/dspl/src/dft/fft_mag.c b/dspl/src/dft/fft_mag.c new file mode 100644 index 0000000..7917c20 --- /dev/null +++ b/dspl/src/dft/fft_mag.c @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + +#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; + fft_t *cfft = NULL; + + if(pfft) + cfft = pfft; + else + { + cfft = (fft_t*) malloc(sizeof(fft_t)); + memset(cfft, 0, sizeof(fft_t)); + } + + err = fft_abs(x, n, cfft, fs, flag, mag, freq); + if(err != RES_OK) + goto error_proc; + + if(mag) + { + if(flag & DSPL_FLAG_LOGMAG) + for(k = 0; k < n; k++) + mag[k] = 20.0 * log10(mag[k] + DBL_EPSILON); + else + for(k = 0; k < n; k++) + mag[k] *= mag[k]; + } +error_proc: + if(cfft && cfft != pfft) + free(cfft); + return err; +} diff --git a/dspl/src/dft/fft_mag_cmplx.c b/dspl/src/dft/fft_mag_cmplx.c new file mode 100644 index 0000000..2cd5169 --- /dev/null +++ b/dspl/src/dft/fft_mag_cmplx.c @@ -0,0 +1,74 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + + + + +#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; + fft_t *cfft = NULL; + + if(pfft) + cfft = pfft; + else + { + cfft = (fft_t*) malloc(sizeof(fft_t)); + memset(cfft, 0, sizeof(fft_t)); + } + + err = fft_abs_cmplx(x, n, cfft, fs, flag, mag, freq); + if(err != RES_OK) + goto error_proc; + + if(mag) + { + if(flag & DSPL_FLAG_LOGMAG) + for(k = 0; k < n; k++) + mag[k] = 20.0 * log10(mag[k] + DBL_EPSILON); + else + for(k = 0; k < n; k++) + mag[k] *= mag[k]; + } +error_proc: + if(cfft && cfft != pfft) + free(cfft); + return err; +} + diff --git a/dspl/src/dft/fft_shift.c b/dspl/src/dft/fft_shift.c new file mode 100644 index 0000000..b1b5e47 --- /dev/null +++ b/dspl/src/dft/fft_shift.c @@ -0,0 +1,129 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + + + +#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; + + if(!x || !y) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + r = n%2; + if(!r) + { + 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; +} diff --git a/dspl/src/dft/fft_shift_cmplx.c b/dspl/src/dft/fft_shift_cmplx.c new file mode 100644 index 0000000..d78015a --- /dev/null +++ b/dspl/src/dft/fft_shift_cmplx.c @@ -0,0 +1,76 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" + + +#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; + + if(!x || !y) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + r = n%2; + if(!r) + { + 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+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; +} + diff --git a/dspl/src/fft_subkernel.c b/dspl/src/dft/fft_subkernel.c similarity index 100% rename from dspl/src/fft_subkernel.c rename to dspl/src/dft/fft_subkernel.c diff --git a/dspl/src/dft/fourier_integral_cmplx.c b/dspl/src/dft/fourier_integral_cmplx.c new file mode 100644 index 0000000..12202f3 --- /dev/null +++ b/dspl/src/dft/fourier_integral_cmplx.c @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API fourier_integral_cmplx(double* t, complex_t* s, int nt, + int nw, double* w, complex_t* y) +{ + int k, m; + complex_t e[2]; + + if(!t || !s || !w || !y) + return ERROR_PTR; + if(nt<1 || nw < 1) + return ERROR_SIZE; + + + memset(y, 0 , nw*sizeof(complex_t)); + + for(k = 0; k < nw; k++) + { + RE(e[1]) = RE(s[0]) * cos(w[k] * t[0]) + + IM(s[0]) * sin(w[k] * t[0]); + IM(e[1]) = -RE(s[0]) * sin(w[k] * t[0]) + + IM(s[0]) * cos(w[k] * t[0]); + for(m = 1; m < nt; m++) + { + RE(e[0]) = RE(e[1]); + IM(e[0]) = IM(e[1]); + RE(e[1]) = RE(s[m]) * cos(w[k] * t[m]) + + IM(s[m]) * sin(w[k] * t[m]); + IM(e[1]) = -RE(s[m]) * sin(w[k] * t[m]) + + IM(s[m]) * cos(w[k] * t[m]); + RE(y[k]) += 0.5 * (RE(e[0]) + RE(e[1]))*(t[m] - t[m-1]); + IM(y[k]) += 0.5 * (IM(e[0]) + IM(e[1]))*(t[m] - t[m-1]); + } + } + + return RES_OK; +} + diff --git a/dspl/src/dft/fourier_series_dec.c b/dspl/src/dft/fourier_series_dec.c new file mode 100644 index 0000000..3f531e3 --- /dev/null +++ b/dspl/src/dft/fourier_series_dec.c @@ -0,0 +1,190 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fourier_series_dec(double* t, double* s, int nt, double period, + int nw, double* w, complex_t* y) + +\brief +Fourier series coefficient calculation for periodic signal + +\param[in] t +Pointer to the time vector. \n +Vector size is `[nt x 1]`. \n +\n + +\param[in] s +Pointer to the signal corresponds to time `t`. \n +Vector size is `[nt x 1]`. \n +\n + +\param[in] nt +Size of time and signal vectors. \n +This value must be positive. \n +\n + +\param[in] period +Signal time period. \n +\n + +\param[in] nw +Number of Fourie series coefficients. \n +\n + +\param[out] w +Pointer to the frequency vector (rad/s). \n +Vector size is `[nw x 1]`. \n +Memory must be allocated. \n +\n + +\param[out] y +Pointer to the complex Fourier series coefficients vector. \n +Vector size is `[nw 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". + +\note +Numerical integration is used for Fourier series coefficients calculation. +This function is not effective. +To increase the speed of calculation of the signal spectrum +it is more expedient to use fast Fourier transform algorithms. +\n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fourier_series_dec(double* t, double* s, int nt, double period, + int nw, double* w, complex_t* y) + +\brief +Расчет коэффициентов разложения в ряд Фурье + +Функция рассчитывает спектр периодического сигнала при усечении ряда Фурье \n + + +\param[in] t +Указатель на массив моментов времени дискретизации исходного сигнала `s`. \n +Размер вектора вектора `[nt x 1]`. \n +Память должна быть выделена. \n +\n + +\param[in] s +Указатель на массив значений исходного сигнала`s`. \n +Размер вектора `[nt x 1]`. \n +Память должна быть выделена. \n +\n + + +\param[in] nt +Размер выборки исходного сигнала. \n +Значение должно быть положительным. \n +\n + +\param[in] period +Период повторения сигнала. \n +\n + +\param[in] nw +Размер усеченного ряда Фурье. \n +\n + +\param[out] w +Указатель на массив частот спектра периодического сигнала. \n +Размер вектора `[nw x 1]`. \n +Память должна быть выделена. \n +\n + +\param[out] y +Указатель массив комплексных значений спектра периодического сигнала. \n +Размер вектора `[nw x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- коэффициенты ряда Фурье рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Для расчета спектра сигнала используется численное интегрирование +исходного сигнала методом трапеций. Данная функция не является +эффективной. Для увеличения скорости расчета спектра сигнала +целесообразнее использовать алгоритмы дискретного +и быстрого преобразования Фурье. +\n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API fourier_series_dec(double* t, double* s, int nt, double period, + int nw, double* w, complex_t* y) +{ + int k, m; + double dw = M_2PI / period; + complex_t e[2]; + + if(!t || !s || !w || !y) + return ERROR_PTR; + if(nt<1 || nw < 1) + return ERROR_SIZE; + if(period <= 0.0) + return ERROR_NEGATIVE; + + memset(y, 0 , nw*sizeof(complex_t)); + + for(k = 0; k < nw; k++) + { + w[k] = (k - nw/2) * dw; + RE(e[1]) = s[0] * cos(w[k] * t[0]); + IM(e[1]) = -s[0] * sin(w[k] * t[0]); + for(m = 1; m < nt; m++) + { + RE(e[0]) = RE(e[1]); + IM(e[0]) = IM(e[1]); + RE(e[1]) = s[m] * cos(w[k] * t[m]); + IM(e[1]) = - s[m] * sin(w[k] * t[m]); + RE(y[k]) += 0.5 * (RE(e[0]) + RE(e[1]))*(t[m] - t[m-1]); + IM(y[k]) += 0.5 * (IM(e[0]) + IM(e[1]))*(t[m] - t[m-1]); + } + RE(y[k]) /= period; + IM(y[k]) /= period; + } + + if(!(nw%2)) + RE(y[0]) = RE(y[1]) = 0.0; + + return RES_OK; +} diff --git a/dspl/src/dft/fourier_series_dec_cmplx.c b/dspl/src/dft/fourier_series_dec_cmplx.c new file mode 100644 index 0000000..2f105b9 --- /dev/null +++ b/dspl/src/dft/fourier_series_dec_cmplx.c @@ -0,0 +1,76 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API fourier_series_dec_cmplx(double* t, complex_t* s, int nt, + double period, int nw, double* w, complex_t* y) +{ + int k, m; + double dw = M_2PI / period; + complex_t e[2]; + + if(!t || !s || !w || !y) + return ERROR_PTR; + if(nt<1 || nw < 1) + return ERROR_SIZE; + if(period <= 0.0) + return ERROR_NEGATIVE; + + memset(y, 0 , nw*sizeof(complex_t)); + + for(k = 0; k < nw; k++) + { + w[k] = (k - nw/2) * dw; + RE(e[1]) = RE(s[0]) * cos(w[k] * t[0]) + + IM(s[0]) * sin(w[k] * t[0]); + IM(e[1]) = -RE(s[0]) * sin(w[k] * t[0]) + + IM(s[0]) * cos(w[k] * t[0]); + for(m = 1; m < nt; m++) + { + RE(e[0]) = RE(e[1]); + IM(e[0]) = IM(e[1]); + RE(e[1]) = RE(s[m]) * cos(w[k] * t[m]) + + IM(s[m]) * sin(w[k] * t[m]); + IM(e[1]) = -RE(s[m]) * sin(w[k] * t[m]) + + IM(s[m]) * cos(w[k] * t[m]); + RE(y[k]) += 0.5 * (RE(e[0]) + RE(e[1]))*(t[m] - t[m-1]); + IM(y[k]) += 0.5 * (IM(e[0]) + IM(e[1]))*(t[m] - t[m-1]); + } + RE(y[k]) /= period; + IM(y[k]) /= period; + } + + if(!(nw%2)) + RE(y[0]) = RE(y[1]) = 0.0; + + return RES_OK; +} diff --git a/dspl/src/dft/fourier_series_rec.c b/dspl/src/dft/fourier_series_rec.c new file mode 100644 index 0000000..341b1f6 --- /dev/null +++ b/dspl/src/dft/fourier_series_rec.c @@ -0,0 +1,185 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include +#include "dspl.h" + + + + + + + + + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fourier_series_rec(double* w, complex_t* s, int nw, + double* t, int nt, complex_t* y) +\brief Time signal reconstruction from Fourier series coefficients. + +Function reconstructs the time signal: + +\f[ +s(t) = \sum\limits_{n = 0}^{n_{\omega}-1} S(\omega_n) \exp(j\omega_n t) +\f] + +\param[in] w +Pointer to the Fourier series spectrum frequency vector \f$\omega_n\f$. \n +Vector size is `[nw x 1]`. \n +\n + +\param[in] s +Pointer to the Fourier series coefficients vector \f$S(\omega_n)\f$. \n +Vector size is `[nw x 1]`. \n +\n + + +\param[in] nw +Number of Fourier series coefficients. \n +This value must be positive. \n +\n + +\param[in] t +Pointer to the reconstructed signal time vector. \n +Vector size is `[nt x 1]`. \n +\n + +\param[in] nt +Size of time vector and reconstructed signal vector . \n +\n + +\param[out] y +Pointer to the reconstructed signal vector. \n +Vector size is `[nt 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". + +\note +The output reconstructed signal is generally complex. +However, subject to the symmetry properties of the vectors `w` and` s` +with respect to zero frequency we get the imaginary part of the vector `y` +at the EPS level. The negligible imaginary part in this case +can be ignored. +\n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int fourier_series_rec(double* w, complex_t* s, int nw, + double* t, int nt, complex_t* y) +\brief Восстановление сигнала при усечении ряда Фурье + +Функция рассчитывает восстановленный сигнал при усечении ряда Фурье: + +\f[ +s(t) = \sum\limits_{n = 0}^{n_{\omega}-1} S(\omega_n) \exp(j\omega_n t) +\f] + +\param[in] w +Указатель на массив частот \f$\omega_n\f$ усеченного ряда Фурье. \n +Размер вектора `[nw x 1]`. \n +Память должна быть выделена и заполнена. \n +\n + +\param[in] s +Указатель на массив значений спектра \f$S(\omega_n)\f$. \n +Размер вектора `[nw x 1]`. \n +Память должна быть выделена и заполнена. \n +\n + + +\param[in] nw +Количество членов усеченного ряда Фурье. \n +Значение должно быть положительным. \n +\n + +\param[in] t +Указатель на массив временных отсчетов восстановленного сигнала. \n +Размер вектора `[nt x 1]`. \n +Память должна быть выделена и заполнена. \n +\n + +\param[in] nt +Размер вектора времени и восстановленного сигнала. \n +\n + +\param[out] y +Указатель на массив восстановленного сигнала. \n +Размер вектора `[nt x 1]`. \n +Память должна быть выделена. \n +\n + +\return +`RES_OK` --- восстановление сигнала прошло успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Выходной восстановленный сигнал в общем случае является комплексным. +Однако при соблюдении свойств симметрии векторов `w` и `s` относительно +нулевой частоты получим мнимую часть элементов вектора `y` на уровне ошибок +округления числа с двойной точностью. Ничтожно малую мнимую часть в этом случае +можно игнорировать. +\n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API fourier_series_rec(double* w, complex_t* s, int nw, + double* t, int nt, complex_t* y) +{ + int k, m; + complex_t e; + + if(!t || !s || !w || !y) + return ERROR_PTR; + if(nt<1 || nw < 1) + return ERROR_SIZE; + + memset(y, 0, nt*sizeof(complex_t)); + + + for(k = 0; k < nw; k++) + { + for(m = 0; m < nt; m++) + { + RE(e) = cos(w[k] * t[m]); + IM(e) = sin(w[k] * t[m]); + + RE(y[m]) += CMRE(s[k], e); + IM(y[m]) += CMIM(s[k], e); + } + } + return RES_OK; +} + diff --git a/dspl/src/dft/goertzel.c b/dspl/src/dft/goertzel.c new file mode 100644 index 0000000..ae21e7a --- /dev/null +++ b/dspl/src/dft/goertzel.c @@ -0,0 +1,157 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int goertzel(double *x, int n, int *ind, int k, complex_t *y) +\brief +Goertzel algorithm individual DFT samples calculation for the real input vector `x`. + +Goertzel algorithm calculates `k` samples of `n`-point DFT, according to +`ind` indexes vector. + +\param[in] x +Pointer to the real input vector `x` \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of vector `x`. \n \n + +\param[in] ind +Pointer to the DFT samples indexes which need +to calculate by Goertzel algorithm. \n +Vector size is `[k x 1]`. \n \n + +\param[in] k +Size of vector `ind`. \n \n + +\param[out] y +Pointer to the DFT samples vector corresponds to indexes `ind`. \n +Vector size is `[k 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". + +\note +Goertzel's algorithm is effective when it is necessary to calculate +several DFT samples of a signal of long duration. \n +However, the size `k` of the vector of indices` ind` can be arbitrary, +including more than the length of the signal `n`. +In this case, some DFT samples will be repeated, but this will not entail +a runtime error. \n +The values of the indices of the DFT spectral samples `ind` +can also be arbitrary integers, including negative ones. +In this case, the DFT samples will be calculated. +with indices modulo `n`. \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int goertzel(double *x, int n, int *ind, int k, complex_t *y) +\brief +Алгоритм Гёрцеля для расчета отдельных спектральных отсчетов дискретного +преобразования Фурье вещественного сигнала `x`. + +Данный алгоритм позволяет рассчитать `k` спектральных отсчетов +`n`-точечного ДПФ, заданных вектором индексов `ind`. + +\param[in] x +Указатель на вектор вещественного входного сигнала. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора входного сигнала. \n \n + +\param[in] ind +Указатель на вектор индексов спектральных отсчетов для расчета которых +будет использоваться алгоритм Герцеля. \n +Размер вектора `[k x 1]`. \n \n + +\param[in] k +Размер вектора индексов спектральных отсчетов `ind`. \n \n + +\param[out] y +Указатель на вектор спектральных отсчетов, соответствующих номерам `ind`. \n +Размер вектора `[k x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` --- расчёт выполнен успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Алгоритм Гёрцеля эффективен когда необходимо рассчитать несколько +спектральных отсчетов сигнала большой длительности. \n +Однако, размер `k` вектора индексов `ind` может быть произвольным, +в том числе больше длины сигнала `n`. +В этом случае некоторые спектральные отсчеты будут повторяться, но это +не повлечет за собой ошибки выполнения. \n +Значения индексов спектральных отсчетов `ind` также могут быть +произвольными целыми, в том числе и отрицательными. +В этом случае будут рассчитаны спектральные отсчеты +с индексами по модулю `n`. \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API goertzel(double *x, int n, int *ind, int k, complex_t *y) +{ + + int m, p; + double wR, wI; + double alpha; + double v[3]; + + if(!x || !y || !ind) + return ERROR_PTR; + + if(n < 1 || k < 1) + return ERROR_SIZE; + + for(p = 0; p < k; p++) + { + wR = cos(M_2PI * (double)ind[p] / (double)n); + wI = sin(M_2PI * (double)ind[p] / (double)n); + + alpha = 2.0 * wR; + v[0] = v[1] = v[2] = 0.0; + + for(m = 0; m < n; m++) + { + v[2] = v[1]; + v[1] = v[0]; + v[0] = x[m]+alpha*v[1] - v[2]; + } + RE(y[p]) = wR * v[0] - v[1]; + IM(y[p]) = wI * v[0]; + } + return RES_OK; +} diff --git a/dspl/src/goertzel.c b/dspl/src/dft/goertzel_cmplx.c similarity index 54% rename from dspl/src/goertzel.c rename to dspl/src/dft/goertzel_cmplx.c index a2bcd3c..26aefdd 100644 --- a/dspl/src/goertzel.c +++ b/dspl/src/dft/goertzel_cmplx.c @@ -1,302 +1,166 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include "dspl.h" - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int goertzel(double *x, int n, int *ind, int k, complex_t *y) -\brief -Goertzel algorithm individual DFT samples calculation for the real input vector `x`. - -Goertzel algorithm calculates `k` samples of `n`-point DFT, according to -`ind` indexes vector. - -\param[in] x -Pointer to the real input vector `x` \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of vector `x`. \n \n - -\param[in] ind -Pointer to the DFT samples indexes which need -to calculate by Goertzel algorithm. \n -Vector size is `[k x 1]`. \n \n - -\param[in] k -Size of vector `ind`. \n \n - -\param[out] y -Pointer to the DFT samples vector corresponds to indexes `ind`. \n -Vector size is `[k 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". - -\note -Goertzel's algorithm is effective when it is necessary to calculate -several DFT samples of a signal of long duration. \n -However, the size `k` of the vector of indices` ind` can be arbitrary, -including more than the length of the signal `n`. -In this case, some DFT samples will be repeated, but this will not entail -a runtime error. \n -The values of the indices of the DFT spectral samples `ind` -can also be arbitrary integers, including negative ones. -In this case, the DFT samples will be calculated. -with indices modulo `n`. \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int goertzel(double *x, int n, int *ind, int k, complex_t *y) -\brief -Алгоритм Гёрцеля для расчета отдельных спектральных отсчетов дискретного -преобразования Фурье вещественного сигнала `x`. - -Данный алгоритм позволяет рассчитать `k` спектральных отсчетов -`n`-точечного ДПФ, заданных вектором индексов `ind`. - -\param[in] x -Указатель на вектор вещественного входного сигнала. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора входного сигнала. \n \n - -\param[in] ind -Указатель на вектор индексов спектральных отсчетов для расчета которых -будет использоваться алгоритм Герцеля. \n -Размер вектора `[k x 1]`. \n \n - -\param[in] k -Размер вектора индексов спектральных отсчетов `ind`. \n \n - -\param[out] y -Указатель на вектор спектральных отсчетов, соответствующих номерам `ind`. \n -Размер вектора `[k x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` --- расчёт выполнен успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Алгоритм Гёрцеля эффективен когда необходимо рассчитать несколько -спектральных отсчетов сигнала большой длительности. \n -Однако, размер `k` вектора индексов `ind` может быть произвольным, -в том числе больше длины сигнала `n`. -В этом случае некоторые спектральные отсчеты будут повторяться, но это -не повлечет за собой ошибки выполнения. \n -Значения индексов спектральных отсчетов `ind` также могут быть -произвольными целыми, в том числе и отрицательными. -В этом случае будут рассчитаны спектральные отсчеты -с индексами по модулю `n`. \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API goertzel(double *x, int n, int *ind, int k, complex_t *y) -{ - - int m, p; - double wR, wI; - double alpha; - double v[3]; - - if(!x || !y || !ind) - return ERROR_PTR; - - if(n < 1 || k < 1) - return ERROR_SIZE; - - for(p = 0; p < k; p++) - { - wR = cos(M_2PI * (double)ind[p] / (double)n); - wI = sin(M_2PI * (double)ind[p] / (double)n); - - alpha = 2.0 * wR; - v[0] = v[1] = v[2] = 0.0; - - for(m = 0; m < n; m++) - { - v[2] = v[1]; - v[1] = v[0]; - v[0] = x[m]+alpha*v[1] - v[2]; - } - RE(y[p]) = wR * v[0] - v[1]; - IM(y[p]) = wI * v[0]; - } - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int goertzel_cmplx(complex_t *x, int n, int *ind, int k, complex_t *y) -\brief -Goertzel algorithm individual DFT samples calculation for -the complex input vector `x`. - -Goertzel algorithm calculates `k` samples of `n`-point DFT, according to -`ind` indexes vector. - -\param[in] x -Pointer to the complex input vector `x` \n -Vector size is `[n x 1]`. \n \n - -\param[in] n -Size of vector `x`. \n \n - -\param[in] ind -Pointer to the DFT samples indexes which need -to calculate by Goertzel algorithm. \n -Vector size is `[k x 1]`. \n \n - -\param[in] k -Size of vector `ind`. \n \n - -\param[out] y -Pointer to the DFT samples vector corresponds to indexes `ind`. \n -Vector size is `[k 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". - -\note -Goertzel's algorithm is effective when it is necessary to calculate -several DFT samples of a signal of long duration. \n -However, the size `k` of the vector of indices` ind` can be arbitrary, -including more than the length of the signal `n`. -In this case, some DFT samples will be repeated, but this will not entail -a runtime error. \n -The values of the indices of the DFT spectral samples `ind` -can also be arbitrary integers, including negative ones. -In this case, the DFT samples will be calculated. -with indices modulo `n`. \n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int goertzel_cmplx(complex_t *x, int n, int *ind, int k, complex_t *y) -\brief -Алгоритм Гёрцеля для расчета отдельных спектральных отсчетов дискретного -преобразования Фурье комплексного сигнала `x`. - -Данный алгоритм позволяет рассчитать `k` спектральных отсчетов -`n`-точечного ДПФ, заданных вектором индексов `ind`. - -\param[in] x -Указатель на вектор комплексного входного сигнала. \n -Размер вектора `[n x 1]`. \n \n - -\param[in] n -Размер вектора входного сигнала. \n \n - -\param[in] ind -Указатель на вектор индексов спектральных отсчетов для расчета которых -будет использоваться алгоритм Герцеля. \n -Размер вектора `[k x 1]`. \n \n - -\param[in] k -Размер вектора индексов спектральных отсчетов `ind`. \n \n - -\param[out] y -Указатель на вектор спектральных отсчетов, соответствующих номерам `ind`. \n -Размер вектора `[k x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` --- функция выполнена успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Алгоритм Герцеля эффективен когда необходимо рассчитать несколько -спектральных отсчетов сигнала большой длительности. \n -Однако, размер `k` вектора индексов `ind` может быть произвольным, -в том числе больше длины сигнала `n`. -В этом случае некоторые спектральные отсчеты -будут повторяться, но это не повлечет за собой ошибки выполнения. \n -Значения индексов спектральных отсчетов `ind` также могут быть -произвольными целыми, в том числе и отрицательными. -В этом случае будут рассчитаны спектральные отсчеты с индексами -по модулю `n`. \n \n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API goertzel_cmplx(complex_t *x, int n, int *ind, int k, complex_t *y) -{ - - int m, p; - complex_t w; - double alpha; - complex_t v[3]; - - if(!x || !y || !ind) - return ERROR_PTR; - - if(n < 1 || k < 1) - return ERROR_SIZE; - - for(p = 0; p < k; p++) - { - RE(w) = cos(M_2PI * (double)ind[p] / (double)n); - IM(w) = sin(M_2PI * (double)ind[p] / (double)n); - - alpha = 2.0 * RE(w); - memset(v, 0, 3*sizeof(complex_t)); - - for(m = 0; m < n; m++) - { - RE(v[2]) = RE(v[1]); - RE(v[1]) = RE(v[0]); - RE(v[0]) = RE(x[m]) + alpha * RE(v[1]) - RE(v[2]); - - IM(v[2]) = IM(v[1]); - IM(v[1]) = IM(v[0]); - IM(v[0]) = IM(x[m]) + alpha * IM(v[1]) - IM(v[2]); - } - - RE(y[p]) = CMRE(w, v[0]) - RE(v[1]); - IM(y[p]) = CMIM(w, v[0]) - IM(v[1]); - } - - return RES_OK; -} - +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int goertzel_cmplx(complex_t *x, int n, int *ind, int k, complex_t *y) +\brief +Goertzel algorithm individual DFT samples calculation for +the complex input vector `x`. + +Goertzel algorithm calculates `k` samples of `n`-point DFT, according to +`ind` indexes vector. + +\param[in] x +Pointer to the complex input vector `x` \n +Vector size is `[n x 1]`. \n \n + +\param[in] n +Size of vector `x`. \n \n + +\param[in] ind +Pointer to the DFT samples indexes which need +to calculate by Goertzel algorithm. \n +Vector size is `[k x 1]`. \n \n + +\param[in] k +Size of vector `ind`. \n \n + +\param[out] y +Pointer to the DFT samples vector corresponds to indexes `ind`. \n +Vector size is `[k 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". + +\note +Goertzel's algorithm is effective when it is necessary to calculate +several DFT samples of a signal of long duration. \n +However, the size `k` of the vector of indices` ind` can be arbitrary, +including more than the length of the signal `n`. +In this case, some DFT samples will be repeated, but this will not entail +a runtime error. \n +The values of the indices of the DFT spectral samples `ind` +can also be arbitrary integers, including negative ones. +In this case, the DFT samples will be calculated. +with indices modulo `n`. \n + +\author Sergey Bakhurin www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup DFT_GROUP +\fn int goertzel_cmplx(complex_t *x, int n, int *ind, int k, complex_t *y) +\brief +Алгоритм Гёрцеля для расчета отдельных спектральных отсчетов дискретного +преобразования Фурье комплексного сигнала `x`. + +Данный алгоритм позволяет рассчитать `k` спектральных отсчетов +`n`-точечного ДПФ, заданных вектором индексов `ind`. + +\param[in] x +Указатель на вектор комплексного входного сигнала. \n +Размер вектора `[n x 1]`. \n \n + +\param[in] n +Размер вектора входного сигнала. \n \n + +\param[in] ind +Указатель на вектор индексов спектральных отсчетов для расчета которых +будет использоваться алгоритм Герцеля. \n +Размер вектора `[k x 1]`. \n \n + +\param[in] k +Размер вектора индексов спектральных отсчетов `ind`. \n \n + +\param[out] y +Указатель на вектор спектральных отсчетов, соответствующих номерам `ind`. \n +Размер вектора `[k x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` --- функция выполнена успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n + +\note +Алгоритм Герцеля эффективен когда необходимо рассчитать несколько +спектральных отсчетов сигнала большой длительности. \n +Однако, размер `k` вектора индексов `ind` может быть произвольным, +в том числе больше длины сигнала `n`. +В этом случае некоторые спектральные отсчеты +будут повторяться, но это не повлечет за собой ошибки выполнения. \n +Значения индексов спектральных отсчетов `ind` также могут быть +произвольными целыми, в том числе и отрицательными. +В этом случае будут рассчитаны спектральные отсчеты с индексами +по модулю `n`. \n \n + +\author Бахурин Сергей www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API goertzel_cmplx(complex_t *x, int n, int *ind, int k, complex_t *y) +{ + + int m, p; + complex_t w; + double alpha; + complex_t v[3]; + + if(!x || !y || !ind) + return ERROR_PTR; + + if(n < 1 || k < 1) + return ERROR_SIZE; + + for(p = 0; p < k; p++) + { + RE(w) = cos(M_2PI * (double)ind[p] / (double)n); + IM(w) = sin(M_2PI * (double)ind[p] / (double)n); + + alpha = 2.0 * RE(w); + memset(v, 0, 3*sizeof(complex_t)); + + for(m = 0; m < n; m++) + { + RE(v[2]) = RE(v[1]); + RE(v[1]) = RE(v[0]); + RE(v[0]) = RE(x[m]) + alpha * RE(v[1]) - RE(v[2]); + + IM(v[2]) = IM(v[1]); + IM(v[1]) = IM(v[0]); + IM(v[0]) = IM(x[m]) + alpha * IM(v[1]) - IM(v[2]); + } + + RE(y[p]) = CMRE(w, v[0]) - RE(v[1]); + IM(y[p]) = CMIM(w, v[0]) - IM(v[1]); + } + + return RES_OK; +} + diff --git a/dspl/src/dft/idft_cmplx.c b/dspl/src/dft/idft_cmplx.c new file mode 100644 index 0000000..1283c28 --- /dev/null +++ b/dspl/src/dft/idft_cmplx.c @@ -0,0 +1,195 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + + +#include +#include +#include "dspl.h" + + +#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; + + if(!x || !y) + return ERROR_PTR; + + if(n<1) + return ERROR_SIZE; + + 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++) + { + 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; + } + return RES_OK; +} + diff --git a/dspl/src/dft/ifft_cmplx.c b/dspl/src/dft/ifft_cmplx.c new file mode 100644 index 0000000..85ccae3 --- /dev/null +++ b/dspl/src/dft/ifft_cmplx.c @@ -0,0 +1,209 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include + +#include "dspl.h" +#include "dspl_internal.h" +#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; + + if(!x || !pfft || !y) + return ERROR_PTR; + if(n<1) + return ERROR_SIZE; + + + 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]); + + err = fft_krn(pfft->t1, pfft->t0, pfft, n, 0); + + 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; +} \ No newline at end of file diff --git a/dspl/src/fft.c b/dspl/src/fft.c deleted file mode 100644 index 5fe7e16..0000000 --- a/dspl/src/fft.c +++ /dev/null @@ -1,1441 +0,0 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include -#include - -#include "dspl.h" -#include "dspl_internal.h" - - -#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; - - if(!x || !pfft || !y) - return ERROR_PTR; - if(n<1) - return ERROR_SIZE; - - - 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]); - - err = fft_krn(pfft->t1, pfft->t0, pfft, n, 0); - - 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; -} - - -#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); -} - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API fft_abs(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; - - - 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; -} - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API fft_abs_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; - - - 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; -} - - - -#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; - - memcpy(pfft->t1, x, n*sizeof(complex_t)); - - return fft_krn(pfft->t1, y, pfft, n, 0); -} - - - -#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 % 4096 == 0) { n1 = 4096; goto label_size; } - if(n % 2048 == 0) { n1 = 2048; goto label_size; } - if(n % 1024 == 0) { n1 = 1024; goto label_size; } - if(n % 512 == 0) { n1 = 512; goto label_size; } - if(n % 256 == 0) { n1 = 256; goto label_size; } - if(n % 128 == 0) { n1 = 128; goto label_size; } - if(n % 64 == 0) { n1 = 64; goto label_size; } - if(n % 32 == 0) { n1 = 32; goto label_size; } - 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++) - { - 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 == 4096) - for(k = 0; k < n2; k++) - dft4096(t0+4096*k, t1+4096*k, p->w4096, p->w256); - - if(n1 == 2048) - for(k = 0; k < n2; k++) - dft2048(t0+2048*k, t1+2048*k, p->w2048, p->w32, p->w64); - - if(n1 == 1024) - for(k = 0; k < n2; k++) - dft1024(t0+1024*k, t1+1024*k, p->w1024, p->w32); - - if(n1 == 512) - for(k = 0; k < n2; k++) - dft512(t0+512*k, t1+512*k, p->w512, p->w32); - - if(n1 == 256) - for(k = 0; k < n2; k++) - dft256(t0+256*k, t1+256*k, p->w256); - - if(n1 == 128) - for(k = 0; k < n2; k++) - dft128(t0+128*k, t1+128*k, p->w128); - - if(n1 == 64) - for(k = 0; k < n2; k++) - dft64(t0+64*k, t1+64*k, p->w64); - - if(n1 == 32) - for(k = 0; k < n2; k++) - dft32(t0+32*k, t1+32*k, p->w32); - - 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; -} - - - - -#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%4096 == 0) { n2 = 4096; goto label_size; } - if(s%2048 == 0) { n2 = 2048; goto label_size; } - if(s%1024 == 0) { n2 = 1024; goto label_size; } - if(s%512 == 0) { n2 = 512; goto label_size; } - if(s%256 == 0) { n2 = 256; goto label_size; } - if(s%128 == 0) { n2 = 128; goto label_size; } - if(s% 64 == 0) { n2 = 64; goto label_size; } - if(s% 32 == 0) { n2 = 32; goto label_size; } - 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; - - /* w32 fill */ - addr = 0; - for(k = 0; k < 4; k++) - { - for(m = 0; m < 8; m++) - { - phi = - M_2PI * (double)(k*m) / 32.0; - RE(pfft->w32[addr]) = cos(phi); - IM(pfft->w32[addr]) = sin(phi); - addr++; - } - } - - - /* w64 fill */ - addr = 0; - for(k = 0; k < 8; k++) - { - for(m = 0; m < 8; m++) - { - phi = - M_2PI * (double)(k*m) / 64.0; - RE(pfft->w64[addr]) = cos(phi); - IM(pfft->w64[addr]) = sin(phi); - addr++; - } - } - - /* w128 fill */ - addr = 0; - for(k = 0; k < 8; k++) - { - for(m = 0; m < 16; m++) - { - phi = - M_2PI * (double)(k*m) / 128.0; - RE(pfft->w128[addr]) = cos(phi); - IM(pfft->w128[addr]) = sin(phi); - addr++; - } - } - - /* w256 fill */ - addr = 0; - for(k = 0; k < 16; k++) - { - for(m = 0; m < 16; m++) - { - phi = - M_2PI * (double)(k*m) / 256.0; - RE(pfft->w256[addr]) = cos(phi); - IM(pfft->w256[addr]) = sin(phi); - addr++; - } - } - - /* w512 fill */ - addr = 0; - for(k = 0; k < 16; k++) - { - for(m = 0; m < 32; m++) - { - phi = - M_2PI * (double)(k*m) / 512.0; - RE(pfft->w512[addr]) = cos(phi); - IM(pfft->w512[addr]) = sin(phi); - addr++; - } - } - - /* w1024 fill */ - if(pfft->w1024 == NULL) - { - pfft->w1024 = (complex_t*) malloc(1024 * sizeof(complex_t)); - addr = 0; - for(k = 0; k < 32; k++) - { - for(m = 0; m < 32; m++) - { - phi = - M_2PI * (double)(k*m) / 1024.0; - RE(pfft->w1024[addr]) = cos(phi); - IM(pfft->w1024[addr]) = sin(phi); - addr++; - } - } - } - - /* w2048 fill */ - if(pfft->w2048 == NULL) - { - pfft->w2048= (complex_t*) malloc(2048 * sizeof(complex_t)); - addr = 0; - for(k = 0; k < 32; k++) - { - for(m = 0; m < 64; m++) - { - phi = - M_2PI * (double)(k*m) / 2048.0; - RE(pfft->w2048[addr]) = cos(phi); - IM(pfft->w2048[addr]) = sin(phi); - addr++; - } - } - } - - /* w4096 fill */ - if(pfft->w4096 == NULL) - { - pfft->w4096= (complex_t*) malloc(4096 * sizeof(complex_t)); - addr = 0; - for(k = 0; k < 16; k++) - { - for(m = 0; m < 256; m++) - { - phi = - M_2PI * (double)(k*m) / 4096.0; - RE(pfft->w4096[addr]) = cos(phi); - IM(pfft->w4096[addr]) = sin(phi); - addr++; - } - } - } - - 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; -} - - - - - -#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); - - if(pfft->w1024) - free(pfft->w1024); - - if(pfft->w2048) - free(pfft->w2048); - - if(pfft->w4096) - free(pfft->w4096); - - memset(pfft, 0, sizeof(fft_t)); -} - - - - - -#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; - fft_t *cfft = NULL; - - if(pfft) - cfft = pfft; - else - { - cfft = (fft_t*) malloc(sizeof(fft_t)); - memset(cfft, 0, sizeof(fft_t)); - } - - err = fft_abs(x, n, cfft, fs, flag, mag, freq); - if(err != RES_OK) - goto error_proc; - - if(mag) - { - if(flag & DSPL_FLAG_LOGMAG) - for(k = 0; k < n; k++) - mag[k] = 20.0 * log10(mag[k] + DBL_EPSILON); - else - for(k = 0; k < n; k++) - mag[k] *= mag[k]; - } -error_proc: - if(cfft && cfft != pfft) - free(cfft); - return err; -} - - - - - - - -#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; - fft_t *cfft = NULL; - - if(pfft) - cfft = pfft; - else - { - cfft = (fft_t*) malloc(sizeof(fft_t)); - memset(cfft, 0, sizeof(fft_t)); - } - - err = fft_abs_cmplx(x, n, cfft, fs, flag, mag, freq); - if(err != RES_OK) - goto error_proc; - - if(mag) - { - if(flag & DSPL_FLAG_LOGMAG) - for(k = 0; k < n; k++) - mag[k] = 20.0 * log10(mag[k] + DBL_EPSILON); - else - for(k = 0; k < n; k++) - mag[k] *= mag[k]; - } -error_proc: - if(cfft && cfft != pfft) - free(cfft); - return err; -} - - - - - -#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; - - if(!x || !y) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - r = n%2; - if(!r) - { - 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; -} - - - -#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; - - if(!x || !y) - return ERROR_PTR; - - if(n<1) - return ERROR_SIZE; - - r = n%2; - if(!r) - { - 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+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; -} - diff --git a/dspl/src/fourier_series.c b/dspl/src/fourier_series.c deleted file mode 100644 index d611d43..0000000 --- a/dspl/src/fourier_series.c +++ /dev/null @@ -1,442 +0,0 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - - -#include -#include -#include -#include "dspl.h" - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fourier_series_dec(double* t, double* s, int nt, double period, - int nw, double* w, complex_t* y) - -\brief -Fourier series coefficient calculation for periodic signal - -\param[in] t -Pointer to the time vector. \n -Vector size is `[nt x 1]`. \n -\n - -\param[in] s -Pointer to the signal corresponds to time `t`. \n -Vector size is `[nt x 1]`. \n -\n - -\param[in] nt -Size of time and signal vectors. \n -This value must be positive. \n -\n - -\param[in] period -Signal time period. \n -\n - -\param[in] nw -Number of Fourie series coefficients. \n -\n - -\param[out] w -Pointer to the frequency vector (rad/s). \n -Vector size is `[nw x 1]`. \n -Memory must be allocated. \n -\n - -\param[out] y -Pointer to the complex Fourier series coefficients vector. \n -Vector size is `[nw 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". - -\note -Numerical integration is used for Fourier series coefficients calculation. -This function is not effective. -To increase the speed of calculation of the signal spectrum -it is more expedient to use fast Fourier transform algorithms. -\n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fourier_series_dec(double* t, double* s, int nt, double period, - int nw, double* w, complex_t* y) - -\brief -Расчет коэффициентов разложения в ряд Фурье - -Функция рассчитывает спектр периодического сигнала при усечении ряда Фурье \n - - -\param[in] t -Указатель на массив моментов времени дискретизации исходного сигнала `s`. \n -Размер вектора вектора `[nt x 1]`. \n -Память должна быть выделена. \n -\n - -\param[in] s -Указатель на массив значений исходного сигнала`s`. \n -Размер вектора `[nt x 1]`. \n -Память должна быть выделена. \n -\n - - -\param[in] nt -Размер выборки исходного сигнала. \n -Значение должно быть положительным. \n -\n - -\param[in] period -Период повторения сигнала. \n -\n - -\param[in] nw -Размер усеченного ряда Фурье. \n -\n - -\param[out] w -Указатель на массив частот спектра периодического сигнала. \n -Размер вектора `[nw x 1]`. \n -Память должна быть выделена. \n -\n - -\param[out] y -Указатель массив комплексных значений спектра периодического сигнала. \n -Размер вектора `[nw x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- коэффициенты ряда Фурье рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Для расчета спектра сигнала используется численное интегрирование -исходного сигнала методом трапеций. Данная функция не является -эффективной. Для увеличения скорости расчета спектра сигнала -целесообразнее использовать алгоритмы дискретного -и быстрого преобразования Фурье. -\n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API fourier_series_dec(double* t, double* s, int nt, double period, - int nw, double* w, complex_t* y) -{ - int k, m; - double dw = M_2PI / period; - complex_t e[2]; - - if(!t || !s || !w || !y) - return ERROR_PTR; - if(nt<1 || nw < 1) - return ERROR_SIZE; - if(period <= 0.0) - return ERROR_NEGATIVE; - - memset(y, 0 , nw*sizeof(complex_t)); - - for(k = 0; k < nw; k++) - { - w[k] = (k - nw/2) * dw; - RE(e[1]) = s[0] * cos(w[k] * t[0]); - IM(e[1]) = -s[0] * sin(w[k] * t[0]); - for(m = 1; m < nt; m++) - { - RE(e[0]) = RE(e[1]); - IM(e[0]) = IM(e[1]); - RE(e[1]) = s[m] * cos(w[k] * t[m]); - IM(e[1]) = - s[m] * sin(w[k] * t[m]); - RE(y[k]) += 0.5 * (RE(e[0]) + RE(e[1]))*(t[m] - t[m-1]); - IM(y[k]) += 0.5 * (IM(e[0]) + IM(e[1]))*(t[m] - t[m-1]); - } - RE(y[k]) /= period; - IM(y[k]) /= period; - } - - if(!(nw%2)) - RE(y[0]) = RE(y[1]) = 0.0; - - return RES_OK; -} - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API fourier_series_dec_cmplx(double* t, complex_t* s, int nt, - double period, int nw, double* w, complex_t* y) -{ - int k, m; - double dw = M_2PI / period; - complex_t e[2]; - - if(!t || !s || !w || !y) - return ERROR_PTR; - if(nt<1 || nw < 1) - return ERROR_SIZE; - if(period <= 0.0) - return ERROR_NEGATIVE; - - memset(y, 0 , nw*sizeof(complex_t)); - - for(k = 0; k < nw; k++) - { - w[k] = (k - nw/2) * dw; - RE(e[1]) = RE(s[0]) * cos(w[k] * t[0]) + - IM(s[0]) * sin(w[k] * t[0]); - IM(e[1]) = -RE(s[0]) * sin(w[k] * t[0]) + - IM(s[0]) * cos(w[k] * t[0]); - for(m = 1; m < nt; m++) - { - RE(e[0]) = RE(e[1]); - IM(e[0]) = IM(e[1]); - RE(e[1]) = RE(s[m]) * cos(w[k] * t[m]) + - IM(s[m]) * sin(w[k] * t[m]); - IM(e[1]) = -RE(s[m]) * sin(w[k] * t[m]) + - IM(s[m]) * cos(w[k] * t[m]); - RE(y[k]) += 0.5 * (RE(e[0]) + RE(e[1]))*(t[m] - t[m-1]); - IM(y[k]) += 0.5 * (IM(e[0]) + IM(e[1]))*(t[m] - t[m-1]); - } - RE(y[k]) /= period; - IM(y[k]) /= period; - } - - if(!(nw%2)) - RE(y[0]) = RE(y[1]) = 0.0; - - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API fourier_integral_cmplx(double* t, complex_t* s, int nt, - int nw, double* w, complex_t* y) -{ - int k, m; - complex_t e[2]; - - if(!t || !s || !w || !y) - return ERROR_PTR; - if(nt<1 || nw < 1) - return ERROR_SIZE; - - - memset(y, 0 , nw*sizeof(complex_t)); - - for(k = 0; k < nw; k++) - { - RE(e[1]) = RE(s[0]) * cos(w[k] * t[0]) + - IM(s[0]) * sin(w[k] * t[0]); - IM(e[1]) = -RE(s[0]) * sin(w[k] * t[0]) + - IM(s[0]) * cos(w[k] * t[0]); - for(m = 1; m < nt; m++) - { - RE(e[0]) = RE(e[1]); - IM(e[0]) = IM(e[1]); - RE(e[1]) = RE(s[m]) * cos(w[k] * t[m]) + - IM(s[m]) * sin(w[k] * t[m]); - IM(e[1]) = -RE(s[m]) * sin(w[k] * t[m]) + - IM(s[m]) * cos(w[k] * t[m]); - RE(y[k]) += 0.5 * (RE(e[0]) + RE(e[1]))*(t[m] - t[m-1]); - IM(y[k]) += 0.5 * (IM(e[0]) + IM(e[1]))*(t[m] - t[m-1]); - } - } - - return RES_OK; -} - - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fourier_series_rec(double* w, complex_t* s, int nw, - double* t, int nt, complex_t* y) -\brief Time signal reconstruction from Fourier series coefficients. - -Function reconstructs the time signal: - -\f[ -s(t) = \sum\limits_{n = 0}^{n_{\omega}-1} S(\omega_n) \exp(j\omega_n t) -\f] - -\param[in] w -Pointer to the Fourier series spectrum frequency vector \f$\omega_n\f$. \n -Vector size is `[nw x 1]`. \n -\n - -\param[in] s -Pointer to the Fourier series coefficients vector \f$S(\omega_n)\f$. \n -Vector size is `[nw x 1]`. \n -\n - - -\param[in] nw -Number of Fourier series coefficients. \n -This value must be positive. \n -\n - -\param[in] t -Pointer to the reconstructed signal time vector. \n -Vector size is `[nt x 1]`. \n -\n - -\param[in] nt -Size of time vector and reconstructed signal vector . \n -\n - -\param[out] y -Pointer to the reconstructed signal vector. \n -Vector size is `[nt 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". - -\note -The output reconstructed signal is generally complex. -However, subject to the symmetry properties of the vectors `w` and` s` -with respect to zero frequency we get the imaginary part of the vector `y` -at the EPS level. The negligible imaginary part in this case -can be ignored. -\n - -\author Sergey Bakhurin www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup DFT_GROUP -\fn int fourier_series_rec(double* w, complex_t* s, int nw, - double* t, int nt, complex_t* y) -\brief Восстановление сигнала при усечении ряда Фурье - -Функция рассчитывает восстановленный сигнал при усечении ряда Фурье: - -\f[ -s(t) = \sum\limits_{n = 0}^{n_{\omega}-1} S(\omega_n) \exp(j\omega_n t) -\f] - -\param[in] w -Указатель на массив частот \f$\omega_n\f$ усеченного ряда Фурье. \n -Размер вектора `[nw x 1]`. \n -Память должна быть выделена и заполнена. \n -\n - -\param[in] s -Указатель на массив значений спектра \f$S(\omega_n)\f$. \n -Размер вектора `[nw x 1]`. \n -Память должна быть выделена и заполнена. \n -\n - - -\param[in] nw -Количество членов усеченного ряда Фурье. \n -Значение должно быть положительным. \n -\n - -\param[in] t -Указатель на массив временных отсчетов восстановленного сигнала. \n -Размер вектора `[nt x 1]`. \n -Память должна быть выделена и заполнена. \n -\n - -\param[in] nt -Размер вектора времени и восстановленного сигнала. \n -\n - -\param[out] y -Указатель на массив восстановленного сигнала. \n -Размер вектора `[nt x 1]`. \n -Память должна быть выделена. \n -\n - -\return -`RES_OK` --- восстановление сигнала прошло успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". \n - -\note -Выходной восстановленный сигнал в общем случае является комплексным. -Однако при соблюдении свойств симметрии векторов `w` и `s` относительно -нулевой частоты получим мнимую часть элементов вектора `y` на уровне ошибок -округления числа с двойной точностью. Ничтожно малую мнимую часть в этом случае -можно игнорировать. -\n - -\author Бахурин Сергей www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API fourier_series_rec(double* w, complex_t* s, int nw, - double* t, int nt, complex_t* y) -{ - int k, m; - complex_t e; - - if(!t || !s || !w || !y) - return ERROR_PTR; - if(nt<1 || nw < 1) - return ERROR_SIZE; - - memset(y, 0, nt*sizeof(complex_t)); - - - for(k = 0; k < nw; k++) - { - for(m = 0; m < nt; m++) - { - RE(e) = cos(w[k] * t[m]); - IM(e) = sin(w[k] * t[m]); - - RE(y[m]) += CMRE(s[k], e); - IM(y[m]) += CMIM(s[k], e); - } - } - return RES_OK; -} - diff --git a/dspl/src/math_poly.c b/dspl/src/math_poly.c new file mode 100644 index 0000000..eac513d --- /dev/null +++ b/dspl/src/math_poly.c @@ -0,0 +1,10 @@ + + +#include "math_poly/poly_z2a_cmplx.c" +#include "math_poly/polyroots.c" +#include "math_poly/polyval.c" +#include "math_poly/polyval_cmplx.c" + + +#include "math_poly/cheby_poly1.c" +#include "math_poly/cheby_poly2.c" diff --git a/dspl/src/math_poly/cheby_poly1.c b/dspl/src/math_poly/cheby_poly1.c new file mode 100644 index 0000000..23141ca --- /dev/null +++ b/dspl/src/math_poly/cheby_poly1.c @@ -0,0 +1,177 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + +#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]; + + 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; + } + + 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; +} + diff --git a/dspl/src/cheby.c b/dspl/src/math_poly/cheby_poly2.c similarity index 54% rename from dspl/src/cheby.c rename to dspl/src/math_poly/cheby_poly2.c index 6a5c179..290d522 100644 --- a/dspl/src/cheby.c +++ b/dspl/src/math_poly/cheby_poly2.c @@ -1,329 +1,177 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - -#include -#include -#include -#include "dspl.h" - - -#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]; - - 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; - } - - 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; -} - - - - -#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]; - - 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; - } - - 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; -} - +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + +#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]; + + 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; + } + + 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/math_poly/poly_z2a_cmplx.c b/dspl/src/math_poly/poly_z2a_cmplx.c new file mode 100644 index 0000000..7c671ce --- /dev/null +++ b/dspl/src/math_poly/poly_z2a_cmplx.c @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN + +#endif +int DSPL_API poly_z2a_cmplx(complex_t* z, int nz, int ord, complex_t* a) +{ + int k, ind, res; + complex_t x[2]; + + if(!z || !a) + return ERROR_PTR; + if(nz < 0) + return ERROR_SIZE; + if(nz > ord || ord < 1) + return ERROR_POLY_ORD; + + RE(x[1]) = 1.0; + IM(x[1]) = 0.0; + + memset(a, 0, (ord+1) * sizeof(complex_t)); + + RE(a[0]) = 1.0; + ind = 1; + for(k = 0; k < nz; k++) + { + RE(x[0]) = -RE(z[k]); + IM(x[0]) = -IM(z[k]); + res = conv_cmplx(a, ind, x, 2, a); + if(res!=RES_OK) + return res; + ind++; + } + + return RES_OK; +} + + diff --git a/dspl/src/polyval.c b/dspl/src/math_poly/polyroots.c similarity index 52% rename from dspl/src/polyval.c rename to dspl/src/math_poly/polyroots.c index 7df35f0..ddb69e7 100644 --- a/dspl/src/polyval.c +++ b/dspl/src/math_poly/polyroots.c @@ -1,384 +1,186 @@ -/* -* Copyright (c) 2015-2019 Sergey Bakhurin -* Digital Signal Processing Library [http://dsplib.org] -* -* 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 -* 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 Lesser General Public License -* along with Foobar. If not, see . -*/ - - -#include -#include -#include "dspl.h" - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN - -#endif -int DSPL_API poly_z2a_cmplx(complex_t* z, int nz, int ord, complex_t* a) -{ - int k, ind, res; - complex_t x[2]; - - if(!z || !a) - return ERROR_PTR; - if(nz < 0) - return ERROR_SIZE; - if(nz > ord || ord < 1) - return ERROR_POLY_ORD; - - RE(x[1]) = 1.0; - IM(x[1]) = 0.0; - - memset(a, 0, (ord+1) * sizeof(complex_t)); - - RE(a[0]) = 1.0; - ind = 1; - for(k = 0; k < nz; k++) - { - RE(x[0]) = -RE(z[k]); - IM(x[0]) = -IM(z[k]); - res = conv_cmplx(a, ind, x, 2, a); - if(res!=RES_OK) - return res; - ind++; - } - - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int polyroots(double* a, int ord, complex_t* r, int* info) -\brief Function calculates real polynomial roots. - -Function calculates roots of the real polynomial \f$P_N(x)\f$ order \f$N\f$ -with `a` coefficient vector size `[(N+1) x 1]`. -\f[ - P_N(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + ... a_N x^N. -\f] - -The roots of the polynomial are calculated as eigenvalues of the polynomial -companion matrix. To calculate the eigenvalues, -a subroutine of the LAPACK package is used. - - -\param[in] a -Pointer to the vector of coefficients. \n -Vector size is `[ord+1 x 1]`. \n -Coefficient `a[0]` corresponds to the \f$a_0\f$ polynomial coefficient. \n -Coefficient `a[ord]` cannot be zero. \n \n - -\param[in] ord -Polynomial order \f$N\f$. \n \n - -\param[out] r -Pointer to the polynomial roots vector. \n -Vector size is `[ord x 1]`. \n -Memory must be allocated. \n -The roots of a real polynomial can be either real or form simple -or multiple complex conjugate pairs of roots. Therefore, the output -root vector is of a complex data type. \n \n - -\param[out] info -Pointer to the LAPACK subroutine error code. \n -This code is returned by the LAPACK subroutine and translated through -this variable for analysis.. \n\n - -\return -`RES_OK` --- roots are calculated successfully. \n -Else \ref ERROR_CODE_GROUP "code error". - -Example: - -\include polyroots_test.c - -This program calculates the roots of the polynomial -\f[ -P(x) = 2 + 2x + x^2 -\f] -and prints the calculated roots. -The result of the program: - -\verbatim -Error code: 0x00000000 -r[0] = -1.00000 1.00000 j -r[1] = -1.00000-1.00000 j -\endverbatim - -\author Sergey Bakhurin. www.dsplib.org -***************************************************************************** */ -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int polyroots(double* a, int ord, complex_t* r, int* info) -\brief Расчет корней вещественного полинома - -Функция рассчитывает корни полинома \f$P_N(x)\f$ \f$N-\f$ого -порядка, заданного вектором коэффициентов `a`. -\f[ - P_N(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + ... a_N x^N. -\f] - -Корни полинома рассчитываются как собственные числа характеристической -матрицы полинома. Для расчета собственных чисел используется подпрограмма -пакета LAPACK. - - -\param[in] a -Указатель на вектор вещественных коэффициентов полинома. \n -Размер вектора `[ord+1 x 1]`. \n -Коэффициент `a[0]` соответствует коэффициенту полинома \f$a_0\f$. \n -Коэффициент `a[ord]` не должен быть равен нулю. \n \n - -\param[in] ord -Порядок полинома \f$N\f$. \n \n - -\param[out] r -Указатель на вектор комплексных корней полинома. \n -Размер вектора `[ord x 1]`. \n -Память должна быть выделена. \n -Корни вещественного полинома могут быть как вещественными, -так и образовывать простые или кратные комплексно-сопряженные пары корней. -Поэтому выходной вектор корней имеет комплексный тип данных. -\n \n - -\param[out] info -Указатель наа код возврата пакета LAPACK. \n -Данный код возвращается подпрограммой LAPACK и транслируется через данную -переменную для возможности анализа. \n\n - -\return -`RES_OK` --- корни полинома рассчитаны успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -Пример расчета корней полинома: - -\include polyroots_test.c - -Данная программа производит расчет корней полинома -\f[ -P(x) = 2 + 2x + x^2 -\f] -и выводит рассчитанные корни на печать. -Результат работы программы: - -\verbatim -Error code: 0x00000000 -r[0] = -1.00000 1.00000 j -r[1] = -1.00000-1.00000 j -\endverbatim - -Получили пару комплексно-сопряженных корней полинома. - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API polyroots(double* a, int ord, complex_t* r, int* info) -{ - complex_t *t = NULL; - int m; - int err; - - if(!a || !r) - return ERROR_PTR; - if(ord<0) - return ERROR_POLY_ORD; - if(a[ord] == 0.0) - return ERROR_POLY_AN; - - t = (complex_t*)malloc(ord * ord * sizeof(complex_t)); - if(!t) - return ERROR_MALLOC; - - for(m = 0; m < ord-1; m++) - { - RE(t[m * (ord+1) + 1]) = 1.0; - RE(t[m + ord * (ord - 1)]) = -a[m] / a[ord]; - } - RE(t[ord * ord - 1]) = -a[ord-1] / a[ord]; - - err = matrix_eig_cmplx(t, ord, r, info); - - if(t) - free(t); - return err; -} - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int polyval(double* a, int ord, double* x, int n, double* y) -\brief Расчет вещественного полинома - -Функция рассчитывает полином \f$P_N(x)\f$ \f$N-\f$ого порядка для вещественного -аргумента, заданного вектором `x`. -\f[ - P_N(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 + - a_3 \cdot x^3 + ... a_N \cdot x^N. -\f] - -Для расчета используется формула Горнера: -\f[ - P_N(x) = a_0 + x \cdot (a_1 + x \cdot (a_2 + \cdot - ( \ldots x \cdot (a_{N-1} + x\cdot a_N) \ldots ))) -\f] - -\param[in] a -Указатель на вектор вещественных коэффициентов полинома. \n -Размер вектора `[ord+1 x 1]`. \n -Коэффициент `a[0]` соответствует коэффициенту полинома \f$a_0\f$. \n \n - -\param[in] ord -Порядок полинома \f$N\f$. \n \n - -\param[in] x -Указатель на вектор аргумента полинома. \n -Размер вектора `[n x 1]`. \n -Значения полинома будут расчитаны для всех значений аргумента вектора `x`. \n\n - -\param[in] n -Размер вектора агрумента полинома. \n \n - -\param[out] y -Указатель на значения полинома для аргумента `x`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n\n - -\return -`RES_OK` --- полином рассчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API polyval(double* a, int ord, double* x, int n, double* y) -{ - int k, m; - - if(!a || !x || !y) - return ERROR_PTR; - if(ord<0) - return ERROR_POLY_ORD; - if(n<1) - return ERROR_SIZE; - - for(k = 0; k < n; k++) - { - y[k] = a[ord]; - for(m = ord-1; m>-1; m--) - y[k] = y[k]*x[k] + a[m]; - } - return RES_OK; -} - - - - - -#ifdef DOXYGEN_ENGLISH - -#endif -#ifdef DOXYGEN_RUSSIAN -/*! **************************************************************************** -\ingroup SPEC_MATH_COMMON_GROUP -\fn int polyval_cmplx(complex_t* a, int ord, complex_t* x, int n, complex_t* y) -\brief Расчет комплексного полинома - -Функция рассчитывает полином \f$P_N(x)\f$ \f$N\f$-го порядка -комплексного аргумента, заданного вектором `x`. \n - -\f[ -P_N(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 + a_3 \cdot x^3 + ... a_N \cdot x^N. -\f] - -Для расчета используется формула Горнера: \n -\f[ - P_N(x) = a_0 + x \cdot (a_1 + x \cdot (a_2 + \cdot - ( \ldots x \cdot (a_{N-1} + x\cdot a_N) \ldots ))) -\f] - -\param[in] a -Указатель на вектор комплексных коэффициентов полинома. \n -Размер вектора `[ord+1 x 1]`. \n -Коэффициент `a[0]` соответствует коэффициенту полинома \f$a_0\f$. \n \n - -\param[in] ord -Порядок полинома \f$N\f$. \n \n - -\param[in] x -Указатель на вектор аргумента полинома. \n -Размер вектора `[n x 1]`. \n -Значения полинома будут расчитаны для всех значений аргумента вектора `x`. \n \n - -\param[in] n -Размер вектора агрумента полинома. \n\n - -\param[out] y -Указатель вектор значения полинома для аргумента `x`. \n -Размер вектора `[n x 1]`. \n -Память должна быть выделена. \n \n - -\return -`RES_OK` --- полином расчитан успешно. \n -В противном случае \ref ERROR_CODE_GROUP "код ошибки". - -\author Бахурин Сергей. www.dsplib.org -***************************************************************************** */ -#endif -int DSPL_API polyval_cmplx(complex_t* a, int ord, - complex_t* x, int n, complex_t* y) -{ - int k, m; - complex_t t; - - if(!a || !x || !y) - return ERROR_PTR; - if(ord<0) - return ERROR_POLY_ORD; - if(n<1) - return ERROR_SIZE; - - for(k = 0; k < n; k++) - { - RE(y[k]) = RE(a[ord]); - IM(y[k]) = IM(a[ord]); - for(m = ord-1; m>-1; m--) - { - RE(t) = CMRE(y[k], x[k]); - IM(t) = CMIM(y[k], x[k]); - RE(y[k]) = RE(t) + RE(a[m]); - IM(y[k]) = IM(t) + IM(a[m]); - } - } - return RES_OK; -} - +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + +#ifdef DOXYGEN_ENGLISH +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int polyroots(double* a, int ord, complex_t* r, int* info) +\brief Function calculates real polynomial roots. + +Function calculates roots of the real polynomial \f$P_N(x)\f$ order \f$N\f$ +with `a` coefficient vector size `[(N+1) x 1]`. +\f[ + P_N(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + ... a_N x^N. +\f] + +The roots of the polynomial are calculated as eigenvalues of the polynomial +companion matrix. To calculate the eigenvalues, +a subroutine of the LAPACK package is used. + + +\param[in] a +Pointer to the vector of coefficients. \n +Vector size is `[ord+1 x 1]`. \n +Coefficient `a[0]` corresponds to the \f$a_0\f$ polynomial coefficient. \n +Coefficient `a[ord]` cannot be zero. \n \n + +\param[in] ord +Polynomial order \f$N\f$. \n \n + +\param[out] r +Pointer to the polynomial roots vector. \n +Vector size is `[ord x 1]`. \n +Memory must be allocated. \n +The roots of a real polynomial can be either real or form simple +or multiple complex conjugate pairs of roots. Therefore, the output +root vector is of a complex data type. \n \n + +\param[out] info +Pointer to the LAPACK subroutine error code. \n +This code is returned by the LAPACK subroutine and translated through +this variable for analysis.. \n\n + +\return +`RES_OK` --- roots are calculated successfully. \n +Else \ref ERROR_CODE_GROUP "code error". + +Example: + +\include polyroots_test.c + +This program calculates the roots of the polynomial +\f[ +P(x) = 2 + 2x + x^2 +\f] +and prints the calculated roots. +The result of the program: + +\verbatim +Error code: 0x00000000 +r[0] = -1.00000 1.00000 j +r[1] = -1.00000-1.00000 j +\endverbatim + +\author Sergey Bakhurin. www.dsplib.org +***************************************************************************** */ +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int polyroots(double* a, int ord, complex_t* r, int* info) +\brief Расчет корней вещественного полинома + +Функция рассчитывает корни полинома \f$P_N(x)\f$ \f$N-\f$ого +порядка, заданного вектором коэффициентов `a`. +\f[ + P_N(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + ... a_N x^N. +\f] + +Корни полинома рассчитываются как собственные числа характеристической +матрицы полинома. Для расчета собственных чисел используется подпрограмма +пакета LAPACK. + + +\param[in] a +Указатель на вектор вещественных коэффициентов полинома. \n +Размер вектора `[ord+1 x 1]`. \n +Коэффициент `a[0]` соответствует коэффициенту полинома \f$a_0\f$. \n +Коэффициент `a[ord]` не должен быть равен нулю. \n \n + +\param[in] ord +Порядок полинома \f$N\f$. \n \n + +\param[out] r +Указатель на вектор комплексных корней полинома. \n +Размер вектора `[ord x 1]`. \n +Память должна быть выделена. \n +Корни вещественного полинома могут быть как вещественными, +так и образовывать простые или кратные комплексно-сопряженные пары корней. +Поэтому выходной вектор корней имеет комплексный тип данных. +\n \n + +\param[out] info +Указатель наа код возврата пакета LAPACK. \n +Данный код возвращается подпрограммой LAPACK и транслируется через данную +переменную для возможности анализа. \n\n + +\return +`RES_OK` --- корни полинома рассчитаны успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +Пример расчета корней полинома: + +\include polyroots_test.c + +Данная программа производит расчет корней полинома +\f[ +P(x) = 2 + 2x + x^2 +\f] +и выводит рассчитанные корни на печать. +Результат работы программы: + +\verbatim +Error code: 0x00000000 +r[0] = -1.00000 1.00000 j +r[1] = -1.00000-1.00000 j +\endverbatim + +Получили пару комплексно-сопряженных корней полинома. + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API polyroots(double* a, int ord, complex_t* r, int* info) +{ + complex_t *t = NULL; + int m; + int err; + + if(!a || !r) + return ERROR_PTR; + if(ord<0) + return ERROR_POLY_ORD; + if(a[ord] == 0.0) + return ERROR_POLY_AN; + + t = (complex_t*)malloc(ord * ord * sizeof(complex_t)); + if(!t) + return ERROR_MALLOC; + + for(m = 0; m < ord-1; m++) + { + RE(t[m * (ord+1) + 1]) = 1.0; + RE(t[m + ord * (ord - 1)]) = -a[m] / a[ord]; + } + RE(t[ord * ord - 1]) = -a[ord-1] / a[ord]; + + err = matrix_eig_cmplx(t, ord, r, info); + + if(t) + free(t); + return err; +} diff --git a/dspl/src/math_poly/polyval.c b/dspl/src/math_poly/polyval.c new file mode 100644 index 0000000..b5dd7bf --- /dev/null +++ b/dspl/src/math_poly/polyval.c @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int polyval(double* a, int ord, double* x, int n, double* y) +\brief Расчет вещественного полинома + +Функция рассчитывает полином \f$P_N(x)\f$ \f$N-\f$ого порядка для вещественного +аргумента, заданного вектором `x`. +\f[ + P_N(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 + + a_3 \cdot x^3 + ... a_N \cdot x^N. +\f] + +Для расчета используется формула Горнера: +\f[ + P_N(x) = a_0 + x \cdot (a_1 + x \cdot (a_2 + \cdot + ( \ldots x \cdot (a_{N-1} + x\cdot a_N) \ldots ))) +\f] + +\param[in] a +Указатель на вектор вещественных коэффициентов полинома. \n +Размер вектора `[ord+1 x 1]`. \n +Коэффициент `a[0]` соответствует коэффициенту полинома \f$a_0\f$. \n \n + +\param[in] ord +Порядок полинома \f$N\f$. \n \n + +\param[in] x +Указатель на вектор аргумента полинома. \n +Размер вектора `[n x 1]`. \n +Значения полинома будут расчитаны для всех значений аргумента вектора `x`. \n\n + +\param[in] n +Размер вектора агрумента полинома. \n \n + +\param[out] y +Указатель на значения полинома для аргумента `x`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n\n + +\return +`RES_OK` --- полином рассчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API polyval(double* a, int ord, double* x, int n, double* y) +{ + int k, m; + + if(!a || !x || !y) + return ERROR_PTR; + if(ord<0) + return ERROR_POLY_ORD; + if(n<1) + return ERROR_SIZE; + + for(k = 0; k < n; k++) + { + y[k] = a[ord]; + for(m = ord-1; m>-1; m--) + y[k] = y[k]*x[k] + a[m]; + } + return RES_OK; +} + diff --git a/dspl/src/math_poly/polyval_cmplx.c b/dspl/src/math_poly/polyval_cmplx.c new file mode 100644 index 0000000..464cf3a --- /dev/null +++ b/dspl/src/math_poly/polyval_cmplx.c @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2015-2019 Sergey Bakhurin +* Digital Signal Processing Library [http://dsplib.org] +* +* 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 +* 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 Lesser General Public License +* along with Foobar. If not, see . +*/ + +#include +#include +#include +#include "dspl.h" + + + + + +#ifdef DOXYGEN_ENGLISH + +#endif +#ifdef DOXYGEN_RUSSIAN +/*! **************************************************************************** +\ingroup SPEC_MATH_POLY_GROUP +\fn int polyval_cmplx(complex_t* a, int ord, complex_t* x, int n, complex_t* y) +\brief Расчет комплексного полинома + +Функция рассчитывает полином \f$P_N(x)\f$ \f$N\f$-го порядка +комплексного аргумента, заданного вектором `x`. \n + +\f[ +P_N(x) = a_0 + a_1 \cdot x + a_2 \cdot x^2 + a_3 \cdot x^3 + ... a_N \cdot x^N. +\f] + +Для расчета используется формула Горнера: \n +\f[ + P_N(x) = a_0 + x \cdot (a_1 + x \cdot (a_2 + \cdot + ( \ldots x \cdot (a_{N-1} + x\cdot a_N) \ldots ))) +\f] + +\param[in] a +Указатель на вектор комплексных коэффициентов полинома. \n +Размер вектора `[ord+1 x 1]`. \n +Коэффициент `a[0]` соответствует коэффициенту полинома \f$a_0\f$. \n \n + +\param[in] ord +Порядок полинома \f$N\f$. \n \n + +\param[in] x +Указатель на вектор аргумента полинома. \n +Размер вектора `[n x 1]`. \n +Значения полинома будут расчитаны для всех значений аргумента вектора `x`. \n \n + +\param[in] n +Размер вектора агрумента полинома. \n\n + +\param[out] y +Указатель вектор значения полинома для аргумента `x`. \n +Размер вектора `[n x 1]`. \n +Память должна быть выделена. \n \n + +\return +`RES_OK` --- полином расчитан успешно. \n +В противном случае \ref ERROR_CODE_GROUP "код ошибки". + +\author Бахурин Сергей. www.dsplib.org +***************************************************************************** */ +#endif +int DSPL_API polyval_cmplx(complex_t* a, int ord, + complex_t* x, int n, complex_t* y) +{ + int k, m; + complex_t t; + + if(!a || !x || !y) + return ERROR_PTR; + if(ord<0) + return ERROR_POLY_ORD; + if(n<1) + return ERROR_SIZE; + + for(k = 0; k < n; k++) + { + RE(y[k]) = RE(a[ord]); + IM(y[k]) = IM(a[ord]); + for(m = ord-1; m>-1; m--) + { + RE(t) = CMRE(y[k], x[k]); + IM(t) = CMIM(y[k], x[k]); + RE(y[k]) = RE(t) + RE(a[m]); + IM(y[k]) = IM(t) + IM(a[m]); + } + } + return RES_OK; +} + diff --git a/make.inc b/make.inc index 8acf6ee..6f4cdac 100644 --- a/make.inc +++ b/make.inc @@ -22,6 +22,8 @@ LAPACK_DOUBLE_LIB_NAME = $(LAPACK_RELEASE_DIR)/liblapack_double.a LAPACK_COMPLEX_SRC_DIR = $(LAPACK_LIB_DIR)/src LAPACK_COMPLEX_LIB_NAME = $(LAPACK_RELEASE_DIR)/liblapack_complex.a + + INC_DIR = ../include RELEASE_DIR = ../_release EXAMPLE_BIN_DIR = ../examples/bin