├── .gitignore ├── .vscode └── launch.json ├── Cargo.toml ├── LICENSE ├── README.md ├── images ├── durer.png ├── durer_dog.png ├── durer_xcorr_2d_biased.png ├── durer_xcorr_2d_coeff.png ├── durer_xcorr_2d_unbiased.png ├── lena.png ├── lena_dct_2d.png └── lena_dct_2d_transformed.png ├── plots ├── b_t_gauss_spline.png ├── c_t_xcorr.png ├── cxy_z_cohere.png ├── h_s_ap.png ├── h_s_besselap.png ├── h_s_buttap.png ├── h_s_cheb1ap.png ├── h_s_cheb2ap.png ├── h_s_ellipap.png ├── h_s_invfreqs.png ├── h_t_impz.png ├── h_z.png ├── h_z.svg ├── h_z_besselap.png ├── h_z_besself.png ├── h_z_bilinear.png ├── h_z_buttap.png ├── h_z_butter.png ├── h_z_cheb1ap.png ├── h_z_cheb2ap.png ├── h_z_cheby1.png ├── h_z_cheby2.png ├── h_z_ellip.png ├── h_z_ellipap.png ├── h_z_fir1.png ├── h_z_fir2.png ├── h_z_firgr.png ├── h_z_firls.png ├── h_z_firpm.png ├── h_z_gammatone_fir.png ├── h_z_gammatone_iir.png ├── h_z_iir_comb.png ├── h_z_iir_notch.png ├── h_z_iir_peak.png ├── h_z_impz.png ├── h_z_invfreqz.png ├── h_z_kaiserord.png ├── h_z_pei_tseng_notch.png ├── h_z_phasez.png ├── h_z_qmf.png ├── h_z_qp_kaiser.png ├── h_z_real_specgram.svg ├── h_z_sftrans.png ├── h_z_sgolay.png ├── h_z_specgram.svg ├── h_z_tfestimate.png ├── h_z_window.png ├── h_z_zftrans.png ├── k_ij_to_kw.svg ├── n_x_state_levels.png ├── p_z_pburg.png ├── p_z_psd.png ├── p_z_pyulear.png ├── phi_n_coifaux.png ├── phi_n_dbaux.png ├── psi_n_coifwavf.png ├── psi_n_dbwavf.png ├── psi_t_cmorwavf.png ├── psi_t_haarwavf.png ├── psi_t_mexihat.png ├── psi_t_morlet.png ├── psi_t_shanwavf.png ├── pxx_z_pwelch.png ├── pxy_z_cpsd.png ├── pz_s_besselap.png ├── pz_s_buttap.png ├── pz_s_cheb1ap.png ├── pz_s_cheb2ap.png ├── pz_s_ellipap.png ├── pz_z_besselap.png ├── pz_z_besself.png ├── pz_z_buttap.png ├── pz_z_butter.png ├── pz_z_cheb1ap.png ├── pz_z_cheb2ap.png ├── pz_z_cheby1.png ├── pz_z_cheby2.png ├── pz_z_ellip.png ├── pz_z_ellipap.png ├── pz_z_fir1.png ├── pz_z_fir2.png ├── pz_z_firgr.png ├── pz_z_firls.png ├── pz_z_firpm.png ├── pz_z_gammatone_fir.png ├── pz_z_gammatone_iir.png ├── pz_z_iir_comb.png ├── pz_z_iir_notch.png ├── pz_z_iir_peak.png ├── pz_z_kaiserord.png ├── pz_z_pei_tseng_notch.png ├── pz_z_qp_kaiser.png ├── s_t_bspline_eval.png ├── t_z_grpdelay.png ├── uy_t_sim_s.png ├── uy_t_sim_z.png ├── windows │ ├── g_f_barthann.png │ ├── g_f_blackman.png │ ├── g_f_blackman_harris.png │ ├── g_f_blackman_nuttall.png │ ├── g_f_bohman.png │ ├── g_f_boxcar.png │ ├── g_f_confined_gaussian.png │ ├── g_f_confined_normal.png │ ├── g_f_dolph_chebyshev.png │ ├── g_f_flattop.png │ ├── g_f_gaussian.png │ ├── g_f_hamming.png │ ├── g_f_hann.png │ ├── g_f_kaiser.png │ ├── g_f_normal.png │ ├── g_f_nuttall.png │ ├── g_f_parzen.png │ ├── g_f_planck_taper.png │ ├── g_f_power_of_sine.png │ ├── g_f_sine.png │ ├── g_f_triangular.png │ ├── g_f_tukey.png │ ├── g_f_ultraspherical.png │ ├── g_f_welch.png │ ├── g_n_barthann.png │ ├── g_n_blackman.png │ ├── g_n_blackman_harris.png │ ├── g_n_blackman_nuttall.png │ ├── g_n_bohman.png │ ├── g_n_boxcar.png │ ├── g_n_confined_gaussian.png │ ├── g_n_confined_normal.png │ ├── g_n_dolph_chebyshev.png │ ├── g_n_flattop.png │ ├── g_n_gaussian.png │ ├── g_n_hamming.png │ ├── g_n_hann.png │ ├── g_n_kaiser.png │ ├── g_n_normal.png │ ├── g_n_nuttall.png │ ├── g_n_parzen.png │ ├── g_n_planck_taper.png │ ├── g_n_power_of_sine.png │ ├── g_n_sine.png │ ├── g_n_triangular.png │ ├── g_n_tukey.png │ ├── g_n_ultraspherical.png │ └── g_n_welch.png ├── x_hat_cceps.png ├── x_hat_rceps.png ├── x_n_cspline_1d.png ├── x_n_findpeaks.png ├── x_n_qspline_1d.png ├── x_n_state_levels.png ├── x_t_chirp.png ├── x_t_idct.png ├── x_t_idft.png ├── x_t_idht.png ├── x_t_movingrms.png ├── x_t_resample.png ├── x_t_sampled_to_continuous.png ├── x_z_dct.png ├── x_z_dft.png ├── x_z_dht.png ├── x_z_dst.png ├── x_z_sdft.svg ├── x_z_sdft_kw.svg ├── xy_t_fftfilt.png ├── xy_t_filter.png ├── xy_t_filtfilt.png ├── xy_t_hilbert.png ├── xy_t_sgolayfilt.png ├── y_t_diric.png ├── y_t_filtic_u.png ├── y_t_gauspuls.png ├── y_t_gmonopuls.png ├── y_t_impulse_s.png ├── y_t_impulse_z.png ├── y_t_meyeraux.png ├── y_t_pulse_train.png ├── y_t_sigmoid_train.png ├── y_t_step_s.png └── y_t_step_z.png └── src ├── analysis ├── cceps.rs ├── cpsd.rs ├── filternorm.rs ├── filtic.rs ├── filtic_u.rs ├── filtord.rs ├── find_freqs.rs ├── find_peaks.rs ├── freqs.rs ├── freqz.rs ├── fwhm.rs ├── grpdelay.rs ├── impulse_s.rs ├── impulse_z.rs ├── impz.rs ├── isallpass.rs ├── islinphase.rs ├── ismaxphase.rs ├── isminphase.rs ├── isstable.rs ├── mod.rs ├── movingrms.rs ├── mscohere.rs ├── pburg.rs ├── peak_to_peak.rs ├── peak_to_rms.rs ├── phasez.rs ├── psd.rs ├── pwelch.rs ├── pyulear.rs ├── rceps.rs ├── real_cpsd.rs ├── real_freqz.rs ├── real_mscohere.rs ├── real_phasez.rs ├── real_pwelch.rs ├── real_specgram.rs ├── rms.rs ├── rssq.rs ├── sim_s.rs ├── sim_z.rs ├── specgram.rs ├── statelevels.rs ├── step_s.rs ├── step_z.rs ├── tfestimate.rs ├── xcorr.rs ├── xcorr_2d.rs ├── xcov.rs └── zero_crossing.rs ├── decompositions ├── maxphase.rs ├── minphase.rs ├── mod.rs ├── residue.rs ├── residued.rs ├── residuez.rs └── split_numer_denom.rs ├── gen ├── bspline │ ├── gauss_spline.rs │ └── mod.rs ├── cheb.rs ├── filter │ ├── besselap.rs │ ├── besself.rs │ ├── buttap.rs │ ├── butter.rs │ ├── buttord.rs │ ├── cheb1ap.rs │ ├── cheb1ord.rs │ ├── cheb2ap.rs │ ├── cheb2ord.rs │ ├── cheby1.rs │ ├── cheby2.rs │ ├── ellip.rs │ ├── ellipap.rs │ ├── ellipord.rs │ ├── fir1.rs │ ├── fir2.rs │ ├── firgr.rs │ ├── firgr │ │ └── remez.rs │ ├── firls.rs │ ├── firpm.rs │ ├── firpm │ │ └── mmfir.rs │ ├── firpmord.rs │ ├── gammatone_fir.rs │ ├── gammatone_iir.rs │ ├── iir_comb.rs │ ├── iir_design.rs │ ├── iir_notch.rs │ ├── iir_peak.rs │ ├── kaiserord.rs │ ├── mod.rs │ ├── pei_tseng_notch.rs │ ├── qp_kaiser.rs │ └── sgolay.rs ├── matrix │ ├── convmtx.rs │ ├── dctmtx.rs │ ├── dftmtx.rs │ ├── dstmtx.rs │ └── mod.rs ├── mod.rs ├── pulse │ ├── gauspuls.rs │ ├── gmonopuls.rs │ ├── mod.rs │ ├── pulstran.rs │ ├── rectpuls.rs │ ├── sigmoid_train.rs │ └── tripuls.rs ├── waveform │ ├── chirp.rs │ ├── diric.rs │ └── mod.rs ├── wavelet │ ├── cmorwavf.rs │ ├── coifaux.rs │ ├── coifwavf.rs │ ├── coifwavf │ │ └── lut.rs │ ├── dbaux.rs │ ├── dbaux │ │ └── lut.rs │ ├── dbwavf.rs │ ├── haarwavf.rs │ ├── mexihat.rs │ ├── meyeraux.rs │ ├── mod.rs │ ├── morlet.rs │ └── shanwavf.rs └── window │ ├── mod.rs │ └── window_gen.rs ├── identification ├── ar │ ├── arburg.rs │ ├── aryule.rs │ ├── levinson.rs │ ├── lpc.rs │ └── mod.rs ├── filter │ ├── invfreqs.rs │ ├── invfreqz.rs │ └── mod.rs └── mod.rs ├── lib.rs ├── maybe_rtf_or_system.rs ├── maybe_system.rs ├── operations ├── convolution │ ├── cconv.rs │ ├── conv.rs │ ├── conv_2d.rs │ ├── deconv.rs │ └── mod.rs ├── decode.rs ├── encode.rs ├── filtering │ ├── fftfilt.rs │ ├── filter.rs │ ├── filter_mut.rs │ ├── filtfilt.rs │ ├── mod.rs │ └── sgolayfilt.rs ├── mod.rs ├── resampling │ ├── decimate.rs │ ├── downsample.rs │ ├── interp.rs │ ├── mod.rs │ ├── resample.rs │ ├── upsample.rs │ └── upsample_fill.rs ├── simplify.rs └── window.rs ├── plot.rs ├── quantities ├── container.rs ├── container_or_single.rs ├── into_list.rs ├── list.rs ├── list_or_single.rs ├── lists.rs ├── lists_or_single.rs ├── matrix.rs ├── matrix_or_single.rs ├── maybe_container.rs ├── maybe_list.rs ├── maybe_lists.rs ├── maybe_matrix.rs ├── maybe_owned_list.rs ├── maybe_owned_lists.rs ├── maybe_owned_matrix.rs ├── mod.rs ├── owned_list.rs ├── owned_list_or_single.rs ├── owned_lists.rs ├── owned_matrix.rs ├── polynomial.rs ├── polynomial │ ├── add.rs │ ├── add_assign.rs │ ├── borrow.rs │ ├── borrow_mut.rs │ ├── debug.rs │ ├── deref.rs │ ├── deref_mut.rs │ ├── eq.rs │ ├── euclid.rs │ ├── fn.rs │ ├── from.rs │ ├── mul.rs │ ├── mul_assign.rs │ ├── neg.rs │ ├── one.rs │ ├── partial_eq.rs │ ├── pow.rs │ ├── product.rs │ ├── sub.rs │ └── sub_assign.rs ├── product_sequence.rs ├── product_sequence │ ├── borrow.rs │ ├── borrow_mut.rs │ ├── debug.rs │ ├── default.rs │ ├── deref.rs │ ├── deref_mut.rs │ ├── from.rs │ ├── mul.rs │ ├── one.rs │ ├── pow.rs │ ├── product.rs │ └── try_from.rs ├── sum_sequence.rs └── sum_sequence │ ├── add.rs │ ├── borrow.rs │ ├── borrow_mut.rs │ ├── debug.rs │ ├── default.rs │ ├── deref.rs │ ├── deref_mut.rs │ ├── from.rs │ ├── neg.rs │ ├── sub.rs │ ├── sum.rs │ ├── try_from.rs │ └── zero.rs ├── rtf_or_system.rs ├── system.rs ├── systems ├── ar.rs ├── ar │ └── debug.rs ├── mod.rs ├── rpk.rs ├── rpk │ ├── add.rs │ ├── neg.rs │ └── sub.rs ├── rtf.rs ├── sos.rs ├── sos │ ├── add.rs │ ├── default.rs │ ├── div.rs │ ├── from.rs │ ├── inv.rs │ ├── mul.rs │ ├── neg.rs │ ├── one.rs │ ├── pow.rs │ ├── product.rs │ ├── sub.rs │ ├── sum.rs │ └── zero.rs ├── ss.rs ├── tf.rs ├── tf │ ├── add.rs │ ├── default.rs │ ├── div.rs │ ├── from.rs │ ├── inv.rs │ ├── mul.rs │ ├── neg.rs │ ├── one.rs │ ├── pow.rs │ ├── product.rs │ ├── sub.rs │ ├── sum.rs │ └── zero.rs ├── zpk.rs └── zpk │ ├── add.rs │ ├── default.rs │ ├── div.rs │ ├── from.rs │ ├── inv.rs │ ├── mul.rs │ ├── neg.rs │ ├── one.rs │ ├── pow.rs │ ├── product.rs │ ├── sub.rs │ └── zero.rs ├── transforms ├── bspline │ ├── bspline_eval.rs │ ├── cspline_1d.rs │ ├── cspline_1d_eval.rs │ ├── mod.rs │ ├── qspline_1d.rs │ └── qspline_1d_eval.rs ├── domain │ ├── bilinear.rs │ ├── impinvar.rs │ └── mod.rs ├── filter │ ├── mod.rs │ ├── qmf.rs │ ├── sftrans.rs │ ├── stabilize.rs │ └── zftrans.rs ├── fourier │ ├── czt.rs │ ├── dct.rs │ ├── dct_2d.rs │ ├── dft.rs │ ├── dft_2d.rs │ ├── dht.rs │ ├── dst.rs │ ├── dst_2d.rs │ ├── dwht.rs │ ├── dwt.rs │ ├── hilbert.rs │ ├── hilbert_2d.rs │ ├── iczt.rs │ ├── idft.rs │ ├── idft_2d.rs │ ├── idht.rs │ ├── idwht.rs │ ├── mod.rs │ ├── sdft.rs │ ├── sdft_kw.rs │ ├── stft.rs │ └── swift.rs ├── mod.rs ├── sampled_to_continuous.rs ├── system │ ├── mod.rs │ ├── to_sos.rs │ ├── to_ss.rs │ ├── to_tf.rs │ └── to_zpk.rs └── window │ ├── mod.rs │ └── to_kw.rs ├── util ├── chain.rs ├── complex_op.rs ├── expm.rs ├── len_eq.rs ├── maybe_len_eq.rs ├── mod.rs ├── not_range.rs ├── overlay.rs ├── result_or_ok.rs ├── truncate_im.rs └── two_sided_range.rs ├── validate_filter_bands.rs └── windows ├── barthann.rs ├── blackman.rs ├── blackman_harris.rs ├── blackman_nuttall.rs ├── bohman.rs ├── boxcar.rs ├── confined_gaussian.rs ├── confined_normal.rs ├── dolph_chebyshev.rs ├── flattop.rs ├── gaussian.rs ├── hamming.rs ├── hann.rs ├── kaiser.rs ├── mod.rs ├── normal.rs ├── nuttall.rs ├── parzen.rs ├── planck_taper.rs ├── power_of_sine.rs ├── sine.rs ├── triangular.rs ├── tukey.rs ├── ultraspherical.rs └── welch.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | /temp -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug unit tests in library 'signal_processing'", 11 | "cargo": { 12 | "args": [ 13 | "test", 14 | "--no-run", 15 | "--lib", 16 | "--package=signal_processing" 17 | ], 18 | "filter": { 19 | "name": "signal_processing", 20 | "kind": "lib" 21 | } 22 | }, 23 | "args": [], 24 | "cwd": "${workspaceFolder}" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal_processing" 3 | version = "0.3.0" 4 | edition = "2021" 5 | license = "MIT" 6 | description = "A signal processing library." 7 | repository = "https://github.com/sigurd4/signal_processing" 8 | keywords = ["signal_processing", "dsp", "dtsp", "filters", "filter-design"] 9 | authors = ["Sigurd Sætherø Spangelo"] 10 | readme = "README.md" 11 | categories = ["computer-vision", "algorithms", "mathematics", "multimedia", "science"] 12 | exclude = ["/plots", "/images", "/temp"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | thiserror = "1.0.60" 18 | moddef = "0.2.2" 19 | array_math = {version = "0.2.44", features = ["ndarray"]} 20 | num = "0.4.3" 21 | option_trait = "0.1.16" 22 | rand = "0.8.5" 23 | ndarray = "0.15.6" 24 | ndarray-linalg = {version = "0.16.0", features = ["intel-mkl"]} 25 | statrs = "0.16.0" 26 | 27 | [dev-dependencies] 28 | plotters = "0.3.5" 29 | linspace = "0.1.1" 30 | image = "0.25.1" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 sigurd4 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A signal processing library in Rust, with the goal of being a decent alternative to Matlab's Signal Processing Toolbox and scipy.signal. 2 | 3 | At the moment this covers most of Octave's signal package's features and scipy.signal's features. Lots of stuff in Matlab's Signal Processing Toolbox that still needs reverse engineering though. I'll make a list of missing features one day. 4 | 5 | I need to start actually writing the documentation on this thing. Hold on. I have exams first... 6 | -------------------------------------------------------------------------------- /images/durer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/durer.png -------------------------------------------------------------------------------- /images/durer_dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/durer_dog.png -------------------------------------------------------------------------------- /images/durer_xcorr_2d_biased.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/durer_xcorr_2d_biased.png -------------------------------------------------------------------------------- /images/durer_xcorr_2d_coeff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/durer_xcorr_2d_coeff.png -------------------------------------------------------------------------------- /images/durer_xcorr_2d_unbiased.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/durer_xcorr_2d_unbiased.png -------------------------------------------------------------------------------- /images/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/lena.png -------------------------------------------------------------------------------- /images/lena_dct_2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/lena_dct_2d.png -------------------------------------------------------------------------------- /images/lena_dct_2d_transformed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/images/lena_dct_2d_transformed.png -------------------------------------------------------------------------------- /plots/b_t_gauss_spline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/b_t_gauss_spline.png -------------------------------------------------------------------------------- /plots/c_t_xcorr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/c_t_xcorr.png -------------------------------------------------------------------------------- /plots/cxy_z_cohere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/cxy_z_cohere.png -------------------------------------------------------------------------------- /plots/h_s_ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_ap.png -------------------------------------------------------------------------------- /plots/h_s_besselap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_besselap.png -------------------------------------------------------------------------------- /plots/h_s_buttap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_buttap.png -------------------------------------------------------------------------------- /plots/h_s_cheb1ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_cheb1ap.png -------------------------------------------------------------------------------- /plots/h_s_cheb2ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_cheb2ap.png -------------------------------------------------------------------------------- /plots/h_s_ellipap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_ellipap.png -------------------------------------------------------------------------------- /plots/h_s_invfreqs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_s_invfreqs.png -------------------------------------------------------------------------------- /plots/h_t_impz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_t_impz.png -------------------------------------------------------------------------------- /plots/h_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z.png -------------------------------------------------------------------------------- /plots/h_z_besselap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_besselap.png -------------------------------------------------------------------------------- /plots/h_z_besself.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_besself.png -------------------------------------------------------------------------------- /plots/h_z_bilinear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_bilinear.png -------------------------------------------------------------------------------- /plots/h_z_buttap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_buttap.png -------------------------------------------------------------------------------- /plots/h_z_butter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_butter.png -------------------------------------------------------------------------------- /plots/h_z_cheb1ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_cheb1ap.png -------------------------------------------------------------------------------- /plots/h_z_cheb2ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_cheb2ap.png -------------------------------------------------------------------------------- /plots/h_z_cheby1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_cheby1.png -------------------------------------------------------------------------------- /plots/h_z_cheby2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_cheby2.png -------------------------------------------------------------------------------- /plots/h_z_ellip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_ellip.png -------------------------------------------------------------------------------- /plots/h_z_ellipap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_ellipap.png -------------------------------------------------------------------------------- /plots/h_z_fir1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_fir1.png -------------------------------------------------------------------------------- /plots/h_z_fir2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_fir2.png -------------------------------------------------------------------------------- /plots/h_z_firgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_firgr.png -------------------------------------------------------------------------------- /plots/h_z_firls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_firls.png -------------------------------------------------------------------------------- /plots/h_z_firpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_firpm.png -------------------------------------------------------------------------------- /plots/h_z_gammatone_fir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_gammatone_fir.png -------------------------------------------------------------------------------- /plots/h_z_gammatone_iir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_gammatone_iir.png -------------------------------------------------------------------------------- /plots/h_z_iir_comb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_iir_comb.png -------------------------------------------------------------------------------- /plots/h_z_iir_notch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_iir_notch.png -------------------------------------------------------------------------------- /plots/h_z_iir_peak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_iir_peak.png -------------------------------------------------------------------------------- /plots/h_z_impz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_impz.png -------------------------------------------------------------------------------- /plots/h_z_invfreqz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_invfreqz.png -------------------------------------------------------------------------------- /plots/h_z_kaiserord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_kaiserord.png -------------------------------------------------------------------------------- /plots/h_z_pei_tseng_notch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_pei_tseng_notch.png -------------------------------------------------------------------------------- /plots/h_z_phasez.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_phasez.png -------------------------------------------------------------------------------- /plots/h_z_qmf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_qmf.png -------------------------------------------------------------------------------- /plots/h_z_qp_kaiser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_qp_kaiser.png -------------------------------------------------------------------------------- /plots/h_z_sftrans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_sftrans.png -------------------------------------------------------------------------------- /plots/h_z_sgolay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_sgolay.png -------------------------------------------------------------------------------- /plots/h_z_tfestimate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_tfestimate.png -------------------------------------------------------------------------------- /plots/h_z_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_window.png -------------------------------------------------------------------------------- /plots/h_z_zftrans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/h_z_zftrans.png -------------------------------------------------------------------------------- /plots/n_x_state_levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/n_x_state_levels.png -------------------------------------------------------------------------------- /plots/p_z_pburg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/p_z_pburg.png -------------------------------------------------------------------------------- /plots/p_z_psd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/p_z_psd.png -------------------------------------------------------------------------------- /plots/p_z_pyulear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/p_z_pyulear.png -------------------------------------------------------------------------------- /plots/phi_n_coifaux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/phi_n_coifaux.png -------------------------------------------------------------------------------- /plots/phi_n_dbaux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/phi_n_dbaux.png -------------------------------------------------------------------------------- /plots/psi_n_coifwavf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_n_coifwavf.png -------------------------------------------------------------------------------- /plots/psi_n_dbwavf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_n_dbwavf.png -------------------------------------------------------------------------------- /plots/psi_t_cmorwavf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_t_cmorwavf.png -------------------------------------------------------------------------------- /plots/psi_t_haarwavf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_t_haarwavf.png -------------------------------------------------------------------------------- /plots/psi_t_mexihat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_t_mexihat.png -------------------------------------------------------------------------------- /plots/psi_t_morlet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_t_morlet.png -------------------------------------------------------------------------------- /plots/psi_t_shanwavf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/psi_t_shanwavf.png -------------------------------------------------------------------------------- /plots/pxx_z_pwelch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pxx_z_pwelch.png -------------------------------------------------------------------------------- /plots/pxy_z_cpsd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pxy_z_cpsd.png -------------------------------------------------------------------------------- /plots/pz_s_besselap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_s_besselap.png -------------------------------------------------------------------------------- /plots/pz_s_buttap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_s_buttap.png -------------------------------------------------------------------------------- /plots/pz_s_cheb1ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_s_cheb1ap.png -------------------------------------------------------------------------------- /plots/pz_s_cheb2ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_s_cheb2ap.png -------------------------------------------------------------------------------- /plots/pz_s_ellipap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_s_ellipap.png -------------------------------------------------------------------------------- /plots/pz_z_besselap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_besselap.png -------------------------------------------------------------------------------- /plots/pz_z_besself.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_besself.png -------------------------------------------------------------------------------- /plots/pz_z_buttap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_buttap.png -------------------------------------------------------------------------------- /plots/pz_z_butter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_butter.png -------------------------------------------------------------------------------- /plots/pz_z_cheb1ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_cheb1ap.png -------------------------------------------------------------------------------- /plots/pz_z_cheb2ap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_cheb2ap.png -------------------------------------------------------------------------------- /plots/pz_z_cheby1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_cheby1.png -------------------------------------------------------------------------------- /plots/pz_z_cheby2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_cheby2.png -------------------------------------------------------------------------------- /plots/pz_z_ellip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_ellip.png -------------------------------------------------------------------------------- /plots/pz_z_ellipap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_ellipap.png -------------------------------------------------------------------------------- /plots/pz_z_fir1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_fir1.png -------------------------------------------------------------------------------- /plots/pz_z_fir2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_fir2.png -------------------------------------------------------------------------------- /plots/pz_z_firgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_firgr.png -------------------------------------------------------------------------------- /plots/pz_z_firls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_firls.png -------------------------------------------------------------------------------- /plots/pz_z_firpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_firpm.png -------------------------------------------------------------------------------- /plots/pz_z_gammatone_fir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_gammatone_fir.png -------------------------------------------------------------------------------- /plots/pz_z_gammatone_iir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_gammatone_iir.png -------------------------------------------------------------------------------- /plots/pz_z_iir_comb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_iir_comb.png -------------------------------------------------------------------------------- /plots/pz_z_iir_notch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_iir_notch.png -------------------------------------------------------------------------------- /plots/pz_z_iir_peak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_iir_peak.png -------------------------------------------------------------------------------- /plots/pz_z_kaiserord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_kaiserord.png -------------------------------------------------------------------------------- /plots/pz_z_pei_tseng_notch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_pei_tseng_notch.png -------------------------------------------------------------------------------- /plots/pz_z_qp_kaiser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/pz_z_qp_kaiser.png -------------------------------------------------------------------------------- /plots/s_t_bspline_eval.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/s_t_bspline_eval.png -------------------------------------------------------------------------------- /plots/t_z_grpdelay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/t_z_grpdelay.png -------------------------------------------------------------------------------- /plots/uy_t_sim_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/uy_t_sim_s.png -------------------------------------------------------------------------------- /plots/uy_t_sim_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/uy_t_sim_z.png -------------------------------------------------------------------------------- /plots/windows/g_f_barthann.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_barthann.png -------------------------------------------------------------------------------- /plots/windows/g_f_blackman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_blackman.png -------------------------------------------------------------------------------- /plots/windows/g_f_blackman_harris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_blackman_harris.png -------------------------------------------------------------------------------- /plots/windows/g_f_blackman_nuttall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_blackman_nuttall.png -------------------------------------------------------------------------------- /plots/windows/g_f_bohman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_bohman.png -------------------------------------------------------------------------------- /plots/windows/g_f_boxcar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_boxcar.png -------------------------------------------------------------------------------- /plots/windows/g_f_confined_gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_confined_gaussian.png -------------------------------------------------------------------------------- /plots/windows/g_f_confined_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_confined_normal.png -------------------------------------------------------------------------------- /plots/windows/g_f_dolph_chebyshev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_dolph_chebyshev.png -------------------------------------------------------------------------------- /plots/windows/g_f_flattop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_flattop.png -------------------------------------------------------------------------------- /plots/windows/g_f_gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_gaussian.png -------------------------------------------------------------------------------- /plots/windows/g_f_hamming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_hamming.png -------------------------------------------------------------------------------- /plots/windows/g_f_hann.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_hann.png -------------------------------------------------------------------------------- /plots/windows/g_f_kaiser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_kaiser.png -------------------------------------------------------------------------------- /plots/windows/g_f_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_normal.png -------------------------------------------------------------------------------- /plots/windows/g_f_nuttall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_nuttall.png -------------------------------------------------------------------------------- /plots/windows/g_f_parzen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_parzen.png -------------------------------------------------------------------------------- /plots/windows/g_f_planck_taper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_planck_taper.png -------------------------------------------------------------------------------- /plots/windows/g_f_power_of_sine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_power_of_sine.png -------------------------------------------------------------------------------- /plots/windows/g_f_sine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_sine.png -------------------------------------------------------------------------------- /plots/windows/g_f_triangular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_triangular.png -------------------------------------------------------------------------------- /plots/windows/g_f_tukey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_tukey.png -------------------------------------------------------------------------------- /plots/windows/g_f_ultraspherical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_ultraspherical.png -------------------------------------------------------------------------------- /plots/windows/g_f_welch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_f_welch.png -------------------------------------------------------------------------------- /plots/windows/g_n_barthann.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_barthann.png -------------------------------------------------------------------------------- /plots/windows/g_n_blackman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_blackman.png -------------------------------------------------------------------------------- /plots/windows/g_n_blackman_harris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_blackman_harris.png -------------------------------------------------------------------------------- /plots/windows/g_n_blackman_nuttall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_blackman_nuttall.png -------------------------------------------------------------------------------- /plots/windows/g_n_bohman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_bohman.png -------------------------------------------------------------------------------- /plots/windows/g_n_boxcar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_boxcar.png -------------------------------------------------------------------------------- /plots/windows/g_n_confined_gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_confined_gaussian.png -------------------------------------------------------------------------------- /plots/windows/g_n_confined_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_confined_normal.png -------------------------------------------------------------------------------- /plots/windows/g_n_dolph_chebyshev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_dolph_chebyshev.png -------------------------------------------------------------------------------- /plots/windows/g_n_flattop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_flattop.png -------------------------------------------------------------------------------- /plots/windows/g_n_gaussian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_gaussian.png -------------------------------------------------------------------------------- /plots/windows/g_n_hamming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_hamming.png -------------------------------------------------------------------------------- /plots/windows/g_n_hann.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_hann.png -------------------------------------------------------------------------------- /plots/windows/g_n_kaiser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_kaiser.png -------------------------------------------------------------------------------- /plots/windows/g_n_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_normal.png -------------------------------------------------------------------------------- /plots/windows/g_n_nuttall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_nuttall.png -------------------------------------------------------------------------------- /plots/windows/g_n_parzen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_parzen.png -------------------------------------------------------------------------------- /plots/windows/g_n_planck_taper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_planck_taper.png -------------------------------------------------------------------------------- /plots/windows/g_n_power_of_sine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_power_of_sine.png -------------------------------------------------------------------------------- /plots/windows/g_n_sine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_sine.png -------------------------------------------------------------------------------- /plots/windows/g_n_triangular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_triangular.png -------------------------------------------------------------------------------- /plots/windows/g_n_tukey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_tukey.png -------------------------------------------------------------------------------- /plots/windows/g_n_ultraspherical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_ultraspherical.png -------------------------------------------------------------------------------- /plots/windows/g_n_welch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/windows/g_n_welch.png -------------------------------------------------------------------------------- /plots/x_hat_cceps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_hat_cceps.png -------------------------------------------------------------------------------- /plots/x_hat_rceps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_hat_rceps.png -------------------------------------------------------------------------------- /plots/x_n_cspline_1d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_n_cspline_1d.png -------------------------------------------------------------------------------- /plots/x_n_findpeaks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_n_findpeaks.png -------------------------------------------------------------------------------- /plots/x_n_qspline_1d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_n_qspline_1d.png -------------------------------------------------------------------------------- /plots/x_n_state_levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_n_state_levels.png -------------------------------------------------------------------------------- /plots/x_t_chirp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_chirp.png -------------------------------------------------------------------------------- /plots/x_t_idct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_idct.png -------------------------------------------------------------------------------- /plots/x_t_idft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_idft.png -------------------------------------------------------------------------------- /plots/x_t_idht.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_idht.png -------------------------------------------------------------------------------- /plots/x_t_movingrms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_movingrms.png -------------------------------------------------------------------------------- /plots/x_t_resample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_resample.png -------------------------------------------------------------------------------- /plots/x_t_sampled_to_continuous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_t_sampled_to_continuous.png -------------------------------------------------------------------------------- /plots/x_z_dct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_z_dct.png -------------------------------------------------------------------------------- /plots/x_z_dft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_z_dft.png -------------------------------------------------------------------------------- /plots/x_z_dht.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_z_dht.png -------------------------------------------------------------------------------- /plots/x_z_dst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/x_z_dst.png -------------------------------------------------------------------------------- /plots/xy_t_fftfilt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/xy_t_fftfilt.png -------------------------------------------------------------------------------- /plots/xy_t_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/xy_t_filter.png -------------------------------------------------------------------------------- /plots/xy_t_filtfilt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/xy_t_filtfilt.png -------------------------------------------------------------------------------- /plots/xy_t_hilbert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/xy_t_hilbert.png -------------------------------------------------------------------------------- /plots/xy_t_sgolayfilt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/xy_t_sgolayfilt.png -------------------------------------------------------------------------------- /plots/y_t_diric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_diric.png -------------------------------------------------------------------------------- /plots/y_t_filtic_u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_filtic_u.png -------------------------------------------------------------------------------- /plots/y_t_gauspuls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_gauspuls.png -------------------------------------------------------------------------------- /plots/y_t_gmonopuls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_gmonopuls.png -------------------------------------------------------------------------------- /plots/y_t_impulse_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_impulse_s.png -------------------------------------------------------------------------------- /plots/y_t_impulse_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_impulse_z.png -------------------------------------------------------------------------------- /plots/y_t_meyeraux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_meyeraux.png -------------------------------------------------------------------------------- /plots/y_t_pulse_train.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_pulse_train.png -------------------------------------------------------------------------------- /plots/y_t_sigmoid_train.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_sigmoid_train.png -------------------------------------------------------------------------------- /plots/y_t_step_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_step_s.png -------------------------------------------------------------------------------- /plots/y_t_step_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sigurd4/signal_processing/20617366bd7c8e784944253566e49249a0880a4b/plots/y_t_step_z.png -------------------------------------------------------------------------------- /src/analysis/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | cceps, 4 | cpsd, 5 | filternorm, 6 | filtic_u, 7 | filtic, 8 | filtord, 9 | find_freqs, 10 | find_peaks, 11 | freqs, 12 | freqz, 13 | fwhm, 14 | grpdelay, 15 | impulse_s, 16 | impulse_z, 17 | impz, 18 | isallpass, 19 | islinphase, 20 | ismaxphase, 21 | isminphase, 22 | isstable, 23 | movingrms, 24 | mscohere, 25 | pburg, 26 | peak_to_peak, 27 | peak_to_rms, 28 | phasez, 29 | psd, 30 | pwelch, 31 | pyulear, 32 | rceps, 33 | real_cpsd, 34 | real_freqz, 35 | real_mscohere, 36 | real_phasez, 37 | real_pwelch, 38 | real_specgram, 39 | rms, 40 | rssq, 41 | sim_s, 42 | sim_z, 43 | specgram, 44 | statelevels, 45 | step_s, 46 | step_z, 47 | tfestimate, 48 | xcorr_2d, 49 | xcorr, 50 | xcov, 51 | zero_crossing 52 | } 53 | ); -------------------------------------------------------------------------------- /src/analysis/pburg.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{systems::Ar, identification::ar::{ArBurg, ArBurgCriterion}, quantities::{List, Lists}, analysis::{Psd, PsdMethod, PsdRange}, System}; 5 | 6 | 7 | pub trait PBurg: Lists 8 | where 9 | X: ComplexFloat, 10 | P: Lists, 11 | F: List, 12 | O: Maybe, 13 | N: Maybe, 14 | FF: Maybe, 15 | M: Maybe, 16 | R: Maybe, 17 | C: Maybe, 18 | { 19 | fn pburg(self, order: O, numtaps: N, frequencies: FF, sampling_frequency: FS, range: R, method: M, criterion: C) -> (P, F) 20 | where 21 | FS: Maybe; 22 | } 23 | 24 | impl PBurg for XX 25 | where 26 | X: ComplexFloat, 27 | XX: Lists, 28 | P: Lists, 29 | F: List, 30 | O: Maybe, 31 | N: Maybe, 32 | FF: Maybe, 33 | M: Maybe, 34 | R: Maybe, 35 | C: Maybe, 36 | Ar, XX::RowsMapped<(Vec, X::Real)>>: ArBurg>> + for<'a> Psd<'a, P, F, N, FF, R, M> + System, 37 | XX::RowsMapped>: Lists 38 | { 39 | fn pburg(self, order: O, numtaps: N, frequencies: FF, sampling_frequency: FS, range: R, method: M, criterion: C) -> (P, F) 40 | where 41 | FS: Maybe 42 | { 43 | let (ar, _) = Ar::arburg(self, order, criterion); 44 | ar.psd(numtaps, frequencies, sampling_frequency, range, method) 45 | } 46 | } 47 | 48 | #[cfg(test)] 49 | mod test 50 | { 51 | use array_math::ArrayOps; 52 | 53 | use crate::{plot, analysis::PBurg}; 54 | 55 | #[test] 56 | fn test() 57 | { 58 | let x = [1.0, 2.0, 3.0, 4.0, 5.0]; 59 | 60 | const N: usize = 1024; 61 | let (psd, f): ([_; N], _) = x.pburg(2, (), (), (), (), (), ()); 62 | 63 | plot::plot_curves("P(e^jw)", "plots/p_z_pburg.png", [&f.zip(psd)]) 64 | .unwrap(); 65 | } 66 | } -------------------------------------------------------------------------------- /src/analysis/peak_to_peak.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Sub; 2 | 3 | use num::Zero; 4 | 5 | use crate::quantities::{List, ListOrSingle, Lists}; 6 | 7 | pub trait PeakToPeak<'a, T>: Lists 8 | where 9 | T: PartialOrd + Sub 10 | { 11 | fn peak_to_peak(&'a self) -> Self::RowsMapped<::Output>; 12 | } 13 | 14 | impl<'a, T, L> PeakToPeak<'a, T> for L 15 | where 16 | L: Lists: List> + 'a, 17 | T: PartialOrd + Sub + Zero + Clone + 'a 18 | { 19 | fn peak_to_peak(&'a self) -> Self::RowsMapped<::Output> 20 | { 21 | self.map_rows_to_owned(|x| { 22 | let x = x.to_vec(); 23 | x.iter() 24 | .map(|x| x.clone()) 25 | .reduce(|a, b| if a == a && a >= b {a} else {b}) 26 | .unwrap_or(T::zero()) 27 | - x.into_iter() 28 | .reduce(|a, b| if a == a && a <= b {a} else {b}) 29 | .unwrap_or(T::zero()) 30 | }) 31 | } 32 | } -------------------------------------------------------------------------------- /src/analysis/peak_to_rms.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | 3 | use crate::quantities::{List, ListOrSingle, Lists}; 4 | 5 | pub trait PeakToRms<'a, T>: Lists 6 | where 7 | T: Float 8 | { 9 | fn peak_to_rms(&'a self) -> Self::RowsMapped; 10 | } 11 | 12 | impl<'a, T, L> PeakToRms<'a, T> for L 13 | where 14 | L: Lists: List> + 'a, 15 | T: Float + FloatConst + 'a 16 | { 17 | fn peak_to_rms(&'a self) -> Self::RowsMapped 18 | { 19 | let one = T::one(); 20 | let two = one + one; 21 | let p2p2rms = T::FRAC_1_SQRT_2()/two; 22 | 23 | self.map_rows_to_owned(|x| { 24 | let x = x.to_vec(); 25 | let p2p = x.iter() 26 | .map(|&x| x) 27 | .reduce(T::max) 28 | .unwrap_or(T::zero()) 29 | - x.into_iter() 30 | .reduce(T::min) 31 | .unwrap_or(T::zero()); 32 | p2p*p2p2rms 33 | }) 34 | } 35 | } -------------------------------------------------------------------------------- /src/analysis/pyulear.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{systems::Ar, identification::ar::ArYule, quantities::{List, Lists}, analysis::{Psd, PsdMethod, PsdRange}, System}; 5 | 6 | pub trait PYuleAr: Lists 7 | where 8 | X: ComplexFloat, 9 | P: Lists, 10 | F: List, 11 | O: Maybe, 12 | N: Maybe, 13 | FF: Maybe, 14 | M: Maybe, 15 | R: Maybe 16 | { 17 | fn pyulear(self, order: O, numtaps: N, frequencies: FF, sampling_frequency: FS, range: R, method: M) -> (P, F) 18 | where 19 | FS: Maybe; 20 | } 21 | 22 | impl PYuleAr for XX 23 | where 24 | X: ComplexFloat, 25 | XX: Lists, 26 | P: Lists, 27 | F: List, 28 | O: Maybe, 29 | N: Maybe, 30 | FF: Maybe, 31 | M: Maybe, 32 | R: Maybe, 33 | Ar, XX::RowsMapped<(Vec, X::Real)>>: ArYule>> + for<'a> Psd<'a, P, F, N, FF, R, M> + System, 34 | XX::RowsMapped>: Lists 35 | { 36 | fn pyulear(self, order: O, numtaps: N, frequencies: FF, sampling_frequency: FS, range: R, method: M) -> (P, F) 37 | where 38 | FS: Maybe<::Real> 39 | { 40 | let (ar, _) = Ar::aryule(self, order); 41 | ar.psd(numtaps, frequencies, sampling_frequency, range, method) 42 | } 43 | } 44 | 45 | #[cfg(test)] 46 | mod test 47 | { 48 | use array_math::ArrayOps; 49 | 50 | use crate::{plot, analysis::PYuleAr}; 51 | 52 | #[test] 53 | fn test() 54 | { 55 | let x = [1.0, 2.0, 3.0, 4.0, 5.0]; 56 | 57 | const N: usize = 1024; 58 | let (psd, f): ([_; N], _) = x.pyulear(2, (), (), (), (), ()); 59 | 60 | plot::plot_curves("P(e^jw)", "plots/p_z_pyulear.png", [&f.zip(psd)]) 61 | .unwrap(); 62 | } 63 | } -------------------------------------------------------------------------------- /src/analysis/rms.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Add; 2 | 3 | use num::{complex::ComplexFloat, Float, NumCast, Zero}; 4 | 5 | use crate::quantities::{List, ListOrSingle, Lists}; 6 | 7 | pub trait Rms<'a, T>: Lists 8 | where 9 | T: ComplexFloat 10 | { 11 | fn rms(&'a self) -> Self::RowsMapped; 12 | } 13 | 14 | impl<'a, T, L> Rms<'a, T> for L 15 | where 16 | L: Lists: List> + 'a, 17 | T: ComplexFloat + 'a 18 | { 19 | fn rms(&'a self) -> Self::RowsMapped 20 | { 21 | self.map_rows_to_owned(|x| { 22 | let x = x.to_vec(); 23 | let l = ::from(x.len()).unwrap(); 24 | x.into_iter() 25 | .map(|x| (x.conj()*x).re()) 26 | .reduce(Add::add) 27 | .map(|x| Float::sqrt(x/l)) 28 | .unwrap_or(T::Real::zero()) 29 | }) 30 | } 31 | } -------------------------------------------------------------------------------- /src/analysis/rssq.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Add; 2 | 3 | use num::{complex::ComplexFloat, Float, Zero}; 4 | 5 | use crate::quantities::{List, ListOrSingle, Lists}; 6 | 7 | pub trait Rssq<'a, T>: Lists 8 | where 9 | T: ComplexFloat 10 | { 11 | fn rssq(&'a self) -> Self::RowsMapped; 12 | } 13 | 14 | impl<'a, T, L> Rssq<'a, T> for L 15 | where 16 | L: Lists: List> + 'a, 17 | T: ComplexFloat + 'a 18 | { 19 | fn rssq(&'a self) -> Self::RowsMapped 20 | { 21 | self.map_rows_to_owned(|x| { 22 | let x = x.to_vec(); 23 | x.into_iter() 24 | .map(|x| (x.conj()*x).re()) 25 | .reduce(Add::add) 26 | .map(|x| Float::sqrt(x)) 27 | .unwrap_or(T::Real::zero()) 28 | }) 29 | } 30 | } -------------------------------------------------------------------------------- /src/decompositions/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | maxphase, 4 | minphase, 5 | residue, 6 | residued, 7 | residuez, 8 | split_numer_denom 9 | } 10 | ); -------------------------------------------------------------------------------- /src/gen/bspline/gauss_spline.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait GaussSpline: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn gauss_spline(self, numtaps: N, order: usize) -> (L::Mapped, L); 13 | } 14 | 15 | impl GaussSpline for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn gauss_spline(self, n: N, order: usize) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let one = T::one(); 27 | let two = one + one; 28 | 29 | let sigma = T::from(order + 1).unwrap()/T::from(12u8).unwrap(); 30 | 31 | let psi = t.map_to_owned(|&x| { 32 | (T::TAU()*sigma).sqrt().recip()*(-x*x/two/sigma).exp() 33 | }); 34 | 35 | (psi, t) 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod test 41 | { 42 | use array_math::ArrayOps; 43 | 44 | use crate::{plot, gen::bspline::GaussSpline}; 45 | 46 | #[test] 47 | fn test() 48 | { 49 | const N: usize = 1024; 50 | let (b, t): (_, [_; N]) = (-1.0..=1.0).gauss_spline((), 3); 51 | 52 | plot::plot_curves("B(t)", "plots/b_t_gauss_spline.png", [&t.zip(b)]) 53 | .unwrap() 54 | } 55 | } -------------------------------------------------------------------------------- /src/gen/bspline/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | gauss_spline 4 | } 5 | ); -------------------------------------------------------------------------------- /src/gen/matrix/convmtx.rs: -------------------------------------------------------------------------------- 1 | use ndarray::Array2; 2 | use num::{traits::FloatConst, Float, Zero}; 3 | use option_trait::Maybe; 4 | 5 | use crate::quantities::{List, Matrix, OwnedList, OwnedListOrSingle}; 6 | 7 | pub trait ConvMatrix: List 8 | where 9 | T: Float + FloatConst, 10 | M: Matrix + Sized, 11 | N: Maybe 12 | { 13 | fn conv_matrix(self, n: N) -> M; 14 | } 15 | 16 | impl ConvMatrix; N], ()> for A 17 | where 18 | T: Float + FloatConst, 19 | A: List, 20 | A::ResizedList<{A::LENGTH + N - 1}>: OwnedList + Clone, 21 | [A::ResizedList<{A::LENGTH + N - 1}>; N]: Matrix 22 | { 23 | fn conv_matrix(self: A, (): ()) -> [A::ResizedList<{A::LENGTH + N - 1}>; N] 24 | { 25 | let len = self.length(); 26 | let mut a = self.static_resize_list((len + N).saturating_sub(1), Zero::zero); 27 | core::array::from_fn(|_| { 28 | let r = a.clone(); 29 | a.as_mut_slice() 30 | .rotate_right(1); 31 | r 32 | }) 33 | } 34 | } 35 | 36 | impl ConvMatrix, usize> for A 37 | where 38 | T: Float + FloatConst, 39 | A: List 40 | { 41 | fn conv_matrix(self, n: usize) -> Array2 42 | { 43 | let mut a = self.into_vec(); 44 | let len = a.len(); 45 | let m = (len + n).saturating_sub(1); 46 | a.resize(m, Zero::zero()); 47 | Array2::from_shape_fn((n, m), |(i, j)| a[(j + m - i) % m]) 48 | } 49 | } 50 | 51 | #[cfg(test)] 52 | mod test 53 | { 54 | use crate::gen::matrix::ConvMatrix; 55 | 56 | #[test] 57 | fn test() 58 | { 59 | let a = [3.0, 4.0, 5.0]; 60 | 61 | const N: usize = 3; 62 | let m: [_; N] = a.conv_matrix(()); 63 | 64 | println!("{:?}", m); 65 | 66 | let m = a.conv_matrix(N); 67 | 68 | println!("{:?}", m); 69 | } 70 | } -------------------------------------------------------------------------------- /src/gen/matrix/dftmtx.rs: -------------------------------------------------------------------------------- 1 | use ndarray::Array2; 2 | use num::{traits::FloatConst, Complex, Float}; 3 | use option_trait::Maybe; 4 | 5 | use crate::quantities::Matrix; 6 | 7 | pub trait DftMatrix: Matrix> 8 | where 9 | T: Float + FloatConst, 10 | N: Maybe 11 | { 12 | fn dft_matrix(n: N) -> Self; 13 | } 14 | 15 | impl DftMatrix for [[Complex; N]; N] 16 | where 17 | T: Float + FloatConst 18 | { 19 | fn dft_matrix((): ()) -> Self 20 | { 21 | let nf = T::from(N).unwrap(); 22 | let w = T::TAU()/nf; 23 | 24 | core::array::from_fn(|i| core::array::from_fn(|j| { 25 | let i = T::from(i).unwrap(); 26 | let j = T::from(j).unwrap(); 27 | Complex::cis(-w*i*j) 28 | })) 29 | } 30 | } 31 | 32 | impl DftMatrix for Array2> 33 | where 34 | T: Float + FloatConst 35 | { 36 | fn dft_matrix(n: usize) -> Self 37 | { 38 | let nf = T::from(n).unwrap(); 39 | let w = T::TAU()/nf; 40 | 41 | Array2::from_shape_fn((n, n), |(i, j)| { 42 | let i = T::from(i).unwrap(); 43 | let j = T::from(j).unwrap(); 44 | Complex::cis(-w*i*j) 45 | }) 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod test 51 | { 52 | use array_math::{ArrayOps, CollumnArrayOps, MatrixMath}; 53 | use num::Complex; 54 | 55 | use crate::{gen::matrix::DftMatrix, transforms::fourier::Dft}; 56 | 57 | #[test] 58 | fn test() 59 | { 60 | let x = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; 61 | 62 | let y1 = x.dft(); 63 | println!("{:?}", y1); 64 | 65 | let t: [[Complex; _]; _] = DftMatrix::dft_matrix(()); 66 | 67 | let y2 = t.mul_matrix(x.as_collumn()).into_uncollumn(); 68 | println!("{:?}", y2); 69 | } 70 | } -------------------------------------------------------------------------------- /src/gen/matrix/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | convmtx, 4 | dctmtx, 5 | dftmtx, 6 | dstmtx 7 | } 8 | ); -------------------------------------------------------------------------------- /src/gen/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | pub mod { 3 | bspline, 4 | filter, 5 | matrix, 6 | pulse, 7 | waveform, 8 | wavelet, 9 | window, 10 | }, 11 | flat(pub) mod { 12 | cheb 13 | } 14 | ); -------------------------------------------------------------------------------- /src/gen/pulse/gauspuls.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait GausPuls: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn gauspuls(self, numtaps: N, fc: T, bw: T) -> (L::Mapped, L::Mapped, L::Mapped, L); 13 | } 14 | 15 | impl GausPuls for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn gauspuls(self, n: N, fc: T, bw: T) -> (L::Mapped, L::Mapped, L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let fv = -bw*bw*fc*fc/(T::from(8u8).unwrap()*(T::from(10u8).unwrap().powf(-T::from(3u8).unwrap()/T::from(10u8).unwrap())).ln()); 27 | let tv = (T::TAU()*T::TAU()*fv).recip(); 28 | let yi = t.map_to_owned(|&t| { 29 | (-t*t/(T::from(2u8).unwrap()*tv)).exp()*(T::TAU()*fc*t).cos() 30 | }); 31 | let yq = t.map_to_owned(|&t| { 32 | (-t*t/(T::from(2u8).unwrap()*tv)).exp()*(T::TAU()*fc*t).sin() 33 | }); 34 | let ye = t.map_to_owned(|&t| { 35 | (-t*t/(T::from(2u8).unwrap()*tv)).exp() 36 | }); 37 | (yi, yq, ye, t) 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod test 43 | { 44 | use array_math::ArrayOps; 45 | 46 | use crate::{plot, gen::pulse::GausPuls}; 47 | 48 | #[test] 49 | fn test() 50 | { 51 | const N: usize = 1024; 52 | let (yi, yq, ye, t): ([_; N], _, _, _) = (-0.003..=0.003).gauspuls((), 1e3, 0.5); 53 | 54 | plot::plot_curves("y(t)", "plots/y_t_gauspuls.png", [&t.zip(yi), &t.zip(yq), &t.zip(ye)]) 55 | .unwrap() 56 | } 57 | } -------------------------------------------------------------------------------- /src/gen/pulse/gmonopuls.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait GMonoPuls: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn gmonopuls(self, numtaps: N, fc: T) -> (L::Mapped, L); 13 | } 14 | 15 | impl GMonoPuls for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn gmonopuls(self, n: N, fc: T) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let scale = T::E().sqrt()*T::TAU()*fc; 27 | let y = t.map_to_owned(|&t| { 28 | if t.is_finite() 29 | { 30 | scale*t*(-T::TAU()*T::PI()*t*t*fc*fc).exp() 31 | } 32 | else 33 | { 34 | T::zero() 35 | } 36 | }); 37 | (y, t) 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod test 43 | { 44 | use array_math::ArrayOps; 45 | 46 | use crate::{plot, gen::pulse::GMonoPuls}; 47 | 48 | #[test] 49 | fn test() 50 | { 51 | const N: usize = 1024; 52 | let (y, t): ([_; N], _) = (-0.001..=0.001).gmonopuls((), 1e3); 53 | 54 | plot::plot_curves("y(t)", "plots/y_t_gmonopuls.png", [&t.zip(y)]) 55 | .unwrap() 56 | } 57 | } -------------------------------------------------------------------------------- /src/gen/pulse/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | gauspuls, 4 | gmonopuls, 5 | pulstran, 6 | rectpuls, 7 | sigmoid_train, 8 | tripuls 9 | } 10 | ); -------------------------------------------------------------------------------- /src/gen/pulse/rectpuls.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait RectPuls: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn rectpuls(self, numtaps: N, bandwidth: T) -> (L::Mapped, L); 13 | } 14 | 15 | impl RectPuls for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn rectpuls(self, n: N, bandwidth: T) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let one = T::one(); 27 | let two = one + one; 28 | let bw_half = bandwidth/two; 29 | 30 | let y = t.map_to_owned(|&t| { 31 | T::from((t >= -bw_half && t < bw_half) as u8).unwrap() 32 | }); 33 | (y, t) 34 | } 35 | } -------------------------------------------------------------------------------- /src/gen/pulse/tripuls.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait TriPuls: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn tripuls(self, numtaps: N, bandwidth: T, skew: SK) -> (L::Mapped, L) 13 | where 14 | SK: Maybe; 15 | } 16 | 17 | impl TriPuls for R 18 | where 19 | T: Float + FloatConst, 20 | L: ListOrSingle, 21 | R: IntoList, 22 | N: Maybe 23 | { 24 | fn tripuls(self, n: N, bandwidth: T, skew: SK) -> (L::Mapped, L) 25 | where 26 | SK: Maybe 27 | { 28 | let t = self.into_list(n); 29 | 30 | let zero = T::zero(); 31 | let one = T::one(); 32 | let two = one + one; 33 | let bw_half = bandwidth/two; 34 | let skew = skew.into_option() 35 | .unwrap_or(zero); 36 | let peak = skew*bw_half; 37 | 38 | let y = t.map_to_owned(|&t| { 39 | if t > -bw_half && t <= peak 40 | { 41 | (t + bw_half)/(peak + bw_half) 42 | } 43 | else if t > peak && t < bw_half 44 | { 45 | (t - bw_half)/(peak - bw_half) 46 | } 47 | else 48 | { 49 | zero 50 | } 51 | }); 52 | (y, t) 53 | } 54 | } -------------------------------------------------------------------------------- /src/gen/waveform/diric.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait Diric: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn diric(self, numtaps: N, order: usize) -> (L::Mapped, L); 13 | } 14 | 15 | impl Diric for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn diric(self, n: N, order: usize) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let n = T::from(order).unwrap(); 27 | let one = T::one(); 28 | let two = one + one; 29 | 30 | let y = t.map_to_owned(|&x| { 31 | if !(x % T::TAU()).is_zero() 32 | { 33 | (n*x/two).sin()/(n*(x/two).sin()) 34 | } 35 | else if (((n - one)*x) % T::TAU()).abs() < T::FRAC_PI_2() 36 | { 37 | one 38 | } 39 | else 40 | { 41 | -one 42 | } 43 | }); 44 | 45 | (y, t) 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod test 51 | { 52 | use array_math::ArrayOps; 53 | 54 | use crate::{plot, gen::waveform::Diric}; 55 | 56 | #[test] 57 | fn test() 58 | { 59 | const N: usize = 1024; 60 | let (y, t): (_, [_; N]) = (-8.0..=8.0).diric((), 6); 61 | 62 | plot::plot_curves("y(t)", "plots/y_t_diric.png", [&t.zip(y)]) 63 | .unwrap() 64 | } 65 | } -------------------------------------------------------------------------------- /src/gen/waveform/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | chirp, 4 | diric 5 | } 6 | ); -------------------------------------------------------------------------------- /src/gen/wavelet/cmorwavf.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Complex, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait CMorWavF: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn cmorwavf(self, numtaps: N, fb: T, fc: T) -> (L::Mapped>, L); 13 | } 14 | 15 | impl CMorWavF for R 16 | where 17 | T: Float + FloatConst, 18 | R: IntoList, 19 | N: Maybe, 20 | L: ListOrSingle 21 | { 22 | fn cmorwavf(self, n: N, fb: T, fc: T) -> (L::Mapped>, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let psi = t.map_to_owned(|&x| { 27 | Complex::from(T::PI()*fb).inv().sqrt()*Complex::cis(T::TAU()*fc*x)*(-x*x/fb).exp() 28 | }); 29 | 30 | (psi, t) 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod test 36 | { 37 | use array_math::ArrayOps; 38 | 39 | use crate::{plot, gen::wavelet::CMorWavF}; 40 | 41 | #[test] 42 | fn test() 43 | { 44 | const N: usize = 1024; 45 | let (psi, t): ([_; N], _) = (-8.0..=8.0).cmorwavf((), 1.5, 1.0); 46 | 47 | plot::plot_curves("ψ(t)", "plots/psi_t_cmorwavf.png", [&t.zip(psi.map(|psi| psi.re)), &t.zip(psi.map(|psi| psi.im))]) 48 | .unwrap() 49 | } 50 | } -------------------------------------------------------------------------------- /src/gen/wavelet/coifaux.rs: -------------------------------------------------------------------------------- 1 | use core::{iter::Sum, ops::{DivAssign, MulAssign}}; 2 | 3 | use num::Float; 4 | use option_trait::Maybe; 5 | 6 | pub fn coifaux(order: usize, scale: S) -> Option> 7 | where 8 | T: Float + Sum + MulAssign + DivAssign, 9 | S: Maybe 10 | { 11 | if let Some(mut h) = crate::gen::wavelet::coifwavf::(order) 12 | { 13 | let one = T::one(); 14 | 15 | let scale = scale.into_option() 16 | .unwrap_or(one); 17 | 18 | h.reverse(); 19 | for h in h.iter_mut() 20 | .skip(1) 21 | .step_by(2) 22 | { 23 | *h = -*h 24 | } 25 | 26 | let s = h.iter() 27 | .copied() 28 | .sum::(); 29 | if !s.is_zero() 30 | { 31 | for c in h.iter_mut() 32 | { 33 | *c /= s; 34 | *c *= scale 35 | } 36 | } 37 | 38 | return Some(h) 39 | } 40 | None 41 | } 42 | 43 | #[cfg(test)] 44 | mod test 45 | { 46 | use linspace::Linspace; 47 | 48 | use crate::plot; 49 | 50 | #[test] 51 | fn test() 52 | { 53 | let phi = crate::gen::wavelet::coifaux(17, ()) 54 | .unwrap(); 55 | 56 | plot::plot_curves("ϕ[n]", "plots/phi_n_coifaux.png", [ 57 | &(0.0..phi.len() as f64).linspace(phi.len()) 58 | .into_iter() 59 | .zip(phi) 60 | .collect::>() 61 | ]).unwrap() 62 | } 63 | } -------------------------------------------------------------------------------- /src/gen/wavelet/coifwavf.rs: -------------------------------------------------------------------------------- 1 | use num::Float; 2 | 3 | moddef::moddef!( 4 | mod { 5 | lut 6 | } 7 | ); 8 | 9 | pub fn coifwavf(k: usize) -> Option> 10 | where 11 | T: Float 12 | { 13 | if k == 0 14 | { 15 | return None 16 | } 17 | if let Some(h) = lut::COIF_LUT.get(k - 1) 18 | { 19 | let h = h.iter() 20 | .map(|&h| T::from(h).unwrap()) 21 | .collect(); 22 | return Some(h) 23 | } 24 | None 25 | } 26 | 27 | #[cfg(test)] 28 | mod test 29 | { 30 | use linspace::Linspace; 31 | 32 | use crate::plot; 33 | 34 | #[test] 35 | fn test() 36 | { 37 | let psi = crate::gen::wavelet::coifwavf(17) 38 | .unwrap(); 39 | 40 | plot::plot_curves("ψ[n]", "plots/psi_n_coifwavf.png", [ 41 | &(0.0..psi.len() as f64).linspace(psi.len()) 42 | .into_iter() 43 | .zip(psi) 44 | .collect::>() 45 | ]).unwrap() 46 | } 47 | } -------------------------------------------------------------------------------- /src/gen/wavelet/dbwavf.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{DivAssign, MulAssign}; 2 | 3 | use ndarray_linalg::Lapack; 4 | use num::{traits::{float::TotalOrder, FloatConst}, Complex, Float}; 5 | use option_trait::Maybe; 6 | 7 | pub fn dbwavf(order: usize) -> Vec 8 | where 9 | T: Float + FloatConst + MulAssign + DivAssign + TotalOrder + Lapack>, 10 | (): Maybe 11 | { 12 | crate::gen::wavelet::dbaux(order, ()) 13 | } 14 | 15 | #[cfg(test)] 16 | mod test 17 | { 18 | use linspace::Linspace; 19 | 20 | use crate::plot; 21 | 22 | #[test] 23 | fn test() 24 | { 25 | let psi = crate::gen::wavelet::dbwavf(38); 26 | 27 | plot::plot_curves("ψ[n]", "plots/psi_n_dbwavf.png", [ 28 | &(0.0..psi.len() as f64).linspace(psi.len()) 29 | .into_iter() 30 | .zip(psi) 31 | .collect::>() 32 | ]).unwrap() 33 | } 34 | } -------------------------------------------------------------------------------- /src/gen/wavelet/haarwavf.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait HaarWavF: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn haarwavf(self, numtaps: N) -> (L::Mapped, L); 13 | } 14 | 15 | impl HaarWavF for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn haarwavf(self, n: N) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let zero = T::zero(); 27 | let one = T::one(); 28 | let two = one + one; 29 | let half = two.recip(); 30 | 31 | let psi = t.map_to_owned(|&x| { 32 | if x >= zero && x < half 33 | { 34 | one 35 | } 36 | else if x >= half && x < one 37 | { 38 | -one 39 | } 40 | else 41 | { 42 | zero 43 | } 44 | }); 45 | 46 | (psi, t) 47 | } 48 | } 49 | 50 | #[cfg(test)] 51 | mod test 52 | { 53 | use array_math::ArrayOps; 54 | 55 | use crate::{plot, gen::wavelet::HaarWavF}; 56 | 57 | #[test] 58 | fn test() 59 | { 60 | const N: usize = 1024; 61 | let (psi, t): (_, [_; N]) = (-0.5..=1.5).haarwavf(()); 62 | 63 | plot::plot_curves("ψ(t)", "plots/psi_t_haarwavf.png", [&t.zip(psi)]) 64 | .unwrap() 65 | } 66 | } -------------------------------------------------------------------------------- /src/gen/wavelet/mexihat.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait Mexihat: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | #[doc(alias = "ricker")] 13 | fn mexihat(self, numtaps: N) -> (L::Mapped, L); 14 | } 15 | 16 | impl Mexihat for R 17 | where 18 | T: Float + FloatConst, 19 | L: ListOrSingle, 20 | R: IntoList, 21 | N: Maybe 22 | { 23 | fn mexihat(self, n: N) -> (L::Mapped, L) 24 | { 25 | let t = self.into_list(n); 26 | 27 | let one = T::one(); 28 | let two = one + one; 29 | 30 | let a = two/(T::from(3u8).unwrap()*T::PI().sqrt()).sqrt(); 31 | 32 | let psi = t.map_to_owned(|&x| { 33 | (one - x*x)*a*(-x*x/two).exp() 34 | }); 35 | 36 | (psi, t) 37 | } 38 | } 39 | 40 | #[cfg(test)] 41 | mod test 42 | { 43 | use array_math::ArrayOps; 44 | 45 | use crate::{plot, gen::wavelet::Mexihat}; 46 | 47 | #[test] 48 | fn test() 49 | { 50 | const N: usize = 1024; 51 | let (psi, t): (_, [_; N]) = (-8.0..=8.0).mexihat(()); 52 | 53 | plot::plot_curves("ψ(t)", "plots/psi_t_mexihat.png", [&t.zip(psi)]) 54 | .unwrap() 55 | } 56 | } -------------------------------------------------------------------------------- /src/gen/wavelet/meyeraux.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait Meyeraux: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn meyeraux(self, numtaps: N) -> (L::Mapped, L); 13 | } 14 | 15 | impl Meyeraux for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn meyeraux(self, n: N) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let y = t.map_to_owned(|&x| { 27 | let x4 = x*x*x*x; 28 | x4*(T::from(35u8).unwrap() + x*(-T::from(84u8).unwrap() + x*(T::from(70u8).unwrap() - x*T::from(20u8).unwrap()))) 29 | }); 30 | 31 | (y, t) 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod test 37 | { 38 | use array_math::ArrayOps; 39 | 40 | use crate::{plot, gen::wavelet::Meyeraux}; 41 | 42 | #[test] 43 | fn test() 44 | { 45 | const N: usize = 1024; 46 | let (y, t): (_, [_; N]) = (0.0..=1.0).meyeraux(()); 47 | 48 | plot::plot_curves("y(t)", "plots/y_t_meyeraux.png", [&t.zip(y)]) 49 | .unwrap() 50 | } 51 | } -------------------------------------------------------------------------------- /src/gen/wavelet/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | cmorwavf, 4 | coifaux, 5 | coifwavf, 6 | dbaux, 7 | dbwavf, 8 | haarwavf, 9 | mexihat, 10 | meyeraux, 11 | morlet, 12 | shanwavf 13 | } 14 | ); -------------------------------------------------------------------------------- /src/gen/wavelet/morlet.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait Morlet: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn morlet(self, numtaps: N) -> (L::Mapped, L); 13 | } 14 | 15 | impl Morlet for R 16 | where 17 | T: Float + FloatConst, 18 | L: ListOrSingle, 19 | R: IntoList, 20 | N: Maybe 21 | { 22 | fn morlet(self, n: N) -> (L::Mapped, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let one = T::one(); 27 | let two = one + one; 28 | let five = T::from(5u8).unwrap(); 29 | 30 | let psi = t.map_to_owned(|&x| { 31 | (five*x).cos()*(-x*x/two).exp() 32 | }); 33 | 34 | (psi, t) 35 | } 36 | } 37 | 38 | #[cfg(test)] 39 | mod test 40 | { 41 | use array_math::ArrayOps; 42 | 43 | use crate::{plot, gen::wavelet::Morlet}; 44 | 45 | #[test] 46 | fn test() 47 | { 48 | const N: usize = 1024; 49 | let (psi, t): (_, [_; N]) = (-8.0..=8.0).morlet(()); 50 | 51 | plot::plot_curves("ψ(t)", "plots/psi_t_morlet.png", [&t.zip(psi)]) 52 | .unwrap() 53 | } 54 | } -------------------------------------------------------------------------------- /src/gen/wavelet/shanwavf.rs: -------------------------------------------------------------------------------- 1 | use num::{traits::FloatConst, Complex, Float}; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{IntoList, ListOrSingle}; 5 | 6 | pub trait ShanWavF: IntoList 7 | where 8 | T: Float, 9 | L: ListOrSingle, 10 | N: Maybe 11 | { 12 | fn shanwavf(self, numtaps: N, fb: T, fc: T) -> (L::Mapped>, L); 13 | } 14 | 15 | impl ShanWavF for R 16 | where 17 | T: Float + FloatConst, 18 | R: IntoList, 19 | N: Maybe, 20 | L: ListOrSingle 21 | { 22 | fn shanwavf(self, n: N, fb: T, fc: T) -> (L::Mapped>, L) 23 | { 24 | let t = self.into_list(n); 25 | 26 | let psi = t.map_to_owned(|&x| { 27 | let fbx = fb*x; 28 | let sinc = if fbx.is_zero() || fbx.is_subnormal() 29 | { 30 | T::one() 31 | } 32 | else 33 | { 34 | (fbx*T::PI()).sin()/(fbx*T::PI()) 35 | }; 36 | (Complex::cis(T::TAU()*fc*x)*sinc)/(fb.sqrt()) 37 | }); 38 | 39 | (psi, t) 40 | } 41 | } 42 | 43 | #[cfg(test)] 44 | mod test 45 | { 46 | use array_math::ArrayOps; 47 | 48 | use crate::{plot, gen::wavelet::ShanWavF}; 49 | 50 | #[test] 51 | fn test() 52 | { 53 | const N: usize = 1024; 54 | let (psi, t): ([_; N], _) = (-8.0..=8.0).shanwavf((), 1.5, 1.0); 55 | 56 | plot::plot_curves("ψ(t)", "plots/psi_t_shanwavf.png", [&t.zip(psi.map(|psi| psi.re)), &t.zip(psi.map(|psi| psi.im))]) 57 | .unwrap() 58 | } 59 | } -------------------------------------------------------------------------------- /src/gen/window/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | window_gen 4 | } 5 | ); -------------------------------------------------------------------------------- /src/gen/window/window_gen.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::List; 5 | 6 | pub enum WindowRange 7 | { 8 | Symmetric, 9 | Periodic 10 | } 11 | 12 | pub trait WindowGen 13 | where 14 | T: ComplexFloat, 15 | N: Maybe, 16 | W: List 17 | { 18 | type Output: Maybe; 19 | 20 | fn window_gen(&self, numtaps: N, range: WindowRange) -> Self::Output; 21 | } -------------------------------------------------------------------------------- /src/identification/ar/aryule.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{systems::Ar, identification::ar::Levinson, quantities::{List, ListOrSingle, Lists, MaybeList, MaybeLists}, System, analysis::{XCorr, XCorrScale}}; 5 | 6 | pub trait ArYule: System + Sized 7 | where 8 | X: Lists, 9 | O: Maybe, 10 | K: Lists 11 | { 12 | fn aryule(x: X, order: O) -> (Self, K); 13 | } 14 | 15 | impl ArYule for Ar 16 | where 17 | T: ComplexFloat>, 18 | A: MaybeList, 19 | AV: ListOrSingle<(A, T::Real)>, 20 | X: Lists, 21 | O: Maybe, 22 | K: Lists, 23 | X::RowOwned: XCorr + List>::RowsMapped>> = Vec>, 24 | X::RowsMapped>: Lists, 25 | Self: Levinson>, O, K> + System 26 | { 27 | fn aryule(x: X, order: O) -> (Self, K) 28 | { 29 | let n = order.as_option() 30 | .copied() 31 | .map(|o| o + 1) 32 | .unwrap_or(A::LENGTH) 33 | .max(2); 34 | let c = x.map_rows_into_owned(|x| { 35 | let (mut c, _): (Vec, _) = x.xcorr((), XCorrScale::Biased, n); 36 | c.reverse(); 37 | c.truncate(c.len() - n); 38 | c.reverse(); 39 | if let Some(c) = c.get_mut(0) 40 | { 41 | *c = c.re().into(); 42 | } 43 | c 44 | }); 45 | Self::levinson(c, order) 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod test 51 | { 52 | use crate::{systems::Ar, identification::ar::ArYule}; 53 | 54 | #[test] 55 | fn test() 56 | { 57 | let x = [1.0, 2.0, 3.0, 4.0, 5.0]; 58 | 59 | const N: usize = 3; 60 | let (ar, k) = Ar::<_, [_; N], _>::aryule(x, ()); 61 | 62 | println!("{:?}", ar); 63 | println!("{:?}", k); 64 | } 65 | } -------------------------------------------------------------------------------- /src/identification/ar/lpc.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{systems::Ar, identification::ar::Levinson, quantities::{List, ListOrSingle, Lists}, System, analysis::{XCorr, XCorrScale}}; 5 | 6 | pub trait Lpc: System + Sized 7 | where 8 | X: Lists, 9 | O: Maybe 10 | { 11 | fn lpc(x: X, order: O) -> Self; 12 | } 13 | 14 | impl Lpc for Ar> 15 | where 16 | T: ComplexFloat>, 17 | X: Lists, 18 | X::RowsMapped<([T; N], T::Real)>: ListOrSingle<([T; N], T::Real)>, 19 | XX: XCorr + List> = Vec>, 20 | Ar: Levinson, (), [T; N - 1]> + System 21 | { 22 | fn lpc(x: X, (): ()) -> Self 23 | { 24 | Ar::new(x.map_rows_into_owned(|x| { 25 | let (mut r, _): (Vec, _) = x.xcorr((), XCorrScale::Biased, N); 26 | let mut r = r.split_off(N); 27 | if let Some(r) = r.get_mut(0) 28 | { 29 | *r = r.re().into() 30 | } 31 | let (Ar {av, ..}, _) = Ar::levinson(r, ()); 32 | av 33 | })) 34 | } 35 | } 36 | 37 | impl Lpc for Ar, X::RowsMapped<(Vec, T::Real)>> 38 | where 39 | T: ComplexFloat>, 40 | X: Lists, 41 | X::RowsMapped<(Vec, T::Real)>: ListOrSingle<(Vec, T::Real)>, 42 | XX: XCorr + List> = Vec>, 43 | Ar, (Vec, T::Real)>: Levinson, usize, Vec> + System 44 | { 45 | fn lpc(x: X, order: usize) -> Self 46 | { 47 | Ar::new(x.map_rows_into_owned(|x| { 48 | let (mut r, _): (Vec, _) = x.xcorr((), XCorrScale::Biased, order + 1); 49 | let mut r = r.split_off(order + 1); 50 | if let Some(r) = r.get_mut(0) 51 | { 52 | *r = r.re().into() 53 | } 54 | let (Ar {av, ..}, _) = Ar::levinson(r, order); 55 | av 56 | })) 57 | } 58 | } -------------------------------------------------------------------------------- /src/identification/ar/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | arburg, 4 | aryule, 5 | levinson, 6 | lpc 7 | } 8 | ); -------------------------------------------------------------------------------- /src/identification/filter/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | invfreqs, 4 | invfreqz 5 | } 6 | ); -------------------------------------------------------------------------------- /src/identification/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | pub mod { 3 | ar, 4 | filter 5 | }, 6 | ); -------------------------------------------------------------------------------- /src/maybe_rtf_or_system.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{ 5 | systems::{Ar, Rpk, Rtf, Sos, Ss, SsAMatrix, SsBMatrix, SsCMatrix, SsDMatrix, Tf, Zpk}, 6 | quantities::{ListOrSingle, MaybeList, MaybeLists, MaybeOwnedList}, 7 | System 8 | }; 9 | 10 | pub trait MaybeRtfOrSystem 11 | where 12 | D: ComplexFloat 13 | { 14 | 15 | } 16 | 17 | impl MaybeRtfOrSystem for () 18 | where 19 | D: ComplexFloat 20 | { 21 | 22 | } 23 | 24 | impl MaybeRtfOrSystem for Rtf 25 | where 26 | W: ComplexFloat::Real>, 27 | S::Set: Into, 28 | S: System 29 | { 30 | 31 | } 32 | 33 | impl MaybeRtfOrSystem for Tf 34 | where 35 | T: ComplexFloat, 36 | B: MaybeLists, 37 | A: MaybeList 38 | { 39 | 40 | } 41 | 42 | impl MaybeRtfOrSystem for Zpk 43 | where 44 | T: ComplexFloat, 45 | K: ComplexFloat, 46 | Z: MaybeList, 47 | P: MaybeList 48 | { 49 | 50 | } 51 | 52 | impl MaybeRtfOrSystem for Ss 53 | where 54 | T: ComplexFloat, 55 | A: SsAMatrix, 56 | B: SsBMatrix, 57 | C: SsCMatrix, 58 | D: SsDMatrix 59 | { 60 | 61 | } 62 | 63 | impl MaybeRtfOrSystem for Sos 64 | where 65 | T: ComplexFloat, 66 | B: Maybe<[T; 3]> + MaybeOwnedList, 67 | A: Maybe<[T; 3]> + MaybeOwnedList, 68 | S: MaybeList> 69 | { 70 | 71 | } 72 | 73 | impl MaybeRtfOrSystem for Rpk 74 | where 75 | T: ComplexFloat, 76 | R: ComplexFloat, 77 | P: ComplexFloat, 78 | RP: MaybeList<(R, P)>, 79 | K: MaybeList 80 | { 81 | 82 | } 83 | 84 | impl MaybeRtfOrSystem for Ar 85 | where 86 | T: ComplexFloat, 87 | A: MaybeList, 88 | AV: ListOrSingle<(A, T::Real)> 89 | { 90 | 91 | } -------------------------------------------------------------------------------- /src/maybe_system.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{ 5 | quantities::{ListOrSingle, MaybeList, MaybeLists, MaybeOwnedList}, 6 | systems::{Ar, Rpk, Sos, Ss, SsAMatrix, SsBMatrix, SsCMatrix, SsDMatrix, Tf, Zpk}, 7 | MaybeRtfOrSystem 8 | }; 9 | 10 | pub trait MaybeSystem: MaybeRtfOrSystem 11 | where 12 | D: ComplexFloat 13 | { 14 | 15 | } 16 | 17 | impl MaybeSystem for () 18 | where 19 | D: ComplexFloat 20 | { 21 | 22 | } 23 | 24 | impl MaybeSystem for Tf 25 | where 26 | T: ComplexFloat, 27 | B: MaybeLists, 28 | A: MaybeList 29 | { 30 | 31 | } 32 | 33 | impl MaybeSystem for Zpk 34 | where 35 | T: ComplexFloat, 36 | K: ComplexFloat, 37 | Z: MaybeList, 38 | P: MaybeList 39 | { 40 | 41 | } 42 | 43 | impl MaybeSystem for Ss 44 | where 45 | T: ComplexFloat, 46 | A: SsAMatrix, 47 | B: SsBMatrix, 48 | C: SsCMatrix, 49 | D: SsDMatrix 50 | { 51 | 52 | } 53 | 54 | impl MaybeSystem for Sos 55 | where 56 | T: ComplexFloat, 57 | B: Maybe<[T; 3]> + MaybeOwnedList, 58 | A: Maybe<[T; 3]> + MaybeOwnedList, 59 | S: MaybeList> 60 | { 61 | 62 | } 63 | 64 | impl MaybeSystem for Rpk 65 | where 66 | T: ComplexFloat, 67 | R: ComplexFloat, 68 | P: ComplexFloat, 69 | RP: MaybeList<(R, P)>, 70 | K: MaybeList 71 | { 72 | 73 | } 74 | 75 | impl MaybeSystem for Ar 76 | where 77 | T: ComplexFloat, 78 | A: MaybeList, 79 | AV: ListOrSingle<(A, T::Real)> 80 | { 81 | 82 | } -------------------------------------------------------------------------------- /src/operations/convolution/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | cconv, 4 | conv_2d, 5 | conv, 6 | deconv 7 | } 8 | ); -------------------------------------------------------------------------------- /src/operations/decode.rs: -------------------------------------------------------------------------------- 1 | use core::ops::RangeInclusive; 2 | 3 | use num::{Bounded, Float, Integer, NumCast}; 4 | 5 | use crate::quantities::Lists; 6 | 7 | pub trait Decode: Lists 8 | where 9 | I: Integer + Bounded, 10 | T: Float 11 | { 12 | fn decode(self, dynamic_range: RangeInclusive) -> Self::Mapped; 13 | } 14 | 15 | impl Decode for L 16 | where 17 | I: Integer + Bounded + NumCast + Clone, 18 | T: Float, 19 | L: Lists 20 | { 21 | fn decode(self, dynamic_range: RangeInclusive) -> Self::Mapped 22 | { 23 | let one = T::one(); 24 | 25 | let imax = T::from(I::max_value()) 26 | .map(|m| m + one) 27 | .unwrap_or_else(T::max_value); 28 | let imin = T::from(I::min_value()) 29 | .unwrap_or_else(T::min_value); 30 | 31 | self.map_into_owned(|y| { 32 | let y = T::from(y).unwrap(); 33 | (y - imin)/(imax - imin)*(*dynamic_range.end() - *dynamic_range.start()) + *dynamic_range.start() 34 | }) 35 | } 36 | } -------------------------------------------------------------------------------- /src/operations/filtering/filter.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{util::ComplexOp, operations::filtering::FilterMut, quantities::Lists, systems::Rtf, RtfOrSystem, System}; 5 | 6 | pub trait Filter: System 7 | where 8 | Self::Set: ComplexOp, 9 | X: Into<>::Output> + ComplexFloat::Real>, 10 | XX: Lists 11 | { 12 | type Output: Lists<>::Output>; 13 | 14 | fn filter>::Output>>>(self, x: XX, w: W) -> Self::Output; 15 | } 16 | 17 | impl Filter for S 18 | where 19 | S: System, 20 | S::Set: ComplexOp, 21 | X: Into + ComplexFloat, 22 | XX: Lists, 23 | W: ComplexOp + ComplexFloat::Real>, 24 | Rtf: FilterMut + RtfOrSystem, 25 | O: Lists 26 | { 27 | type Output = O; 28 | 29 | fn filter>>(self, x: XX, w: WW) -> Self::Output 30 | { 31 | Rtf::::new(self, w) 32 | .filter_mut(x) 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod test 38 | { 39 | use array_math::ArrayOps; 40 | use linspace::LinspaceArray; 41 | use rand::distributions::uniform::SampleRange; 42 | 43 | use crate::{plot, gen::filter::{Butter, FilterGenPlane, FilterGenType}, operations::filtering::Filter, systems::Ss}; 44 | 45 | #[test] 46 | fn test() 47 | { 48 | let h: Ss:: = Ss::butter(4, [0.2], FilterGenType::LowPass, FilterGenPlane::Z { sampling_frequency: None }) 49 | .unwrap(); 50 | 51 | const N: usize = 64; 52 | let mut rng = rand::thread_rng(); 53 | let x: [f64; N] = ArrayOps::fill(|_| (-1.0..1.0).sample_single(&mut rng)); 54 | 55 | let y = Filter::::filter(h, x, ()); 56 | 57 | let t: [_; N] = (0.0..N as f64).linspace_array(); 58 | 59 | plot::plot_curves("x(t), y(t)", "plots/xy_t_filter.png", [&t.zip(x), &t.zip(y[0])]) 60 | .unwrap() 61 | } 62 | } -------------------------------------------------------------------------------- /src/operations/filtering/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | fftfilt, 4 | filter_mut, 5 | filter, 6 | filtfilt, 7 | sgolayfilt 8 | } 9 | ); -------------------------------------------------------------------------------- /src/operations/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | pub mod { 3 | convolution, 4 | filtering, 5 | resampling 6 | }, 7 | flat(pub) mod { 8 | decode, 9 | encode, 10 | simplify, 11 | window 12 | } 13 | ); -------------------------------------------------------------------------------- /src/operations/resampling/downsample.rs: -------------------------------------------------------------------------------- 1 | use array_math::max_len; 2 | use option_trait::Maybe; 3 | 4 | use crate::quantities::{List, ListOrSingle, Lists}; 5 | 6 | pub trait Downsample: Lists 7 | where 8 | N: Maybe, 9 | Y: List 10 | { 11 | fn downsample(self, n: N, phase: usize) -> Self::RowsMapped; 12 | } 13 | 14 | impl Downsample> for L 15 | where 16 | L: Lists>, 17 | T: Clone 18 | { 19 | fn downsample(self, n: usize, mut phase: usize) -> Self::RowsMapped> 20 | { 21 | phase %= n; 22 | 23 | self.map_rows_into_owned(|x| { 24 | x.into_vec() 25 | .into_iter() 26 | .skip(phase) 27 | .step_by(n) 28 | .collect() 29 | }) 30 | } 31 | } 32 | 33 | impl Downsample for L 34 | where 35 | L: Lists, Width = usize>, 36 | T: Clone, 37 | [(); 0 - L::WIDTH % max_len(N, 1)]: 38 | { 39 | fn downsample(self, (): (), mut phase: usize) -> Self::RowsMapped<[T; N]> 40 | { 41 | let n = L::WIDTH/max_len(N, 1); 42 | phase %= n; 43 | 44 | self.map_rows_into_owned(|x| { 45 | x.into_vec() 46 | .into_iter() 47 | .skip(phase) 48 | .step_by(n) 49 | .collect::>() 50 | .try_into() 51 | .ok() 52 | .unwrap() 53 | }) 54 | } 55 | } -------------------------------------------------------------------------------- /src/operations/resampling/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | decimate, 4 | downsample, 5 | interp, 6 | resample, 7 | upsample_fill, 8 | upsample 9 | } 10 | ); -------------------------------------------------------------------------------- /src/operations/resampling/upsample.rs: -------------------------------------------------------------------------------- 1 | use array_math::max_len; 2 | use num::Zero; 3 | use option_trait::Maybe; 4 | 5 | use crate::quantities::{List, ListOrSingle, Lists}; 6 | 7 | pub trait Upsample: Lists 8 | where 9 | N: Maybe, 10 | Y: List 11 | { 12 | fn upsample(self, n: N, phase: usize) -> Self::RowsMapped; 13 | } 14 | 15 | impl Upsample> for L 16 | where 17 | L: Lists>, 18 | T: Copy + Zero 19 | { 20 | fn upsample(self, n: usize, mut phase: usize) -> Self::RowsMapped> 21 | { 22 | phase %= n; 23 | 24 | let zero = T::zero(); 25 | 26 | self.map_rows_into_owned(|x| { 27 | x.into_vec() 28 | .into_iter() 29 | .flat_map(|x| { 30 | let mut y = vec![zero; n]; 31 | if let Some(y) = y.get_mut(phase) 32 | { 33 | *y = x 34 | } 35 | y 36 | }).collect() 37 | }) 38 | } 39 | } 40 | 41 | impl Upsample for L 42 | where 43 | L: Lists, Width = usize>, 44 | T: Copy + Zero, 45 | [(); 0 - N % max_len(L::WIDTH, 1)]: 46 | { 47 | fn upsample(self, (): (), mut phase: usize) -> Self::RowsMapped<[T; N]> 48 | { 49 | let n = N / L::WIDTH.max(1); 50 | phase %= n; 51 | 52 | let zero = T::zero(); 53 | 54 | self.map_rows_into_owned(|x| { 55 | x.into_vec() 56 | .into_iter() 57 | .flat_map(|x| { 58 | let mut y = vec![zero; n]; 59 | if let Some(y) = y.get_mut(phase) 60 | { 61 | *y = x 62 | } 63 | y 64 | }).collect::>() 65 | .try_into() 66 | .ok() 67 | .unwrap() 68 | }) 69 | } 70 | } -------------------------------------------------------------------------------- /src/operations/resampling/upsample_fill.rs: -------------------------------------------------------------------------------- 1 | use crate::quantities::{List, ListOrSingle, Lists}; 2 | 3 | pub trait UpsampleFill: Lists 4 | where 5 | V: List, 6 | Y: List 7 | { 8 | fn upsample_fill(self, interleave: V, phase: usize) -> Self::RowsMapped; 9 | } 10 | 11 | impl UpsampleFill> for L 12 | where 13 | V: List, 14 | L: Lists>, 15 | T: Clone 16 | { 17 | fn upsample_fill(self, interleave: V, mut phase: usize) -> Self::RowsMapped> 18 | { 19 | let interleave = interleave.into_vec(); 20 | 21 | phase %= interleave.len() + 1; 22 | 23 | self.map_rows_into_owned(|x| { 24 | x.into_vec() 25 | .into_iter() 26 | .flat_map(|x| { 27 | let mut y = interleave.clone(); 28 | y.insert(phase, x); 29 | y 30 | }).collect() 31 | }) 32 | } 33 | } 34 | 35 | impl UpsampleFill for L 36 | where 37 | V: List, 38 | L: Lists, Width = usize>, 39 | T: Clone 40 | { 41 | fn upsample_fill(self, interleave: V, mut phase: usize) -> Self::RowsMapped<[T; L::WIDTH*(V::WIDTH + 1)]> 42 | { 43 | let interleave = interleave.into_vec(); 44 | 45 | phase %= interleave.len() + 1; 46 | 47 | self.map_rows_into_owned(|x| { 48 | x.into_vec() 49 | .into_iter() 50 | .flat_map(|x| { 51 | let mut y = interleave.clone(); 52 | y.insert(phase, x); 53 | y 54 | }).collect::>() 55 | .try_into() 56 | .ok() 57 | .unwrap() 58 | }) 59 | } 60 | } -------------------------------------------------------------------------------- /src/quantities/matrix.rs: -------------------------------------------------------------------------------- 1 | use ndarray::{Array1, Array2, ArrayView1, ArrayView2}; 2 | 3 | use crate::quantities::{Lists, MaybeMatrix, MatrixOrSingle}; 4 | 5 | pub trait Matrix: Lists + MaybeMatrix + MatrixOrSingle 6 | { 7 | 8 | } 9 | 10 | impl Matrix for Vec 11 | { 12 | 13 | } 14 | impl Matrix for [T] 15 | { 16 | 17 | } 18 | impl Matrix for [T; N] 19 | { 20 | 21 | } 22 | impl Matrix for &[T] 23 | { 24 | 25 | } 26 | impl Matrix for &[T; N] 27 | { 28 | 29 | } 30 | 31 | impl Matrix for [[T; N]; M] 32 | { 33 | 34 | } 35 | impl Matrix for &[[T; N]; M] 36 | { 37 | 38 | } 39 | 40 | impl Matrix for [&[T; N]; M] 41 | { 42 | 43 | } 44 | impl Matrix for &[&[T; N]; M] 45 | { 46 | 47 | } 48 | 49 | impl Matrix for Vec<[T; N]> 50 | { 51 | 52 | } 53 | impl Matrix for &[[T; N]] 54 | { 55 | 56 | } 57 | impl Matrix for [[T; N]] 58 | { 59 | 60 | } 61 | 62 | impl Matrix for Vec<&[T; N]> 63 | { 64 | 65 | } 66 | impl Matrix for &[&[T; N]] 67 | { 68 | 69 | } 70 | impl Matrix for [&[T; N]] 71 | { 72 | 73 | } 74 | 75 | impl Matrix for Array1 76 | { 77 | 78 | } 79 | impl<'b, T> Matrix for ArrayView1<'b, T> 80 | { 81 | 82 | } 83 | 84 | impl Matrix for Array2 85 | { 86 | 87 | } 88 | impl<'b, T> Matrix for ArrayView2<'b, T> 89 | { 90 | 91 | } -------------------------------------------------------------------------------- /src/quantities/maybe_owned_list.rs: -------------------------------------------------------------------------------- 1 | use ndarray::Array1; 2 | use option_trait::StaticMaybe; 3 | 4 | use crate::quantities::{MaybeList, OwnedListOrSingle}; 5 | 6 | use super::{ListOrSingle, MaybeContainer}; 7 | 8 | pub trait MaybeOwnedList: MaybeList + Sized 9 | { 10 | fn maybe_from_len_fn(n: <<>::Some as ListOrSingle>::Length as StaticMaybe>::Opposite, f: F) -> Self 11 | where 12 | Self: MaybeContainer>>, 13 | F: FnMut(usize) -> T; 14 | 15 | fn as_mut_slice_option(&mut self) -> Option<&'_ mut [T]>; 16 | } 17 | 18 | impl MaybeOwnedList for () 19 | { 20 | fn maybe_from_len_fn(_: <<>::Some as ListOrSingle>::Length as StaticMaybe>::Opposite, _: F) -> Self 21 | where 22 | Self: MaybeContainer>>, 23 | F: FnMut(usize) -> T 24 | { 25 | 26 | } 27 | fn as_mut_slice_option(&mut self) -> Option<&'_ mut [T]> 28 | { 29 | None 30 | } 31 | } 32 | 33 | impl MaybeOwnedList for Vec 34 | { 35 | fn maybe_from_len_fn(n: <>::Length as StaticMaybe>::Opposite, f: F) -> Self 36 | where 37 | F: FnMut(usize) -> T 38 | { 39 | Self::from_len_fn(n, f) 40 | } 41 | fn as_mut_slice_option(&mut self) -> Option<&'_ mut [T]> 42 | { 43 | Some(self.as_mut_slice()) 44 | } 45 | } 46 | impl MaybeOwnedList for [T; N] 47 | { 48 | fn maybe_from_len_fn(n: <>::Length as StaticMaybe>::Opposite, f: F) -> Self 49 | where 50 | F: FnMut(usize) -> T 51 | { 52 | Self::from_len_fn(n, f) 53 | } 54 | fn as_mut_slice_option(&mut self) -> Option<&'_ mut [T]> 55 | { 56 | Some(self.as_mut_slice()) 57 | } 58 | } 59 | 60 | impl MaybeOwnedList for Array1 61 | { 62 | fn maybe_from_len_fn(n: <>::Length as StaticMaybe>::Opposite, f: F) -> Self 63 | where 64 | F: FnMut(usize) -> T 65 | { 66 | Self::from_len_fn(n, f) 67 | } 68 | fn as_mut_slice_option(&mut self) -> Option<&'_ mut [T]> 69 | { 70 | Some(self.as_mut_slice()) 71 | } 72 | } -------------------------------------------------------------------------------- /src/quantities/maybe_owned_matrix.rs: -------------------------------------------------------------------------------- 1 | use ndarray::{Array1, Array2}; 2 | 3 | use crate::quantities::{MaybeMatrix, MaybeOwnedLists}; 4 | 5 | pub trait MaybeOwnedMatrix: MaybeMatrix + MaybeOwnedLists 6 | { 7 | 8 | } 9 | 10 | impl MaybeOwnedMatrix for () 11 | { 12 | 13 | } 14 | 15 | impl MaybeOwnedMatrix for Vec 16 | { 17 | 18 | } 19 | impl MaybeOwnedMatrix for [T; N] 20 | { 21 | 22 | } 23 | 24 | impl MaybeOwnedMatrix for [[T; N]; M] 25 | { 26 | 27 | } 28 | impl MaybeOwnedMatrix for Vec<[T; N]> 29 | { 30 | 31 | } 32 | 33 | impl MaybeOwnedMatrix for Array1 34 | { 35 | 36 | } 37 | 38 | impl MaybeOwnedMatrix for Array2 39 | { 40 | 41 | } -------------------------------------------------------------------------------- /src/quantities/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | container_or_single, 4 | container, 5 | into_list, 6 | list_or_single, 7 | list, 8 | lists_or_single, 9 | lists, 10 | matrix_or_single, 11 | matrix, 12 | maybe_container, 13 | maybe_list, 14 | maybe_lists, 15 | maybe_matrix, 16 | maybe_owned_list, 17 | maybe_owned_lists, 18 | maybe_owned_matrix, 19 | owned_list_or_single, 20 | owned_list, 21 | owned_lists, 22 | owned_matrix, 23 | polynomial, 24 | product_sequence, 25 | sum_sequence 26 | } 27 | ); -------------------------------------------------------------------------------- /src/quantities/owned_list.rs: -------------------------------------------------------------------------------- 1 | use ndarray::Array1; 2 | 3 | use crate::quantities::{List, OwnedListOrSingle}; 4 | 5 | use super::OwnedLists; 6 | 7 | pub trait OwnedList: List + OwnedListOrSingle + OwnedLists 8 | { 9 | 10 | } 11 | 12 | impl OwnedList for Vec 13 | { 14 | 15 | } 16 | impl OwnedList for [T; N] 17 | { 18 | 19 | } 20 | 21 | impl OwnedList for Array1 22 | { 23 | 24 | } -------------------------------------------------------------------------------- /src/quantities/owned_list_or_single.rs: -------------------------------------------------------------------------------- 1 | use ndarray::Array1; 2 | use option_trait::StaticMaybe; 3 | 4 | use crate::quantities::ListOrSingle; 5 | 6 | pub trait OwnedListOrSingle: ListOrSingle + Sized 7 | { 8 | fn from_len_fn(n: >::Opposite, f: F) -> Self 9 | where 10 | F: FnMut(usize) -> T; 11 | fn as_mut_slice(&mut self) -> &'_ mut [T]; 12 | } 13 | 14 | impl OwnedListOrSingle for T 15 | { 16 | fn from_len_fn((): >::Opposite, mut f: F) -> Self 17 | where 18 | F: FnMut(usize) -> T 19 | { 20 | f(0) 21 | } 22 | fn as_mut_slice(&mut self) -> &'_ mut [T] 23 | { 24 | core::slice::from_mut(self) 25 | } 26 | } 27 | 28 | impl OwnedListOrSingle for Vec 29 | { 30 | fn from_len_fn(n: >::Opposite, f: F) -> Self 31 | where 32 | F: FnMut(usize) -> T 33 | { 34 | (0..n).map(f) 35 | .collect() 36 | } 37 | fn as_mut_slice(&mut self) -> &'_ mut [T] 38 | { 39 | self 40 | } 41 | } 42 | impl OwnedListOrSingle for [T; N] 43 | { 44 | fn from_len_fn((): >::Opposite, f: F) -> Self 45 | where 46 | F: FnMut(usize) -> T 47 | { 48 | core::array::from_fn(f) 49 | } 50 | fn as_mut_slice(&mut self) -> &'_ mut [T] 51 | { 52 | self.as_mut_slice() 53 | } 54 | } 55 | 56 | impl OwnedListOrSingle for Array1 57 | { 58 | fn from_len_fn(n: >::Opposite, f: F) -> Self 59 | where 60 | F: FnMut(usize) -> T 61 | { 62 | Self::from_shape_fn(n, f) 63 | } 64 | fn as_mut_slice(&mut self) -> &'_ mut [T] 65 | { 66 | self.as_slice_mut().unwrap() 67 | } 68 | } -------------------------------------------------------------------------------- /src/quantities/owned_matrix.rs: -------------------------------------------------------------------------------- 1 | use ndarray::{Array1, Array2}; 2 | 3 | use crate::quantities::{Matrix, MaybeOwnedMatrix, OwnedLists}; 4 | 5 | pub trait OwnedMatrix: Matrix + OwnedLists + MaybeOwnedMatrix 6 | { 7 | 8 | } 9 | 10 | impl OwnedMatrix for Vec 11 | { 12 | 13 | } 14 | impl OwnedMatrix for [T; N] 15 | { 16 | 17 | } 18 | 19 | impl OwnedMatrix for [[T; N]; M] 20 | { 21 | 22 | } 23 | impl OwnedMatrix for Vec<[T; N]> 24 | { 25 | 26 | } 27 | 28 | impl OwnedMatrix for Array1 29 | { 30 | 31 | } 32 | 33 | impl OwnedMatrix for Array2 34 | { 35 | 36 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/add_assign.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, AddAssign}; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl AddAssign for Polynomial 6 | where 7 | C: MaybeLists, 8 | for<'a> C::View<'a>: MaybeLists, 9 | for<'a> Polynomial>: Add 10 | { 11 | fn add_assign(&mut self, rhs: Rhs) 12 | { 13 | *self = self.as_view() + rhs 14 | } 15 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/borrow.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::Borrow; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl Borrow for Polynomial 6 | where 7 | C: MaybeLists 8 | { 9 | fn borrow(&self) -> &C 10 | { 11 | &self.c 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/borrow_mut.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::BorrowMut; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl BorrowMut for Polynomial 6 | where 7 | C: MaybeLists 8 | { 9 | fn borrow_mut(&mut self) -> &mut C 10 | { 11 | &mut self.c 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/debug.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl Debug for Polynomial 6 | where 7 | C: MaybeLists + Debug 8 | { 9 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 10 | { 11 | self.c.fmt(f) 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/deref.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Deref; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl Deref for Polynomial 6 | where 7 | C: MaybeLists 8 | { 9 | type Target = C; 10 | 11 | fn deref(&self) -> &Self::Target 12 | { 13 | &self.c 14 | } 15 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/deref_mut.rs: -------------------------------------------------------------------------------- 1 | use core::ops::DerefMut; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl DerefMut for Polynomial 6 | where 7 | C: MaybeLists 8 | { 9 | fn deref_mut(&mut self) -> &mut Self::Target 10 | { 11 | &mut self.c 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/eq.rs: -------------------------------------------------------------------------------- 1 | use crate::quantities::{MaybeLists, Polynomial}; 2 | 3 | impl Eq for Polynomial 4 | where 5 | C: MaybeLists, 6 | T: Eq, 7 | Self: PartialEq 8 | { 9 | 10 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/fn.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{AddAssign, MulAssign}; 2 | 3 | use array_math::SliceMath; 4 | use num::{One, Zero}; 5 | 6 | use crate::quantities::{MaybeList, MaybeLists, Polynomial}; 7 | 8 | impl FnOnce<(X,)> for Polynomial 9 | where 10 | C: MaybeLists, 11 | T: One + Zero + AddAssign + MulAssign + Copy, 12 | X: Copy 13 | { 14 | type Output = C::RowsMapped; 15 | 16 | extern "rust-call" fn call_once(self, args: (X,)) -> Self::Output 17 | { 18 | self.call(args) 19 | } 20 | } 21 | 22 | impl FnMut<(X,)> for Polynomial 23 | where 24 | C: MaybeLists, 25 | T: One + Zero + AddAssign + MulAssign + Copy, 26 | X: Copy 27 | { 28 | extern "rust-call" fn call_mut(&mut self, args: (X,)) -> Self::Output 29 | { 30 | self.call(args) 31 | } 32 | } 33 | 34 | impl Fn<(X,)> for Polynomial 35 | where 36 | C: MaybeLists, 37 | T: One + Zero + AddAssign + MulAssign + Copy, 38 | X: Copy 39 | { 40 | extern "rust-call" fn call(&self, (x,): (X,)) -> Self::Output 41 | { 42 | self.map_rows_to_owned(|p| p.as_view_slice_option() 43 | .map(|p| p.rpolynomial(x)) 44 | .unwrap_or_else(One::one) 45 | ) 46 | } 47 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/mul_assign.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Mul, MulAssign}; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl MulAssign for Polynomial 6 | where 7 | C: MaybeLists, 8 | for<'a> C::View<'a>: MaybeLists, 9 | for<'a> Polynomial>: Mul 10 | { 11 | fn mul_assign(&mut self, rhs: Rhs) 12 | { 13 | *self = self.as_view()*rhs 14 | } 15 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/neg.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Neg; 2 | 3 | use array_math::ArrayOps; 4 | 5 | use crate::quantities::Polynomial; 6 | 7 | macro_rules! impl_neg { 8 | (($(<$($a:lifetime),* $(,)? $($c:ident),* >)?) $s:ty [$n:tt] $(where $($w:tt)*)?) => { 9 | impl<$($($a,)* $(const $c: usize,)*)? T> Neg for Polynomial 10 | where 11 | Polynomial::: From> + Neg, 12 | $($($w)*)? 13 | { 14 | type Output = as Neg>::Output; 15 | 16 | fn neg(self) -> Self::Output 17 | { 18 | -Polynomial::::from(self) 19 | } 20 | } 21 | }; 22 | (($(<$($a:lifetime),* $(,)? $($c:ident),* >)?) $s:ty $(where $($w:tt)*)?) => { 23 | impl<$($($a,)* $(const $c: usize,)*)? T> Neg for Polynomial 24 | where 25 | Polynomial::>: From> + Neg, 26 | $($($w)*)? 27 | { 28 | type Output = > as Neg>::Output; 29 | 30 | fn neg(self) -> Self::Output 31 | { 32 | -Polynomial::>::from(self) 33 | } 34 | } 35 | }; 36 | } 37 | 38 | impl_neg!(() () [1]); 39 | impl Neg for Polynomial 40 | where 41 | T: Neg 42 | { 43 | type Output = Polynomial<::Output, [::Output; N]>; 44 | 45 | fn neg(self) -> Self::Output 46 | { 47 | Polynomial::new(self.c.neg_all()) 48 | } 49 | } 50 | impl_neg!((<'a, N>) &'a [T; N] [N]); 51 | impl Neg for Polynomial> 52 | where 53 | T: Neg 54 | { 55 | type Output = Polynomial<::Output, Vec<::Output>>; 56 | 57 | fn neg(self) -> Self::Output 58 | { 59 | Polynomial::new( 60 | self.c.into_iter() 61 | .map(|c| -c) 62 | .collect() 63 | ) 64 | } 65 | } 66 | impl_neg!((<'a>) &'a [T]); -------------------------------------------------------------------------------- /src/quantities/polynomial/one.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Mul; 2 | 3 | 4 | use num::{One}; 5 | 6 | use crate::quantities::Polynomial; 7 | 8 | impl One for Polynomial> 9 | where 10 | Self: Mul, 11 | Polynomial: Into 12 | { 13 | fn one() -> Self 14 | { 15 | Polynomial::new(()).into() 16 | } 17 | } 18 | impl One for Polynomial 19 | where 20 | Self: Mul, 21 | Polynomial: Into 22 | { 23 | fn one() -> Self 24 | { 25 | Polynomial::new(()).into() 26 | } 27 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/partial_eq.rs: -------------------------------------------------------------------------------- 1 | use array_math::SliceMath; 2 | use num::Zero; 3 | 4 | use crate::quantities::{MaybeLists, Polynomial}; 5 | 6 | impl PartialEq> for Polynomial 7 | where 8 | T: Zero + PartialEq, 9 | C1: MaybeLists, 10 | C2: MaybeLists 11 | { 12 | fn eq(&self, other: &Polynomial) -> bool 13 | { 14 | let a = self.as_view_slices_option(); 15 | let b = other.as_view_slices_option(); 16 | 17 | if a.is_some() != b.is_some() 18 | { 19 | return false 20 | } 21 | 22 | if let Some(a) = a && let Some(b) = b 23 | { 24 | if a.len() != b.len() 25 | { 26 | return false 27 | } 28 | 29 | return a.into_iter() 30 | .zip(b.into_iter()) 31 | .all(|(a, b)| a.trim_zeros_front() == b.trim_zeros_front()) 32 | } 33 | true 34 | } 35 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/pow.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{BitAnd, Mul, Shr}; 2 | 3 | use num::{pow::Pow, Integer, One, Unsigned}; 4 | 5 | use crate::quantities::{MaybeList, Polynomial}; 6 | 7 | impl Pow for Polynomial 8 | where 9 | T: Clone + One, 10 | S: MaybeList, 11 | I: Unsigned + Integer + BitAnd + Shr + Copy, 12 | Self: Into>>, 13 | Polynomial>: Mul>, Output = Polynomial>> 14 | { 15 | type Output = Polynomial>; 16 | 17 | fn pow(self, mut n: I) -> Self::Output 18 | { 19 | let mut x = self.into(); 20 | let mut r = if (n & I::one()) == I::one() 21 | { 22 | x.clone() 23 | } 24 | else 25 | { 26 | Polynomial::one() 27 | }; 28 | 29 | loop 30 | { 31 | n = n >> 1usize; 32 | if n == I::zero() 33 | { 34 | break; 35 | } 36 | x = x.clone()*x.clone(); 37 | if (n & I::one()) == I::one() 38 | { 39 | r = r*x.clone(); 40 | } 41 | } 42 | 43 | r 44 | } 45 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/product.rs: -------------------------------------------------------------------------------- 1 | use core::iter::Product; 2 | 3 | use num::One; 4 | 5 | use crate::quantities::{MaybeLists, Polynomial}; 6 | 7 | impl Product> for Polynomial 8 | where 9 | C1: MaybeLists, 10 | C2: MaybeLists, 11 | Polynomial: Into, 12 | Self: One 13 | { 14 | fn product>>(iter: I) -> Self 15 | { 16 | iter.map(|p| p.into()) 17 | .reduce(|a, b| a*b) 18 | .unwrap_or_else(One::one) 19 | } 20 | } -------------------------------------------------------------------------------- /src/quantities/polynomial/sub_assign.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Sub, SubAssign}; 2 | 3 | use crate::quantities::{MaybeLists, Polynomial}; 4 | 5 | impl SubAssign for Polynomial 6 | where 7 | C: MaybeLists, 8 | for<'a> C::View<'a>: MaybeLists, 9 | for<'a> Polynomial>: Sub 10 | { 11 | fn sub_assign(&mut self, rhs: Rhs) 12 | { 13 | *self = self.as_view() - rhs 14 | } 15 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/borrow.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::Borrow; 2 | 3 | use crate::quantities::{MaybeList, ProductSequence}; 4 | 5 | impl Borrow for ProductSequence 6 | where 7 | S: MaybeList 8 | { 9 | fn borrow(&self) -> &S 10 | { 11 | &self.s 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/borrow_mut.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::BorrowMut; 2 | 3 | use crate::quantities::{MaybeList, ProductSequence}; 4 | 5 | impl BorrowMut for ProductSequence 6 | where 7 | S: MaybeList 8 | { 9 | fn borrow_mut(&mut self) -> &mut S 10 | { 11 | &mut self.s 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/debug.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | 3 | use crate::quantities::{MaybeList, ProductSequence}; 4 | 5 | impl Debug for ProductSequence 6 | where 7 | S: MaybeList + Debug 8 | { 9 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 10 | { 11 | self.s.fmt(f) 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/default.rs: -------------------------------------------------------------------------------- 1 | use crate::quantities::{MaybeList, ProductSequence}; 2 | 3 | impl Default for ProductSequence 4 | where 5 | S: MaybeList, 6 | ProductSequence: Into 7 | { 8 | fn default() -> Self 9 | { 10 | ProductSequence::new(()).into() 11 | } 12 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/deref.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Deref; 2 | 3 | use crate::quantities::{MaybeList, ProductSequence}; 4 | 5 | impl Deref for ProductSequence 6 | where 7 | S: MaybeList 8 | { 9 | type Target = S; 10 | 11 | fn deref(&self) -> &Self::Target 12 | { 13 | &self.s 14 | } 15 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/deref_mut.rs: -------------------------------------------------------------------------------- 1 | use core::ops::DerefMut; 2 | 3 | use crate::quantities::{MaybeList, ProductSequence}; 4 | 5 | impl DerefMut for ProductSequence 6 | where 7 | S: MaybeList 8 | { 9 | fn deref_mut(&mut self) -> &mut Self::Target 10 | { 11 | &mut self.s 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/mul.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Mul; 2 | 3 | use crate::{quantities::{MaybeList, ProductSequence}, util::Chain}; 4 | 5 | impl Mul> for ProductSequence 6 | where 7 | S1: MaybeList + Chain>, 8 | S2: MaybeList 9 | { 10 | type Output = ProductSequence>::Output>; 11 | 12 | fn mul(self, rhs: ProductSequence) -> Self::Output 13 | { 14 | ProductSequence::new( 15 | self.s.chain(rhs.s) 16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/one.rs: -------------------------------------------------------------------------------- 1 | use core::{iter::Product, ops::Mul}; 2 | 3 | use num::One; 4 | 5 | use crate::quantities::{MaybeList, ProductSequence}; 6 | 7 | impl One for ProductSequence 8 | where 9 | T: Clone + Product + One + PartialEq, 10 | S: MaybeList, 11 | Self: Mul, 12 | ProductSequence: Into 13 | { 14 | fn one() -> Self 15 | { 16 | ProductSequence::new(()).into() 17 | } 18 | fn is_one(&self) -> bool 19 | where 20 | Self: PartialEq 21 | { 22 | self.is_one() 23 | } 24 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/pow.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{BitAnd, Shr}; 2 | 3 | use num::{pow::Pow, Integer, Unsigned}; 4 | 5 | use crate::quantities::{MaybeList, ProductSequence}; 6 | 7 | impl Pow for ProductSequence 8 | where 9 | T: Clone, 10 | S: MaybeList, 11 | I: Unsigned + Integer + BitAnd + Shr + Copy, 12 | Self: Into>> 13 | { 14 | type Output = ProductSequence>; 15 | 16 | fn pow(self, mut n: I) -> Self::Output 17 | { 18 | let mut x = self.into(); 19 | let mut r = if (n & I::one()) == I::one() 20 | { 21 | x.clone() 22 | } 23 | else 24 | { 25 | ProductSequence::one() 26 | }; 27 | 28 | loop 29 | { 30 | n = n >> 1usize; 31 | if n == I::zero() 32 | { 33 | break; 34 | } 35 | x = x.as_view()*x.as_view(); 36 | if (n & I::one()) == I::one() 37 | { 38 | r = r*x.as_view(); 39 | } 40 | } 41 | 42 | r 43 | } 44 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/product.rs: -------------------------------------------------------------------------------- 1 | use core::iter::Product; 2 | 3 | use num::One; 4 | 5 | use crate::quantities::{MaybeList, ProductSequence}; 6 | 7 | impl Product> for ProductSequence 8 | where 9 | S1: MaybeList, 10 | S2: MaybeList, 11 | ProductSequence: Into>, 12 | ProductSequence: One 13 | { 14 | fn product>>(iter: I) -> Self 15 | { 16 | iter.map(Into::into) 17 | .reduce(|a, b| a*b) 18 | .unwrap_or_else(One::one) 19 | } 20 | } -------------------------------------------------------------------------------- /src/quantities/product_sequence/try_from.rs: -------------------------------------------------------------------------------- 1 | use core::array::TryFromSliceError; 2 | 3 | use crate::quantities::ProductSequence; 4 | 5 | impl TryFrom>> for ProductSequence 6 | where 7 | T1: Into 8 | { 9 | type Error = Vec; 10 | 11 | fn try_from(s: ProductSequence>) -> Result 12 | { 13 | Ok(ProductSequence::new( 14 | <[T1; M]>::try_from(s.s)? 15 | .map(Into::into) 16 | )) 17 | } 18 | } 19 | impl TryFrom> for ProductSequence 20 | where 21 | T1: Clone + Into 22 | { 23 | type Error = TryFromSliceError; 24 | 25 | fn try_from(s: ProductSequence) -> Result 26 | { 27 | Ok(ProductSequence::new( 28 | <&[T1; M]>::try_from(s.s)? 29 | .clone() 30 | .map(Into::into) 31 | )) 32 | } 33 | } 34 | impl<'a, T, const M: usize> TryFrom> for ProductSequence 35 | { 36 | type Error = TryFromSliceError; 37 | 38 | fn try_from(s: ProductSequence) -> Result 39 | { 40 | Ok(ProductSequence::new( 41 | <&'a [T; M]>::try_from(s.s)? 42 | )) 43 | } 44 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/add.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Add; 2 | 3 | use crate::{util::Chain, quantities::{MaybeList, SumSequence}}; 4 | 5 | impl Add> for SumSequence 6 | where 7 | S1: MaybeList + Chain>, 8 | S2: MaybeList 9 | { 10 | type Output = SumSequence>::Output>; 11 | 12 | fn add(self, rhs: SumSequence) -> Self::Output 13 | { 14 | SumSequence::new( 15 | self.s.chain(rhs.s) 16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/borrow.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::Borrow; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl Borrow for SumSequence 6 | where 7 | S: MaybeList 8 | { 9 | fn borrow(&self) -> &S 10 | { 11 | &self.s 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/borrow_mut.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::BorrowMut; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl BorrowMut for SumSequence 6 | where 7 | S: MaybeList 8 | { 9 | fn borrow_mut(&mut self) -> &mut S 10 | { 11 | &mut self.s 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/debug.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl Debug for SumSequence 6 | where 7 | S: MaybeList + Debug 8 | { 9 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 10 | { 11 | self.s.fmt(f) 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/default.rs: -------------------------------------------------------------------------------- 1 | use crate::quantities::{MaybeList, SumSequence}; 2 | 3 | impl Default for SumSequence 4 | where 5 | S: MaybeList, 6 | SumSequence: Into 7 | { 8 | fn default() -> Self 9 | { 10 | SumSequence::new(()).into() 11 | } 12 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/deref.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Deref; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl Deref for SumSequence 6 | where 7 | S: MaybeList 8 | { 9 | type Target = S; 10 | 11 | fn deref(&self) -> &Self::Target 12 | { 13 | &self.s 14 | } 15 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/deref_mut.rs: -------------------------------------------------------------------------------- 1 | use core::ops::DerefMut; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl DerefMut for SumSequence 6 | where 7 | S: MaybeList 8 | { 9 | fn deref_mut(&mut self) -> &mut Self::Target 10 | { 11 | &mut self.s 12 | } 13 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/neg.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Neg; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl Neg for SumSequence 6 | where 7 | T: Neg + Clone, 8 | S: MaybeList, 9 | S::MaybeMapped<::Output>: MaybeList<::Output> 10 | { 11 | type Output = SumSequence<::Output, S::MaybeMapped<::Output>>; 12 | 13 | fn neg(self) -> Self::Output 14 | { 15 | SumSequence::new( 16 | self.into_inner() 17 | .maybe_map_into_owned(Neg::neg) 18 | ) 19 | } 20 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/sub.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Neg, Sub}; 2 | 3 | use crate::quantities::{MaybeList, SumSequence}; 4 | 5 | impl Sub> for SumSequence 6 | where 7 | S1: MaybeList, 8 | S2: MaybeList, 9 | S3: MaybeList, 10 | SumSequence: Neg>, 11 | Self: Add> 12 | { 13 | type Output = >>::Output; 14 | 15 | fn sub(self, rhs: SumSequence) -> Self::Output 16 | { 17 | self + (-rhs) 18 | } 19 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/sum.rs: -------------------------------------------------------------------------------- 1 | use core::iter::Sum; 2 | 3 | use num::Zero; 4 | 5 | use crate::quantities::{MaybeList, SumSequence}; 6 | 7 | impl Sum> for SumSequence 8 | where 9 | S1: MaybeList, 10 | S2: MaybeList, 11 | SumSequence: Into>, 12 | SumSequence: Zero 13 | { 14 | fn sum>>(iter: I) -> Self 15 | { 16 | iter.map(Into::into) 17 | .reduce(|a, b| a + b) 18 | .unwrap_or_else(Zero::zero) 19 | } 20 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/try_from.rs: -------------------------------------------------------------------------------- 1 | use core::array::TryFromSliceError; 2 | 3 | use crate::quantities::SumSequence; 4 | 5 | impl TryFrom>> for SumSequence 6 | where 7 | T1: Into 8 | { 9 | type Error = Vec; 10 | 11 | fn try_from(s: SumSequence>) -> Result 12 | { 13 | Ok(SumSequence::new( 14 | <[T1; M]>::try_from(s.s)? 15 | .map(Into::into) 16 | )) 17 | } 18 | } 19 | impl TryFrom> for SumSequence 20 | where 21 | T1: Clone + Into 22 | { 23 | type Error = TryFromSliceError; 24 | 25 | fn try_from(s: SumSequence) -> Result 26 | { 27 | Ok(SumSequence::new( 28 | <&[T1; M]>::try_from(s.s)? 29 | .clone() 30 | .map(Into::into) 31 | )) 32 | } 33 | } 34 | impl<'a, T, const M: usize> TryFrom> for SumSequence 35 | { 36 | type Error = TryFromSliceError; 37 | 38 | fn try_from(s: SumSequence) -> Result 39 | { 40 | Ok(SumSequence::new( 41 | <&'a [T; M]>::try_from(s.s)? 42 | )) 43 | } 44 | } -------------------------------------------------------------------------------- /src/quantities/sum_sequence/zero.rs: -------------------------------------------------------------------------------- 1 | use core::{iter::Sum, ops::Add}; 2 | 3 | use num::Zero; 4 | 5 | use crate::quantities::{MaybeList, SumSequence}; 6 | 7 | impl Zero for SumSequence 8 | where 9 | T: Zero + Clone + Sum, 10 | S: MaybeList, 11 | Self: Add, 12 | SumSequence: Into 13 | { 14 | fn zero() -> Self 15 | { 16 | SumSequence::new(()).into() 17 | } 18 | fn is_zero(&self) -> bool 19 | { 20 | self.is_zero() 21 | } 22 | } -------------------------------------------------------------------------------- /src/rtf_or_system.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{ 5 | quantities::{ListOrSingle, MaybeList, MaybeLists, MaybeOwnedList}, 6 | systems::{Ar, Rpk, Sos, Ss, SsAMatrix, SsBMatrix, SsCMatrix, SsDMatrix, Tf, Zpk, Rtf}, 7 | MaybeRtfOrSystem, 8 | System 9 | }; 10 | 11 | pub trait RtfOrSystem: MaybeRtfOrSystem 12 | { 13 | type Set: ComplexFloat; 14 | } 15 | 16 | impl !RtfOrSystem for () {} 17 | 18 | impl RtfOrSystem for Rtf 19 | where 20 | W: ComplexFloat::Real>, 21 | S::Set: Into, 22 | S: System 23 | { 24 | type Set = W; 25 | } 26 | 27 | impl RtfOrSystem for Tf 28 | where 29 | T: ComplexFloat, 30 | B: MaybeLists, 31 | A: MaybeList 32 | { 33 | type Set = T; 34 | } 35 | 36 | impl RtfOrSystem for Zpk 37 | where 38 | T: ComplexFloat, 39 | K: ComplexFloat, 40 | Z: MaybeList, 41 | P: MaybeList 42 | { 43 | type Set = K; 44 | } 45 | 46 | impl RtfOrSystem for Ss 47 | where 48 | T: ComplexFloat, 49 | A: SsAMatrix, 50 | B: SsBMatrix, 51 | C: SsCMatrix, 52 | D: SsDMatrix 53 | { 54 | type Set = T; 55 | } 56 | 57 | impl RtfOrSystem for Sos 58 | where 59 | T: ComplexFloat, 60 | B: Maybe<[T; 3]> + MaybeOwnedList, 61 | A: Maybe<[T; 3]> + MaybeOwnedList, 62 | S: MaybeList> 63 | { 64 | type Set = T; 65 | } 66 | 67 | impl RtfOrSystem for Rpk 68 | where 69 | T: ComplexFloat, 70 | R: ComplexFloat, 71 | P: ComplexFloat, 72 | RP: MaybeList<(R, P)>, 73 | K: MaybeList 74 | { 75 | type Set = T; 76 | } 77 | 78 | impl RtfOrSystem for Ar 79 | where 80 | T: ComplexFloat, 81 | A: MaybeList, 82 | AV: ListOrSingle<(A, T::Real)> 83 | { 84 | type Set = T; 85 | } -------------------------------------------------------------------------------- /src/system.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{ 5 | quantities::{ListOrSingle, MaybeList, MaybeLists, MaybeOwnedList}, 6 | systems::{Ar, Rpk, Sos, Ss, SsAMatrix, SsBMatrix, SsCMatrix, SsDMatrix, Tf, Zpk}, 7 | RtfOrSystem, 8 | MaybeSystem 9 | }; 10 | 11 | pub trait System: RtfOrSystem + MaybeSystem 12 | { 13 | 14 | } 15 | 16 | impl System for Tf 17 | where 18 | T: ComplexFloat, 19 | B: MaybeLists, 20 | A: MaybeList 21 | { 22 | 23 | } 24 | 25 | impl System for Zpk 26 | where 27 | T: ComplexFloat, 28 | K: ComplexFloat, 29 | Z: MaybeList, 30 | P: MaybeList 31 | { 32 | 33 | } 34 | 35 | impl System for Ss 36 | where 37 | T: ComplexFloat, 38 | A: SsAMatrix, 39 | B: SsBMatrix, 40 | C: SsCMatrix, 41 | D: SsDMatrix 42 | { 43 | 44 | } 45 | 46 | impl System for Sos 47 | where 48 | T: ComplexFloat, 49 | B: Maybe<[T; 3]> + MaybeOwnedList, 50 | A: Maybe<[T; 3]> + MaybeOwnedList, 51 | S: MaybeList> 52 | { 53 | 54 | } 55 | 56 | impl System for Rpk 57 | where 58 | T: ComplexFloat, 59 | R: ComplexFloat, 60 | P: ComplexFloat, 61 | RP: MaybeList<(R, P)>, 62 | K: MaybeList 63 | { 64 | 65 | } 66 | 67 | impl System for Ar 68 | where 69 | T: ComplexFloat, 70 | A: MaybeList, 71 | AV: ListOrSingle<(A, T::Real)> 72 | { 73 | 74 | } -------------------------------------------------------------------------------- /src/systems/ar.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::quantities::{ListOrSingle, MaybeList}; 6 | 7 | moddef::moddef!( 8 | mod { 9 | debug 10 | } 11 | ); 12 | 13 | #[derive(Clone, Copy)] 14 | pub struct Ar 15 | where 16 | T: ComplexFloat, 17 | A: MaybeList, 18 | AV: ListOrSingle<(A, T::Real)> 19 | { 20 | pub av: AV, 21 | phantom: PhantomData<(A, T)> 22 | } 23 | 24 | impl Ar 25 | where 26 | T: ComplexFloat, 27 | A: MaybeList, 28 | AV: ListOrSingle<(A, T::Real)> 29 | { 30 | pub fn new(av: AV) -> Self 31 | { 32 | Self { 33 | av, 34 | phantom: PhantomData 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/systems/ar/debug.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | use num::complex::ComplexFloat; 3 | 4 | use crate::{systems::Ar, quantities::{ListOrSingle, MaybeList}}; 5 | 6 | impl Debug for Ar 7 | where 8 | T: ComplexFloat, 9 | A: MaybeList, 10 | AV: ListOrSingle<(A, T::Real)> + Debug 11 | { 12 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 13 | { 14 | f.debug_struct("Ar") 15 | .field("av", &self.av) 16 | .finish() 17 | } 18 | } -------------------------------------------------------------------------------- /src/systems/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | ar, 4 | rpk, 5 | rtf, 6 | sos, 7 | ss, 8 | tf, 9 | zpk 10 | } 11 | ); 12 | 13 | pub enum IrType 14 | { 15 | FIR, 16 | IIR 17 | } -------------------------------------------------------------------------------- /src/systems/rpk/neg.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Neg; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{quantities::{MaybeList, Polynomial, SumSequence}, systems::Rpk}; 6 | 7 | impl Neg for Rpk 8 | where 9 | T: ComplexFloat, 10 | T2: ComplexFloat, 11 | R: ComplexFloat, 12 | P: ComplexFloat, 13 | RP: MaybeList<(R, P)>, 14 | RP::MaybeMapped<(R, P)>: MaybeList<(R, P)>, 15 | K: MaybeList, 16 | K2: MaybeList, 17 | Polynomial: Neg> 18 | { 19 | type Output = Rpk, K2>; 20 | 21 | fn neg(self) -> Self::Output 22 | { 23 | Rpk { 24 | rp: SumSequence::new(self.rp.into_inner().maybe_map_into_owned(|(r, p)| (-r, p))), 25 | k: -self.k 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/systems/rpk/sub.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Neg, Sub}; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{quantities::MaybeList, systems::Rpk}; 6 | 7 | impl Sub> for Rpk 8 | where 9 | T1: ComplexFloat, 10 | T2: ComplexFloat, 11 | R1: ComplexFloat, 12 | R2: ComplexFloat, 13 | P1: ComplexFloat, 14 | P2: ComplexFloat, 15 | RP1: MaybeList<(R1, P1)>, 16 | RP2: MaybeList<(R2, P2)>, 17 | K1: MaybeList, 18 | K2: MaybeList, 19 | Rpk: Neg, 20 | Self: Add< as Neg>::Output>, 21 | { 22 | type Output = as Neg>::Output>>::Output; 23 | 24 | fn sub(self, rhs: Rpk) -> Self::Output 25 | { 26 | self + (-rhs) 27 | } 28 | } -------------------------------------------------------------------------------- /src/systems/rtf.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::System; 5 | pub struct Rtf 6 | where 7 | W: ComplexFloat::Real>, 8 | S::Set: Into, 9 | S: System 10 | { 11 | pub sys: S, 12 | pub w: Vec 13 | } 14 | 15 | impl Rtf 16 | where 17 | W: ComplexFloat::Real>, 18 | S::Set: Into, 19 | S: System 20 | { 21 | pub fn new>>(sys: S, w: WW) -> Self 22 | { 23 | Rtf { 24 | sys, 25 | w: w.into_option() 26 | .unwrap_or_else(std::vec::Vec::new) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/systems/sos/add.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Mul}; 2 | 3 | use num::complex::ComplexFloat; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::Sos, decompositions::SplitNumerDenom, systems::Tf, transforms::system::{ToSos, ToTf}}; 7 | 8 | impl Add> for Sos 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | T3: ComplexFloat, 13 | B1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 14 | B2: Maybe<[T2; 3]> + MaybeOwnedList + Clone, 15 | A1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 16 | A2: Maybe<[T2; 3]> + MaybeOwnedList + Clone, 17 | A3: Maybe<[T3; 3]> + MaybeOwnedList, 18 | S1: MaybeList>, 19 | S2: MaybeList>, 20 | S3: MaybeList>, 21 | S4: MaybeList>, 22 | 23 | Self: SplitNumerDenom, 24 | Sos: SplitNumerDenom, 25 | 26 | ::OutputNum: ToTf, (), (), ()>, 27 | as SplitNumerDenom>::OutputNum: ToTf, (), (), ()>, 28 | 29 | Tf>: Add>, Output = Tf>>, 30 | Tf>: ToSos>, (), ()>, 31 | 32 | ::OutputDen: Mul< as SplitNumerDenom>::OutputDen, Output = Sos>, 33 | Sos>>: Mul, Output = Sos> 34 | { 35 | type Output = Sos; 36 | 37 | fn add(self, rhs: Sos) -> Self::Output 38 | { 39 | let (n1, d1) = self.split_numer_denom(); 40 | let (n2, d2) = rhs.split_numer_denom(); 41 | 42 | let n1 = n1.to_tf((), ()); 43 | let n2 = n2.to_tf((), ()); 44 | 45 | let n = n1 + n2; 46 | let n = n.to_sos((), ()); 47 | 48 | let d = d1*d2; 49 | n*d 50 | } 51 | } -------------------------------------------------------------------------------- /src/systems/sos/default.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{quantities::{List, MaybeOwnedList, ProductSequence}, systems::{Sos, Tf}}; 5 | 6 | impl Default for Sos 7 | where 8 | T: ComplexFloat, 9 | B: Maybe<[T; 3]> + MaybeOwnedList, 10 | A: Maybe<[T; 3]> + MaybeOwnedList, 11 | S: List>, 12 | ProductSequence, S>: Default 13 | { 14 | fn default() -> Self 15 | { 16 | Self { 17 | sos: Default::default() 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/systems/sos/div.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Div, Mul}; 2 | 3 | use num::{complex::ComplexFloat, traits::Inv}; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}}; 7 | 8 | impl Div> for Sos 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | B1: Maybe<[T1; 3]> + MaybeOwnedList, 13 | B2: Maybe<[T2; 3]> + MaybeOwnedList, 14 | A1: Maybe<[T1; 3]> + MaybeOwnedList, 15 | A2: Maybe<[T2; 3]> + MaybeOwnedList, 16 | S1: MaybeList>, 17 | S2: MaybeList>, 18 | Sos: Inv, 19 | Self: Mul< as Inv>::Output, Output = O> 20 | { 21 | type Output = O; 22 | 23 | fn div(self, rhs: Sos) -> Self::Output 24 | { 25 | self*rhs.inv() 26 | } 27 | } -------------------------------------------------------------------------------- /src/systems/sos/from.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | use option_trait::Maybe; 3 | 4 | use crate::{quantities::{List, MaybeOwnedList, ProductSequence}, systems::{Sos, Tf}}; 5 | 6 | impl<'a, T1, T2, B1, B2, A1, A2, S1, S2> From<&'a Sos> for Sos 7 | where 8 | T1: ComplexFloat, 9 | T2: ComplexFloat, 10 | B1: Maybe<[T1; 3]> + MaybeOwnedList, 11 | B2: Maybe<[T2; 3]> + MaybeOwnedList, 12 | A1: Maybe<[T1; 3]> + MaybeOwnedList, 13 | A2: Maybe<[T2; 3]> + MaybeOwnedList, 14 | S1: List>, 15 | S2: List>, 16 | S1::View<'a>: List>, 17 | ProductSequence, S1::View<'a>>: Into, S2>> 18 | { 19 | fn from(sos: &'a Sos) -> Self 20 | { 21 | Sos { 22 | sos: sos.sos.as_view().into() 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/systems/sos/inv.rs: -------------------------------------------------------------------------------- 1 | use num::{complex::ComplexFloat, traits::Inv}; 2 | use option_trait::Maybe; 3 | 4 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}}; 5 | 6 | impl Inv for Sos 7 | where 8 | T1: ComplexFloat, 9 | T2: ComplexFloat, 10 | B1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 11 | B2: Maybe<[T2; 3]> + MaybeOwnedList, 12 | A1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 13 | A2: Maybe<[T2; 3]> + MaybeOwnedList, 14 | S1: MaybeList, MaybeMapped> = S2>, 15 | S2: MaybeList>, 16 | Tf: Inv> 17 | { 18 | type Output = Sos; 19 | 20 | fn inv(self) -> Self::Output 21 | { 22 | Sos::new(self.sos.into_inner() 23 | .maybe_map_into_owned(|sos| sos.inv()) 24 | ) 25 | } 26 | } -------------------------------------------------------------------------------- /src/systems/sos/mul.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Mul; 2 | 3 | use num::complex::ComplexFloat; 4 | use option_trait::{Maybe, MaybeOr, StaticMaybe}; 5 | 6 | use crate::{util::ComplexOp, quantities::{MaybeList, MaybeOwnedList, ProductSequence}, systems::{Sos, Tf}, transforms::system::ToTf}; 7 | 8 | impl Mul> for Sos 9 | where 10 | T1: ComplexFloat + ComplexOp, 11 | T2: ComplexFloat + Into, 12 | T3: ComplexFloat, 13 | B1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 14 | B2: Maybe<[T2; 3]> + MaybeOwnedList + Clone, 15 | B3: Maybe<[T3; 3]> + MaybeOwnedList, 16 | A1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 17 | A2: Maybe<[T2; 3]> + MaybeOwnedList + Clone, 18 | A3: Maybe<[T3; 3]> + MaybeOwnedList, 19 | S1: MaybeList>, 20 | S2: MaybeList>, 21 | S3: MaybeList>, 22 | S1::MaybeMapped>: MaybeList>, 23 | S2::MaybeMapped>: MaybeList>, 24 | ProductSequence, S1::MaybeMapped>>: Mul, S2::MaybeMapped>>, Output = ProductSequence, S3>>, 25 | Tf: ToTf, 26 | Tf: ToTf, 27 | B1::MaybeMapped: MaybeOr<[T3; 3], B2::MaybeMapped, Output = B3>, 28 | A1::MaybeMapped: MaybeOr<[T3; 3], A2::MaybeMapped, Output = A3>, 29 | B2::MaybeMapped: StaticMaybe<[T3; 3]>, 30 | A2::MaybeMapped: StaticMaybe<[T3; 3]> 31 | { 32 | type Output = Sos; 33 | 34 | fn mul(self, rhs: Sos) -> Self::Output 35 | { 36 | Sos { 37 | sos: ProductSequence::new(self.sos.into_inner().maybe_map_into_owned(|sos| sos.to_tf((), ()))) 38 | *ProductSequence::new(rhs.sos.into_inner().maybe_map_into_owned(|sos| sos.to_tf((), ()))) 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/systems/sos/neg.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Neg; 2 | 3 | use num::complex::ComplexFloat; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}, transforms::system::{ToSos, ToTf}}; 7 | 8 | impl Neg for Sos 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | B1: Maybe<[T1; 3]> + MaybeOwnedList, 13 | B2: Maybe<[T2; 3]> + MaybeOwnedList, 14 | A1: Maybe<[T1; 3]> + MaybeOwnedList, 15 | A2: Maybe<[T2; 3]> + MaybeOwnedList, 16 | S: MaybeList>, 17 | Tf: Neg> + ToTf + Default, 18 | Self: ToSos>, (), ()> 19 | { 20 | type Output = Sos>>; 21 | 22 | fn neg(self) -> Self::Output 23 | { 24 | let Sos::<_, _, _, Vec<_>> {sos} = self.to_sos((), ()); 25 | let mut first = true; 26 | 27 | let mut sos: Vec<_> = sos.into_inner() 28 | .into_iter() 29 | .map(|sos| { 30 | if first 31 | { 32 | first = false; 33 | -sos 34 | } 35 | else 36 | { 37 | sos.to_tf((), ()) 38 | } 39 | }).collect(); 40 | if first 41 | { 42 | sos.push(-Tf::one()) 43 | } 44 | 45 | Sos::new(sos) 46 | } 47 | } -------------------------------------------------------------------------------- /src/systems/sos/one.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | 3 | use num::{complex::ComplexFloat, One}; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}, transforms::system::ToTf}; 7 | 8 | impl One for Sos 9 | where 10 | T: ComplexFloat, 11 | B: Maybe<[T; 3]> + MaybeOwnedList, 12 | A: Maybe<[T; 3]> + MaybeOwnedList, 13 | S: MaybeList>, 14 | Self: Mul + Default + ToTf, Vec, (), ()> + Clone, 15 | { 16 | fn one() -> Self 17 | { 18 | Self::one() 19 | } 20 | fn is_one(&self) -> bool 21 | where 22 | Self: PartialEq, 23 | { 24 | self.is_one() 25 | } 26 | } -------------------------------------------------------------------------------- /src/systems/sos/pow.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{BitAnd, Shr}; 2 | 3 | use num::{complex::ComplexFloat, pow::Pow, traits::Inv, Integer}; 4 | use option_trait::{Maybe, MaybeOr}; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}, transforms::system::ToSos}; 7 | 8 | impl Pow for Sos 9 | where 10 | T: ComplexFloat, 11 | B: Maybe<[T; 3]> + MaybeOwnedList, 12 | A: Maybe<[T; 3]> + MaybeOwnedList, 13 | [T; 3]: MaybeOr<[T; 3], [T; 3], Output = [T; 3]>, 14 | S: MaybeList>, 15 | I: Integer + BitAnd + Shr + Copy, 16 | Self: ToSos>, (), ()> + Inv>, (), ()>>, 17 | { 18 | type Output = Sos>>; 19 | 20 | fn pow(self, mut n: I) -> Self::Output 21 | { 22 | let mut x: Sos>> = if n < I::zero() 23 | { 24 | self.inv() 25 | .to_sos((), ()) 26 | } 27 | else 28 | { 29 | self.to_sos((), ()) 30 | }; 31 | let mut r = if (n & I::one()) == I::one() 32 | { 33 | x.clone() 34 | } 35 | else 36 | { 37 | Sos::one() 38 | }; 39 | 40 | let two = I::one() + I::one(); 41 | loop 42 | { 43 | n = n/two; 44 | if n == I::zero() 45 | { 46 | break; 47 | } 48 | x = x.as_view()*x.as_view(); 49 | if (n & I::one()) == I::one() 50 | { 51 | r = r*x.as_view(); 52 | } 53 | } 54 | 55 | r 56 | } 57 | } -------------------------------------------------------------------------------- /src/systems/sos/product.rs: -------------------------------------------------------------------------------- 1 | use std::{iter::Product, ops::Mul}; 2 | 3 | use num::{complex::ComplexFloat, One}; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}, transforms::system::ToSos}; 7 | 8 | impl Product> for Sos 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | B1: Maybe<[T1; 3]> + MaybeOwnedList, 13 | B2: Maybe<[T2; 3]> + MaybeOwnedList, 14 | A1: Maybe<[T1; 3]> + MaybeOwnedList, 15 | A2: Maybe<[T2; 3]> + MaybeOwnedList, 16 | S1: MaybeList>, 17 | S2: MaybeList>, 18 | Sos: ToSos, 19 | Sos: Mul> + One 20 | { 21 | fn product>>(iter: I) -> Self 22 | { 23 | iter.map(|sos| sos.to_sos((), ())) 24 | .reduce(|a, b| a*b) 25 | .unwrap_or_else(One::one) 26 | } 27 | } -------------------------------------------------------------------------------- /src/systems/sos/sub.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Sub, Mul}; 2 | 3 | use num::complex::ComplexFloat; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}, decompositions::SplitNumerDenom, transforms::system::{ToSos, ToTf}}; 7 | 8 | impl Sub> for Sos 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | T3: ComplexFloat, 13 | B1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 14 | B2: Maybe<[T2; 3]> + MaybeOwnedList + Clone, 15 | A1: Maybe<[T1; 3]> + MaybeOwnedList + Clone, 16 | A2: Maybe<[T2; 3]> + MaybeOwnedList + Clone, 17 | A3: Maybe<[T3; 3]> + MaybeOwnedList, 18 | S1: MaybeList>, 19 | S2: MaybeList>, 20 | S3: MaybeList>, 21 | S4: MaybeList>, 22 | 23 | Self: SplitNumerDenom, 24 | Sos: SplitNumerDenom, 25 | 26 | ::OutputNum: ToTf, (), (), ()>, 27 | as SplitNumerDenom>::OutputNum: ToTf, (), (), ()>, 28 | 29 | Tf>: Sub>, Output = Tf>>, 30 | Tf>: ToSos>, (), ()>, 31 | 32 | ::OutputDen: Mul< as SplitNumerDenom>::OutputDen, Output = Sos>, 33 | Sos>>: Mul, Output = Sos> 34 | { 35 | type Output = Sos; 36 | 37 | fn sub(self, rhs: Sos) -> Self::Output 38 | { 39 | let (n1, d1) = self.split_numer_denom(); 40 | let (n2, d2) = rhs.split_numer_denom(); 41 | 42 | let n1 = n1.to_tf((), ()); 43 | let n2 = n2.to_tf((), ()); 44 | 45 | let n = n1 - n2; 46 | let n = n.to_sos((), ()); 47 | 48 | let d = d1*d2; 49 | n*d 50 | } 51 | } -------------------------------------------------------------------------------- /src/systems/sos/sum.rs: -------------------------------------------------------------------------------- 1 | use core::{iter::Sum, ops::Add}; 2 | 3 | use num::{complex::ComplexFloat, Zero}; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList}, systems::{Sos, Tf}, transforms::system::ToSos}; 7 | 8 | impl Sum> for Sos 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | B1: Maybe<[T1; 3]> + MaybeOwnedList, 13 | B2: Maybe<[T2; 3]> + MaybeOwnedList, 14 | A1: Maybe<[T1; 3]> + MaybeOwnedList, 15 | A2: Maybe<[T2; 3]> + MaybeOwnedList, 16 | S1: MaybeList>, 17 | S2: MaybeList>, 18 | Sos: ToSos, 19 | Sos: Add> + Zero 20 | { 21 | fn sum>>(iter: I) -> Self 22 | { 23 | iter.map(|sos| sos.to_sos((), ())) 24 | .reduce(|a, b| a + b) 25 | .unwrap_or_else(Zero::zero) 26 | } 27 | } -------------------------------------------------------------------------------- /src/systems/sos/zero.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Add; 2 | 3 | use num::{complex::ComplexFloat, Zero}; 4 | use option_trait::Maybe; 5 | 6 | use crate::{quantities::{MaybeList, MaybeOwnedList, ProductSequence, Polynomial}, systems::{Sos, Tf}}; 7 | 8 | impl Zero for Sos 9 | where 10 | T: ComplexFloat, 11 | B: Maybe<[T; 3]> + MaybeOwnedList, 12 | A: Maybe<[T; 3]> + MaybeOwnedList, 13 | S: MaybeList>, 14 | Polynomial: Into>, 15 | Polynomial: Into>, 16 | ProductSequence, [Tf; 1]>: Into, S>>, 17 | Self: Add 18 | { 19 | fn zero() -> Self 20 | { 21 | Self::zero() 22 | } 23 | fn is_zero(&self) -> bool 24 | { 25 | self.is_zero() 26 | } 27 | } -------------------------------------------------------------------------------- /src/systems/tf/add.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Mul; 2 | use std::ops::Add; 3 | 4 | use num::complex::ComplexFloat; 5 | 6 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, operations::Simplify, systems::Tf}; 7 | 8 | impl Add> for Tf 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | T3: ComplexFloat, 13 | B1: MaybeLists, 14 | A1: MaybeList + Clone, 15 | B2: MaybeLists, 16 | A2: MaybeList + Clone, 17 | B3: MaybeLists, 18 | A3: MaybeList, 19 | Polynomial: Mul, Output = Polynomial>, 20 | Polynomial: Mul, Output: Add< as Mul>>::Output, Output = Polynomial>>, 21 | Polynomial: Mul>, 22 | Tf: Simplify 23 | { 24 | type Output = as Simplify>::Output; 25 | 26 | fn add(self, rhs: Tf) -> Self::Output 27 | { 28 | Tf { 29 | b: self.b*rhs.a.clone() + rhs.b*self.a.clone(), 30 | a: self.a*rhs.a 31 | }.simplify() 32 | } 33 | } -------------------------------------------------------------------------------- /src/systems/tf/default.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | 3 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, systems::Tf}; 4 | 5 | impl Default for Tf 6 | where 7 | T: ComplexFloat, 8 | B: MaybeLists, 9 | A: MaybeList, 10 | Polynomial: From>, 11 | Polynomial: From> 12 | { 13 | fn default() -> Self 14 | { 15 | Self { 16 | b: Polynomial::new(()).into(), 17 | a: Polynomial::new(()).into() 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/systems/tf/div.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Div; 2 | use std::ops::Mul; 3 | 4 | use num::complex::ComplexFloat; 5 | 6 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, operations::Simplify, systems::Tf}; 7 | 8 | impl Div> for Tf 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | T3: ComplexFloat, 13 | B1: MaybeLists, 14 | A1: MaybeList, 15 | B2: MaybeLists, 16 | A2: MaybeList, 17 | B3: MaybeLists, 18 | A3: MaybeList, 19 | Polynomial: Mul, Output = Polynomial>, 20 | Polynomial: Mul, Output = Polynomial>, 21 | Tf: Simplify 22 | { 23 | type Output = as Simplify>::Output; 24 | 25 | fn div(self, rhs: Tf) -> Self::Output 26 | { 27 | Tf { 28 | b: self.b*rhs.a, 29 | a: self.a*rhs.b 30 | }.simplify() 31 | } 32 | } -------------------------------------------------------------------------------- /src/systems/tf/from.rs: -------------------------------------------------------------------------------- 1 | 2 | use num::complex::ComplexFloat; 3 | 4 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, systems::Tf}; 5 | 6 | impl<'a, T1, B1, A1, T2, B2, A2> From<&'a Tf> for Tf 7 | where 8 | T1: ComplexFloat, 9 | T2: ComplexFloat, 10 | B1: MaybeLists, 11 | A1: MaybeList, 12 | B2: MaybeLists, 13 | A2: MaybeList, 14 | B1::View<'a>: MaybeLists, 15 | A1::View<'a>: MaybeLists, 16 | Polynomial>: Into>, 17 | Polynomial>: Into>, 18 | { 19 | fn from(tf: &'a Tf) -> Self 20 | { 21 | Tf { 22 | b: tf.b.as_view().into(), 23 | a: tf.a.as_view().into() 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/systems/tf/inv.rs: -------------------------------------------------------------------------------- 1 | use num::{complex::ComplexFloat, traits::Inv}; 2 | 3 | use crate::{quantities::MaybeList, systems::Tf}; 4 | 5 | impl Inv for Tf 6 | where 7 | T: ComplexFloat, 8 | B: MaybeList, 9 | A: MaybeList 10 | { 11 | type Output = Tf; 12 | 13 | fn inv(self) -> Self::Output 14 | { 15 | Tf { 16 | b: self.a, 17 | a: self.b 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/systems/tf/mul.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, operations::Simplify, systems::Tf}; 6 | 7 | impl Mul> for Tf 8 | where 9 | T1: ComplexFloat, 10 | T2: ComplexFloat, 11 | T3: ComplexFloat, 12 | B1: MaybeLists, 13 | A1: MaybeList, 14 | B2: MaybeLists, 15 | A2: MaybeList, 16 | B3: MaybeLists, 17 | A3: MaybeList, 18 | Polynomial: Mul, Output = Polynomial>, 19 | Polynomial: Mul, Output = Polynomial>, 20 | Tf: Simplify 21 | { 22 | type Output = as Simplify>::Output; 23 | 24 | fn mul(self, rhs: Tf) -> Self::Output 25 | { 26 | Tf { 27 | b: self.b*rhs.b, 28 | a: self.a*rhs.a 29 | }.simplify() 30 | } 31 | } -------------------------------------------------------------------------------- /src/systems/tf/neg.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Neg; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, systems::Tf}; 6 | 7 | impl Neg for Tf 8 | where 9 | T: ComplexFloat, 10 | B1: MaybeLists, 11 | B2: MaybeLists, 12 | A: MaybeList, 13 | Polynomial: Neg> 14 | { 15 | type Output = Tf; 16 | 17 | fn neg(self) -> Self::Output 18 | { 19 | Tf { 20 | b: -self.b, 21 | a: self.a 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/systems/tf/one.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | 3 | use num::{complex::ComplexFloat, One}; 4 | 5 | use crate::{quantities::MaybeList, systems::Tf}; 6 | 7 | impl One for Tf 8 | where 9 | T: ComplexFloat, 10 | Self: Mul + Default, 11 | B: MaybeList, 12 | A: MaybeList 13 | { 14 | fn one() -> Self 15 | { 16 | Self::one() 17 | } 18 | fn is_one(&self) -> bool 19 | { 20 | self.is_one() 21 | } 22 | } -------------------------------------------------------------------------------- /src/systems/tf/pow.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{AddAssign, BitAnd, Shr}; 2 | 3 | use num::{complex::ComplexFloat, pow::Pow, traits::Inv, Integer, One}; 4 | 5 | use crate::{quantities::MaybeList, operations::Simplify, systems::Tf, transforms::system::ToTf}; 6 | 7 | impl Pow for Tf 8 | where 9 | T: ComplexFloat + AddAssign, 10 | B: MaybeList, 11 | A: MaybeList, 12 | I: Integer + BitAnd + Shr + Copy, 13 | Self: ToTf, Vec, (), ()> + Inv, Vec, (), ()>>, 14 | Tf, Vec>: Simplify, Vec>> 15 | { 16 | type Output = Tf, Vec>; 17 | 18 | fn pow(self, mut n: I) -> Self::Output 19 | { 20 | let mut x = if n < I::zero() 21 | { 22 | self.inv() 23 | .to_tf((), ()) 24 | } 25 | else 26 | { 27 | self.to_tf((), ()) 28 | }; 29 | let mut r = if (n & I::one()) == I::one() 30 | { 31 | x.clone() 32 | } 33 | else 34 | { 35 | One::one() 36 | }; 37 | 38 | let two = I::one() + I::one(); 39 | loop 40 | { 41 | n = n/two; 42 | if n == I::zero() 43 | { 44 | break; 45 | } 46 | x = x.as_view()*x.as_view(); 47 | if (n & I::one()) == I::one() 48 | { 49 | r = r*x.as_view(); 50 | } 51 | } 52 | 53 | r 54 | } 55 | } -------------------------------------------------------------------------------- /src/systems/tf/product.rs: -------------------------------------------------------------------------------- 1 | use std::{iter::Product, ops::Mul}; 2 | 3 | use num::{complex::ComplexFloat, One}; 4 | 5 | use crate::{quantities::{MaybeList, MaybeLists}, systems::Tf, transforms::system::ToTf}; 6 | 7 | impl Product> for Tf 8 | where 9 | T1: ComplexFloat, 10 | T2: ComplexFloat, 11 | B1: MaybeLists, 12 | A1: MaybeList, 13 | B2: MaybeLists, 14 | A2: MaybeList, 15 | Tf: ToTf, 16 | Tf: Mul> + One 17 | { 18 | fn product>>(iter: I) -> Self 19 | { 20 | iter.map(|tf| tf.to_tf((), ())) 21 | .reduce(|a, b| a*b) 22 | .unwrap_or_else(One::one) 23 | } 24 | } -------------------------------------------------------------------------------- /src/systems/tf/sub.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Mul, Sub}; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, operations::Simplify, systems::Tf}; 6 | 7 | impl Sub> for Tf 8 | where 9 | T1: ComplexFloat, 10 | T2: ComplexFloat, 11 | T3: ComplexFloat, 12 | B1: MaybeLists, 13 | A1: MaybeList + Clone, 14 | B2: MaybeLists, 15 | A2: MaybeList + Clone, 16 | B3: MaybeLists, 17 | A3: MaybeList, 18 | Polynomial: Mul, Output = Polynomial>, 19 | Polynomial: Mul, Output: Sub< as Mul>>::Output, Output = Polynomial>>, 20 | Polynomial: Mul>, 21 | Tf: Simplify 22 | { 23 | type Output = as Simplify>::Output; 24 | 25 | fn sub(self, rhs: Tf) -> Self::Output 26 | { 27 | Tf { 28 | b: self.b*rhs.a.clone() - rhs.b*self.a.clone(), 29 | a: self.a*rhs.a 30 | }.simplify() 31 | } 32 | } -------------------------------------------------------------------------------- /src/systems/tf/sum.rs: -------------------------------------------------------------------------------- 1 | use core::{iter::Sum, ops::Mul}; 2 | 3 | use num::{complex::ComplexFloat, Zero}; 4 | 5 | use crate::{quantities::{MaybeList, MaybeLists}, systems::Tf}; 6 | 7 | impl Sum> for Tf 8 | where 9 | T1: ComplexFloat, 10 | T2: ComplexFloat, 11 | B1: MaybeLists, 12 | A1: MaybeList, 13 | B2: MaybeLists, 14 | A2: MaybeList, 15 | Tf: Into>, 16 | Tf: Mul> + Zero 17 | { 18 | fn sum>>(iter: I) -> Self 19 | { 20 | iter.map(|tf| tf.into()) 21 | .reduce(|a, b| a + b) 22 | .unwrap_or_else(Zero::zero) 23 | } 24 | } -------------------------------------------------------------------------------- /src/systems/tf/zero.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Add; 2 | 3 | use num::{complex::ComplexFloat, Zero}; 4 | 5 | use crate::{quantities::{MaybeList, MaybeLists, Polynomial}, systems::Tf}; 6 | 7 | impl Zero for Tf 8 | where 9 | T: ComplexFloat, 10 | B: MaybeLists, 11 | A: MaybeList, 12 | Polynomial: Into>, 13 | Polynomial: Into>, 14 | Self: Add 15 | { 16 | fn zero() -> Self 17 | { 18 | Tf::zero() 19 | } 20 | fn is_zero(&self) -> bool 21 | { 22 | self.is_zero() 23 | } 24 | } -------------------------------------------------------------------------------- /src/systems/zpk/default.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | 3 | use crate::{quantities::{MaybeList, ProductSequence}, systems::Zpk}; 4 | 5 | impl Default for Zpk 6 | where 7 | T: ComplexFloat, 8 | Z: MaybeList, 9 | P: MaybeList, 10 | K: ComplexFloat, 11 | ProductSequence: Default, 12 | ProductSequence: Default 13 | { 14 | fn default() -> Self 15 | { 16 | Self { 17 | z: Default::default(), 18 | p: Default::default(), 19 | k: K::one() 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/systems/zpk/div.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Div; 2 | use std::ops::Mul; 3 | 4 | use num::complex::ComplexFloat; 5 | 6 | use crate::{util::ComplexOp, quantities::{MaybeList, ProductSequence}, operations::Simplify, systems::Zpk}; 7 | 8 | impl Div> for Zpk 9 | where 10 | T1: ComplexFloat + ComplexOp, 11 | T2: ComplexFloat + Into, 12 | T3: ComplexFloat, 13 | K1: ComplexFloat + ComplexOp, 14 | K2: ComplexFloat + Into, 15 | K3: ComplexFloat + Div, 16 | Z1: MaybeList, 17 | Z2: MaybeList, 18 | Z3: MaybeList, 19 | P1: MaybeList, 20 | P2: MaybeList, 21 | P3: MaybeList, 22 | Z1::MaybeMapped: MaybeList, 23 | Z2::MaybeMapped: MaybeList, 24 | P1::MaybeMapped: MaybeList, 25 | P2::MaybeMapped: MaybeList, 26 | ProductSequence>: Mul>, Output = ProductSequence>, 27 | ProductSequence>: Mul>, Output = ProductSequence>, 28 | Zpk: Simplify 29 | { 30 | type Output = as Simplify>::Output; 31 | 32 | fn div(self, rhs: Zpk) -> Self::Output 33 | { 34 | Zpk { 35 | z: ProductSequence::new(self.z.into_inner().maybe_map_into_owned(|z| z.into())) 36 | *ProductSequence::new(rhs.p.into_inner().maybe_map_into_owned(|p| p.into())), 37 | p: ProductSequence::new(self.p.into_inner().maybe_map_into_owned(|p| p.into())) 38 | *ProductSequence::new(rhs.z.into_inner().maybe_map_into_owned(|z| z.into())), 39 | k: self.k.into()/rhs.k.into() 40 | }.simplify() 41 | } 42 | } -------------------------------------------------------------------------------- /src/systems/zpk/from.rs: -------------------------------------------------------------------------------- 1 | use num::complex::ComplexFloat; 2 | 3 | use crate::{quantities::{MaybeList, ProductSequence}, systems::Zpk}; 4 | 5 | impl<'a, T1, T2, K1, K2, Z1, Z2, P1, P2> From<&'a Zpk> for Zpk 6 | where 7 | T1: ComplexFloat, 8 | T2: ComplexFloat, 9 | K1: ComplexFloat + Into, 10 | K2: ComplexFloat, 11 | Z1: MaybeList, 12 | P1: MaybeList, 13 | Z2: MaybeList, 14 | P2: MaybeList, 15 | Z1::View<'a>: MaybeList, 16 | P1::View<'a>: MaybeList, 17 | ProductSequence>: Into>, 18 | ProductSequence>: Into> 19 | { 20 | fn from(zpk: &'a Zpk) -> Self 21 | { 22 | Zpk { 23 | z: zpk.z.as_view().into(), 24 | p: zpk.p.as_view().into(), 25 | k: zpk.k.into() 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/systems/zpk/inv.rs: -------------------------------------------------------------------------------- 1 | use num::{complex::ComplexFloat, traits::Inv}; 2 | 3 | use crate::{quantities::MaybeList, systems::Zpk}; 4 | 5 | impl Inv for Zpk 6 | where 7 | T: ComplexFloat, 8 | K: ComplexFloat + Inv>, 9 | Z: MaybeList, 10 | P: MaybeList 11 | { 12 | type Output = Zpk::Output>; 13 | 14 | fn inv(self) -> Self::Output 15 | { 16 | Zpk { 17 | z: self.p, 18 | p: self.z, 19 | k: self.k.inv() 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/systems/zpk/mul.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{util::ComplexOp, quantities::{MaybeList, ProductSequence}, operations::Simplify, systems::Zpk}; 6 | 7 | impl Mul> for Zpk 8 | where 9 | T1: ComplexFloat + ComplexOp, 10 | T2: ComplexFloat + Into, 11 | T3: ComplexFloat, 12 | T4: ComplexFloat, 13 | K1: ComplexFloat + ComplexOp, 14 | K2: ComplexFloat + Into, 15 | K3: ComplexFloat + Mul, 16 | Z1: MaybeList, 17 | Z2: MaybeList, 18 | Z3: MaybeList, 19 | P1: MaybeList, 20 | P2: MaybeList, 21 | P3: MaybeList, 22 | Z1::MaybeMapped: MaybeList, 23 | Z2::MaybeMapped: MaybeList, 24 | P1::MaybeMapped: MaybeList, 25 | P2::MaybeMapped: MaybeList, 26 | ProductSequence>: Mul>, Output = ProductSequence>, 27 | ProductSequence>: Mul>, Output = ProductSequence>, 28 | Zpk: Simplify 29 | { 30 | type Output = as Simplify>::Output; 31 | 32 | fn mul(self, rhs: Zpk) -> Self::Output 33 | { 34 | Zpk { 35 | z: ProductSequence::new(self.z.into_inner().maybe_map_into_owned(|z| z.into())) 36 | *ProductSequence::new(rhs.z.into_inner().maybe_map_into_owned(|z| z.into())), 37 | p: ProductSequence::new(self.p.into_inner().maybe_map_into_owned(|p| p.into())) 38 | *ProductSequence::new(rhs.p.into_inner().maybe_map_into_owned(|p| p.into())), 39 | k: self.k.into()*rhs.k.into() 40 | }.simplify() 41 | } 42 | } -------------------------------------------------------------------------------- /src/systems/zpk/neg.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Neg; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | use crate::{quantities::MaybeList, systems::Zpk}; 6 | 7 | impl Neg for Zpk 8 | where 9 | T: ComplexFloat, 10 | K: ComplexFloat, 11 | Z: MaybeList, 12 | P: MaybeList 13 | { 14 | type Output = Zpk; 15 | 16 | fn neg(self) -> Self::Output 17 | { 18 | Zpk { 19 | z: self.z, 20 | p: self.p, 21 | k: -self.k 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/systems/zpk/one.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Mul; 2 | 3 | use num::{complex::ComplexFloat, One}; 4 | 5 | use crate::{quantities::List, systems::Zpk}; 6 | 7 | impl One for Zpk 8 | where 9 | T: ComplexFloat, 10 | K: ComplexFloat, 11 | Z: List, 12 | P: List, 13 | Self: Default + Mul 14 | { 15 | fn one() -> Self 16 | { 17 | Zpk::default() 18 | } 19 | 20 | fn is_one(&self) -> bool 21 | { 22 | self.k.is_one() && self.p.as_view_slice().is_empty() && self.z.as_view_slice().is_empty() 23 | } 24 | } -------------------------------------------------------------------------------- /src/systems/zpk/pow.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{BitAnd, Shr}; 2 | 3 | use num::{complex::ComplexFloat, pow::Pow, traits::Inv, Integer, One}; 4 | 5 | use crate::{util::ComplexOp, quantities::MaybeList, transforms::system::ToZpk, systems::Zpk}; 6 | 7 | 8 | impl Pow for Zpk 9 | where 10 | T: ComplexFloat + ComplexOp, 11 | Z: MaybeList, 12 | P: MaybeList, 13 | K: ComplexFloat + ComplexOp, 14 | I: Integer + BitAnd + Shr + Copy, 15 | Self: ToZpk, Vec, K, (), ()> + Inv, Vec, K, (), ()>> 16 | { 17 | type Output = Zpk, Vec, K>; 18 | 19 | fn pow(self, mut n: I) -> Self::Output 20 | { 21 | let mut x = if n < I::zero() 22 | { 23 | self.inv() 24 | .to_zpk((), ()) 25 | } 26 | else 27 | { 28 | self.to_zpk((), ()) 29 | }; 30 | let mut r = if (n & I::one()) == I::one() 31 | { 32 | x.clone() 33 | } 34 | else 35 | { 36 | One::one() 37 | }; 38 | 39 | let two = I::one() + I::one(); 40 | loop 41 | { 42 | n = n/two; 43 | if n == I::zero() 44 | { 45 | break; 46 | } 47 | x = x.as_view()*x.as_view(); 48 | if (n & I::one()) == I::one() 49 | { 50 | r = r*x.as_view(); 51 | } 52 | } 53 | 54 | r 55 | } 56 | } -------------------------------------------------------------------------------- /src/systems/zpk/product.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Mul; 2 | use std::iter::Product; 3 | 4 | use num::{complex::ComplexFloat, One}; 5 | 6 | use crate::{quantities::List, systems::Zpk}; 7 | 8 | impl<'a, T1, T2, Z1, Z2, P1, P2, K1, K2> Product<&'a Zpk> for Zpk 9 | where 10 | T1: ComplexFloat, 11 | T2: ComplexFloat, 12 | K1: ComplexFloat, 13 | K2: ComplexFloat, 14 | Z1: List, 15 | P1: List, 16 | Z2: List, 17 | P2: List, 18 | &'a Zpk: Into, 19 | Self: One + 'a 20 | { 21 | fn product>>(iter: I) -> Self 22 | { 23 | iter.map(|zpk| zpk.into()) 24 | .reduce(Mul::mul) 25 | .unwrap_or_else(One::one) 26 | } 27 | } -------------------------------------------------------------------------------- /src/systems/zpk/zero.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Add; 2 | 3 | use num::{complex::ComplexFloat, Zero}; 4 | 5 | use crate::{quantities::MaybeList, systems::Zpk}; 6 | 7 | impl Zero for Zpk 8 | where 9 | T: ComplexFloat, 10 | Z: MaybeList, 11 | P: MaybeList, 12 | K: ComplexFloat, 13 | Self: Default + Add 14 | { 15 | fn zero() -> Self 16 | { 17 | Self::zero() 18 | } 19 | fn is_zero(&self) -> bool 20 | { 21 | self.is_zero() 22 | } 23 | } -------------------------------------------------------------------------------- /src/transforms/bspline/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | bspline_eval, 4 | cspline_1d_eval, 5 | cspline_1d, 6 | qspline_1d_eval, 7 | qspline_1d 8 | } 9 | ); -------------------------------------------------------------------------------- /src/transforms/domain/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | bilinear, 4 | impinvar 5 | } 6 | ); -------------------------------------------------------------------------------- /src/transforms/filter/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | qmf, 4 | sftrans, 5 | stabilize, 6 | zftrans 7 | } 8 | ); -------------------------------------------------------------------------------- /src/transforms/fourier/dft.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{AddAssign, MulAssign}; 2 | 3 | use array_math::SliceMath; 4 | use num::{complex::ComplexFloat, Complex}; 5 | 6 | use crate::quantities::{Lists, OwnedLists}; 7 | 8 | pub trait Dft: Lists 9 | where 10 | T: ComplexFloat 11 | { 12 | fn dft(self) -> Self::Mapped>; 13 | } 14 | 15 | impl Dft for L 16 | where 17 | T: ComplexFloat + Into>, 18 | L: Lists, 19 | L::Mapped>: OwnedLists>, 20 | Complex: ComplexFloat + MulAssign + AddAssign 21 | { 22 | fn dft(self) -> Self::Mapped> 23 | { 24 | let mut h = self.map_into_owned(|h| h.into()); 25 | for h in h.as_mut_slices() 26 | { 27 | h.fft() 28 | } 29 | h 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod test 35 | { 36 | use core::f64::consts::TAU; 37 | 38 | use array_math::ArrayOps; 39 | use linspace::LinspaceArray; 40 | 41 | use crate::{plot, transforms::fourier::Dft}; 42 | 43 | #[test] 44 | fn test() 45 | { 46 | const N: usize = 1024; 47 | const T: f64 = 1.0; 48 | const F: f64 = 220.0; 49 | 50 | let x: [_; N] = ArrayOps::fill(|i| (TAU*F*i as f64/N as f64*T).sin()); 51 | 52 | let xf = x.dft(); 53 | let w = (0.0..TAU).linspace_array(); 54 | 55 | plot::plot_curves("X(e^jw)", "plots/x_z_dft.png", [&w.zip(xf.map(|xf| xf.norm()))]) 56 | .unwrap() 57 | } 58 | } -------------------------------------------------------------------------------- /src/transforms/fourier/dft_2d.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{AddAssign, MulAssign}; 2 | 3 | use array_math::SliceMath; 4 | use num::{complex::ComplexFloat, Complex}; 5 | 6 | use crate::quantities::{Matrix, MaybeMatrix, OwnedLists, OwnedMatrix}; 7 | 8 | pub trait Dft2d: Matrix 9 | where 10 | T: ComplexFloat, 11 | Self::Mapped>: Matrix> 12 | { 13 | fn dft_2d(self) -> Self::Mapped>; 14 | } 15 | 16 | impl Dft2d for M 17 | where 18 | T: ComplexFloat + Into>, 19 | M: Matrix, 20 | M::Mapped>: OwnedMatrix> + 'static, 21 | Complex: ComplexFloat + MulAssign + AddAssign, 22 | > as MaybeMatrix>>::Transpose: OwnedMatrix, Transpose: Into>>> 23 | { 24 | fn dft_2d(self) -> Self::Mapped> 25 | { 26 | let mut h = self.map_into_owned(|h| h.into()); 27 | for h in h.as_mut_slices() 28 | { 29 | h.fft(); 30 | } 31 | let mut ht = h.matrix_transpose(); 32 | for ht in ht.as_mut_slices() 33 | { 34 | ht.fft(); 35 | } 36 | ht.matrix_transpose() 37 | .into() 38 | } 39 | } -------------------------------------------------------------------------------- /src/transforms/fourier/dht.rs: -------------------------------------------------------------------------------- 1 | use num::{complex::ComplexFloat, Complex}; 2 | 3 | use crate::{quantities::{Lists, ContainerOrSingle}, transforms::fourier::Dft}; 4 | 5 | pub trait Dht: Lists 6 | where 7 | T: ComplexFloat 8 | { 9 | fn dht(self) -> Self::Mapped; 10 | } 11 | 12 | impl Dht for L 13 | where 14 | T: ComplexFloat, 15 | L: Lists, 16 | Self: Dft, 17 | Self::Mapped>: Lists, Mapped = Self::Mapped>, 18 | { 19 | fn dht(self) -> Self::Mapped 20 | { 21 | let y = self.dft(); 22 | y.map_into_owned(|y| y.re - y.im) 23 | } 24 | } 25 | 26 | #[cfg(test)] 27 | mod test 28 | { 29 | use core::f64::consts::TAU; 30 | 31 | use array_math::ArrayOps; 32 | use linspace::LinspaceArray; 33 | 34 | use crate::{plot, transforms::fourier::Dht}; 35 | 36 | #[test] 37 | fn test() 38 | { 39 | const N: usize = 1024; 40 | const T: f64 = 1.0; 41 | const F: f64 = 220.0; 42 | 43 | let x: [_; N] = ArrayOps::fill(|i| (TAU*F*i as f64/N as f64*T).sin()); 44 | 45 | let xf = x.dht(); 46 | 47 | let w = (0.0..TAU).linspace_array(); 48 | 49 | plot::plot_curves("X(e^jw)", "plots/x_z_dht.png", [&w.zip(xf)]) 50 | .unwrap() 51 | } 52 | } -------------------------------------------------------------------------------- /src/transforms/fourier/hilbert_2d.rs: -------------------------------------------------------------------------------- 1 | use core::ops::MulAssign; 2 | 3 | use num::{complex::ComplexFloat, Complex, Zero, One}; 4 | 5 | use crate::{quantities::{ContainerOrSingle, Matrix, OwnedLists, OwnedMatrix}, transforms::fourier::{Dft2d, Idft2d}, util::TruncateIm}; 6 | 7 | pub trait Hilbert2d: Matrix 8 | where 9 | T: ComplexFloat 10 | { 11 | fn hilbert_2d(self) -> Self::Owned; 12 | } 13 | 14 | impl Hilbert2d for M 15 | where 16 | T: ComplexFloat + Into>> + 'static, 17 | Complex: MulAssign, 18 | M: Matrix>: OwnedMatrix, Mapped>: Matrix, Mapped: Into>> + Idft2d>> + Dft2d, 19 | { 20 | fn hilbert_2d(self) -> M::Owned 21 | { 22 | let one = T::Real::one(); 23 | let zero = T::Real::zero(); 24 | 25 | let (m, n) = self.matrix_dim(); 26 | 27 | let mut y = self.dft_2d(); 28 | 29 | let mhalf = m/2 + 1; 30 | let nhalf = n/2 + 1; 31 | 32 | for (i, y) in y.as_mut_slices() 33 | .into_iter() 34 | .enumerate() 35 | { 36 | for (j, y) in y.iter_mut() 37 | .enumerate() 38 | { 39 | if i == 0 || j == 0 40 | { 41 | *y = zero.into() 42 | } 43 | else 44 | { 45 | *y *= if (j > nhalf) ^ (i > mhalf) {one} else {-one} 46 | } 47 | } 48 | } 49 | 50 | y.idft_2d() 51 | .map_into_owned(|y| y.truncate_im::()) 52 | .into() 53 | } 54 | } 55 | 56 | #[cfg(test)] 57 | mod test 58 | { 59 | use super::Hilbert2d; 60 | 61 | #[test] 62 | fn test() 63 | { 64 | let x = [ 65 | [1.0, 2.0, 3.0, 4.0], 66 | [5.0, 6.0, 0.0, 8.0], 67 | [9.0, 10.0, 11.0, 12.0], 68 | [13.0, 14.0, 15.0, 16.0] 69 | ]; 70 | let y = Hilbert2d::::hilbert_2d(x); 71 | println!("{:?}", y) 72 | } 73 | } -------------------------------------------------------------------------------- /src/transforms/fourier/idft.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{AddAssign, MulAssign}; 2 | 3 | use array_math::SliceMath; 4 | use num::{complex::ComplexFloat, Complex}; 5 | 6 | use crate::quantities::{Lists, OwnedLists}; 7 | 8 | pub trait Idft: Lists 9 | where 10 | T: ComplexFloat 11 | { 12 | fn idft(self) -> Self::Mapped>; 13 | } 14 | 15 | impl Idft for L 16 | where 17 | T: ComplexFloat + Into>, 18 | L: Lists, 19 | L::Mapped>: OwnedLists>, 20 | Complex: ComplexFloat + MulAssign + AddAssign + MulAssign 21 | { 22 | fn idft(self) -> Self::Mapped> 23 | { 24 | let mut h = self.map_into_owned(|h| h.into()); 25 | for h in h.as_mut_slices() 26 | { 27 | h.ifft() 28 | } 29 | h 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod test 35 | { 36 | use core::f64::consts::TAU; 37 | 38 | use array_math::ArrayOps; 39 | use linspace::LinspaceArray; 40 | 41 | use crate::{plot, transforms::fourier::{Dft, Idft}}; 42 | 43 | #[test] 44 | fn test() 45 | { 46 | const N: usize = 1024; 47 | const T: f64 = 0.1; 48 | const F: f64 = 220.0; 49 | 50 | let t: [_; N] = (0.0..T).linspace_array(); 51 | let x = t.map(|t| (TAU*F*t).sin()); 52 | 53 | let xf = x.dft(); 54 | let y = xf.idft(); 55 | 56 | plot::plot_curves("x(t)", "plots/x_t_idft.png", [&t.zip(y.map(|y| y.re))]) 57 | .unwrap() 58 | } 59 | } -------------------------------------------------------------------------------- /src/transforms/fourier/idft_2d.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{AddAssign, MulAssign}; 2 | 3 | use array_math::SliceMath; 4 | use num::{complex::ComplexFloat, Complex}; 5 | 6 | use crate::quantities::{Matrix, MaybeMatrix, OwnedLists, OwnedMatrix}; 7 | 8 | pub trait Idft2d: Matrix 9 | where 10 | T: ComplexFloat, 11 | Self::Mapped>: Matrix> 12 | { 13 | fn idft_2d(self) -> Self::Mapped>; 14 | } 15 | 16 | impl Idft2d for M 17 | where 18 | T: ComplexFloat + Into>, 19 | M: Matrix, 20 | M::Mapped>: OwnedMatrix> + 'static, 21 | Complex: ComplexFloat + MulAssign + AddAssign + MulAssign, 22 | > as MaybeMatrix>>::Transpose: OwnedMatrix, Transpose: Into>>> 23 | { 24 | fn idft_2d(self) -> Self::Mapped> 25 | { 26 | let mut h = self.map_into_owned(|h| h.into()); 27 | for h in h.as_mut_slices() 28 | { 29 | h.ifft(); 30 | } 31 | let mut ht = h.matrix_transpose(); 32 | for ht in ht.as_mut_slices() 33 | { 34 | ht.ifft(); 35 | } 36 | ht.matrix_transpose() 37 | .into() 38 | } 39 | } -------------------------------------------------------------------------------- /src/transforms/fourier/idht.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | use num::{complex::ComplexFloat, Complex}; 5 | 6 | use crate::{quantities::{Lists, ContainerOrSingle}, transforms::fourier::Idft}; 7 | 8 | pub trait Idht: Lists 9 | where 10 | T: ComplexFloat 11 | { 12 | fn idht(self) -> Self::Mapped; 13 | } 14 | 15 | impl Idht for L 16 | where 17 | T: ComplexFloat, 18 | L: Lists, 19 | Self: Idft, 20 | Self::Mapped>: Lists, Mapped = Self::Mapped>, 21 | { 22 | fn idht(self) -> Self::Mapped 23 | { 24 | let y = self.idft(); 25 | y.map_into_owned(|y| y.re + y.im) 26 | } 27 | } 28 | 29 | #[cfg(test)] 30 | mod test 31 | { 32 | use core::f64::consts::TAU; 33 | 34 | use array_math::ArrayOps; 35 | use linspace::LinspaceArray; 36 | 37 | use crate::{plot, transforms::fourier::{Dht, Idht}}; 38 | 39 | #[test] 40 | fn test() 41 | { 42 | const N: usize = 1024; 43 | const T: f64 = 0.1; 44 | const F: f64 = 220.0; 45 | 46 | let t: [_; N] = (0.0..T).linspace_array(); 47 | let x = t.map(|t| (TAU*F*t).sin()); 48 | 49 | let xf = x.dht(); 50 | let y = xf.idht(); 51 | 52 | plot::plot_curves("x(t)", "plots/x_t_idht.png", [&t.zip(y.map(|y| y))]) 53 | .unwrap() 54 | } 55 | } -------------------------------------------------------------------------------- /src/transforms/fourier/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | czt, 4 | dct_2d, 5 | dct, 6 | dft_2d, 7 | dft, 8 | dht, 9 | dst_2d, 10 | dst, 11 | dwht, 12 | dwt, 13 | hilbert_2d, 14 | hilbert, 15 | iczt, 16 | idft_2d, 17 | idft, 18 | idht, 19 | idwht, 20 | sdft_kw, 21 | sdft, 22 | stft, 23 | swift 24 | } 25 | ); -------------------------------------------------------------------------------- /src/transforms/fourier/swift.rs: -------------------------------------------------------------------------------- 1 | use num::{complex::ComplexFloat, traits::MulAddAssign, Complex}; 2 | 3 | use crate::quantities::ListOrSingle; 4 | 5 | pub trait Swift: ComplexFloat 6 | where 7 | Complex: Into, 8 | T: ComplexFloat, 9 | X: ListOrSingle, 10 | { 11 | fn swift(&mut self, x: X, omega: T::Real, tau: T::Real); 12 | } 13 | 14 | impl Swift for Complex 15 | where 16 | T: ComplexFloat, 17 | X: ListOrSingle, 18 | Complex: MulAddAssign, T> 19 | { 20 | fn swift(&mut self, x: X, omega: T::Real, tau: T::Real) 21 | { 22 | let w = Complex::from_polar((-tau.recip()).exp(), omega); 23 | for &x in x.as_view_slice() 24 | { 25 | self.mul_add_assign(w, x) 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/transforms/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | sampled_to_continuous, 4 | }, 5 | pub mod { 6 | bspline, 7 | domain, 8 | filter, 9 | fourier, 10 | system, 11 | window 12 | } 13 | ); -------------------------------------------------------------------------------- /src/transforms/sampled_to_continuous.rs: -------------------------------------------------------------------------------- 1 | use core::{iter::Sum, ops::Mul}; 2 | 3 | use num::{complex::ComplexFloat, traits::FloatConst, Float, NumCast, One, Zero}; 4 | use option_trait::Maybe; 5 | 6 | use crate::quantities::{IntoList, List, ListOrSingle}; 7 | 8 | pub trait SampledToContinuous: List 9 | where 10 | T: ComplexFloat, 11 | L: ListOrSingle, 12 | R: IntoList, 13 | N: Maybe 14 | { 15 | fn sampled_to_continuous(self, t: R, numtaps: N, sampling_rate: T::Real) -> (L::Mapped, L); 16 | } 17 | 18 | impl SampledToContinuous for LL 19 | where 20 | LL: List, 21 | T: ComplexFloat + Mul + Sum, 22 | L: ListOrSingle, 23 | R: IntoList, 24 | N: Maybe 25 | { 26 | fn sampled_to_continuous(self, t: R, numtaps: N, sampling_rate: T::Real) -> (L::Mapped, L) 27 | { 28 | let t = t.into_list(numtaps); 29 | 30 | let xt = t.map_to_owned(|&t| { 31 | self.to_vec() 32 | .into_iter() 33 | .enumerate() 34 | .map(|(i, x)| { 35 | let n = t*sampling_rate - ::from(i).unwrap(); 36 | let sinc = if n.is_zero() || n.is_subnormal() 37 | { 38 | T::Real::one() 39 | } 40 | else 41 | { 42 | Float::sin(T::Real::PI()*n)/(T::Real::PI()*n) 43 | }; 44 | 45 | x*sinc 46 | }).sum::() 47 | }); 48 | 49 | (xt, t) 50 | } 51 | } 52 | 53 | #[cfg(test)] 54 | mod test 55 | { 56 | use array_math::ArrayOps; 57 | 58 | use crate::{plot, transforms::SampledToContinuous}; 59 | 60 | #[test] 61 | fn test() 62 | { 63 | let xn = [1.0, 2.0, 3.0, 4.0, 5.0]; 64 | let n = core::array::from_fn(|i| i as f64); 65 | 66 | const N: usize = 1024; 67 | let (xt, t): (_, [_; N]) = xn.sampled_to_continuous(0.0..5.0, (), 1.0); 68 | 69 | plot::plot_curves("x(t)", "plots/x_t_sampled_to_continuous.png", [&t.zip(xt), &n.zip(xn)]) 70 | .unwrap(); 71 | } 72 | } -------------------------------------------------------------------------------- /src/transforms/system/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | to_sos, 4 | to_ss, 5 | to_tf, 6 | to_zpk 7 | } 8 | ); -------------------------------------------------------------------------------- /src/transforms/window/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | to_kw 4 | } 5 | ); -------------------------------------------------------------------------------- /src/util/complex_op.rs: -------------------------------------------------------------------------------- 1 | use num::{complex::ComplexFloat, traits::FloatConst, Complex, Float}; 2 | 3 | pub trait ComplexOp: ComplexFloat + Into<>::Output> 4 | where 5 | Rhs: ComplexFloat + Into<>::Output> 6 | { 7 | type Output: ComplexFloat; 8 | } 9 | 10 | impl ComplexOp for T 11 | where 12 | T: ComplexFloat 13 | { 14 | type Output = T; 15 | } 16 | impl ComplexOp for Complex 17 | where 18 | T: Float + FloatConst 19 | { 20 | type Output = Complex; 21 | } 22 | impl ComplexOp> for T 23 | where 24 | T: Float + FloatConst 25 | { 26 | type Output = Complex; 27 | } -------------------------------------------------------------------------------- /src/util/len_eq.rs: -------------------------------------------------------------------------------- 1 | pub trait LenEq {} 2 | 3 | impl LenEq for usize {} -------------------------------------------------------------------------------- /src/util/not_range.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Range, RangeInclusive}; 2 | 3 | pub auto trait NotRange 4 | { 5 | 6 | } 7 | 8 | impl !NotRange for Range 9 | { 10 | 11 | } 12 | impl !NotRange for RangeInclusive 13 | { 14 | 15 | } -------------------------------------------------------------------------------- /src/util/result_or_ok.rs: -------------------------------------------------------------------------------- 1 | pub trait ResultOrOk 2 | where 3 | T: ?Sized, 4 | E: ?Sized 5 | { 6 | fn into_result(self) -> Result 7 | where 8 | Self: Sized, 9 | T: Sized, 10 | E: Sized; 11 | fn as_result(&self) -> Result<&T, &E>; 12 | fn as_result_mut(&mut self) -> Result<&mut T, &mut E>; 13 | } 14 | 15 | impl ResultOrOk for T 16 | { 17 | fn into_result(self) -> Result 18 | where 19 | Self: Sized, 20 | T: Sized, 21 | E: Sized 22 | { 23 | Ok(self) 24 | } 25 | fn as_result(&self) -> Result<&T, &E> 26 | { 27 | Ok(self) 28 | } 29 | fn as_result_mut(&mut self) -> Result<&mut T, &mut E> 30 | { 31 | Ok(self) 32 | } 33 | } 34 | impl ResultOrOk for Result 35 | { 36 | fn into_result(self) -> Result 37 | where 38 | Self: Sized, 39 | T: Sized, 40 | E: Sized 41 | { 42 | self 43 | } 44 | fn as_result(&self) -> Result<&T, &E> 45 | { 46 | self.as_ref() 47 | } 48 | fn as_result_mut(&mut self) -> Result<&mut T, &mut E> 49 | { 50 | self.as_mut() 51 | } 52 | } -------------------------------------------------------------------------------- /src/util/truncate_im.rs: -------------------------------------------------------------------------------- 1 | use core::any::Any; 2 | 3 | use num::complex::ComplexFloat; 4 | 5 | pub trait TruncateIm: ComplexFloat 6 | { 7 | fn truncate_im(self) -> T 8 | where 9 | T: ComplexFloat + 'static, 10 | Self::Real: Into; 11 | } 12 | 13 | impl TruncateIm for C 14 | where 15 | Self: ComplexFloat + 'static 16 | { 17 | fn truncate_im(self) -> T 18 | where 19 | T: ComplexFloat + 'static, 20 | Self::Real: Into 21 | { 22 | let mut t = T::zero(); 23 | if let Some(t) = ::downcast_mut::(&mut t as &mut dyn Any) 24 | { 25 | *t = self 26 | } 27 | else 28 | { 29 | t = self.re().into() 30 | } 31 | t 32 | } 33 | } -------------------------------------------------------------------------------- /src/util/two_sided_range.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Range, RangeBounds, RangeInclusive}; 2 | 3 | pub trait TwoSidedRange: RangeBounds 4 | { 5 | fn start(&self) -> &T; 6 | fn end(&self) -> &T; 7 | fn is_end_inclusive(&self) -> bool; 8 | } 9 | 10 | impl TwoSidedRange for Range where Self: RangeBounds 11 | { 12 | fn end(&self) -> &T 13 | { 14 | &self.end 15 | } 16 | fn start(&self) -> &T 17 | { 18 | &self.start 19 | } 20 | fn is_end_inclusive(&self) -> bool 21 | { 22 | false 23 | } 24 | } 25 | impl TwoSidedRange for RangeInclusive where Self: RangeBounds 26 | { 27 | fn end(&self) -> &T 28 | { 29 | self.end() 30 | } 31 | fn start(&self) -> &T 32 | { 33 | self.start() 34 | } 35 | fn is_end_inclusive(&self) -> bool 36 | { 37 | true 38 | } 39 | } -------------------------------------------------------------------------------- /src/validate_filter_bands.rs: -------------------------------------------------------------------------------- 1 | use num::Float; 2 | 3 | use crate::gen::filter::FilterBandError; 4 | 5 | pub(crate) fn validate_filter_bands( 6 | passband_frequencies: &[T; F], 7 | stopband_frequencies: &[T; F], 8 | sampling_frequency: Option 9 | ) -> Result<(), FilterBandError> 10 | where 11 | T: Float 12 | { 13 | if let Some(sampling_frequency) = sampling_frequency 14 | { 15 | if !(sampling_frequency > T::zero()) || !sampling_frequency.is_finite() 16 | { 17 | return Err(FilterBandError::InvalidSamplingFrequency) 18 | } 19 | } 20 | if !passband_frequencies.is_sorted() 21 | { 22 | return Err(FilterBandError::EdgesNotNondecreasing) 23 | } 24 | if !stopband_frequencies.is_sorted() 25 | { 26 | return Err(FilterBandError::EdgesNotNondecreasing) 27 | } 28 | /*if passband_frequencies.iter() 29 | .any(|f| *f < T::zero() || *f > T::one()) 30 | { 31 | return Err(FilterBandError::EdgesOutOfRange) 32 | }*/ 33 | /*if stopband_frequencies.iter() 34 | .any(|f| *f < T::zero() || *f > T::one()) 35 | { 36 | return Err(FilterBandError::EdgesOutOfRange) 37 | }*/ 38 | 39 | Ok(()) 40 | } -------------------------------------------------------------------------------- /src/windows/boxcar.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | use num::{traits::FloatConst, Float}; 5 | 6 | use crate::gen::window::{WindowGen, WindowRange}; 7 | 8 | pub struct Boxcar; 9 | 10 | impl WindowGen for Boxcar 11 | where 12 | T: Float + FloatConst 13 | { 14 | type Output = [T; N]; 15 | 16 | fn window_gen(&self, (): (), _: WindowRange) -> Self::Output 17 | { 18 | [T::one(); N] 19 | } 20 | } 21 | impl WindowGen, usize> for Boxcar 22 | where 23 | T: Float + FloatConst 24 | { 25 | type Output = Vec; 26 | 27 | fn window_gen(&self, n: usize, _: WindowRange) -> Self::Output 28 | { 29 | vec![T::one(); n] 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod test 35 | { 36 | use core::f64::consts::{PI, TAU}; 37 | 38 | use array_math::ArrayOps; 39 | use linspace::LinspaceArray; 40 | 41 | use crate::{plot, gen::window::{WindowGen, WindowRange}, analysis::FreqZ, systems::Tf}; 42 | 43 | use super::Boxcar; 44 | 45 | #[test] 46 | fn test() 47 | { 48 | const N: usize = 1024; 49 | let w: [_; N/2] = Boxcar.window_gen((), WindowRange::Symmetric); 50 | let n = (0.0..1.0).linspace_array(); 51 | 52 | plot::plot_curves("g(n/N)", "plots/windows/g_n_boxcar.png", [&n.zip(w)]).unwrap(); 53 | 54 | let (mut w_f, mut omega): ([_; N], _) = Tf::new(w, ()).freqz((), false); 55 | omega.map_assign(|omega| (omega + PI) % TAU - PI); 56 | w_f.rotate_right(N/2); 57 | omega.rotate_right(N/2); 58 | 59 | plot::plot_curves("G(e^jw)", "plots/windows/g_f_boxcar.png", [&omega.zip(w_f.map(|w| 20.0*w.norm().log10()))]).unwrap(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/windows/mod.rs: -------------------------------------------------------------------------------- 1 | moddef::moddef!( 2 | flat(pub) mod { 3 | barthann, 4 | blackman_harris, 5 | blackman_nuttall, 6 | blackman, 7 | bohman, 8 | boxcar, 9 | confined_gaussian, 10 | confined_normal, 11 | dolph_chebyshev, 12 | flattop, 13 | gaussian, 14 | hamming, 15 | hann, 16 | kaiser, 17 | normal, 18 | nuttall, 19 | parzen, 20 | planck_taper, 21 | power_of_sine, 22 | sine, 23 | triangular, 24 | tukey, 25 | ultraspherical, 26 | welch 27 | } 28 | ); --------------------------------------------------------------------------------