diff --git a/.github/license_header.txt b/.github/license_header.txt new file mode 100644 index 0000000..7719530 --- /dev/null +++ b/.github/license_header.txt @@ -0,0 +1,3 @@ +Copyright (C) 2024 Analog Devices, Inc. + +SPDX short identifier: ADIBSD OR GPL-2.0-or-later diff --git a/.github/workflows/.pre-commit-config.yaml b/.github/workflows/.pre-commit-config.yaml deleted file mode 100644 index 2e5f622..0000000 --- a/.github/workflows/.pre-commit-config.yaml +++ /dev/null @@ -1,12 +0,0 @@ -repos: -- repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.1 - hooks: - - id: insert-license - files: bindings\/python\/genalyzer\/.*\.py$ - args: - - --license-filepath - - .github/license_header.txt - - --use-current-year - - --no-extra-eol - - --detect-license-in-X-top-lines=3 \ No newline at end of file diff --git a/.github/workflows/license_header.txt b/.github/workflows/license_header.txt deleted file mode 100644 index f3eb502..0000000 --- a/.github/workflows/license_header.txt +++ /dev/null @@ -1,3 +0,0 @@ -Copyright (C) 2024 Analog Devices, Inc. - -SPDX short identifier: ADIBSD \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..9f85750 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,33 @@ +repos: +- repo: https://github.com/Lucas-C/pre-commit-hooks + rev: v1.5.1 + hooks: + - id: insert-license + files: bindings\/python\/genalyzer\/.*\.py$ + args: + - --license-filepath + - .github/license_header.txt + - --use-current-year + - --no-extra-eol + - --detect-license-in-X-top-lines=3 + - id: insert-license + files: ^(?!tests\/|examples\/).*\.((hpp|h|cpp|c))$ + args: + - --comment-style + - // + - --license-filepath + - .github/license_header.txt + - --use-current-year + - --no-extra-eol + - --detect-license-in-X-top-lines=3 +- repo: https://github.com/cmake-lint/cmake-lint + rev: 1.4.3 + hooks: + - id: cmakelint + args: + - --linelength=200 + - --filter=-readability/mixedcase,-package/consistency +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v19.1.5 + hooks: + - id: clang-format \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f0cc5f6..f5645b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ if(BUILD_TESTS_EXAMPLES) # Add custom target to run tests with coverage add_custom_target( coverage - COMMAND ${CMAKE_CTEST_COMMAND} --progress && lcov -c -d bindings/c/src -o main_coverage.info && genhtml main_coverage.info -o coverage + COMMAND ${CMAKE_CTEST_COMMAND} --progress && lcov -c -d bindings/c/src -o main_coverage.info && genhtml main_coverage.info -o coverage WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) message(STATUS "Coverage flags enabled") diff --git a/bindings/c/include/cgenalyzer.h b/bindings/c/include/cgenalyzer.h index 4881829..036941f 100644 --- a/bindings/c/include/cgenalyzer.h +++ b/bindings/c/include/cgenalyzer.h @@ -1,24 +1,6 @@ -/* - * cgenalyzer - genalyzer API header file - * - * Copyright (C) 2022 Analog Devices, Inc. - * Author: Peter Derounian - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * */ - +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef CGENALYZER_H #define CGENALYZER_H @@ -30,10 +12,11 @@ /** * \mainpage Genalyzer Library API Documentation * \section Overview - * The Genalyzer Library provides analysis routines for data converter testing. The - * library contains routines that analyze waveforms, FFTs, and the output of the traditional code - * density tests: histogram, DNL, and INL. In addition, the library provides basic signal - * generation and processing utilties. + * The Genalyzer Library provides analysis routines for data converter testing. + * The library contains routines that analyze waveforms, FFTs, and the output + * of the traditional code density tests: histogram, DNL, and INL. In + * addition, the library provides basic signal generation and processing + * utilties. * \section AnalysisRoutines Analysis Routines * The library provides the following types of analysis: * \li \ref gn_dnl_analysis "DNL Analysis" @@ -41,121 +24,134 @@ * \li \ref gn_hist_analysis "Histogram Analysis" * \li \ref gn_inl_analysis "INL Analysis" * \li \ref gn_wf_analysis "Waveform Analysis" - * - * Each analysis routine returns results by filling a Keys array (rkeys) and a corresponding Values - * array (rvalues). Together, rkeys and rvalues represent a set of key-value result pairs: - * rkeys[0] corresponds to rvalues[0], rkeys[1] to rvalues[1], and so on. + * + * Each analysis routine returns results by filling a Keys array (rkeys) and a + * corresponding Values array (rvalues). Together, rkeys and rvalues represent + * a set of key-value result pairs: rkeys[0] corresponds to rvalues[0], + * rkeys[1] to rvalues[1], and so on. */ /* Enumerations */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup Enumerations Enumerations - * @{ - */ + /** + * \defgroup Enumerations Enumerations + * @{ + */ -/** - * @brief GnAnalysisType enumerates analysis types - */ -typedef enum GnAnalysisType { - GnAnalysisTypeDNL, ///< DNL (differential nonlinearity) - GnAnalysisTypeFourier, ///< Fourier (FFT) - GnAnalysisTypeHistogram, ///< Histogram - GnAnalysisTypeINL, ///< INL (integral nonlinearity) - GnAnalysisTypeWaveform ///< Waveform - } GnAnalysisType; + /** + * @brief GnAnalysisType enumerates analysis types + */ + typedef enum GnAnalysisType + { + GnAnalysisTypeDNL, ///< DNL (differential nonlinearity) + GnAnalysisTypeFourier, ///< Fourier (FFT) + GnAnalysisTypeHistogram, ///< Histogram + GnAnalysisTypeINL, ///< INL (integral nonlinearity) + GnAnalysisTypeWaveform ///< Waveform + } GnAnalysisType; -/** - * @brief GnCodeFormat enumerates binary code formats - */ -typedef enum GnCodeFormat { - GnCodeFormatOffsetBinary, ///< Offset Binary - GnCodeFormatTwosComplement ///< Two's Complement - } GnCodeFormat; + /** + * @brief GnCodeFormat enumerates binary code formats + */ + typedef enum GnCodeFormat + { + GnCodeFormatOffsetBinary, ///< Offset Binary + GnCodeFormatTwosComplement ///< Two's Complement + } GnCodeFormat; -/** - * @brief GnDnlSignal enumerates signal types for which DNL can be computed - */ -typedef enum GnDnlSignal { - GnDnlSignalRamp, ///< Ramp - GnDnlSignalTone ///< Tone (Sinusoid) - } GnDnlSignal; + /** + * @brief GnDnlSignal enumerates signal types for which DNL can be computed + */ + typedef enum GnDnlSignal + { + GnDnlSignalRamp, ///< Ramp + GnDnlSignalTone ///< Tone (Sinusoid) + } GnDnlSignal; -/** - * @brief GnFACompTag enumerates Fourier analysis component tags - */ -typedef enum GnFACompTag { - GnFACompTagDC, ///< DC component (always Bin 0) - GnFACompTagSignal, ///< Signal component - GnFACompTagHD, ///< Harmonic distortion - GnFACompTagIMD, ///< Intermodulation distortion - GnFACompTagILOS, ///< Interleaving offset component - GnFACompTagILGT, ///< Interleaving gain/timing/BW component - GnFACompTagCLK, ///< Clock component - GnFACompTagUserDist, ///< User-designated distortion - GnFACompTagNoise ///< Noise component (e.g. WorstOther) - } GnFACompTag; + /** + * @brief GnFACompTag enumerates Fourier analysis component tags + */ + typedef enum GnFACompTag + { + GnFACompTagDC, ///< DC component (always Bin 0) + GnFACompTagSignal, ///< Signal component + GnFACompTagHD, ///< Harmonic distortion + GnFACompTagIMD, ///< Intermodulation distortion + GnFACompTagILOS, ///< Interleaving offset component + GnFACompTagILGT, ///< Interleaving gain/timing/BW component + GnFACompTagCLK, ///< Clock component + GnFACompTagUserDist, ///< User-designated distortion + GnFACompTagNoise ///< Noise component (e.g. WorstOther) + } GnFACompTag; -/** - * @brief GnFASsb enumerates the component categories for which the number of single side bins - * (SSB) can be set - */ -typedef enum GnFASsb { - GnFASsbDefault, ///< Default SSB (applies to auto-generated components) - GnFASsbDC, ///< SSB for DC component - GnFASsbSignal, ///< SSB for Signal components - GnFASsbWO, ///< SSB for WorstOther components - } GnFASsb; + /** + * @brief GnFASsb enumerates the component categories for which the number of + * single side bins (SSB) can be set + */ + typedef enum GnFASsb + { + GnFASsbDefault, ///< Default SSB (applies to auto-generated components) + GnFASsbDC, ///< SSB for DC component + GnFASsbSignal, ///< SSB for Signal components + GnFASsbWO, ///< SSB for WorstOther components + } GnFASsb; -/** - * @brief GnFreqAxisFormat enumerates frequency axis formats - */ -typedef enum GnFreqAxisFormat { - GnFreqAxisFormatBins, ///< Bins - GnFreqAxisFormatFreq, ///< Frequency - GnFreqAxisFormatNorm ///< Normalized - } GnFreqAxisFormat; + /** + * @brief GnFreqAxisFormat enumerates frequency axis formats + */ + typedef enum GnFreqAxisFormat + { + GnFreqAxisFormatBins, ///< Bins + GnFreqAxisFormatFreq, ///< Frequency + GnFreqAxisFormatNorm ///< Normalized + } GnFreqAxisFormat; -/** - * @brief GnFreqAxisType enumerates frequency axis types - */ -typedef enum GnFreqAxisType { - GnFreqAxisTypeDcCenter, ///< DC centered, e.g. [-fs/2, fs/2) (complex FFT only) - GnFreqAxisTypeDcLeft, ///< DC on left, e.g. [0, fs) (complex FFT only) - GnFreqAxisTypeReal ///< Real axis, e.g. [0, fs/2] (real FFT only) - } GnFreqAxisType; + /** + * @brief GnFreqAxisType enumerates frequency axis types + */ + typedef enum GnFreqAxisType + { + GnFreqAxisTypeDcCenter, ///< DC centered, e.g. [-fs/2, fs/2) (complex FFT + ///< only) + GnFreqAxisTypeDcLeft, ///< DC on left, e.g. [0, fs) (complex FFT only) + GnFreqAxisTypeReal ///< Real axis, e.g. [0, fs/2] (real FFT only) + } GnFreqAxisType; -/** - * @brief GnInlLineFit enumerates INL line fitting options - */ -typedef enum GnInlLineFit { - GnInlLineFitBestFit, ///< Best fit - GnInlLineFitEndFit, ///< End fit - GnInlLineFitNoFit ///< No fit - } GnInlLineFit; + /** + * @brief GnInlLineFit enumerates INL line fitting options + */ + typedef enum GnInlLineFit + { + GnInlLineFitBestFit, ///< Best fit + GnInlLineFitEndFit, ///< End fit + GnInlLineFitNoFit ///< No fit + } GnInlLineFit; -/** - * @brief GnRfftScale enumerates real FFT scaling options - */ -typedef enum GnRfftScale { - GnRfftScaleDbfsDc, ///< Full-scale sinusoid measures -3 dBFS - GnRfftScaleDbfsSin, ///< Full-scale sinusoid measures 0 dBFS - GnRfftScaleNative ///< Full-scale sinusoid measures -6 dBFS - } GnRfftScale; + /** + * @brief GnRfftScale enumerates real FFT scaling options + */ + typedef enum GnRfftScale + { + GnRfftScaleDbfsDc, ///< Full-scale sinusoid measures -3 dBFS + GnRfftScaleDbfsSin, ///< Full-scale sinusoid measures 0 dBFS + GnRfftScaleNative ///< Full-scale sinusoid measures -6 dBFS + } GnRfftScale; -/** - * @brief GnWindow enumerates window functions - */ -typedef enum GnWindow { - GnWindowBlackmanHarris, ///< Blackman-Harris - GnWindowHann, ///< Hann ("Hanning") - GnWindowNoWindow ///< No window (Rectangular) - } GnWindow; + /** + * @brief GnWindow enumerates window functions + */ + typedef enum GnWindow + { + GnWindowBlackmanHarris, ///< Blackman-Harris + GnWindowHann, ///< Hann ("Hanning") + GnWindowNoWindow ///< No window (Rectangular) + } GnWindow; -/** @} Enumerations */ + /** @} Enumerations */ #ifdef __cplusplus } // extern "C" @@ -163,14 +159,15 @@ typedef enum GnWindow { /* API Utilities */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifdef _WIN32 #ifdef GENALYZER_EXPORTS -#define __api __declspec(dllexport) +#define __api __declspec (dllexport) #else -#define __api __declspec(dllimport) +#define __api __declspec (dllimport) #endif #elif __GNUC__ >= 4 && !defined(MATLAB_MEX_FILE) \ && !defined(MATLAB_LOADLIBRARY) @@ -179,115 +176,118 @@ extern "C" { #define __api #endif -/** - * \defgroup APIUtilities API Utilities - * @{ - */ + /** + * \defgroup APIUtilities API Utilities + * @{ + */ -/** - * @brief gn_analysis_results_key_sizes - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the key sizes. See \ref gn_set_string_termination. - */ -__api int gn_analysis_results_key_sizes( - size_t* key_sizes, ///< [out] Key size array pointer - size_t key_sizes_size, ///< [in] Key size array size - GnAnalysisType type ///< [in] Analysis type - ); + /** + * @brief gn_analysis_results_key_sizes + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the key sizes. See \ref + * gn_set_string_termination. + */ + __api int gn_analysis_results_key_sizes ( + size_t *key_sizes, ///< [out] Key size array pointer + size_t key_sizes_size, ///< [in] Key size array size + GnAnalysisType type ///< [in] Analysis type + ); -/** - * @brief gn_analysis_results_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_analysis_results_size( - size_t* size, ///< [out] Number of key-value result pairs - GnAnalysisType type ///< [in] Analysis type - ); + /** + * @brief gn_analysis_results_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_analysis_results_size ( + size_t *size, ///< [out] Number of key-value result pairs + GnAnalysisType type ///< [in] Analysis type + ); -/** - * @brief gn_enum_value - * @return 0 on success, non-zero otherwise - */ -__api int gn_enum_value( - int* value, ///< [out] Underlying value of enumeration::enumerator - const char* enumeration, ///< [in] Enumeration name - const char* enumerator ///< [in] Enumerator name - ); + /** + * @brief gn_enum_value + * @return 0 on success, non-zero otherwise + */ + __api int gn_enum_value ( + int *value, ///< [out] Underlying value of enumeration::enumerator + const char *enumeration, ///< [in] Enumeration name + const char *enumerator ///< [in] Enumerator name + ); -/** - * @brief gn_error_check - * @return Always returns 0 - */ -__api int gn_error_check( - bool* error ///< [out] true if an error has occurred; false otherwise -); + /** + * @brief gn_error_check + * @return Always returns 0 + */ + __api int gn_error_check ( + bool *error ///< [out] true if an error has occurred; false otherwise + ); -/** - * @brief gn_error_clear - * @return Always returns 0 - */ -__api int gn_error_clear(); + /** + * @brief gn_error_clear + * @return Always returns 0 + */ + __api int gn_error_clear (); -/** - * @brief gn_error_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_error_string( - char* buf, ///< [out] Pointer to character array - size_t size ///< [in] Size of character array - ); + /** + * @brief gn_error_string + * @return 0 on success, non-zero otherwise + */ + __api int gn_error_string (char *buf, ///< [out] Pointer to character array + size_t size ///< [in] Size of character array + ); -/** - * @brief gn_set_string_termination - * @return Always returns 0 - * @details Some functions in this library return strings by filling character buffers (arrays) - * provided by the caller. This function sets a global library setting that determines whether or - * not strings should be null-terminated. If set to true, functions that return strings will - * write a '\0' as the last character. In addition, functions that return the size of a string - * will include the null terminator in the size. - */ -__api int gn_set_string_termination( - bool null_terminated ///< [in] If true, strings are terminated with '\0' -); + /** + * @brief gn_set_string_termination + * @return Always returns 0 + * @details Some functions in this library return strings by filling + * character buffers (arrays) provided by the caller. This function sets a + * global library setting that determines whether or not strings should be + * null-terminated. If set to true, functions that return strings will write + * a '\0' as the last character. In addition, functions that return the size + * of a string will include the null terminator in the size. + */ + __api int gn_set_string_termination ( + bool null_terminated ///< [in] If true, strings are terminated with '\0' + ); -/** - * @brief gn_version_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_version_string( - char* buf, ///< [in,out] Pointer to character array - size_t size ///< [in] Size of character array - ); + /** + * @brief gn_version_string + * @return 0 on success, non-zero otherwise + */ + __api int + gn_version_string (char *buf, ///< [in,out] Pointer to character array + size_t size ///< [in] Size of character array + ); -/** - * \defgroup APIUtilityHelpers Helpers - * @{ - */ + /** + * \defgroup APIUtilityHelpers Helpers + * @{ + */ -/** - * @brief gn_error_string_size - * @return Always returns 0 - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_error_string_size( - size_t* size ///< [out] Number of characters in error string -); + /** + * @brief gn_error_string_size + * @return Always returns 0 + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_error_string_size ( + size_t *size ///< [out] Number of characters in error string + ); -/** - * @brief gn_version_string_size - * @return Always returns 0 - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_version_string_size( - size_t* size ///< [out] Number of characters in version string -); + /** + * @brief gn_version_string_size + * @return Always returns 0 + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_version_string_size ( + size_t *size ///< [out] Number of characters in version string + ); -/** @} APIUtilityHelpers */ + /** @} APIUtilityHelpers */ -/** @} APIUtilities */ + /** @} APIUtilities */ #ifdef __cplusplus } // extern "C" @@ -295,81 +295,76 @@ __api int gn_version_string_size( /* Array Operations */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup ArrayOperations Array Operations - * @{ - */ + /** + * \defgroup ArrayOperations Array Operations + * @{ + */ -/** - * @brief gn_abs - * @return 0 on success, non-zero otherwise - */ -__api int gn_abs( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_abs + * @return 0 on success, non-zero otherwise + */ + __api int gn_abs (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * @brief gn_angle - * @return 0 on success, non-zero otherwise - */ -__api int gn_angle( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_angle + * @return 0 on success, non-zero otherwise + */ + __api int gn_angle (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * @brief gn_db - * @return 0 on success, non-zero otherwise - */ -__api int gn_db( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_db + * @return 0 on success, non-zero otherwise + */ + __api int gn_db (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * @brief gn_db10 - * @return 0 on success, non-zero otherwise - */ -__api int gn_db10( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_db10 + * @return 0 on success, non-zero otherwise + */ + __api int gn_db10 (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * @brief gn_db20 - * @return 0 on success, non-zero otherwise - */ -__api int gn_db20( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_db20 + * @return 0 on success, non-zero otherwise + */ + __api int gn_db20 (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * @brief gn_norm - * @return 0 on success, non-zero otherwise - */ -__api int gn_norm( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_norm + * @return 0 on success, non-zero otherwise + */ + __api int gn_norm (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** @} ArrayOperations */ + /** @} ArrayOperations */ #ifdef __cplusplus } // extern "C" @@ -377,243 +372,244 @@ __api int gn_norm( /* Code Density */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup CodeDensity Code Density - * @{ - */ + /** + * \defgroup CodeDensity Code Density + * @{ + */ -/** - * @brief gn_code_axis - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_axis( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_code_axis + * @return 0 on success, non-zero otherwise + */ + __api int gn_code_axis (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_code_axisx - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_axisx( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - int64_t min, ///< [in] Min code - int64_t max ///< [in] Max code - ); + /** + * @brief gn_code_axisx + * @return 0 on success, non-zero otherwise + */ + __api int gn_code_axisx (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + int64_t min, ///< [in] Min code + int64_t max ///< [in] Max code + ); -/** - * @brief gn_dnl - * @return 0 on success, non-zero otherwise - */ -__api int gn_dnl( - double* dnl, ///< [out] Output array pointer - size_t dnl_size, ///< [in] Output array size - const uint64_t* hist, ///< [in] Input array pointer - size_t hist_size, ///< [in] Input array size - GnDnlSignal type ///< [in] Signal type - ); + /** + * @brief gn_dnl + * @return 0 on success, non-zero otherwise + */ + __api int gn_dnl (double *dnl, ///< [out] Output array pointer + size_t dnl_size, ///< [in] Output array size + const uint64_t *hist, ///< [in] Input array pointer + size_t hist_size, ///< [in] Input array size + GnDnlSignal type ///< [in] Signal type + ); -/** - * @brief gn_dnl_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
min Minumum value - *
max Maximum value - *
avg Average value - *
rms RMS value - *
min_index Index of first occurence of minimum value - *
max_index Index of first occurence of maximum value - *
first_nm_index Index of first non-missing code - *
last_nm_index Index of last non-missing code - *
nm_range Non-missing code range (1 + (last_nm_index - first_nm_index)) - *
- */ -__api int gn_dnl_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const double* dnl, ///< [in] Input array pointer - size_t dnl_size ///< [in] Input array size - ); + /** + * @brief gn_dnl_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general + * description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
min Minumum value + *
max Maximum value + *
avg Average value + *
rms RMS value + *
min_index Index of first occurence of minimum value + *
max_index Index of first occurence of maximum value + *
first_nm_index Index of first non-missing code + *
last_nm_index Index of last non-missing code + *
nm_range Non-missing code range (1 + (last_nm_index + * - first_nm_index)) + *
+ */ + __api int + gn_dnl_analysis (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const double *dnl, ///< [in] Input array pointer + size_t dnl_size ///< [in] Input array size + ); -/** - * @brief gn_hist16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_hist16( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format, ///< [in] Code format - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); + /** + * @brief gn_hist16 + * @return 0 on success, non-zero otherwise + */ + __api int gn_hist16 (uint64_t *hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int16_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format, ///< [in] Code format + bool preserve ///< [in] If true, hist is not cleared + ///< before computing the histogram + ); -/** - * @brief gn_hist32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_hist32( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format, ///< [in] Code format - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); + /** + * @brief gn_hist32 + * @return 0 on success, non-zero otherwise + */ + __api int gn_hist32 (uint64_t *hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int32_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format, ///< [in] Code format + bool preserve ///< [in] If true, hist is not cleared + ///< before computing the histogram + ); -/** - * @brief gn_hist64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_hist64( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format, ///< [in] Code format - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); + /** + * @brief gn_hist64 + * @return 0 on success, non-zero otherwise + */ + __api int gn_hist64 (uint64_t *hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int64_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format, ///< [in] Code format + bool preserve ///< [in] If true, hist is not cleared + ///< before computing the histogram + ); -/** - * @brief gn_histx16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_histx16( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int64_t min, ///< [in] Min code - int64_t max, ///< [in] Max code - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); + /** + * @brief gn_histx16 + * @return 0 on success, non-zero otherwise + */ + __api int gn_histx16 (uint64_t *hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int16_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int64_t min, ///< [in] Min code + int64_t max, ///< [in] Max code + bool preserve ///< [in] If true, hist is not cleared + ///< before computing the histogram + ); -/** - * @brief gn_histx32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_histx32( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int64_t min, ///< [in] Min code - int64_t max, ///< [in] Max code - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); + /** + * @brief gn_histx32 + * @return 0 on success, non-zero otherwise + */ + __api int gn_histx32 (uint64_t *hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int32_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int64_t min, ///< [in] Min code + int64_t max, ///< [in] Max code + bool preserve ///< [in] If true, hist is not cleared + ///< before computing the histogram + ); -/** - * @brief gn_histx64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_histx64( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int64_t min, ///< [in] Min code - int64_t max, ///< [in] Max code - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); + /** + * @brief gn_histx64 + * @return 0 on success, non-zero otherwise + */ + __api int gn_histx64 (uint64_t *hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int64_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int64_t min, ///< [in] Min code + int64_t max, ///< [in] Max code + bool preserve ///< [in] If true, hist is not cleared + ///< before computing the histogram + ); -/** - * @brief gn_hist_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
sum Sum of all histogram bins - *
first_nz_index First non-zero bin - *
last_nz_index Last non-zero bin - *
nz_range Non-zero bin range (1 + (last_nz_index - first_nz_index)) - *
- */ -__api int gn_hist_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const uint64_t* hist, ///< [in] Input array pointer - size_t hist_size ///< [in] Input array size - ); + /** + * @brief gn_hist_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general + * description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
sum Sum of all histogram bins + *
first_nz_index First non-zero bin + *
last_nz_index Last non-zero bin + *
nz_range Non-zero bin range (1 + (last_nz_index - + * first_nz_index)) + *
+ */ + __api int + gn_hist_analysis (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const uint64_t *hist, ///< [in] Input array pointer + size_t hist_size ///< [in] Input array size + ); -/** - * @brief gn_inl - * @return 0 on success, non-zero otherwise - */ -__api int gn_inl( - double* inl, ///< [out] Output array pointer - size_t inl_size, ///< [in] Output array size - const double* dnl, ///< [in] Input array pointer - size_t dnl_size, ///< [in] Input array size - GnInlLineFit fit ///< [in] Line fit type - ); + /** + * @brief gn_inl + * @return 0 on success, non-zero otherwise + */ + __api int gn_inl (double *inl, ///< [out] Output array pointer + size_t inl_size, ///< [in] Output array size + const double *dnl, ///< [in] Input array pointer + size_t dnl_size, ///< [in] Input array size + GnInlLineFit fit ///< [in] Line fit type + ); -/** - * @brief gn_inl_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
min Minumum value - *
max Maximum value - *
min_index Index of first occurence of minimum value - *
max_index Index of first occurence of maximum value - *
- */ -__api int gn_inl_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const double* inl, ///< [in] Input array pointer - size_t inl_size ///< [in] Input array size - ); + /** + * @brief gn_inl_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general + * description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
min Minumum value + *
max Maximum value + *
min_index Index of first occurence of minimum value + *
max_index Index of first occurence of maximum value + *
+ */ + __api int + gn_inl_analysis (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const double *inl, ///< [in] Input array pointer + size_t inl_size ///< [in] Input array size + ); -/** - * \defgroup CodeDensityHelpers Helpers - * @{ - */ + /** + * \defgroup CodeDensityHelpers Helpers + * @{ + */ -/** - * @brief gn_code_density_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_density_size( - size_t* size, ///< [out] Output array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_code_density_size + * @return 0 on success, non-zero otherwise + */ + __api int + gn_code_density_size (size_t *size, ///< [out] Output array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_code_densityx_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_densityx_size( - size_t* size, ///< [out] Output array size - int64_t min, ///< [in] Min code - int64_t max ///< [in] Max code - ); + /** + * @brief gn_code_densityx_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_code_densityx_size (size_t *size, ///< [out] Output array size + int64_t min, ///< [in] Min code + int64_t max ///< [in] Max code + ); -/** @} CodeDensityHelpers */ + /** @} CodeDensityHelpers */ -/** @} CodeDensity */ + /** @} CodeDensity */ #ifdef __cplusplus } // extern "C" @@ -621,473 +617,468 @@ __api int gn_code_densityx_size( /* Fourier Analysis */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup FourierAnalysis Fourier Analysis - * @{ - */ + /** + * \defgroup FourierAnalysis Fourier Analysis + * @{ + */ -/** - * @brief gn_fft_analysis returns all Fourier analysis results - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description Units - *
signaltype Signal type: 0=Real, 1=Complex - *
nfft FFT size - *
datasize Data size - *
fbin Frequency bin size Hz - *
fdata Data rate S/s - *
fsample Sample rate S/s - *
fshift Shift frequency Hz - *
fsnr Full-scale-to-noise ratio (a.k.a. "SNRFS") dB - *
snr Signal-to-noise ratio dB - *
sinad Signal-to-noise-and-distortion ratio dB - *
sfdr Spurious-free dynamic range dB - *
abn Average bin noise dBFS - *
nsd Noise spectral density dBFS/Hz - *
carrierindex Order index of the Carrier tone - *
maxspurindex Order index of the MaxSpur tone - *
ab_width Analysis band width Hz - *
ab_i1 Analysis band first index - *
ab_i2 Analysis band last index - *
{PREFIX}_nbins Number of bins associated with PREFIX - *
{PREFIX}_rss Root-sum-square associated with PREFIX - *
{TONEKEY}:orderindex Tone order index - *
{TONEKEY}:freq Tone frequency Hz - *
{TONEKEY}:ffinal Tone final frequency Hz - *
{TONEKEY}:fwavg Tone weighted-average frequency Hz - *
{TONEKEY}:i1 Tone first index - *
{TONEKEY}:i2 Tone last index - *
{TONEKEY}:nbins Tone number of bins - *
{TONEKEY}:inband 0: tone is in-band; 1: tone is out-of-band - *
{TONEKEY}:mag Tone magnitude - *
{TONEKEY}:mag_dbfs Tone magnitude relative to full-scale dBFS - *
{TONEKEY}:mag_dbc Tone magnitude relative to carrier dBc - *
{TONEKEY}:phase Tone phase rad - *
{TONEKEY}:phase_c Tone phase relative to carrier rad - *
- */ -__api int gn_fft_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - const double* in, ///< [in] Interleaved Re/Im input array pointer - size_t in_size, ///< [in] Input array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); + /** + * @brief gn_fft_analysis returns all Fourier analysis results + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general + * description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description Units
+ * signaltype Signal type: 0=Real, 1=Complex
+ * nfft FFT size
datasize + * Data size
fbin + * Frequency bin size Hz
fdata + * Data rate S/s
fsample + * Sample rate S/s
+ * fshift Shift frequency Hz
fsnr + * Full-scale-to-noise ratio (a.k.a. "SNRFS") dB
snr + * Signal-to-noise ratio dB
sinad + * Signal-to-noise-and-distortion ratio dB
sfdr + * Spurious-free dynamic range dB
abn + * Average bin noise dBFS
nsd + * Noise spectral density dBFS/Hz
+ * carrierindex Order index of the Carrier tone
+ * maxspurindex Order index of the MaxSpur tone
+ * ab_width Analysis band width Hz
ab_i1 + * Analysis band first index
ab_i2 + * Analysis band last index
{PREFIX}_nbins + * Number of bins associated with PREFIX
+ * {PREFIX}_rss Root-sum-square associated with PREFIX + *
{TONEKEY}:orderindex Tone order index
+ * {TONEKEY}:freq Tone frequency Hz
{TONEKEY}:ffinal + * Tone final frequency Hz
+ * {TONEKEY}:fwavg Tone weighted-average frequency Hz
+ * {TONEKEY}:i1 Tone first index
{TONEKEY}:i2 + * Tone last index
+ * {TONEKEY}:nbins Tone number of bins
+ * {TONEKEY}:inband 0: tone is in-band; 1: tone is out-of-band + *
{TONEKEY}:mag Tone magnitude
+ * {TONEKEY}:mag_dbfs Tone magnitude relative to full-scale dBFS + *
{TONEKEY}:mag_dbc Tone magnitude relative to carrier + * dBc
{TONEKEY}:phase Tone phase rad
+ * {TONEKEY}:phase_c Tone phase relative to carrier rad + *
+ */ + __api int gn_fft_analysis ( + char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + const double *in, ///< [in] Interleaved Re/Im input array pointer + size_t in_size, ///< [in] Input array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); -/** - * @brief gn_fft_analysis_select returns select Fourier analysis results - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_analysis_select( - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* in, ///< [in] Interleaved Re/Im input array pointer - size_t in_size, ///< [in] Input array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); + /** + * @brief gn_fft_analysis_select returns select Fourier analysis results + * @return 0 on success, non-zero otherwise + */ + __api int gn_fft_analysis_select ( + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + const char **rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double *in, ///< [in] Interleaved Re/Im input array pointer + size_t in_size, ///< [in] Input array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); -/** - * @brief gn_fft_analysis_single returns a single Fourier analysis result - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_analysis_single( - double* rvalue, ///< [out] Result value - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - const char* rkey, ///< [in] Result key - const double* in, ///< [in] Interleaved Re/Im input array pointer - size_t in_size, ///< [in] Input array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); + /** + * @brief gn_fft_analysis_single returns a single Fourier analysis result + * @return 0 on success, non-zero otherwise + */ + __api int gn_fft_analysis_single ( + double *rvalue, ///< [out] Result value + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + const char *rkey, ///< [in] Result key + const double *in, ///< [in] Interleaved Re/Im input array pointer + size_t in_size, ///< [in] Input array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); -/** - * \defgroup FourierAnalysisConfiguration Configuration - * @{ - */ + /** + * \defgroup FourierAnalysisConfiguration Configuration + * @{ + */ -/** - * @brief gn_fa_analysis_band - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_analysis_band( - const char* obj_key, ///< [in] Object key - double center, ///< [in] Analysis band center - double width ///< [in] Analysis band width - ); + /** + * @brief gn_fa_analysis_band + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_analysis_band (const char *obj_key, ///< [in] Object key + double center, ///< [in] Analysis band center + double width ///< [in] Analysis band width + ); -/** - * @brief gn_fa_analysis_band_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_analysis_band_e( - const char* obj_key, ///< [in] Object key - const char* center, ///< [in] Analysis band center expression - const char* width ///< [in] Analysis band width expression - ); + /** + * @brief gn_fa_analysis_band_e + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_analysis_band_e ( + const char *obj_key, ///< [in] Object key + const char *center, ///< [in] Analysis band center expression + const char *width ///< [in] Analysis band width expression + ); -/** - * @brief gn_fa_clk - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_clk( - const char* obj_key, ///< [in] Object key - const int* clk, ///< [in] Pointer to array of clock divisors - size_t clk_size, ///< [in] Size of array of clock divisors - bool as_noise ///< [in] If true, CLK components will be treated as noise - ); + /** + * @brief gn_fa_clk + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_clk ( + const char *obj_key, ///< [in] Object key + const int *clk, ///< [in] Pointer to array of clock divisors + size_t clk_size, ///< [in] Size of array of clock divisors + bool as_noise ///< [in] If true, CLK components will be treated as noise + ); -/** - * @brief gn_fa_conv_offset - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_conv_offset( - const char* obj_key, ///< [in] Object key - bool enable ///< [in] If true, enable converter offset - ); + /** + * @brief gn_fa_conv_offset + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fa_conv_offset (const char *obj_key, ///< [in] Object key + bool enable ///< [in] If true, enable converter offset + ); -/** - * @brief gn_fa_create - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_create( - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_fa_create + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_create (const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_fa_dc - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_dc( - const char* obj_key, ///< [in] Object key - bool as_dist ///< [in] If true, treat DC as distortion - ); + /** + * @brief gn_fa_dc + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_dc (const char *obj_key, ///< [in] Object key + bool as_dist ///< [in] If true, treat DC as distortion + ); -/** - * @brief gn_fa_fdata - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fdata( - const char* obj_key, ///< [in] Object key - double f ///< [in] fdata - ); + /** + * @brief gn_fa_fdata + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fdata (const char *obj_key, ///< [in] Object key + double f ///< [in] fdata + ); -/** - * @brief gn_fa_fdata_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fdata_e( - const char* obj_key, ///< [in] Object key - const char* f ///< [in] fdata expression - ); + /** + * @brief gn_fa_fdata_e + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fdata_e (const char *obj_key, ///< [in] Object key + const char *f ///< [in] fdata expression + ); -/** - * @brief gn_fa_fixed_tone - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fixed_tone( - const char* obj_key, ///< [in] Object key - const char* comp_key, ///< [in] Component key - GnFACompTag tag, ///< [in] Tag - double freq, ///< [in] Frequency - int ssb ///< [in] Number of single-side bins - ); + /** + * @brief gn_fa_fixed_tone + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fixed_tone (const char *obj_key, ///< [in] Object key + const char *comp_key, ///< [in] Component key + GnFACompTag tag, ///< [in] Tag + double freq, ///< [in] Frequency + int ssb ///< [in] Number of single-side bins + ); -/** - * @brief gn_fa_fixed_tone_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fixed_tone_e( - const char* obj_key, ///< [in] Object key - const char* comp_key, ///< [in] Component key - GnFACompTag tag, ///< [in] Tag - const char* freq, ///< [in] Frequency expression - int ssb ///< [in] Number of single-side bins - ); + /** + * @brief gn_fa_fixed_tone_e + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fa_fixed_tone_e (const char *obj_key, ///< [in] Object key + const char *comp_key, ///< [in] Component key + GnFACompTag tag, ///< [in] Tag + const char *freq, ///< [in] Frequency expression + int ssb ///< [in] Number of single-side bins + ); -/** - * @brief gn_fa_fsample - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fsample( - const char* obj_key, ///< [in] Object key - double f ///< [in] fsample - ); + /** + * @brief gn_fa_fsample + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fsample (const char *obj_key, ///< [in] Object key + double f ///< [in] fsample + ); -/** - * @brief gn_fa_fsample_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fsample_e( - const char* obj_key, ///< [in] Object key - const char* f ///< [in] fsample expression - ); + /** + * @brief gn_fa_fsample_e + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fsample_e (const char *obj_key, ///< [in] Object key + const char *f ///< [in] fsample expression + ); -/** - * @brief gn_fa_fshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fshift( - const char* obj_key, ///< [in] Object key - double f ///< [in] fshift - ); + /** + * @brief gn_fa_fshift + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fshift (const char *obj_key, ///< [in] Object key + double f ///< [in] fshift + ); -/** - * @brief gn_fa_fshift_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fshift_e( - const char* obj_key, ///< [in] Object key - const char* f ///< [in] fshift expression - ); + /** + * @brief gn_fa_fshift_e + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_fshift_e (const char *obj_key, ///< [in] Object key + const char *f ///< [in] fshift expression + ); -/** - * @brief gn_fa_fund_images - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fund_images( - const char* obj_key, ///< [in] Object key - bool enable ///< [in] If true, enable fundamental images - ); + /** + * @brief gn_fa_fund_images + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fa_fund_images (const char *obj_key, ///< [in] Object key + bool enable ///< [in] If true, enable fundamental images + ); -/** - * @brief gn_fa_hd - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_hd( - const char* obj_key, ///< [in] Object key - int n ///< [in] Order of harmonic distortion, i.e., the maximum harmonic - ); + /** + * @brief gn_fa_hd + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_hd ( + const char *obj_key, ///< [in] Object key + int n ///< [in] Order of harmonic distortion, i.e., the maximum harmonic + ); -/** - * @brief gn_fa_ilv - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_ilv( - const char* obj_key, ///< [in] Object key - const int* ilv, ///< [in] Pointer to array of interleaving factors - size_t ilv_size, ///< [in] Size of array of interleaving factors - bool as_noise ///< [in] If true, ILV components will be treated as noise - ); + /** + * @brief gn_fa_ilv + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_ilv ( + const char *obj_key, ///< [in] Object key + const int *ilv, ///< [in] Pointer to array of interleaving factors + size_t ilv_size, ///< [in] Size of array of interleaving factors + bool as_noise ///< [in] If true, ILV components will be treated as noise + ); -/** - * @brief gn_fa_imd - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_imd( - const char* obj_key, ///< [in] Object key - int n ///< [in] Order of intermodulation distortion - ); + /** + * @brief gn_fa_imd + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_imd (const char *obj_key, ///< [in] Object key + int n ///< [in] Order of intermodulation distortion + ); -/** - * @brief gn_fa_load - * @return 0 on success, non-zero otherwise - * @details If obj_key is empty, the object key is derived from filename. - */ -__api int gn_fa_load( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* filename, ///< [in] Filename - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_fa_load + * @return 0 on success, non-zero otherwise + * @details If obj_key is empty, the object key is derived from filename. + */ + __api int gn_fa_load (char *buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char *filename, ///< [in] Filename + const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_fa_max_tone - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_max_tone( - const char* obj_key, ///< [in] Object key - const char* comp_key, ///< [in] Component key - GnFACompTag tag, ///< [in] Tag - int ssb ///< [in] Number of single-side bins - ); + /** + * @brief gn_fa_max_tone + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_max_tone (const char *obj_key, ///< [in] Object key + const char *comp_key, ///< [in] Component key + GnFACompTag tag, ///< [in] Tag + int ssb ///< [in] Number of single-side bins + ); -/** - * @brief gn_fa_preview - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_preview( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - bool cplx ///< [in] If true, preview will include complex components - ); + /** + * @brief gn_fa_preview + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_preview ( + char *buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + bool cplx ///< [in] If true, preview will include complex components + ); -/** - * @brief gn_fa_quad_errors - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_quad_errors( - const char* obj_key, ///< [in] Object key - bool enable ///< [in] If true, enable quadrature errors - ); + /** + * @brief gn_fa_quad_errors + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fa_quad_errors (const char *obj_key, ///< [in] Object key + bool enable ///< [in] If true, enable quadrature errors + ); -/** - * @brief gn_fa_remove_comp - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_remove_comp( - const char* obj_key, ///< [in] Object key - const char* comp_key ///< [in] Component key - ); + /** + * @brief gn_fa_remove_comp + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_remove_comp (const char *obj_key, ///< [in] Object key + const char *comp_key ///< [in] Component key + ); -/** - * @brief gn_fa_reset - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_reset( - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_fa_reset + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_reset (const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_fa_ssb - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_ssb( - const char* obj_key, ///< [in] Object key - GnFASsb group, ///< [in] SSB group - int ssb ///< [in] Number of single-side bins - ); + /** + * @brief gn_fa_ssb + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_ssb (const char *obj_key, ///< [in] Object key + GnFASsb group, ///< [in] SSB group + int ssb ///< [in] Number of single-side bins + ); -/** - * @brief gn_fa_var - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_var( - const char* obj_key, ///< [in] Object key - const char* name, ///< [in] Variable name - double value ///< [in] Variable value - ); + /** + * @brief gn_fa_var + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_var (const char *obj_key, ///< [in] Object key + const char *name, ///< [in] Variable name + double value ///< [in] Variable value + ); -/** - * @brief gn_fa_wo - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_wo( - const char* obj_key, ///< [in] Object key - int n ///< [in] Number of worst others - ); + /** + * @brief gn_fa_wo + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_wo (const char *obj_key, ///< [in] Object key + int n ///< [in] Number of worst others + ); -/** @} FourierAnalysisConfiguration */ + /** @} FourierAnalysisConfiguration */ -/** - * \defgroup FourierAnalysisResults Results - * @{ - */ + /** + * \defgroup FourierAnalysisResults Results + * @{ + */ -/** - * @brief gn_fa_result - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_result( - double* result, ///< [out] Result associated with rkey - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* rvalues, ///< [in] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* rkey ///< [in] Key of desired result -); + /** + * @brief gn_fa_result + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fa_result (double *result, ///< [out] Result associated with rkey + const char **rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double *rvalues, ///< [in] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char *rkey ///< [in] Key of desired result + ); -/** - * @brief gn_fa_result_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_result_string( - char* result, ///< [out] Result string associated with rkey - size_t result_size, ///< [in] Size of result string - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* rvalues, ///< [in] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* rkey ///< [in] Key of desired result -); - -/** @} FourierAnalysisResults */ + /** + * @brief gn_fa_result_string + * @return 0 on success, non-zero otherwise + */ + __api int gn_fa_result_string ( + char *result, ///< [out] Result string associated with rkey + size_t result_size, ///< [in] Size of result string + const char **rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double *rvalues, ///< [in] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char *rkey ///< [in] Key of desired result + ); + + /** @} FourierAnalysisResults */ -/** - * \defgroup FourierAnalysisHelpers Helpers - * @{ - */ + /** + * \defgroup FourierAnalysisHelpers Helpers + * @{ + */ -/** - * @brief gn_fa_load_key_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_fa_load_key_size( - size_t* size, ///< [out] Number of characters in key - const char* filename, ///< [in] Filename - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_fa_load_key_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int + gn_fa_load_key_size (size_t *size, ///< [out] Number of characters in key + const char *filename, ///< [in] Filename + const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_fa_preview_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_fa_preview_size( - size_t* size, ///< [out] Number of characters in compenent list string - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - bool cplx ///< [in] If true, list will include complex components - ); + /** + * @brief gn_fa_preview_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_fa_preview_size ( + size_t *size, ///< [out] Number of characters in compenent list string + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + bool cplx ///< [in] If true, list will include complex components + ); -/** - * @brief gn_fa_result_string_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_fa_result_string_size( - size_t* size, ///< [out] Number of characters result string - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* rvalues, ///< [in] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* rkey ///< [in] Key of desired result - ); + /** + * @brief gn_fa_result_string_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_fa_result_string_size ( + size_t *size, ///< [out] Number of characters result string + const char **rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double *rvalues, ///< [in] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char *rkey ///< [in] Key of desired result + ); -/** - * @brief gn_fft_analysis_results_key_sizes - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the key sizes. See \ref gn_set_string_termination. - */ -__api int gn_fft_analysis_results_key_sizes( - size_t* key_sizes, ///< [out] Key size array pointer - size_t key_sizes_size, ///< [in] Key size array size - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - size_t in_size, ///< [in] Input array size - size_t nfft ///< [in] FFT size - ); + /** + * @brief gn_fft_analysis_results_key_sizes + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the key sizes. See \ref + * gn_set_string_termination. + */ + __api int gn_fft_analysis_results_key_sizes ( + size_t *key_sizes, ///< [out] Key size array pointer + size_t key_sizes_size, ///< [in] Key size array size + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + size_t in_size, ///< [in] Input array size + size_t nfft ///< [in] FFT size + ); -/** - * @brief gn_fft_analysis_results_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_analysis_results_size( - size_t* size, ///< [out] Number of key-value result pairs - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - size_t in_size, ///< [in] Input array size - size_t nfft ///< [in] FFT size - ); + /** + * @brief gn_fft_analysis_results_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_fft_analysis_results_size ( + size_t *size, ///< [out] Number of key-value result pairs + const char + *cfg_id, ///< [in] Configuration identifier (filename or object key) + size_t in_size, ///< [in] Input array size + size_t nfft ///< [in] FFT size + ); -/** @} FourierAnalysisHelpers */ + /** @} FourierAnalysisHelpers */ -/** @} FourierAnalysis */ + /** @} FourierAnalysis */ #ifdef __cplusplus } // extern "C" @@ -1095,182 +1086,181 @@ __api int gn_fft_analysis_results_size( /* Fourier Transforms */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup FourierTransforms Fourier Transforms - * @{ - */ + /** + * \defgroup FourierTransforms Fourier Transforms + * @{ + */ /** - * @brief gn_fft - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const double* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const double* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window ///< [in] Window - ); + * @brief gn_fft + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fft (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const double *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const double *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window ///< [in] Window + ); -/** - * @brief gn_fft16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft16( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int16_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_fft16 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fft16 (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int16_t *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int16_t *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_fft32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft32( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int32_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_fft32 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fft32 (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int32_t *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int32_t *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_fft64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft64( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int64_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_fft64 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fft64 (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int64_t *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int64_t *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_rfft - * @return 0 on success, non-zero otherwise - * @details This function will be implemented in the future. - */ -__api int gn_rfft( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnRfftScale scale ///< [in] Scaling mode - ); + /** + * @brief gn_rfft + * @return 0 on success, non-zero otherwise + * @details This function will be implemented in the future. + */ + __api int + gn_rfft (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnRfftScale scale ///< [in] Scaling mode + ); -/** - * @brief gn_rfft16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft16( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format, ///< [in] Code format - GnRfftScale scale ///< [in] Scaling mode - ); + /** + * @brief gn_rfft16 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_rfft16 (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int16_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format, ///< [in] Code format + GnRfftScale scale ///< [in] Scaling mode + ); -/** - * @brief gn_rfft32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft32( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format, ///< [in] Code format - GnRfftScale scale ///< [in] Scaling mode - ); + /** + * @brief gn_rfft32 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_rfft32 (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int32_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format, ///< [in] Code format + GnRfftScale scale ///< [in] Scaling mode + ); -/** - * @brief gn_rfft64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft64( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format, ///< [in] Code format - GnRfftScale scale ///< [in] Scaling mode - ); + /** + * @brief gn_rfft64 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_rfft64 (double *out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int64_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format, ///< [in] Code format + GnRfftScale scale ///< [in] Scaling mode + ); -/** - * \defgroup FourierTransformHelpers Helpers - * @{ - */ + /** + * \defgroup FourierTransformHelpers Helpers + * @{ + */ -/** - * @brief gn_fft_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_size( - size_t* out_size, ///< [out] Output array size - size_t i_size, ///< [in] In-phase input array size - size_t q_size, ///< [in] Quadrature input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft ///< [in] FFT size - ); + /** + * @brief gn_fft_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_fft_size (size_t *out_size, ///< [out] Output array size + size_t i_size, ///< [in] In-phase input array size + size_t q_size, ///< [in] Quadrature input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft ///< [in] FFT size + ); -/** - * @brief gn_rfft_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft_size( - size_t* out_size, ///< [out] Output array size - size_t in_size, ///< [in] Input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft ///< [in] FFT size - ); + /** + * @brief gn_rfft_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_rfft_size (size_t *out_size, ///< [out] Output array size + size_t in_size, ///< [in] Input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft ///< [in] FFT size + ); -/** @} FourierTransformHelpers */ + /** @} FourierTransformHelpers */ -/** @} FourierTransforms */ + /** @} FourierTransforms */ #ifdef __cplusplus } // extern "C" @@ -1278,89 +1268,86 @@ __api int gn_rfft_size( /* Fourier Utilities */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup FourierUtilities Fourier Utilities - * @{ - */ + /** + * \defgroup FourierUtilities Fourier Utilities + * @{ + */ -/** - * @brief gn_alias - * @return 0 on success, non-zero otherwise - */ -__api int gn_alias( - double* out, ///< [out] Output pointer - double fs, ///< [in] Sample rate (S/s) - double freq, ///< [in] Frequency (Hz) - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); + /** + * @brief gn_alias + * @return 0 on success, non-zero otherwise + */ + __api int gn_alias (double *out, ///< [out] Output pointer + double fs, ///< [in] Sample rate (S/s) + double freq, ///< [in] Frequency (Hz) + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); -/** - * @brief gn_coherent - * @return 0 on success, non-zero otherwise - */ -__api int gn_coherent( - double* out, ///< [out] Output pointer - size_t nfft, ///< [in] FFT size - double fs, ///< [in] Sample rate (S/s) - double freq ///< [in] Desired frequency (Hz) - ); + /** + * @brief gn_coherent + * @return 0 on success, non-zero otherwise + */ + __api int gn_coherent (double *out, ///< [out] Output pointer + size_t nfft, ///< [in] FFT size + double fs, ///< [in] Sample rate (S/s) + double freq ///< [in] Desired frequency (Hz) + ); -/** - * @brief gn_fftshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_fftshift( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_fftshift + * @return 0 on success, non-zero otherwise + */ + __api int gn_fftshift (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * @brief gn_freq_axis - * @return 0 on success, non-zero otherwise - */ -__api int gn_freq_axis( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type, ///< [in] Frequency axis type - double fs, ///< [in] Sample rate (S/s) - GnFreqAxisFormat axis_format ///< [in] Frequency axis format - ); + /** + * @brief gn_freq_axis + * @return 0 on success, non-zero otherwise + */ + __api int + gn_freq_axis (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type, ///< [in] Frequency axis type + double fs, ///< [in] Sample rate (S/s) + GnFreqAxisFormat axis_format ///< [in] Frequency axis format + ); -/** - * @brief gn_ifftshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_ifftshift( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); + /** + * @brief gn_ifftshift + * @return 0 on success, non-zero otherwise + */ + __api int gn_ifftshift (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); -/** - * \defgroup FourierUtilityHelpers Helpers - * @{ - */ + /** + * \defgroup FourierUtilityHelpers Helpers + * @{ + */ -/** - * @brief gn_freq_axis_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_freq_axis_size( - size_t* size, ///< [out] Output array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); + /** + * @brief gn_freq_axis_size + * @return 0 on success, non-zero otherwise + */ + __api int + gn_freq_axis_size (size_t *size, ///< [out] Output array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); -/** @} FourierUtilityHelpers */ + /** @} FourierUtilityHelpers */ -/** @} FourierUtilities */ + /** @} FourierUtilities */ #ifdef __cplusplus } // extern "C" @@ -1368,129 +1355,129 @@ __api int gn_freq_axis_size( /* Manager */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup Manager Manager - * @{ - */ + /** + * \defgroup Manager Manager + * @{ + */ -/** - * @brief gn_mgr_clear - * @return Always returns 0 - */ -__api int gn_mgr_clear(); + /** + * @brief gn_mgr_clear + * @return Always returns 0 + */ + __api int gn_mgr_clear (); -/** - * @brief gn_mgr_compare - * @return 0 on success, non-zero otherwise - */ -__api int gn_mgr_compare( - bool* result, ///< [out] true if the objects are equal, false otherwise - const char* obj_key1, ///< [in] Object key 1 - const char* obj_key2 ///< [in] Object key 2 - ); + /** + * @brief gn_mgr_compare + * @return 0 on success, non-zero otherwise + */ + __api int gn_mgr_compare ( + bool *result, ///< [out] true if the objects are equal, false otherwise + const char *obj_key1, ///< [in] Object key 1 + const char *obj_key2 ///< [in] Object key 2 + ); -/** - * @brief gn_mgr_contains - * @return Always returns 0 - */ -__api int gn_mgr_contains( - bool* result, ///< [out] true if Manager contains key, false otherwise - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_mgr_contains + * @return Always returns 0 + */ + __api int gn_mgr_contains ( + bool *result, ///< [out] true if Manager contains key, false otherwise + const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_mgr_remove - * @return Always returns 0 - */ -__api int gn_mgr_remove( - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_mgr_remove + * @return Always returns 0 + */ + __api int gn_mgr_remove (const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_mgr_save - * @return 0 on success, non-zero otherwise - * @details If filename is empty, the filename is derived from obj_key. - */ -__api int gn_mgr_save( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* obj_key, ///< [in] Object key - const char* filename ///< [in] Filename - ); + /** + * @brief gn_mgr_save + * @return 0 on success, non-zero otherwise + * @details If filename is empty, the filename is derived from obj_key. + */ + __api int gn_mgr_save (char *buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char *obj_key, ///< [in] Object key + const char *filename ///< [in] Filename + ); -/** - * @brief gn_mgr_size - * @return Always returns 0 - */ -__api int gn_mgr_size( - size_t* size ///< [out] Number of objects owned by the manager - ); + /** + * @brief gn_mgr_size + * @return Always returns 0 + */ + __api int + gn_mgr_size (size_t *size ///< [out] Number of objects owned by the manager + ); -/** - * @brief gn_mgr_to_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_mgr_to_string( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_mgr_to_string + * @return 0 on success, non-zero otherwise + */ + __api int gn_mgr_to_string (char *buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_mgr_type - * @return 0 on success, non-zero otherwise - */ -__api int gn_mgr_type( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_mgr_type + * @return 0 on success, non-zero otherwise + */ + __api int gn_mgr_type (char *buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char *obj_key ///< [in] Object key + ); -/** - * \defgroup ManagerHelpers Helpers - * @{ - */ + /** + * \defgroup ManagerHelpers Helpers + * @{ + */ -/** - * @brief gn_mgr_save_filename_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_mgr_save_filename_size( - size_t* size, ///< [out] Number of characters in filename - const char* obj_key, ///< [in] Object key - const char* filename ///< [in] Filename - ); + /** + * @brief gn_mgr_save_filename_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_mgr_save_filename_size ( + size_t *size, ///< [out] Number of characters in filename + const char *obj_key, ///< [in] Object key + const char *filename ///< [in] Filename + ); -/** - * @brief gn_mgr_to_string_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_mgr_to_string_size( - size_t* size, ///< [out] Number of characters in the string - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_mgr_to_string_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_mgr_to_string_size ( + size_t *size, ///< [out] Number of characters in the string + const char *obj_key ///< [in] Object key + ); -/** - * @brief gn_mgr_type_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_mgr_type_size( - size_t* size, ///< [out] Number of characters in object type string - const char* obj_key ///< [in] Object key - ); + /** + * @brief gn_mgr_type_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not + * a null terminator is included in the size. See \ref + * gn_set_string_termination. + */ + __api int gn_mgr_type_size ( + size_t *size, ///< [out] Number of characters in object type string + const char *obj_key ///< [in] Object key + ); -/** @} ManagerHelpers */ + /** @} ManagerHelpers */ -/** @} Manager */ + /** @} Manager */ #ifdef __cplusplus } // extern "C" @@ -1498,258 +1485,251 @@ __api int gn_mgr_type_size( /* Signal Processing */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup SignalProcessing Signal Processing - * @{ - */ + /** + * \defgroup SignalProcessing Signal Processing + * @{ + */ -/** - * @brief gn_downsample - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); + /** + * @brief gn_downsample + * @return 0 on success, non-zero otherwise + */ + __api int gn_downsample ( + double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); -/** - * @brief gn_downsample16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample16( - int16_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); + /** + * @brief gn_downsample16 + * @return 0 on success, non-zero otherwise + */ + __api int gn_downsample16 ( + int16_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int16_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); -/** - * @brief gn_downsample32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample32( - int32_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); + /** + * @brief gn_downsample32 + * @return 0 on success, non-zero otherwise + */ + __api int gn_downsample32 ( + int32_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int32_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); -/** - * @brief gn_downsample64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample64( - int64_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); + /** + * @brief gn_downsample64 + * @return 0 on success, non-zero otherwise + */ + __api int gn_downsample64 ( + int64_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int64_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); -/** - * @brief gn_fshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const double* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - double fs, ///< [in] Sample rate - double fshift ///< [in] Shift frequency - ); + /** + * @brief gn_fshift + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fshift (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const double *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + double fs, ///< [in] Sample rate + double fshift ///< [in] Shift frequency + ); -/** - * @brief gn_fshift16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift16( - int16_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int16_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Code width - double fs, ///< [in] Sample rate - double fshift, ///< [in] Shift frequency - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_fshift16 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fshift16 (int16_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int16_t *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int16_t *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Code width + double fs, ///< [in] Sample rate + double fshift, ///< [in] Shift frequency + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_fshift32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift32( - int32_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int32_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Code width - double fs, ///< [in] Sample rate - double fshift, ///< [in] Shift frequency - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_fshift32 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fshift32 (int32_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int32_t *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int32_t *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Code width + double fs, ///< [in] Sample rate + double fshift, ///< [in] Shift frequency + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_fshift64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift64( - int64_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int64_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Code width - double fs, ///< [in] Sample rate - double fshift, ///< [in] Shift frequency - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_fshift64 + * @return 0 on success, non-zero otherwise + */ + __api int + gn_fshift64 (int64_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int64_t *i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int64_t *q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Code width + double fs, ///< [in] Sample rate + double fshift, ///< [in] Shift frequency + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_normalize16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_normalize16( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_normalize16 + * @return 0 on success, non-zero otherwise + */ + __api int gn_normalize16 (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int16_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_normalize32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_normalize32( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_normalize32 + * @return 0 on success, non-zero otherwise + */ + __api int gn_normalize32 (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int32_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_normalize64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_normalize64( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); + /** + * @brief gn_normalize64 + * @return 0 on success, non-zero otherwise + */ + __api int gn_normalize64 (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int64_t *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_polyval - * @return 0 on success, non-zero otherwise - */ -__api int gn_polyval( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - const double* c, ///< [in] Coefficient array pointer - size_t c_size ///< [in] Coefficient array size - ); + /** + * @brief gn_polyval + * @return 0 on success, non-zero otherwise + */ + __api int gn_polyval (double *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + const double *c, ///< [in] Coefficient array pointer + size_t c_size ///< [in] Coefficient array size + ); -/** - * @brief gn_quantize16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_quantize16( - int16_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - double fsr, ///< [in] Full-scale range - int n, ///< [in] Resolution - double noise, ///< [in] Input referred RMS noise - GnCodeFormat format ///< [in] Code format -); + /** + * @brief gn_quantize16 + * @return 0 on success, non-zero otherwise + */ + __api int gn_quantize16 (int16_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + double fsr, ///< [in] Full-scale range + int n, ///< [in] Resolution + double noise, ///< [in] Input referred RMS noise + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_quantize32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_quantize32( - int32_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - double fsr, ///< [in] Full-scale range - int n, ///< [in] Resolution - double noise, ///< [in] Input referred RMS noise - GnCodeFormat format ///< [in] Code format -); + /** + * @brief gn_quantize32 + * @return 0 on success, non-zero otherwise + */ + __api int gn_quantize32 (int32_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + double fsr, ///< [in] Full-scale range + int n, ///< [in] Resolution + double noise, ///< [in] Input referred RMS noise + GnCodeFormat format ///< [in] Code format + ); -/** - * @brief gn_quantize64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_quantize64( - int64_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - double fsr, ///< [in] Full-scale range - int n, ///< [in] Resolution - double noise, ///< [in] Input referred RMS noise - GnCodeFormat format ///< [in] Code format -); + /** + * @brief gn_quantize64 + * @return 0 on success, non-zero otherwise + */ + __api int gn_quantize64 (int64_t *out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double *in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + double fsr, ///< [in] Full-scale range + int n, ///< [in] Resolution + double noise, ///< [in] Input referred RMS noise + GnCodeFormat format ///< [in] Code format + ); -/** - * \defgroup SignalProcessingHelpers Helpers - * @{ - */ + /** + * \defgroup SignalProcessingHelpers Helpers + * @{ + */ -/** - * @brief gn_downsample_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample_size( - size_t* out_size, ///< [out] Output array size - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If bool, 'in' is interleaved I/Q data - ); + /** + * @brief gn_downsample_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_downsample_size ( + size_t *out_size, ///< [out] Output array size + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If bool, 'in' is interleaved I/Q data + ); -/** - * @brief gn_fshift_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift_size( - size_t* out_size, ///< [out] Output array size - size_t i_size, ///< [in] In-phase input array size - size_t q_size ///< [in] Quadrature input array size - ); + /** + * @brief gn_fshift_size + * @return 0 on success, non-zero otherwise + */ + __api int gn_fshift_size (size_t *out_size, ///< [out] Output array size + size_t i_size, ///< [in] In-phase input array size + size_t q_size ///< [in] Quadrature input array size + ); -/** @} SignalProcessingHelpers */ + /** @} SignalProcessingHelpers */ -/** @} SignalProcessing */ + /** @} SignalProcessing */ #ifdef __cplusplus } // extern "C" @@ -1757,137 +1737,135 @@ __api int gn_fshift_size( /* Waveforms */ #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * \defgroup Waveforms Waveforms - * @{ - */ + /** + * \defgroup Waveforms Waveforms + * @{ + */ -/** - * @brief gn_cos - * @return 0 on success, non-zero otherwise - */ -__api int gn_cos( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double fs, ///< [in] Sample rate (S/s) - double ampl, ///< [in] Amplitude - double freq, ///< [in] Frequency (Hz) - double phase, ///< [in] Phase (rad) - double td, ///< [in] Time delay (s) - double tj ///< [in] RMS Aperture jitter (s) - ); + /** + * @brief gn_cos + * @return 0 on success, non-zero otherwise + */ + __api int gn_cos (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double fs, ///< [in] Sample rate (S/s) + double ampl, ///< [in] Amplitude + double freq, ///< [in] Frequency (Hz) + double phase, ///< [in] Phase (rad) + double td, ///< [in] Time delay (s) + double tj ///< [in] RMS Aperture jitter (s) + ); -/** - * @brief gn_gaussian - * @return 0 on success, non-zero otherwise - */ -__api int gn_gaussian( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double mean, ///< [in] Mean - double sd ///< [in] Standard deviation - ); + /** + * @brief gn_gaussian + * @return 0 on success, non-zero otherwise + */ + __api int gn_gaussian (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double mean, ///< [in] Mean + double sd ///< [in] Standard deviation + ); -/** - * @brief gn_ramp - * @return 0 on success, non-zero otherwise - */ -__api int gn_ramp( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double start, ///< [in] Start value - double stop, ///< [in] Stop value - double noise ///< [in] RMS noise - ); + /** + * @brief gn_ramp + * @return 0 on success, non-zero otherwise + */ + __api int gn_ramp (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double start, ///< [in] Start value + double stop, ///< [in] Stop value + double noise ///< [in] RMS noise + ); -/** - * @brief gn_sin - * @return 0 on success, non-zero otherwise - */ -__api int gn_sin( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double fs, ///< [in] Sample rate (S/s) - double ampl, ///< [in] Amplitude - double freq, ///< [in] Frequency (Hz) - double phase, ///< [in] Phase (rad) - double td, ///< [in] Time delay (s) - double tjrms ///< [in] RMS Aperture jitter (s) - ); + /** + * @brief gn_sin + * @return 0 on success, non-zero otherwise + */ + __api int gn_sin (double *out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double fs, ///< [in] Sample rate (S/s) + double ampl, ///< [in] Amplitude + double freq, ///< [in] Frequency (Hz) + double phase, ///< [in] Phase (rad) + double td, ///< [in] Time delay (s) + double tjrms ///< [in] RMS Aperture jitter (s) + ); -/** - * @brief gn_wf_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
min Minumum value - *
max Maximum value - *
mid Middle value ((max + min) / 2) - *
range Range (max - min) - *
avg Average value - *
rms RMS value - *
rmsac RMS value with DC removed - *
min_index Index of first occurence of minimum value - *
max_index Index of first occurence of maximum value - *
- */ -__api int gn_wf_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const double* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); + /** + * @brief gn_wf_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general + * description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
min Minumum value + *
max Maximum value + *
mid Middle value ((max + min) / 2) + *
range Range (max - min) + *
avg Average value + *
rms RMS value + *
rmsac RMS value with DC removed + *
min_index Index of first occurence of minimum value + *
max_index Index of first occurence of maximum value + *
+ */ + __api int + gn_wf_analysis (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const double *in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); -/** - * @brief gn_wf_analysis16 - * @return 0 on success, non-zero otherwise - * @details See description of \ref gn_wf_analysis. - */ -__api int gn_wf_analysis16( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const int16_t* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); + /** + * @brief gn_wf_analysis16 + * @return 0 on success, non-zero otherwise + * @details See description of \ref gn_wf_analysis. + */ + __api int + gn_wf_analysis16 (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const int16_t *in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); -/** - * @brief gn_wf_analysis32 - * @return 0 on success, non-zero otherwise - * @details See description of \ref gn_wf_analysis. - */ -__api int gn_wf_analysis32( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const int32_t* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); + /** + * @brief gn_wf_analysis32 + * @return 0 on success, non-zero otherwise + * @details See description of \ref gn_wf_analysis. + */ + __api int + gn_wf_analysis32 (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const int32_t *in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); -/** - * @brief gn_wf_analysis64 - * @return 0 on success, non-zero otherwise - * @details See description of \ref gn_wf_analysis. - */ -__api int gn_wf_analysis64( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const int64_t* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); - -/** @} Waveforms */ + /** + * @brief gn_wf_analysis64 + * @return 0 on success, non-zero otherwise + * @details See description of \ref gn_wf_analysis. + */ + __api int + gn_wf_analysis64 (char **rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double *rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const int64_t *in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); + + /** @} Waveforms */ #ifdef __cplusplus } // extern "C" diff --git a/bindings/c/include/cgenalyzer_private.h b/bindings/c/include/cgenalyzer_private.h index 1d0e41a..478083a 100644 --- a/bindings/c/include/cgenalyzer_private.h +++ b/bindings/c/include/cgenalyzer_private.h @@ -1,24 +1,6 @@ -/* - * cgenalyzer_private - genalyzer private header file - * - * Copyright (C) 2022 Analog Devices, Inc. - * Author: Srikanth Pagadarai - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * */ - +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef CGENALYZER_PRIVATE_H #define CGENALYZER_PRIVATE_H @@ -33,10 +15,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -60,172 +42,184 @@ constexpr int gn_failure = 1; namespace gn = ::genalyzer_impl; -namespace util { - - class log - { - public: - - log() - : m_log {}, - m_flag {false} - {} - - public: - - bool check() - { - return m_flag; - } - - void clear() - { - m_log.clear(); - m_flag = false; - } - - std::string_view get() const - { - return m_log; - } - - void set(const char* msg) - { - m_log = msg; - m_flag = true; - } - - size_t size() const - { - return m_log.size(); - } - - public: - - void append() {} - - template - void append(const char* s, Types... the_rest) - { - m_log.append(s); - append(the_rest...); - } - - void prepend() {} - - template - void prepend(const char* s, Types... the_rest) - { - prepend(the_rest...); - m_log.insert(0, s); - } - - private: - - std::string m_log; - bool m_flag; - - }; // class log - - static log gn_error_log; - - template - int return_on_exception(const char* s, Types... the_rest) - { - gn_error_log.set(s); - gn_error_log.append(the_rest...); - return gn_failure; - } +namespace util +{ + +class log +{ +public: + log () : m_log{}, m_flag{ false } {} + +public: + bool + check () + { + return m_flag; + } + + void + clear () + { + m_log.clear (); + m_flag = false; + } + + std::string_view + get () const + { + return m_log; + } + + void + set (const char *msg) + { + m_log = msg; + m_flag = true; + } + + size_t + size () const + { + return m_log.size (); + } + +public: + void + append () + { + } + + template + void + append (const char *s, Types... the_rest) + { + m_log.append (s); + append (the_rest...); + } + + void + prepend () + { + } + + template + void + prepend (const char *s, Types... the_rest) + { + prepend (the_rest...); + m_log.insert (0, s); + } + +private: + std::string m_log; + bool m_flag; + +}; // class log + +static log gn_error_log; + +template +int +return_on_exception (const char *s, Types... the_rest) +{ + gn_error_log.set (s); + gn_error_log.append (the_rest...); + return gn_failure; +} - template - int check_pointer(const T* p) +template +int +check_pointer (const T *p) +{ + if (nullptr == p) { - if (nullptr == p) { - throw std::runtime_error("check_pointer : pointer is NULL"); - } - return gn_success; + throw std::runtime_error ("check_pointer : pointer is NULL"); } + return gn_success; +} - size_t terminated_size(size_t string_size); - void fill_string_buffer( - const char* src, // Pointer to source - size_t src_size, // Size of source; should not count null-terminator, if it exists - char* dst, // Pointer to destination - size_t dst_size // Size of destination - ); - std::string get_object_key_from_filename(const std::string& filename); +size_t terminated_size (size_t string_size); +void fill_string_buffer (const char *src, // Pointer to source + size_t src_size, // Size of source; should not count + // null-terminator, if it exists + char *dst, // Pointer to destination + size_t dst_size // Size of destination +); +std::string get_object_key_from_filename (const std::string &filename); } #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - using namespace genalyzer_impl; - - struct gn_config_private { - bool _gn_config_calloced = false; - - // waveform and FFT settings - tone_type ttype; - gn::size_t npts; - gn::real_t sample_rate; - gn::real_t *tone_freq; - gn::real_t *tone_ampl; - gn::real_t *tone_phase; - gn::size_t num_tones; - gn::real_t fsr; - int qres; - gn::real_t noise_rms; - GnCodeFormat code_format; - gn::size_t nfft; - gn::size_t fft_navg; - GnFreqAxisType axis_type; - gn::real_t data_rate; - gn::real_t shift_freq; - GnWindow win; - gn::real_t ramp_start; - gn::real_t ramp_stop; - - // analysis settings - char *obj_key; - char *comp_key; - int ssb_fund; - int ssb_rest; - int max_harm_order; - GnDnlSignal dnla_signal_type; - GnInlLineFit inla_fit; - gn::size_t _code_density_size; - - // keys, values and sizes for Fourier analysis results - char **_fa_result_keys; - gn::real_t *_fa_result_values; - gn::size_t *_fa_result_key_sizes; - gn::size_t _fa_results_size; - - // keys, values and sizes for waveform analysis results - char **_wfa_result_keys; - gn::real_t *_wfa_result_values; - gn::size_t *_wfa_result_key_sizes; - gn::size_t _wfa_results_size; - - // keys, values and sizes for histogram results - char **_hist_result_keys; - gn::real_t *_hist_result_values; - gn::size_t *_hist_result_key_sizes; - gn::size_t _hist_results_size; - - // keys, values and sizes for DNL results - char **_dnl_result_keys; - gn::real_t *_dnl_result_values; - gn::size_t *_dnl_result_key_sizes; - gn::size_t _dnl_results_size; - - // keys, values and sizes for INL results - char **_inl_result_keys; - gn::real_t *_inl_result_values; - gn::size_t *_inl_result_key_sizes; - gn::size_t _inl_results_size; - }; + using namespace genalyzer_impl; + + struct gn_config_private + { + bool _gn_config_calloced = false; + + // waveform and FFT settings + tone_type ttype; + gn::size_t npts; + gn::real_t sample_rate; + gn::real_t *tone_freq; + gn::real_t *tone_ampl; + gn::real_t *tone_phase; + gn::size_t num_tones; + gn::real_t fsr; + int qres; + gn::real_t noise_rms; + GnCodeFormat code_format; + gn::size_t nfft; + gn::size_t fft_navg; + GnFreqAxisType axis_type; + gn::real_t data_rate; + gn::real_t shift_freq; + GnWindow win; + gn::real_t ramp_start; + gn::real_t ramp_stop; + + // analysis settings + char *obj_key; + char *comp_key; + int ssb_fund; + int ssb_rest; + int max_harm_order; + GnDnlSignal dnla_signal_type; + GnInlLineFit inla_fit; + gn::size_t _code_density_size; + + // keys, values and sizes for Fourier analysis results + char **_fa_result_keys; + gn::real_t *_fa_result_values; + gn::size_t *_fa_result_key_sizes; + gn::size_t _fa_results_size; + + // keys, values and sizes for waveform analysis results + char **_wfa_result_keys; + gn::real_t *_wfa_result_values; + gn::size_t *_wfa_result_key_sizes; + gn::size_t _wfa_results_size; + + // keys, values and sizes for histogram results + char **_hist_result_keys; + gn::real_t *_hist_result_values; + gn::size_t *_hist_result_key_sizes; + gn::size_t _hist_results_size; + + // keys, values and sizes for DNL results + char **_dnl_result_keys; + gn::real_t *_dnl_result_values; + gn::size_t *_dnl_result_key_sizes; + gn::size_t _dnl_results_size; + + // keys, values and sizes for INL results + char **_inl_result_keys; + gn::real_t *_inl_result_values; + gn::size_t *_inl_result_key_sizes; + gn::size_t _inl_results_size; + }; #ifdef __cplusplus } diff --git a/bindings/c/include/cgenalyzer_simplified_beta.h b/bindings/c/include/cgenalyzer_simplified_beta.h index d1d9c73..868b157 100644 --- a/bindings/c/include/cgenalyzer_simplified_beta.h +++ b/bindings/c/include/cgenalyzer_simplified_beta.h @@ -1,24 +1,6 @@ -/* - * cgenalyzer - genalyzer (beta) simplified API header file - * - * Copyright (C) 2022 Analog Devices, Inc. - * Author: Srikanth Pagadarai - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * */ - +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef CGENALYZER_SIMPLIFIED_BETA_H #define CGENALYZER_SIMPLIFIED_BETA_H @@ -33,9 +15,9 @@ extern "C" #ifdef _WIN32 #ifdef GENALYZER_EXPORTS -#define __api __declspec(dllexport) +#define __api __declspec (dllexport) #else -#define __api __declspec(dllimport) +#define __api __declspec (dllimport) #endif #elif __GNUC__ >= 4 && !defined(MATLAB_MEX_FILE) \ && !defined(MATLAB_LOADLIBRARY) @@ -43,15 +25,15 @@ extern "C" #else #define __api #endif - + // opaque pointer typedef struct gn_config_private *gn_config; typedef enum tone_type { - REAL_COSINE, - REAL_SINE, - COMPLEX_EXP + REAL_COSINE, + REAL_SINE, + COMPLEX_EXP } tone_type; /** @@ -59,20 +41,16 @@ extern "C" * @return 0 on success, non-zero otherwise * @param c genalyzer Configuration struct */ - __api int gn_config_free( - gn_config *c - ); + __api int gn_config_free (gn_config *c); /** * @brief set configuration struct member: tone_type * @return 0 on success, non-zero otherwise - * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, REAL_SINE, COMPLEX_EXP + * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, + * REAL_SINE, COMPLEX_EXP * @param c genalyzer Configuration struct */ - __api int gn_config_set_ttype( - tone_type ttype, - gn_config *c - ); + __api int gn_config_set_ttype (tone_type ttype, gn_config *c); /** * @brief set configuration struct member: npts @@ -80,10 +58,7 @@ extern "C" * @param npts Number of sample points in the generated waveform * @param c genalyzer Configuration struct */ - __api int gn_config_set_npts( - size_t npts, - gn_config *c - ); + __api int gn_config_set_npts (size_t npts, gn_config *c); /** * @brief get configuration struct member: npts @@ -91,10 +66,7 @@ extern "C" * @param npts Number of sample points in the generated waveform * @param c genalyzer Configuration struct */ - __api int gn_config_get_npts( - size_t *npts, - gn_config *c - ); + __api int gn_config_get_npts (size_t *npts, gn_config *c); /** * @brief set configuration struct member: sample_rate @@ -102,10 +74,7 @@ extern "C" * @param sample_rate Input Sample rate of the data converter * @param c genalyzer Configuration struct */ - __api int gn_config_set_sample_rate( - double sample_rate, - gn_config *c - ); + __api int gn_config_set_sample_rate (double sample_rate, gn_config *c); /** * @brief get configuration struct member: sample_rate @@ -113,10 +82,7 @@ extern "C" * @param sample_rate Input Sample rate of the data converter * @param c genalyzer Configuration struct */ - __api int gn_config_get_sample_rate( - double *sample_rate, - gn_config *c - ); + __api int gn_config_get_sample_rate (double *sample_rate, gn_config *c); /** * @brief set configuration struct member: data_rate @@ -124,10 +90,7 @@ extern "C" * @param data_rate Input data rate of the data converter * @param c genalyzer Configuration struct */ - __api int gn_config_set_data_rate( - double data_rate, - gn_config *c - ); + __api int gn_config_set_data_rate (double data_rate, gn_config *c); /** * @brief set configuration struct member: shift_freq @@ -135,10 +98,7 @@ extern "C" * @param shift_freq Shift frequency of the data converter * @param c genalyzer Configuration struct */ - __api int gn_config_set_shift_freq( - double shift_freq, - gn_config *c - ); + __api int gn_config_set_shift_freq (double shift_freq, gn_config *c); /** * @brief set configuration struct member: num_tones @@ -146,10 +106,7 @@ extern "C" * @param num_tones Number of tones to generate * @param c genalyzer Configuration struct */ - __api int gn_config_set_num_tones( - size_t num_tones, - gn_config *c - ); + __api int gn_config_set_num_tones (size_t num_tones, gn_config *c); /** * @brief set configuration struct member: tone_freq @@ -157,10 +114,7 @@ extern "C" * @param tone_freq Input array of tone frequencies to generate * @param c genalyzer Configuration struct */ - __api int gn_config_set_tone_freq( - double *tone_freq, - gn_config *c - ); + __api int gn_config_set_tone_freq (double *tone_freq, gn_config *c); /** * @brief set configuration struct member: tone_ampl @@ -168,10 +122,7 @@ extern "C" * @param tone_ampl Input array of tone scales to generate * @param c genalyzer Configuration struct */ - __api int gn_config_set_tone_ampl( - double *tone_ampl, - gn_config *c - ); + __api int gn_config_set_tone_ampl (double *tone_ampl, gn_config *c); /** * @brief set configuration struct member: tone_phase @@ -179,10 +130,7 @@ extern "C" * @param tone_phase Input array of tone phases to generate * @param c genalyzer Configuration struct */ - __api int gn_config_set_tone_phase( - double *tone_phase, - gn_config *c - ); + __api int gn_config_set_tone_phase (double *tone_phase, gn_config *c); /** * @brief set configuration struct member: fsr @@ -190,10 +138,7 @@ extern "C" * @param fsr Full-scale range of the waveform * @param c genalyzer Configuration struct */ - __api int gn_config_set_fsr( - double fsr, - gn_config *c - ); + __api int gn_config_set_fsr (double fsr, gn_config *c); /** * @brief set configuration struct member: qres @@ -201,10 +146,7 @@ extern "C" * @param qres Quantization resolution * @param c genalyzer Configuration struct */ - __api int gn_config_set_qres( - int qres, - gn_config *c - ); + __api int gn_config_set_qres (int qres, gn_config *c); /** * @brief set configuration struct member: noise_rms @@ -212,10 +154,7 @@ extern "C" * @param noise_rms RMS Noise * @param c genalyzer Configuration struct */ - __api int gn_config_set_noise_rms( - double noise_rms, - gn_config *c - ); + __api int gn_config_set_noise_rms (double noise_rms, gn_config *c); /** * @brief set configuration struct member: code_format @@ -223,10 +162,7 @@ extern "C" * @param code_format Code format of data * @param c genalyzer Configuration struct */ - __api int gn_config_set_code_format( - GnCodeFormat code_format, - gn_config *c - ); + __api int gn_config_set_code_format (GnCodeFormat code_format, gn_config *c); /** * @brief set configuration struct member: nfft @@ -234,10 +170,7 @@ extern "C" * @param nfft FFT order * @param c genalyzer Configuration struct */ - __api int gn_config_set_nfft( - size_t nfft, - gn_config *c - ); + __api int gn_config_set_nfft (size_t nfft, gn_config *c); /** * @brief get configuration struct member: nfft @@ -245,43 +178,31 @@ extern "C" * @param nfft FFT order * @param c genalyzer Configuration struct */ - __api int gn_config_get_nfft( - size_t *nfft, - gn_config *c - ); - + __api int gn_config_get_nfft (size_t *nfft, gn_config *c); + /** * @brief set configuration struct member: navg * @return 0 on success, non-zero otherwise * @param fft_navg Num. of FFTs to average * @param c genalyzer Configuration struct */ - __api int gn_config_set_fft_navg( - size_t fft_navg, - gn_config *c - ); - + __api int gn_config_set_fft_navg (size_t fft_navg, gn_config *c); + /** * @brief set configuration struct member: win * @return 0 on success, non-zero otherwise * @param win Window function used * @param c genalyzer Configuration struct */ - __api int gn_config_set_win( - GnWindow win, - gn_config *c - ); - + __api int gn_config_set_win (GnWindow win, gn_config *c); + /** * @brief set configuration struct member: ssb_fund * @return 0 on success, non-zero otherwise * @param ssb_fund Single side bin fundamental * @param c genalyzer Configuration struct */ - __api int gn_config_set_ssb_fund( - int ssb_fund, - gn_config *c - ); + __api int gn_config_set_ssb_fund (int ssb_fund, gn_config *c); /** * @brief set configuration struct member: ssb_rest @@ -289,10 +210,7 @@ extern "C" * @param ssb_rest Single side bins rest * @param c genalyzer Configuration struct */ - __api int gn_config_set_ssb_rest( - int ssb_rest, - gn_config *c - ); + __api int gn_config_set_ssb_rest (int ssb_rest, gn_config *c); /** * @brief set configuration struct member: max_harm_order @@ -300,10 +218,7 @@ extern "C" * @param max_harm_order Max order of harmonic * @param c genalyzer Configuration struct */ - __api int gn_config_set_max_harm_order( - int max_harm_order, - gn_config *c - ); + __api int gn_config_set_max_harm_order (int max_harm_order, gn_config *c); /** * @brief set configuration struct member: dnla_signal_type @@ -311,10 +226,8 @@ extern "C" * @param dnla_signal_type DNL analysis signal type * @param c genalyzer Configuration struct */ - __api int gn_config_set_dnla_signal_type( - GnDnlSignal dnla_signal_type, - gn_config *c - ); + __api int gn_config_set_dnla_signal_type (GnDnlSignal dnla_signal_type, + gn_config *c); /** * @brief set configuration struct member: inla_fit @@ -322,10 +235,7 @@ extern "C" * @param inla_fit INL analysis line fit * @param c genalyzer Configuration struct */ - __api int gn_config_set_inla_fit( - GnInlLineFit inla_fit, - gn_config *c - ); + __api int gn_config_set_inla_fit (GnInlLineFit inla_fit, gn_config *c); /** * @brief set configuration struct member: ramp_start @@ -333,55 +243,42 @@ extern "C" * @param ramp_start start value of ramp * @param c genalyzer Configuration struct */ - __api int gn_config_set_ramp_start( - double ramp_start, - gn_config *c - ); - + __api int gn_config_set_ramp_start (double ramp_start, gn_config *c); + /** * @brief set configuration struct member: ramp_stop * @return 0 on success, non-zero otherwise * @param ramp_stop stop value of ramp * @param c genalyzer Configuration struct */ - __api int gn_config_set_ramp_stop( - double ramp_stop, - gn_config *c - ); - + __api int gn_config_set_ramp_stop (double ramp_stop, gn_config *c); + /** * @brief get configuration struct member: _code_density_size * @return 0 on success, non-zero otherwise * @param code_density_size code density size * @param c genalyzer Configuration struct */ - __api int gn_config_get_code_density_size( - size_t *code_density_size, - gn_config *c - ); + __api int gn_config_get_code_density_size (size_t *code_density_size, + gn_config *c); /** * @brief Configure tone parameters to be used in measurement * @return 0 on success, non-zero otherwise - * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, REAL_SINE, COMPLEX_EXP + * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, + * REAL_SINE, COMPLEX_EXP * @param npts Number of sample points in the generated waveform * @param sample_rate Input Sample rate of the data converter * @param num_tones Number of tones to generate * @param tone_freq Input array of tone frequencies to generate * @param tone_ampl Input array of tone scales to generate - * @param tone_phase Input array of tone phases to generate + * @param tone_phase Input array of tone phases to generate * @param c Configuration struct containing tone parameters */ - __api int gn_config_gen_tone ( - tone_type ttype, - size_t npts, - double sample_rate, - size_t num_tones, - double *tone_freq, - double *tone_ampl, - double *tone_phase, - gn_config *c - ); + __api int gn_config_gen_tone (tone_type ttype, size_t npts, + double sample_rate, size_t num_tones, + double *tone_freq, double *tone_ampl, + double *tone_phase, gn_config *c); /** * @brief Configure tone parameters to be used in measurement @@ -391,29 +288,20 @@ extern "C" * @param ramp_stop Input stop value of ramp * @param c Configuration struct containing ramp parameters */ - __api int gn_config_gen_ramp( - size_t npts, - double ramp_start, - double ramp_stop, - gn_config *c - ); + __api int gn_config_gen_ramp (size_t npts, double ramp_start, + double ramp_stop, gn_config *c); /** * @brief Configure quantization parameters to be used in measurement * @return 0 on success, non-zero otherwise * @param npts Number of sample points in the generated waveform - * @param fsr Full-scale range of the waveform + * @param fsr Full-scale range of the waveform * @param qres Quantization resolution * @param qnoise Quantization noise * @param c Configuration structure */ - __api int gn_config_quantize( - size_t npts, - double fsr, - int qres, - double qnoise, - gn_config *c - ); + __api int gn_config_quantize (size_t npts, double fsr, int qres, + double qnoise, gn_config *c); /** * @brief Configure parameters to compute histogram @@ -422,202 +310,188 @@ extern "C" * @param qres Quantization resolution * @param c Configuration structure */ - __api int gn_config_histz_nla( - size_t npts, - int qres, - gn_config *c - ); + __api int gn_config_histz_nla (size_t npts, int qres, gn_config *c); /** - * @brief Configure FFT parameters + * @brief Configure FFT parameters * @return 0 on success, non-zero otherwise */ - __api int gn_config_fftz( - size_t npts, ///< [npts] Number of sample points in the input waveform - int qres, ///< [qres] Quantization resolution - size_t navg, ///< [navg] Number of FFT averages - size_t nfft, ///< [nfft] FFT order - GnWindow win, ///< [win] Window function to apply, Options: GnWindowBlackmanHarris, GnWindowHann, GnWindowNoWindow - gn_config *c ///< [c] Configuration structure containing test parameters - ); + __api int gn_config_fftz ( + size_t npts, ///< [npts] Number of sample points in the input waveform + int qres, ///< [qres] Quantization resolution + size_t navg, ///< [navg] Number of FFT averages + size_t nfft, ///< [nfft] FFT order + GnWindow win, ///< [win] Window function to apply, Options: + ///< GnWindowBlackmanHarris, GnWindowHann, GnWindowNoWindow + gn_config *c ///< [c] Configuration structure containing test parameters + ); /** * @brief Generate sinusoidal tone based on supplied configuration. - * @return 0 on success, non-zero otherwise + * @return 0 on success, non-zero otherwise */ - __api int gn_config_fa( - double fixed_tone_freq, ///< [fixed_tone_freq] Fixed tone frequency - gn_config *c ///< [c] Configuration structure containing test parameters - ); + __api int gn_config_fa ( + double fixed_tone_freq, ///< [fixed_tone_freq] Fixed tone frequency + gn_config *c ///< [c] Configuration structure containing test parameters + ); /** - * @brief Generate sinusoidal tone based on supplied configuration without specifying tone manually. + * @brief Generate sinusoidal tone based on supplied configuration without + * specifying tone manually. * @return 0 on success, non-zero otherwise */ - __api int gn_config_fa_auto( - uint8_t ssb_width, ///< [ssb_width] Number of bins to use for fundamental search and keepout of other tones - gn_config *c ///< [c] Configuration structure containing test parameters - ); - + __api int gn_config_fa_auto ( + uint8_t ssb_width, ///< [ssb_width] Number of bins to use for fundamental + ///< search and keepout of other tones + gn_config *c ///< [c] Configuration structure containing test parameters + ); + /** * @brief Generate ramp based on supplied configuration. * @param out Output array of ramp generated * @param c Configuration structure of test and waveform to generate */ - __api int gn_gen_ramp( - double **out, - gn_config *c - ); - + __api int gn_gen_ramp (double **out, gn_config *c); + /** * @brief Generate sinusoidal tone based on supplied configuration. - * @return 0 on success, non-zero otherwise + * @return 0 on success, non-zero otherwise * @param out Output array of generated tone * @param c Configuration structure containing test parameters */ - __api int gn_gen_real_tone( - double **out, - gn_config *c - ); + __api int gn_gen_real_tone (double **out, gn_config *c); /** * @brief Generate sinusoidal tone based on supplied configuration. - * @return 0 on success, non-zero otherwise + * @return 0 on success, non-zero otherwise * @param outi In-phase output array of generated tone * @param outq Quadrature output array of generated tone * @param c Configuration structure containing test parameters */ - __api int gn_gen_complex_tone( - double **outi, - double **outq, - gn_config *c - ); + __api int gn_gen_complex_tone (double **outi, double **outq, gn_config *c); /** * @brief Quantize waveform based on supplied configuration. * @return 0 on success, non-zero otherwise */ - __api int gn_quantize( - int32_t **out, ///< [out] Quantized output waveform - const double *in, ///< [in] Input waveform to be quantized - gn_config *c ///< [c] Configuration structure containing test parameters - ); + __api int gn_quantize ( + int32_t **out, ///< [out] Quantized output waveform + const double *in, ///< [in] Input waveform to be quantized + gn_config *c ///< [c] Configuration structure containing test parameters + ); /** - * @brief Compute FFT of quantized input waveform - * @return 0 on success, non-zero otherwise - */ - __api int gn_fftz( - double **out, ///< [out] Interleaved Re/Im FFT output - const int32_t *in_i, ///< [in_i] In-phase input - const int32_t *in_q, ///< [in_q] Quadrature input - gn_config *c ///< [c] Configuration structure containing test parameters - ); + * @brief Compute FFT of quantized input waveform + * @return 0 on success, non-zero otherwise + */ + __api int gn_fftz ( + double **out, ///< [out] Interleaved Re/Im FFT output + const int32_t *in_i, ///< [in_i] In-phase input + const int32_t *in_q, ///< [in_q] Quadrature input + gn_config *c ///< [c] Configuration structure containing test parameters + ); /** * @brief Compute histogram of quantized waveform * @return 0 on success, non-zero otherwise */ - __api int gn_histz( - uint64_t **hist, ///< [hist] Output - Histogram of input quantized waveform - size_t *hist_len, ///< [hist_len] Output - Histogram size - const int32_t *qwf, ///< [qwf] Input - Quantized input waveform - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); + __api int gn_histz ( + uint64_t * + *hist, ///< [hist] Output - Histogram of input quantized waveform + size_t *hist_len, ///< [hist_len] Output - Histogram size + const int32_t *qwf, ///< [qwf] Input - Quantized input waveform + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); /** * @brief Compute histogram of quantized waveform * @return 0 on success, non-zero otherwise */ - __api int gn_dnlz( - double **dnl, - size_t *dnl_len, - const uint64_t *hist, - gn_config *c - ); + __api int gn_dnlz (double **dnl, size_t *dnl_len, const uint64_t *hist, + gn_config *c); /** * @brief Compute histogram of quantized waveform * @return 0 on success, non-zero otherwise */ - - __api int gn_inlz( - double **inl, - size_t *inl_len, - const double *dnl, - gn_config *c - ); - + + __api int gn_inlz (double **inl, size_t *inl_len, const double *dnl, + gn_config *c); + /** * @brief Do waveform analysis and all get results * @return 0 on success, non-zero otherwise */ - __api int gn_get_wfa_results( - char ***rkeys, - double **rvalues, - size_t *results_size, ///< [results_size] size of results - const int32_t *qwf, ///< [qwf] Input - Quantized input array pointer - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); + __api int gn_get_wfa_results ( + char ***rkeys, double **rvalues, + size_t *results_size, ///< [results_size] size of results + const int32_t *qwf, ///< [qwf] Input - Quantized input array pointer + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); - /** + /** * @brief Do histogram analysis and get results * @return 0 on success, non-zero otherwise */ - __api int gn_get_ha_results( - char ***rkeys, ///< [rkeys] Output - Result keys - double **rvalues, ///< [rvalues] Output - Result values - size_t *results_size, ///< [results_size] Output - Size of results - const uint64_t *hist, ///< [hist] Input - Histogram input to be analyzed - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); + __api int gn_get_ha_results ( + char ***rkeys, ///< [rkeys] Output - Result keys + double **rvalues, ///< [rvalues] Output - Result values + size_t *results_size, ///< [results_size] Output - Size of results + const uint64_t *hist, ///< [hist] Input - Histogram input to be analyzed + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); /** * @brief Do DNL analysis and get results * @return 0 on success, non-zero otherwise */ - __api int gn_get_dnla_results( - char ***rkeys, ///< [rkeys] Output - Result keys - double **rvalues, ///< [rvalues] Output - Result values - size_t *results_size, ///< [results_size] Output - Size of results - const double *dnl, ///< [dnl] Input - DNL input to be analyzed - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); + __api int gn_get_dnla_results ( + char ***rkeys, ///< [rkeys] Output - Result keys + double **rvalues, ///< [rvalues] Output - Result values + size_t *results_size, ///< [results_size] Output - Size of results + const double *dnl, ///< [dnl] Input - DNL input to be analyzed + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); /** * @brief Do INL analysis and get results * @return 0 on success, non-zero otherwise */ - __api int gn_get_inla_results( - char ***rkeys, ///< [rkeys] Output - Result keys - double **rvalues, ///< [rvalues] Output - Result values - size_t *results_size, ///< [results_size] Output - Size of results - const double *inl, ///< [dnl] Input - INL input to be analyzed - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); + __api int gn_get_inla_results ( + char ***rkeys, ///< [rkeys] Output - Result keys + double **rvalues, ///< [rvalues] Output - Result values + size_t *results_size, ///< [results_size] Output - Size of results + const double *inl, ///< [dnl] Input - INL input to be analyzed + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); /** * @brief Do Fourier analysis and get a single result * @return 0 on success, non-zero otherwise */ - __api int gn_get_fa_single_result( - double *rvalue, - const char* metric_name, - double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); + __api int gn_get_fa_single_result ( + double *rvalue, const char *metric_name, + double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); /** * @brief Do Fourier analysis and all get results * @return 0 on success, non-zero otherwise */ - __api int gn_get_fa_results( - char ***rkeys, - double **rvalues, - size_t *results_size, ///< [results_size] size of results - double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); - + __api int gn_get_fa_results ( + char ***rkeys, double **rvalues, + size_t *results_size, ///< [results_size] size of results + double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer + gn_config * + c ///< [c] Input - Configuration structure containing test parameters + ); + #ifdef __cplusplus } #endif diff --git a/bindings/c/src/CMakeLists.txt b/bindings/c/src/CMakeLists.txt index 45c70e7..d579528 100644 --- a/bindings/c/src/CMakeLists.txt +++ b/bindings/c/src/CMakeLists.txt @@ -53,11 +53,11 @@ configure_file(${PROJECT_SOURCE_DIR}/libgenalyzer.pc.cmakein ${GENALYZER_PC} @ON install(FILES ${GENALYZER_PC} DESTINATION ${INSTALL_LIB_DIR}/pkgconfig) install(TARGETS genalyzer - ARCHIVE DESTINATION lib - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" - RUNTIME DESTINATION bin - FRAMEWORK DESTINATION lib - PUBLIC_HEADER DESTINATION include) + ARCHIVE DESTINATION lib + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" + RUNTIME DESTINATION bin + FRAMEWORK DESTINATION lib + PUBLIC_HEADER DESTINATION include) include(GNUInstallDirs) diff --git a/bindings/c/src/cgenalyzer.cpp b/bindings/c/src/cgenalyzer.cpp index b0c240a..8661250 100644 --- a/bindings/c/src/cgenalyzer.cpp +++ b/bindings/c/src/cgenalyzer.cpp @@ -1,54 +1,72 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "cgenalyzer.h" #include "cgenalyzer_private.h" using namespace util; -namespace util { +namespace util +{ + +static bool gn_null_terminate = true; - static bool gn_null_terminate = true; +size_t +terminated_size (size_t string_size) +{ + return string_size + (util::gn_null_terminate ? 1 : 0); +} - size_t terminated_size(size_t string_size) +void +fill_string_buffer (const char *src, // Pointer to source + size_t src_size, // Size of source; should not count + // null-terminator, if it exists + char *dst, // Pointer to destination + size_t dst_size // Size of destination +) +{ + if (nullptr == src) { - return string_size + (util::gn_null_terminate ? 1 : 0); + throw std::runtime_error ("fill_string_buffer : source is NULL"); } - - void fill_string_buffer( - const char* src, // Pointer to source - size_t src_size, // Size of source; should not count null-terminator, if it exists - char* dst, // Pointer to destination - size_t dst_size // Size of destination - ) + if (nullptr == dst) { - if (nullptr == src) { - throw std::runtime_error("fill_string_buffer : source is NULL"); - } - if (nullptr == dst) { - throw std::runtime_error("fill_string_buffer : destination is NULL"); - } - if (dst_size < terminated_size(src_size)) { - throw std::runtime_error("fill_string_buffer : destination too small"); - } - for (size_t i = 0; i < src_size; ++i) { - dst[i] = src[i]; - } - if (gn_null_terminate) { - dst[src_size] = '\0'; - } + throw std::runtime_error ("fill_string_buffer : destination is NULL"); + } + if (dst_size < terminated_size (src_size)) + { + throw std::runtime_error ("fill_string_buffer : destination too small"); } + for (size_t i = 0; i < src_size; ++i) + { + dst[i] = src[i]; + } + if (gn_null_terminate) + { + dst[src_size] = '\0'; + } +} - std::string get_object_key_from_filename(const std::string& filename) +std::string +get_object_key_from_filename (const std::string &filename) +{ + static const std::regex re{ "(" + gn::manager::key_pattern + ")[.]json$", + std::regex::icase }; + std::smatch matches; + if (std::regex_search (filename, matches, re)) { - static const std::regex re {"(" + gn::manager::key_pattern + ")[.]json$", std::regex::icase}; - std::smatch matches; - if (std::regex_search(filename, matches, re)) { - if (1 == matches.size()) { - throw std::runtime_error("unable to derive object key from filename '" + filename + "'"); - } - return matches[1].str(); - } else { - throw std::runtime_error("invalid filename '" + filename + "'"); + if (1 == matches.size ()) + { + throw std::runtime_error ( + "unable to derive object key from filename '" + filename + "'"); } + return matches[1].str (); + } + else + { + throw std::runtime_error ("invalid filename '" + filename + "'"); } +} } // namespace util @@ -56,148 +74,189 @@ namespace util { /* API Utilities */ /**************************************************************************/ -int gn_analysis_results_key_sizes(size_t* key_sizes, size_t key_sizes_size, GnAnalysisType type) +int +gn_analysis_results_key_sizes (size_t *key_sizes, size_t key_sizes_size, + GnAnalysisType type) { - try { - util::check_pointer(key_sizes); - std::vector keys; - switch (gn::get_enum(type)) + try + { + util::check_pointer (key_sizes); + std::vector keys; + switch (gn::get_enum (type)) { - case gn::AnalysisType::DNL : - keys = gn::dnl_analysis_ordered_keys(); - break; - case gn::AnalysisType::Histogram : - keys = gn::hist_analysis_ordered_keys(); - break; - case gn::AnalysisType::INL : - keys = gn::inl_analysis_ordered_keys(); - break; - case gn::AnalysisType::Waveform : - keys = gn::wf_analysis_ordered_keys(); - break; - default : - throw std::runtime_error("Invalid analysis type"); + case gn::AnalysisType::DNL: + keys = gn::dnl_analysis_ordered_keys (); + break; + case gn::AnalysisType::Histogram: + keys = gn::hist_analysis_ordered_keys (); + break; + case gn::AnalysisType::INL: + keys = gn::inl_analysis_ordered_keys (); + break; + case gn::AnalysisType::Waveform: + keys = gn::wf_analysis_ordered_keys (); + break; + default: + throw std::runtime_error ("Invalid analysis type"); } - if (keys.size() != key_sizes_size) { - throw std::runtime_error("Number of keys does not match output array size"); + if (keys.size () != key_sizes_size) + { + throw std::runtime_error ( + "Number of keys does not match output array size"); } - for (size_t i = 0; i < key_sizes_size; ++i) { - key_sizes[i] = util::terminated_size(keys[i].size()); + for (size_t i = 0; i < key_sizes_size; ++i) + { + key_sizes[i] = util::terminated_size (keys[i].size ()); } - return gn_success; - } catch (const std::exception& e) { - std::fill(key_sizes, key_sizes + key_sizes_size, 0); - return util::return_on_exception("gn_analysis_results_key_sizes : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + std::fill (key_sizes, key_sizes + key_sizes_size, 0); + return util::return_on_exception ("gn_analysis_results_key_sizes : ", + e.what ()); } } -int gn_analysis_results_size(size_t* size, GnAnalysisType type) +int +gn_analysis_results_size (size_t *size, GnAnalysisType type) { - try { - util::check_pointer(size); - switch (gn::get_enum(type)) + try + { + util::check_pointer (size); + switch (gn::get_enum (type)) { - case gn::AnalysisType::DNL : - *size = gn::dnl_analysis_ordered_keys().size(); - break; - case gn::AnalysisType::Histogram : - *size = gn::hist_analysis_ordered_keys().size(); - break; - case gn::AnalysisType::INL : - *size = gn::inl_analysis_ordered_keys().size(); - break; - case gn::AnalysisType::Waveform : - *size = gn::wf_analysis_ordered_keys().size(); - break; - default : - throw std::runtime_error("Invalid analysis type"); + case gn::AnalysisType::DNL: + *size = gn::dnl_analysis_ordered_keys ().size (); + break; + case gn::AnalysisType::Histogram: + *size = gn::hist_analysis_ordered_keys ().size (); + break; + case gn::AnalysisType::INL: + *size = gn::inl_analysis_ordered_keys ().size (); + break; + case gn::AnalysisType::Waveform: + *size = gn::wf_analysis_ordered_keys ().size (); + break; + default: + throw std::runtime_error ("Invalid analysis type"); } - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_analysis_results_size : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_analysis_results_size : ", + e.what ()); } } -int gn_enum_value(int* value, const char* enumeration, const char* enumerator) +int +gn_enum_value (int *value, const char *enumeration, const char *enumerator) { - try { - util::check_pointer(value); - *value = gn::enum_value(enumeration, enumerator); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_enum_value : ", e.what()); + try + { + util::check_pointer (value); + *value = gn::enum_value (enumeration, enumerator); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_enum_value : ", e.what ()); } } -int gn_error_check(bool* error) +int +gn_error_check (bool *error) { - try { - util::check_pointer(error); - *error = util::gn_error_log.check(); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_error_check : ", e.what()); + try + { + util::check_pointer (error); + *error = util::gn_error_log.check (); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_error_check : ", e.what ()); } } -int gn_error_clear() +int +gn_error_clear () { - util::gn_error_log.clear(); - return gn_success; + util::gn_error_log.clear (); + return gn_success; } -int gn_error_string(char* buf, size_t size) +int +gn_error_string (char *buf, size_t size) { - try { - std::string_view s = util::gn_error_log.get(); - util::fill_string_buffer(s.data(), s.size(), buf, size); - } catch (const std::exception&) { - return gn_failure; + try + { + std::string_view s = util::gn_error_log.get (); + util::fill_string_buffer (s.data (), s.size (), buf, size); + } + catch (const std::exception &) + { + return gn_failure; } - return gn_success; + return gn_success; } -int gn_set_string_termination(bool null_terminated) +int +gn_set_string_termination (bool null_terminated) { - util::gn_null_terminate = null_terminated; - return gn_success; + util::gn_null_terminate = null_terminated; + return gn_success; } -int gn_version_string(char* buf, size_t size) +int +gn_version_string (char *buf, size_t size) { - try { - std::string_view s = gn::version_string(); - util::fill_string_buffer(s.data(), s.size(), buf, size); - } catch (const std::exception& e) { - return util::return_on_exception("gn_version_string : ", e.what()); + try + { + std::string_view s = gn::version_string (); + util::fill_string_buffer (s.data (), s.size (), buf, size); + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_version_string : ", e.what ()); } - return gn_success; + return gn_success; } /**************************************************************************/ /* API Utility Helpers */ /**************************************************************************/ -int gn_error_string_size(size_t* size) +int +gn_error_string_size (size_t *size) { - try { - util::check_pointer(size); - *size = util::terminated_size(util::gn_error_log.size()); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_error_string_size : ", e.what()); + try + { + util::check_pointer (size); + *size = util::terminated_size (util::gn_error_log.size ()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_error_string_size : ", e.what ()); } } -int gn_version_string_size(size_t* size) +int +gn_version_string_size (size_t *size) { - try { - util::check_pointer(size); - *size = util::terminated_size(gn::version_string().size()); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_version_string_size : ", e.what()); + try + { + util::check_pointer (size); + *size = util::terminated_size (gn::version_string ().size ()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_version_string_size : ", + e.what ()); } } @@ -205,63 +264,87 @@ int gn_version_string_size(size_t* size) /* Array Operations */ /**************************************************************************/ -int gn_abs(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_abs (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::abs(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_abs : ", e.what()); + try + { + gn::abs (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_abs : ", e.what ()); } } -int gn_angle(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_angle (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::angle(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_angle : ", e.what()); + try + { + gn::angle (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_angle : ", e.what ()); } } -int gn_db(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_db (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::db(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_db : ", e.what()); + try + { + gn::db (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_db : ", e.what ()); } } -int gn_db10(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_db10 (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::db10(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_db10 : ", e.what()); + try + { + gn::db10 (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_db10 : ", e.what ()); } } -int gn_db20(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_db20 (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::db20(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_db20 : ", e.what()); + try + { + gn::db20 (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_db20 : ", e.what ()); } } -int gn_norm(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_norm (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::norm(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_norm : ", e.what()); + try + { + gn::norm (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_norm : ", e.what ()); } } @@ -269,192 +352,250 @@ int gn_norm(double* out, size_t out_size, const double* in, size_t in_size) /* Code Density */ /**************************************************************************/ -namespace { +namespace +{ - template - int gn_hist(const char* suffix, uint64_t* hist, size_t hist_size, - const T* in, size_t in_size, int n, GnCodeFormat format, bool preserve) +template +int +gn_hist (const char *suffix, uint64_t *hist, size_t hist_size, const T *in, + size_t in_size, int n, GnCodeFormat format, bool preserve) +{ + try { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::hist(hist, hist_size, in, in_size, n, f, preserve); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_hist", suffix, " : ", e.what()); - } + gn::CodeFormat f = gn::get_enum (format); + gn::hist (hist, hist_size, in, in_size, n, f, preserve); + return gn_success; } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_hist", suffix, " : ", e.what ()); + } +} - template - int gn_histx(const char* suffix, uint64_t* hist, size_t hist_size, - const T* in, size_t in_size, int64_t min, int64_t max, bool preserve) +template +int +gn_histx (const char *suffix, uint64_t *hist, size_t hist_size, const T *in, + size_t in_size, int64_t min, int64_t max, bool preserve) +{ + try { - try { - gn::histx(hist, hist_size, in, in_size, min, max, preserve); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_histx", suffix, " : ", e.what()); - } + gn::histx (hist, hist_size, in, in_size, min, max, preserve); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_histx", suffix, " : ", e.what ()); } +} } // namespace anonymous -int gn_code_axis(double* out, size_t size, int n, GnCodeFormat format) +int +gn_code_axis (double *out, size_t size, int n, GnCodeFormat format) { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::code_axis(out, size, n, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_code_axis : ", e.what()); + try + { + gn::CodeFormat f = gn::get_enum (format); + gn::code_axis (out, size, n, f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_code_axis : ", e.what ()); } } -int gn_code_axisx(double* out, size_t size, int64_t min, int64_t max) +int +gn_code_axisx (double *out, size_t size, int64_t min, int64_t max) { - try { - gn::code_axisx(out, size, min, max); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_code_axisx : ", e.what()); + try + { + gn::code_axisx (out, size, min, max); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_code_axisx : ", e.what ()); } } -int gn_dnl(double* dnl, size_t dnl_size, const uint64_t* hist, size_t hist_size, GnDnlSignal type) +int +gn_dnl (double *dnl, size_t dnl_size, const uint64_t *hist, size_t hist_size, + GnDnlSignal type) { - try { - gn::DnlSignal t = gn::get_enum(type); - gn::dnl(dnl, dnl_size, hist, hist_size, t); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_dnl : ", e.what()); + try + { + gn::DnlSignal t = gn::get_enum (type); + gn::dnl (dnl, dnl_size, hist, hist_size, t); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_dnl : ", e.what ()); } } -int gn_dnl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const double* dnl, size_t dnl_size) +int +gn_dnl_analysis (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const double *dnl, size_t dnl_size) { - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::dnl_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); + try + { + util::check_pointer (rkeys); + util::check_pointer (rvalues); + const std::vector &keys = gn::dnl_analysis_ordered_keys (); + if (keys.size () != rkeys_size) + { + throw std::runtime_error ("Size of result key array is wrong"); } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); + if (rvalues_size != rkeys_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); } - std::map results = gn::dnl_analysis(dnl, dnl_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); + std::map results = gn::dnl_analysis (dnl, dnl_size); + for (size_t i = 0; i < keys.size (); ++i) + { + const std::string &src = keys[i]; + char *dst = rkeys[i]; + size_t dst_size = util::terminated_size (src.size ()); + util::fill_string_buffer (src.data (), src.size (), dst, dst_size); + rvalues[i] = results.at (src); } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_dnl_analysis : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_dnl_analysis : ", e.what ()); } } -int gn_hist16(uint64_t* hist, size_t hist_size, const int16_t* in, size_t in_size, - int n, GnCodeFormat format, bool preserve) +int +gn_hist16 (uint64_t *hist, size_t hist_size, const int16_t *in, size_t in_size, + int n, GnCodeFormat format, bool preserve) { - return gn_hist("16", hist, hist_size, in, in_size, n, format, preserve); + return gn_hist ("16", hist, hist_size, in, in_size, n, format, preserve); } -int gn_hist32(uint64_t* hist, size_t hist_size, const int32_t* in, size_t in_size, - int n, GnCodeFormat format, bool preserve) +int +gn_hist32 (uint64_t *hist, size_t hist_size, const int32_t *in, size_t in_size, + int n, GnCodeFormat format, bool preserve) { - return gn_hist("32", hist, hist_size, in, in_size, n, format, preserve); + return gn_hist ("32", hist, hist_size, in, in_size, n, format, preserve); } -int gn_hist64(uint64_t* hist, size_t hist_size, const int64_t* in, size_t in_size, - int n, GnCodeFormat format, bool preserve) +int +gn_hist64 (uint64_t *hist, size_t hist_size, const int64_t *in, size_t in_size, + int n, GnCodeFormat format, bool preserve) { - return gn_hist("64", hist, hist_size, in, in_size, n, format, preserve); + return gn_hist ("64", hist, hist_size, in, in_size, n, format, preserve); } -int gn_histx16(uint64_t* hist, size_t hist_size, const int16_t* in, size_t in_size, - int64_t min, int64_t max, bool preserve) +int +gn_histx16 (uint64_t *hist, size_t hist_size, const int16_t *in, + size_t in_size, int64_t min, int64_t max, bool preserve) { - return gn_histx("16", hist, hist_size, in, in_size, min, max, preserve); + return gn_histx ("16", hist, hist_size, in, in_size, min, max, preserve); } -int gn_histx32(uint64_t* hist, size_t hist_size, const int32_t* in, size_t in_size, - int64_t min, int64_t max, bool preserve) +int +gn_histx32 (uint64_t *hist, size_t hist_size, const int32_t *in, + size_t in_size, int64_t min, int64_t max, bool preserve) { - return gn_histx("32", hist, hist_size, in, in_size, min, max, preserve); + return gn_histx ("32", hist, hist_size, in, in_size, min, max, preserve); } -int gn_histx64(uint64_t* hist, size_t hist_size, const int64_t* in, size_t in_size, - int64_t min, int64_t max, bool preserve) +int +gn_histx64 (uint64_t *hist, size_t hist_size, const int64_t *in, + size_t in_size, int64_t min, int64_t max, bool preserve) { - return gn_histx("64", hist, hist_size, in, in_size, min, max, preserve); + return gn_histx ("64", hist, hist_size, in, in_size, min, max, preserve); } -int gn_hist_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const uint64_t* hist, size_t hist_size) +int +gn_hist_analysis (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const uint64_t *hist, size_t hist_size) { - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::hist_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); + try + { + util::check_pointer (rkeys); + util::check_pointer (rvalues); + const std::vector &keys = gn::hist_analysis_ordered_keys (); + if (keys.size () != rkeys_size) + { + throw std::runtime_error ("Size of result key array is wrong"); } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); + if (rvalues_size != rkeys_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); } - std::map results = gn::hist_analysis(hist, hist_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); + std::map results + = gn::hist_analysis (hist, hist_size); + for (size_t i = 0; i < keys.size (); ++i) + { + const std::string &src = keys[i]; + char *dst = rkeys[i]; + size_t dst_size = util::terminated_size (src.size ()); + util::fill_string_buffer (src.data (), src.size (), dst, dst_size); + rvalues[i] = results.at (src); } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_hist_analysis : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_hist_analysis : ", e.what ()); } } -int gn_inl(double* inl, size_t inl_size, const double* dnl, size_t dnl_size, GnInlLineFit fit) +int +gn_inl (double *inl, size_t inl_size, const double *dnl, size_t dnl_size, + GnInlLineFit fit) { - try { - gn::InlLineFit f = gn::get_enum(fit); - gn::inl(inl, inl_size, dnl, dnl_size, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_inl : ", e.what()); + try + { + gn::InlLineFit f = gn::get_enum (fit); + gn::inl (inl, inl_size, dnl, dnl_size, f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_inl : ", e.what ()); } } -int gn_inl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const double* inl, size_t inl_size) +int +gn_inl_analysis (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const double *inl, size_t inl_size) { - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::inl_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); + try + { + util::check_pointer (rkeys); + util::check_pointer (rvalues); + const std::vector &keys = gn::inl_analysis_ordered_keys (); + if (keys.size () != rkeys_size) + { + throw std::runtime_error ("Size of result key array is wrong"); } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); + if (rvalues_size != rkeys_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); } - std::map results = gn::inl_analysis(inl, inl_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); + std::map results = gn::inl_analysis (inl, inl_size); + for (size_t i = 0; i < keys.size (); ++i) + { + const std::string &src = keys[i]; + char *dst = rkeys[i]; + size_t dst_size = util::terminated_size (src.size ()); + util::fill_string_buffer (src.data (), src.size (), dst, dst_size); + rvalues[i] = results.at (src); } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_inl_analysis : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_inl_analysis : ", e.what ()); } } @@ -462,28 +603,36 @@ int gn_inl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rva /* Code Density Helpers */ /**************************************************************************/ -int gn_code_density_size(size_t* size, int n, GnCodeFormat format) +int +gn_code_density_size (size_t *size, int n, GnCodeFormat format) { - try { - util::check_pointer(size); - gn::CodeFormat f = gn::get_enum(format); - *size = gn::code_density_size(n, f); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_code_density_size : ", e.what()); + try + { + util::check_pointer (size); + gn::CodeFormat f = gn::get_enum (format); + *size = gn::code_density_size (n, f); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_code_density_size : ", e.what ()); } } -int gn_code_densityx_size(size_t* size, int64_t min, int64_t max) +int +gn_code_densityx_size (size_t *size, int64_t min, int64_t max) { - try { - util::check_pointer(size); - *size = gn::code_densityx_size(min, max); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_code_densityx_size : ", e.what()); + try + { + util::check_pointer (size); + *size = gn::code_densityx_size (min, max); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_code_densityx_size : ", e.what ()); } } @@ -491,192 +640,267 @@ int gn_code_densityx_size(size_t* size, int64_t min, int64_t max) /* Fourier Analysis */ /**************************************************************************/ -namespace { +namespace +{ - using fa_ptr = std::shared_ptr; +using fa_ptr = std::shared_ptr; - fa_ptr get_fa_object(const std::string& obj_key) +fa_ptr +get_fa_object (const std::string &obj_key) +{ + gn::object::pointer pobj = gn::manager::get_object (obj_key); + const gn::ObjectType obj_type = gn::ObjectType::FourierAnalysis; + if (obj_type != pobj->object_type ()) { - gn::object::pointer pobj = gn::manager::get_object(obj_key); - const gn::ObjectType obj_type = gn::ObjectType::FourierAnalysis; - if (obj_type != pobj->object_type()) { - throw std::runtime_error("object '" + obj_key + "' is not of type " - + gn::object_type_map.at(static_cast(obj_type))); - } - return std::static_pointer_cast(pobj); + throw std::runtime_error ( + "object '" + obj_key + "' is not of type " + + gn::object_type_map.at (static_cast (obj_type))); } + return std::static_pointer_cast (pobj); +} - fa_ptr get_fa_object_or_load_from_file(std::string cfg_id) +fa_ptr +get_fa_object_or_load_from_file (std::string cfg_id) +{ + if (gn::manager::contains (cfg_id)) { - if (gn::manager::contains(cfg_id)) { - return get_fa_object(cfg_id); - } else { - return gn::fourier_analysis::load(cfg_id); - } + return get_fa_object (cfg_id); + } + else + { + return gn::fourier_analysis::load (cfg_id); } +} - size_t get_fa_result_key_index(const char** rkeys, size_t rkeys_size, const char* rkey) +size_t +get_fa_result_key_index (const char **rkeys, size_t rkeys_size, + const char *rkey) +{ + size_t i = 0; + for (; i < rkeys_size; ++i) { - size_t i = 0; - for (; i < rkeys_size; ++i) { - if (0 == strcmp(rkeys[i], rkey)) { - break; - } - } - if (rkeys_size == i) { - throw std::runtime_error("Result key '" + std::string(rkey) + "' not found"); + if (0 == strcmp (rkeys[i], rkey)) + { + break; } - return i; } + if (rkeys_size == i) + { + throw std::runtime_error ("Result key '" + std::string (rkey) + + "' not found"); + } + return i; +} - std::string get_fa_result_string(const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) +std::string +get_fa_result_string (const char **rkeys, size_t rkeys_size, + const double *rvalues, size_t rvalues_size, + const char *rkey) +{ + if (rkeys_size != rvalues_size) { - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - if (gn::fa_result_map.contains(rkey, true)) { - gn::FAResult renum = static_cast(gn::fa_result_map.at(rkey)); - if (gn::FAResult::CarrierIndex == renum || - gn::FAResult::MaxSpurIndex == renum) { - // Caller requests the Carrier or MaxSpur tone key. - size_t key_index = get_fa_result_key_index(rkeys, rkeys_size, rkey); - size_t order_index = static_cast(rvalues[key_index]); - int order_index_int = static_cast(gn::FAToneResult::OrderIndex); - std::string search_str = ":" + gn::fa_tone_result_map.at(order_index_int); - const char* search_cstr = search_str.c_str(); - size_t i = 0; - for (; i < rvalues_size; ++i) { - if (strstr(rkeys[i], search_cstr)) { - if (rvalues[i] == order_index) { - break; - } + throw std::runtime_error ( + "Size of result keys does not match size of result values"); + } + if (gn::fa_result_map.contains (rkey, true)) + { + gn::FAResult renum + = static_cast (gn::fa_result_map.at (rkey)); + if (gn::FAResult::CarrierIndex == renum + || gn::FAResult::MaxSpurIndex == renum) + { + // Caller requests the Carrier or MaxSpur tone key. + size_t key_index = get_fa_result_key_index (rkeys, rkeys_size, rkey); + size_t order_index = static_cast (rvalues[key_index]); + int order_index_int + = static_cast (gn::FAToneResult::OrderIndex); + std::string search_str + = ":" + gn::fa_tone_result_map.at (order_index_int); + const char *search_cstr = search_str.c_str (); + size_t i = 0; + for (; i < rvalues_size; ++i) + { + if (strstr (rkeys[i], search_cstr)) + { + if (rvalues[i] == order_index) + { + break; } } - if (rvalues_size == i) { - return "Not Found"; - } else { - return gn::fourier_analysis::split_key(rkeys[i]).first; - } } - } else { - // In the future, there could be a string associated with a tone result. + if (rvalues_size == i) + { + return "Not Found"; + } + else + { + return gn::fourier_analysis::split_key (rkeys[i]).first; + } } - throw std::runtime_error("no string associated with result key '" + std::string(rkey) + "'"); } + else + { + // In the future, there could be a string associated with a tone result. + } + throw std::runtime_error ("no string associated with result key '" + + std::string (rkey) + "'"); +} - int get_fa_single_result( - const gn::fourier_analysis_results& results, const char* rkey, double* rvalue) +int +get_fa_single_result (const gn::fourier_analysis_results &results, + const char *rkey, double *rvalue) +{ + *rvalue = 0.0; + std::pair keys + = gn::fourier_analysis::split_key (rkey); + if (!keys.first.empty ()) { - *rvalue = 0.0; - std::pair keys = gn::fourier_analysis::split_key(rkey); - if (!keys.first.empty()) { - if (keys.second.empty()) { - if (gn::fa_result_map.contains(keys.first)) { - int i = gn::fa_result_map.at(keys.first); - *rvalue = results.get(static_cast(i)); - return gn_success; - } - } else { - if (results.contains_tone(keys.first)) { - const gn::fa_tone_results& tres = results.get_tone(keys.first); - if (gn::fa_tone_result_map.at(keys.second)) { - int i = gn::fa_tone_result_map.at(keys.second); - *rvalue = tres.get(static_cast(i)); - return gn_success; - } + if (keys.second.empty ()) + { + if (gn::fa_result_map.contains (keys.first)) + { + int i = gn::fa_result_map.at (keys.first); + *rvalue = results.get (static_cast (i)); + return gn_success; + } + } + else + { + if (results.contains_tone (keys.first)) + { + const gn::fa_tone_results &tres = results.get_tone (keys.first); + if (gn::fa_tone_result_map.at (keys.second)) + { + int i = gn::fa_tone_result_map.at (keys.second); + *rvalue = tres.get (static_cast (i)); + return gn_success; } } } - return gn_failure; } + return gn_failure; +} } // namespace anonymous -int gn_fft_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const char* cfg_id, const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) +int +gn_fft_analysis (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const char *cfg_id, const double *in, + size_t in_size, size_t nfft, GnFreqAxisType axis_type) { - try { - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); + try + { + if (rkeys_size != rvalues_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); } - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); - // The rest of this function flattens results into a key-array and value-array pair - size_t i = 0; // index for rkeys, rvalues - const std::map& rmap = results.results; - for (int j = 0; j < static_cast(gn::FAResult::__SIZE__); ++j) { - const std::string& src = gn::fa_result_map.at(j); - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = rmap.at(static_cast(j)); - i += 1; + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + gn::FreqAxisType at = gn::get_enum (axis_type); + gn::fourier_analysis_results results + = obj->analyze (in, in_size, nfft, at); + // The rest of this function flattens results into a key-array and + // value-array pair + size_t i = 0; // index for rkeys, rvalues + const std::map &rmap = results.results; + for (int j = 0; j < static_cast (gn::FAResult::__SIZE__); ++j) + { + const std::string &src = gn::fa_result_map.at (j); + char *dst = rkeys[i]; + size_t dst_size = util::terminated_size (src.size ()); + util::fill_string_buffer (src.data (), src.size (), dst, dst_size); + rvalues[i] = rmap.at (static_cast (j)); + i += 1; } - for (const std::string& tkey : results.tone_keys) { - const gn::fa_tone_results& tone_results = results.get_tone(tkey); - const std::map& trmap = tone_results.results; - for (int j = 0; j < static_cast(gn::FAToneResult::__SIZE__); ++j) { - std::string src = gn::fourier_analysis::flat_tone_key(tkey, j); - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = trmap.at(static_cast(j)); - i += 1; + for (const std::string &tkey : results.tone_keys) + { + const gn::fa_tone_results &tone_results = results.get_tone (tkey); + const std::map &trmap + = tone_results.results; + for (int j = 0; j < static_cast (gn::FAToneResult::__SIZE__); + ++j) + { + std::string src = gn::fourier_analysis::flat_tone_key (tkey, j); + char *dst = rkeys[i]; + size_t dst_size = util::terminated_size (src.size ()); + util::fill_string_buffer (src.data (), src.size (), dst, + dst_size); + rvalues[i] = trmap.at (static_cast (j)); + i += 1; } } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_execute : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_execute : ", e.what ()); } } -int gn_fft_analysis_select(double* rvalues, size_t rvalues_size, - const char* cfg_id, const char** rkeys, size_t rkeys_size, - const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) +int +gn_fft_analysis_select (double *rvalues, size_t rvalues_size, + const char *cfg_id, const char **rkeys, + size_t rkeys_size, const double *in, size_t in_size, + size_t nfft, GnFreqAxisType axis_type) { - try { - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); + try + { + if (rkeys_size != rvalues_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); } - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); - std::string missing_keys {}; - for (size_t i = 0; i < rkeys_size; ++i) { - int error = get_fa_single_result(results, rkeys[i], &rvalues[i]); - if (error) { - if (!missing_keys.empty()) { - missing_keys += ", "; + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + gn::FreqAxisType at = gn::get_enum (axis_type); + gn::fourier_analysis_results results + = obj->analyze (in, in_size, nfft, at); + std::string missing_keys{}; + for (size_t i = 0; i < rkeys_size; ++i) + { + int error = get_fa_single_result (results, rkeys[i], &rvalues[i]); + if (error) + { + if (!missing_keys.empty ()) + { + missing_keys += ", "; } - missing_keys.append("'" + std::string(rkeys[i]) + "'"); + missing_keys.append ("'" + std::string (rkeys[i]) + "'"); } } - if (!missing_keys.empty()) { - throw std::runtime_error("Keys not found: " + missing_keys); + if (!missing_keys.empty ()) + { + throw std::runtime_error ("Keys not found: " + missing_keys); } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_execute2 : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_execute2 : ", e.what ()); } } -int gn_fft_analysis_single(double* rvalue, - const char* cfg_id, const char* rkey, - const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) +int +gn_fft_analysis_single (double *rvalue, const char *cfg_id, const char *rkey, + const double *in, size_t in_size, size_t nfft, + GnFreqAxisType axis_type) { - try { - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); - int error = get_fa_single_result(results, rkey, rvalue); - if (error) { - throw std::runtime_error("Key '" + std::string(rkey) + "' not found"); + try + { + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + gn::FreqAxisType at = gn::get_enum (axis_type); + gn::fourier_analysis_results results + = obj->analyze (in, in_size, nfft, at); + int error = get_fa_single_result (results, rkey, rvalue); + if (error) + { + throw std::runtime_error ("Key '" + std::string (rkey) + + "' not found"); } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_execute1 : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_execute1 : ", e.what ()); } } @@ -684,324 +908,433 @@ int gn_fft_analysis_single(double* rvalue, /* Fourier Analysis Configuration */ /**************************************************************************/ -int gn_fa_analysis_band(const char* obj_key, double center, double width) +int +gn_fa_analysis_band (const char *obj_key, double center, double width) { - try { - fa_ptr obj = get_fa_object(obj_key); - std::string center_s = gn::to_string(center, gn::FPFormat::Eng); - std::string width_s = gn::to_string(width, gn::FPFormat::Eng); - obj->set_analysis_band(center_s, width_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_analysis_band : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + std::string center_s = gn::to_string (center, gn::FPFormat::Eng); + std::string width_s = gn::to_string (width, gn::FPFormat::Eng); + obj->set_analysis_band (center_s, width_s); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_analysis_band : ", e.what ()); } } -int gn_fa_analysis_band_e(const char* obj_key, const char* center, const char* width) +int +gn_fa_analysis_band_e (const char *obj_key, const char *center, + const char *width) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_analysis_band(center, width); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_analysis_band_e : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_analysis_band (center, width); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_analysis_band_e : ", e.what ()); } } -int gn_fa_clk(const char* obj_key, const int* clk, size_t clk_size, bool as_noise) +int +gn_fa_clk (const char *obj_key, const int *clk, size_t clk_size, bool as_noise) { - try { - fa_ptr obj = get_fa_object(obj_key); - std::set clk2 (clk, clk + clk_size); - obj->set_clk(clk2); - obj->clk_as_noise = as_noise; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_clk : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + std::set clk2 (clk, clk + clk_size); + obj->set_clk (clk2); + obj->clk_as_noise = as_noise; + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_clk : ", e.what ()); } } -int gn_fa_conv_offset(const char* obj_key, bool enable) +int +gn_fa_conv_offset (const char *obj_key, bool enable) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->en_conv_offset = enable; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_conv_offset : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->en_conv_offset = enable; + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_conv_offset : ", e.what ()); } } -int gn_fa_create(const char* obj_key) +int +gn_fa_create (const char *obj_key) { - try { - gn::manager::add_object(obj_key, gn::fourier_analysis::create(), false); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_create : ", e.what()); + try + { + gn::manager::add_object (obj_key, gn::fourier_analysis::create (), + false); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_create : ", e.what ()); } } -int gn_fa_dc(const char* obj_key, bool as_dist) +int +gn_fa_dc (const char *obj_key, bool as_dist) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->dc_as_dist = as_dist; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_dc : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->dc_as_dist = as_dist; + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_dc : ", e.what ()); } } -int gn_fa_fdata(const char* obj_key, double f) +int +gn_fa_fdata (const char *obj_key, double f) { - try { - fa_ptr obj = get_fa_object(obj_key); - std::string f_s = gn::to_string(f, gn::FPFormat::Eng); - obj->set_fdata(f_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fdata : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + std::string f_s = gn::to_string (f, gn::FPFormat::Eng); + obj->set_fdata (f_s); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fdata : ", e.what ()); } } -int gn_fa_fdata_e(const char* obj_key, const char* f) +int +gn_fa_fdata_e (const char *obj_key, const char *f) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_fdata(f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fdata_e : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_fdata (f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fdata_e : ", e.what ()); } } -int gn_fa_fixed_tone( - const char* obj_key, const char* comp_key, GnFACompTag tag, double freq, int ssb) +int +gn_fa_fixed_tone (const char *obj_key, const char *comp_key, GnFACompTag tag, + double freq, int ssb) { - try { - fa_ptr obj = get_fa_object(obj_key); - gn::FACompTag t = gn::get_enum(tag); - std::string freq_s = gn::to_string(freq, gn::FPFormat::Eng); - obj->add_fixed_tone(comp_key, t, freq_s, ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fixed_tone : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + gn::FACompTag t = gn::get_enum (tag); + std::string freq_s = gn::to_string (freq, gn::FPFormat::Eng); + obj->add_fixed_tone (comp_key, t, freq_s, ssb); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fixed_tone : ", e.what ()); } } -int gn_fa_fixed_tone_e( - const char* obj_key, const char* comp_key, GnFACompTag tag, const char* freq, int ssb) +int +gn_fa_fixed_tone_e (const char *obj_key, const char *comp_key, GnFACompTag tag, + const char *freq, int ssb) { - try { - fa_ptr obj = get_fa_object(obj_key); - gn::FACompTag t = gn::get_enum(tag); - obj->add_fixed_tone(comp_key, t, freq, ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fixed_tone_e : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + gn::FACompTag t = gn::get_enum (tag); + obj->add_fixed_tone (comp_key, t, freq, ssb); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fixed_tone_e : ", e.what ()); } } -int gn_fa_fsample(const char* obj_key, double f) +int +gn_fa_fsample (const char *obj_key, double f) { - try { - fa_ptr obj = get_fa_object(obj_key); - std::string f_s = gn::to_string(f, gn::FPFormat::Eng); - obj->set_fsample(f_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fsample : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + std::string f_s = gn::to_string (f, gn::FPFormat::Eng); + obj->set_fsample (f_s); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fsample : ", e.what ()); } } -int gn_fa_fsample_e(const char* obj_key, const char* f) +int +gn_fa_fsample_e (const char *obj_key, const char *f) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_fsample(f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fsample_e : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_fsample (f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fsample_e : ", e.what ()); } } -int gn_fa_fshift(const char* obj_key, double f) +int +gn_fa_fshift (const char *obj_key, double f) { - try { - fa_ptr obj = get_fa_object(obj_key); - std::string f_s = gn::to_string(f, gn::FPFormat::Eng); - obj->set_fshift(f_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fshift : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + std::string f_s = gn::to_string (f, gn::FPFormat::Eng); + obj->set_fshift (f_s); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fshift : ", e.what ()); } } -int gn_fa_fshift_e(const char* obj_key, const char* f) +int +gn_fa_fshift_e (const char *obj_key, const char *f) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_fshift(f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fshift_e : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_fshift (f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fshift_e : ", e.what ()); } } -int gn_fa_fund_images(const char* obj_key, bool enable) +int +gn_fa_fund_images (const char *obj_key, bool enable) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->en_fund_images = enable; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fund_images : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->en_fund_images = enable; + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_fund_images : ", e.what ()); } } -int gn_fa_hd(const char* obj_key, int n) +int +gn_fa_hd (const char *obj_key, int n) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_hd(n); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_hd : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_hd (n); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_hd : ", e.what ()); } } -int gn_fa_ilv(const char* obj_key, const int* ilv, size_t ilv_size, bool as_noise) +int +gn_fa_ilv (const char *obj_key, const int *ilv, size_t ilv_size, bool as_noise) { - try { - fa_ptr obj = get_fa_object(obj_key); - std::set ilv2 (ilv, ilv + ilv_size); - obj->set_ilv(ilv2); - obj->ilv_as_noise = as_noise; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_ilv : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + std::set ilv2 (ilv, ilv + ilv_size); + obj->set_ilv (ilv2); + obj->ilv_as_noise = as_noise; + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_ilv : ", e.what ()); } } -int gn_fa_imd(const char* obj_key, int n) +int +gn_fa_imd (const char *obj_key, int n) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_imd(n); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_imd : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_imd (n); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_imd : ", e.what ()); } } -int gn_fa_load(char* buf, size_t size, const char* filename, const char* obj_key) +int +gn_fa_load (char *buf, size_t size, const char *filename, const char *obj_key) { - try { - std::string key (obj_key); - if (key.empty()) { - key = util::get_object_key_from_filename(filename); + try + { + std::string key (obj_key); + if (key.empty ()) + { + key = util::get_object_key_from_filename (filename); } - gn::manager::add_object(key, gn::fourier_analysis::load(filename), true); - util::fill_string_buffer(key.data(), key.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_load : ", e.what()); + gn::manager::add_object (key, gn::fourier_analysis::load (filename), + true); + util::fill_string_buffer (key.data (), key.size (), buf, size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_load : ", e.what ()); } } -int gn_fa_max_tone( - const char* obj_key, - const char* comp_key, - GnFACompTag tag, - int ssb) +int +gn_fa_max_tone (const char *obj_key, const char *comp_key, GnFACompTag tag, + int ssb) { - try { - fa_ptr obj = get_fa_object(obj_key); - gn::FACompTag t = gn::get_enum(tag); - obj->add_max_tone(comp_key, t, "0.0", "fdata", ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_max_tone : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + gn::FACompTag t = gn::get_enum (tag); + obj->add_max_tone (comp_key, t, "0.0", "fdata", ssb); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_max_tone : ", e.what ()); } } -int gn_fa_preview(char* buf, size_t size, const char* cfg_id, bool cplx) +int +gn_fa_preview (char *buf, size_t size, const char *cfg_id, bool cplx) { - try { - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - std::string s = obj->preview(cplx); - util::fill_string_buffer(s.data(), s.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_preview : ", e.what()); + try + { + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + std::string s = obj->preview (cplx); + util::fill_string_buffer (s.data (), s.size (), buf, size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_preview : ", e.what ()); } } -int gn_fa_quad_errors(const char* obj_key, bool enable) +int +gn_fa_quad_errors (const char *obj_key, bool enable) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->en_quad_errors = enable; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_quad_errors : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->en_quad_errors = enable; + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_quad_errors : ", e.what ()); } } -int gn_fa_remove_comp(const char* obj_key, const char* comp_key) +int +gn_fa_remove_comp (const char *obj_key, const char *comp_key) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->remove_comp(comp_key); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_remove_comp : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->remove_comp (comp_key); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_remove_comp : ", e.what ()); } } -int gn_fa_reset(const char* obj_key) +int +gn_fa_reset (const char *obj_key) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->reset(); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_reset : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->reset (); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_reset : ", e.what ()); } } -int gn_fa_ssb(const char* obj_key, GnFASsb group, int ssb) +int +gn_fa_ssb (const char *obj_key, GnFASsb group, int ssb) { - try { - gn::FASsb g = gn::get_enum(group); - fa_ptr obj = get_fa_object(obj_key); - obj->set_ssb(g, ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_ssb_dc : ", e.what()); + try + { + gn::FASsb g = gn::get_enum (group); + fa_ptr obj = get_fa_object (obj_key); + obj->set_ssb (g, ssb); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_ssb_dc : ", e.what ()); } } -int gn_fa_var(const char* obj_key, const char* name, double value) +int +gn_fa_var (const char *obj_key, const char *name, double value) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_var(name, value); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_var : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_var (name, value); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_var : ", e.what ()); } } -int gn_fa_wo(const char* obj_key, int n) +int +gn_fa_wo (const char *obj_key, int n) { - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_wo(n); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_wo : ", e.what()); + try + { + fa_ptr obj = get_fa_object (obj_key); + obj->set_wo (n); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_wo : ", e.what ()); } } @@ -1009,33 +1342,46 @@ int gn_fa_wo(const char* obj_key, int n) /* Fourier Analysis Results */ /**************************************************************************/ -int gn_fa_result(double* result, const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) +int +gn_fa_result (double *result, const char **rkeys, size_t rkeys_size, + const double *rvalues, size_t rvalues_size, const char *rkey) { - try { - util::check_pointer(result); - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); + try + { + util::check_pointer (result); + if (rkeys_size != rvalues_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); } - size_t key_index = get_fa_result_key_index(rkeys, rkeys_size, rkey); - *result = rvalues[key_index]; - return gn_success; - } catch (const std::exception& e) { - *result = 0.0; - return util::return_on_exception("gn_fa_result : ", e.what()); + size_t key_index = get_fa_result_key_index (rkeys, rkeys_size, rkey); + *result = rvalues[key_index]; + return gn_success; + } + catch (const std::exception &e) + { + *result = 0.0; + return util::return_on_exception ("gn_fa_result : ", e.what ()); } } -int gn_fa_result_string(char* result, size_t result_size, const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) +int +gn_fa_result_string (char *result, size_t result_size, const char **rkeys, + size_t rkeys_size, const double *rvalues, + size_t rvalues_size, const char *rkey) { - try { - util::check_pointer(result); - std::string rstr = get_fa_result_string(rkeys, rkeys_size, rvalues, rvalues_size, rkey); - util::fill_string_buffer(rstr.data(), rstr.size(), result, result_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_result_string : ", e.what()); + try + { + util::check_pointer (result); + std::string rstr = get_fa_result_string (rkeys, rkeys_size, rvalues, + rvalues_size, rkey); + util::fill_string_buffer (rstr.data (), rstr.size (), result, + result_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fa_result_string : ", e.what ()); } } @@ -1043,79 +1389,110 @@ int gn_fa_result_string(char* result, size_t result_size, const char** rkeys, si /* Fourier Analysis Helpers */ /**************************************************************************/ -int gn_fa_load_key_size(size_t* size, const char* filename, const char* obj_key) +int +gn_fa_load_key_size (size_t *size, const char *filename, const char *obj_key) { - try { - util::check_pointer(size); - std::string key (obj_key); - if (key.empty()) { - key = util::get_object_key_from_filename(filename); + try + { + util::check_pointer (size); + std::string key (obj_key); + if (key.empty ()) + { + key = util::get_object_key_from_filename (filename); } - *size = util::terminated_size(key.size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_load_key_size : ", e.what()); + *size = util::terminated_size (key.size ()); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_fa_load_key_size : ", e.what ()); } } -int gn_fa_preview_size(size_t* size, const char* cfg_id, bool cplx) +int +gn_fa_preview_size (size_t *size, const char *cfg_id, bool cplx) { - try { - util::check_pointer(size); - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - std::string s = obj->preview(cplx); - *size = util::terminated_size(s.size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_preview_size : ", e.what()); + try + { + util::check_pointer (size); + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + std::string s = obj->preview (cplx); + *size = util::terminated_size (s.size ()); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_fa_preview_size : ", e.what ()); } } -int gn_fa_result_string_size(size_t* size, const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) +int +gn_fa_result_string_size (size_t *size, const char **rkeys, size_t rkeys_size, + const double *rvalues, size_t rvalues_size, + const char *rkey) { - try { - util::check_pointer(size); - std::string rstr = get_fa_result_string(rkeys, rkeys_size, rvalues, rvalues_size, rkey); - *size = util::terminated_size(rstr.size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_result_string_size : ", e.what()); + try + { + util::check_pointer (size); + std::string rstr = get_fa_result_string (rkeys, rkeys_size, rvalues, + rvalues_size, rkey); + *size = util::terminated_size (rstr.size ()); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_fa_result_string_size : ", + e.what ()); } } -int gn_fft_analysis_results_key_sizes(size_t* key_sizes, size_t key_sizes_size, - const char* cfg_id, size_t in_size, size_t nfft) +int +gn_fft_analysis_results_key_sizes (size_t *key_sizes, size_t key_sizes_size, + const char *cfg_id, size_t in_size, + size_t nfft) { - try { - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - std::vector key_sizes_src = obj->result_key_lengths(in_size, nfft); - if (key_sizes_src.size() != key_sizes_size) { - throw std::runtime_error("Number of keys does not match output array size"); + try + { + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + std::vector key_sizes_src + = obj->result_key_lengths (in_size, nfft); + if (key_sizes_src.size () != key_sizes_size) + { + throw std::runtime_error ( + "Number of keys does not match output array size"); } - for (size_t i = 0; i < key_sizes_size; ++i) { - key_sizes[i] = util::terminated_size(key_sizes_src[i]); + for (size_t i = 0; i < key_sizes_size; ++i) + { + key_sizes[i] = util::terminated_size (key_sizes_src[i]); } - return gn_success; - } catch (const std::exception& e) { - std::fill(key_sizes, key_sizes + key_sizes_size, 0); - return util::return_on_exception("gn_fa_results_key_sizes : ", e.what()); + return gn_success; + } + catch (const std::exception &e) + { + std::fill (key_sizes, key_sizes + key_sizes_size, 0); + return util::return_on_exception ("gn_fa_results_key_sizes : ", + e.what ()); } } -int gn_fft_analysis_results_size(size_t* size, const char* cfg_id, size_t in_size, size_t nfft) +int +gn_fft_analysis_results_size (size_t *size, const char *cfg_id, size_t in_size, + size_t nfft) { - try { - util::check_pointer(size); - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - *size = obj->results_size(in_size, nfft); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_results_size : ", e.what()); + try + { + util::check_pointer (size); + fa_ptr obj = get_fa_object_or_load_from_file (cfg_id); + *size = obj->results_size (in_size, nfft); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_fa_results_size : ", e.what ()); } } @@ -1123,131 +1500,172 @@ int gn_fft_analysis_results_size(size_t* size, const char* cfg_id, size_t in_siz /* Fourier Transforms */ /**************************************************************************/ -namespace { +namespace +{ - template - int gn_fftxx(const char* suffix, double* out, size_t out_size, - const T* i, size_t i_size, const T* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +template +int +gn_fftxx (const char *suffix, double *out, size_t out_size, const T *i, + size_t i_size, const T *q, size_t q_size, int n, size_t navg, + size_t nfft, GnWindow window, GnCodeFormat format) +{ + try { - try { - gn::Window w = gn::get_enum(window); - gn::CodeFormat f = gn::get_enum(format); - gn::fft(i, i_size, q, q_size, out, out_size, n, navg, nfft, w, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fft", suffix, " : ", e.what()); - } + gn::Window w = gn::get_enum (window); + gn::CodeFormat f = gn::get_enum (format); + gn::fft (i, i_size, q, q_size, out, out_size, n, navg, nfft, w, f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fft", suffix, " : ", e.what ()); } +} - template - int gn_rfftxx(const char* suffix, double* out, size_t out_size, - const T* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +template +int +gn_rfftxx (const char *suffix, double *out, size_t out_size, const T *in, + size_t in_size, int n, size_t navg, size_t nfft, GnWindow window, + GnCodeFormat format, GnRfftScale scale) +{ + try { - try { - gn::Window w = gn::get_enum(window); - gn::CodeFormat f = gn::get_enum(format); - gn::RfftScale s = gn::get_enum(scale); - gn::rfft(in, in_size, out, out_size, n, navg, nfft, w, f, s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_rfft", suffix, " : ", e.what()); - } + gn::Window w = gn::get_enum (window); + gn::CodeFormat f = gn::get_enum (format); + gn::RfftScale s = gn::get_enum (scale); + gn::rfft (in, in_size, out, out_size, n, navg, nfft, w, f, s); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_rfft", suffix, " : ", e.what ()); } +} } // namespace anonymous -int gn_fft(double* out, size_t out_size, - const double* i, size_t i_size, const double* q, size_t q_size, - size_t navg, size_t nfft, GnWindow window) +int +gn_fft (double *out, size_t out_size, const double *i, size_t i_size, + const double *q, size_t q_size, size_t navg, size_t nfft, + GnWindow window) { - try { - gn::Window w = gn::get_enum(window); - gn::fft(i, i_size, q, q_size, out, out_size, navg, nfft, w); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fft : ", e.what()); + try + { + gn::Window w = gn::get_enum (window); + gn::fft (i, i_size, q, q_size, out, out_size, navg, nfft, w); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fft : ", e.what ()); } } -int gn_fft16(double* out, size_t out_size, - const int16_t* i, size_t i_size, const int16_t* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +int +gn_fft16 (double *out, size_t out_size, const int16_t *i, size_t i_size, + const int16_t *q, size_t q_size, int n, size_t navg, size_t nfft, + GnWindow window, GnCodeFormat format) { - return gn_fftxx("16", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); + return gn_fftxx ("16", out, out_size, i, i_size, q, q_size, n, navg, nfft, + window, format); } -int gn_fft32(double* out, size_t out_size, - const int32_t* i, size_t i_size, const int32_t* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +int +gn_fft32 (double *out, size_t out_size, const int32_t *i, size_t i_size, + const int32_t *q, size_t q_size, int n, size_t navg, size_t nfft, + GnWindow window, GnCodeFormat format) { - return gn_fftxx("32", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); + return gn_fftxx ("32", out, out_size, i, i_size, q, q_size, n, navg, nfft, + window, format); } -int gn_fft64(double* out, size_t out_size, - const int64_t* i, size_t i_size, const int64_t* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +int +gn_fft64 (double *out, size_t out_size, const int64_t *i, size_t i_size, + const int64_t *q, size_t q_size, int n, size_t navg, size_t nfft, + GnWindow window, GnCodeFormat format) { - return gn_fftxx("64", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); + return gn_fftxx ("64", out, out_size, i, i_size, q, q_size, n, navg, nfft, + window, format); } -int gn_rfft(double* out, size_t out_size, const double* in, size_t in_size, - size_t navg, size_t nfft, GnWindow window, GnRfftScale scale) +int +gn_rfft (double *out, size_t out_size, const double *in, size_t in_size, + size_t navg, size_t nfft, GnWindow window, GnRfftScale scale) { - try { - gn::Window w = gn::get_enum(window); - gn::RfftScale s = gn::get_enum(scale); - gn::rfft(in, in_size, out, out_size, navg, nfft, w, s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_rfft : ", e.what()); + try + { + gn::Window w = gn::get_enum (window); + gn::RfftScale s = gn::get_enum (scale); + gn::rfft (in, in_size, out, out_size, navg, nfft, w, s); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_rfft : ", e.what ()); } } -int gn_rfft16(double* out, size_t out_size, const int16_t* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +int +gn_rfft16 (double *out, size_t out_size, const int16_t *in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, + GnCodeFormat format, GnRfftScale scale) { - return gn_rfftxx("16", out, out_size, in, in_size, n, navg, nfft, window, format, scale); + return gn_rfftxx ("16", out, out_size, in, in_size, n, navg, nfft, window, + format, scale); } -int gn_rfft32(double* out, size_t out_size, const int32_t* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +int +gn_rfft32 (double *out, size_t out_size, const int32_t *in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, + GnCodeFormat format, GnRfftScale scale) { - return gn_rfftxx("32", out, out_size, in, in_size, n, navg, nfft, window, format, scale); + return gn_rfftxx ("32", out, out_size, in, in_size, n, navg, nfft, window, + format, scale); } -int gn_rfft64(double* out, size_t out_size, const int64_t* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +int +gn_rfft64 (double *out, size_t out_size, const int64_t *in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, + GnCodeFormat format, GnRfftScale scale) { - return gn_rfftxx("64", out, out_size, in, in_size, n, navg, nfft, window, format, scale); + return gn_rfftxx ("64", out, out_size, in, in_size, n, navg, nfft, window, + format, scale); } /**************************************************************************/ /* Fourier Transform Helpers */ /**************************************************************************/ -int gn_fft_size(size_t* out_size, size_t i_size, size_t q_size, size_t navg, size_t nfft) +int +gn_fft_size (size_t *out_size, size_t i_size, size_t q_size, size_t navg, + size_t nfft) { - try { - util::check_pointer(out_size); - *out_size = gn::fft_size(i_size, q_size, navg, nfft); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_fft_size : ", e.what()); + try + { + util::check_pointer (out_size); + *out_size = gn::fft_size (i_size, q_size, navg, nfft); + return gn_success; + } + catch (const std::exception &e) + { + *out_size = 0; + return util::return_on_exception ("gn_fft_size : ", e.what ()); } } -int gn_rfft_size(size_t* out_size, size_t in_size, size_t navg, size_t nfft) +int +gn_rfft_size (size_t *out_size, size_t in_size, size_t navg, size_t nfft) { - try { - util::check_pointer(out_size); - *out_size = gn::rfft_size(in_size, navg, nfft); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_rfft_size : ", e.what()); + try + { + util::check_pointer (out_size); + *out_size = gn::rfft_size (in_size, navg, nfft); + return gn_success; + } + catch (const std::exception &e) + { + *out_size = 0; + return util::return_on_exception ("gn_rfft_size : ", e.what ()); } } @@ -1255,59 +1673,79 @@ int gn_rfft_size(size_t* out_size, size_t in_size, size_t navg, size_t nfft) /* Fourier Utilities */ /**************************************************************************/ -int gn_alias(double* out, double fs, double freq, GnFreqAxisType axis_type) +int +gn_alias (double *out, double fs, double freq, GnFreqAxisType axis_type) { - try { - util::check_pointer(out); - gn::FreqAxisType at = gn::get_enum(axis_type); - *out = gn::alias(fs, freq, at); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_alias : ", e.what()); + try + { + util::check_pointer (out); + gn::FreqAxisType at = gn::get_enum (axis_type); + *out = gn::alias (fs, freq, at); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_alias : ", e.what ()); } } -int gn_coherent(double* out, size_t nfft, double fs, double freq) +int +gn_coherent (double *out, size_t nfft, double fs, double freq) { - try { - util::check_pointer(out); - *out = gn::coherent(nfft, fs, freq); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_coherent : ", e.what()); + try + { + util::check_pointer (out); + *out = gn::coherent (nfft, fs, freq); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_coherent : ", e.what ()); } } -int gn_fftshift(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_fftshift (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::fftshift(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fftshift : ", e.what()); + try + { + gn::fftshift (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fftshift : ", e.what ()); } } -int gn_freq_axis(double* out, size_t size, - size_t nfft, GnFreqAxisType axis_type, double fs, GnFreqAxisFormat axis_format) +int +gn_freq_axis (double *out, size_t size, size_t nfft, GnFreqAxisType axis_type, + double fs, GnFreqAxisFormat axis_format) { - try { - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::FreqAxisFormat af = gn::get_enum(axis_format); - gn::freq_axis(out, size, nfft, at, fs, af); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fftshift : ", e.what()); + try + { + gn::FreqAxisType at = gn::get_enum (axis_type); + gn::FreqAxisFormat af = gn::get_enum (axis_format); + gn::freq_axis (out, size, nfft, at, fs, af); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fftshift : ", e.what ()); } } -int gn_ifftshift(double* out, size_t out_size, const double* in, size_t in_size) +int +gn_ifftshift (double *out, size_t out_size, const double *in, size_t in_size) { - try { - gn::ifftshift(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_ifftshift : ", e.what()); + try + { + gn::ifftshift (in, in_size, out, out_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_ifftshift : ", e.what ()); } } @@ -1315,16 +1753,20 @@ int gn_ifftshift(double* out, size_t out_size, const double* in, size_t in_size) /* Fourier Utility Helpers */ /**************************************************************************/ -int gn_freq_axis_size(size_t* size, size_t nfft, GnFreqAxisType axis_type) +int +gn_freq_axis_size (size_t *size, size_t nfft, GnFreqAxisType axis_type) { - try { - util::check_pointer(size); - gn::FreqAxisType at = gn::get_enum(axis_type); - *size = gn::freq_axis_size(nfft, at); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_freq_axis_size : ", e.what()); + try + { + util::check_pointer (size); + gn::FreqAxisType at = gn::get_enum (axis_type); + *size = gn::freq_axis_size (nfft, at); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_freq_axis_size : ", e.what ()); } } @@ -1332,71 +1774,91 @@ int gn_freq_axis_size(size_t* size, size_t nfft, GnFreqAxisType axis_type) /* Manager */ /**************************************************************************/ -int gn_mgr_clear() +int +gn_mgr_clear () { - gn::manager::clear(); - return gn_success; + gn::manager::clear (); + return gn_success; } -int gn_mgr_compare(bool* result, const char* obj_key1, const char* obj_key2) +int +gn_mgr_compare (bool *result, const char *obj_key1, const char *obj_key2) { - try { - *result = gn::manager::equal(obj_key1, obj_key2); - return gn_success; - } catch (const std::exception& e) { - *result = false; - return util::return_on_exception("gn_mgr_equal : ", e.what()); + try + { + *result = gn::manager::equal (obj_key1, obj_key2); + return gn_success; + } + catch (const std::exception &e) + { + *result = false; + return util::return_on_exception ("gn_mgr_equal : ", e.what ()); } } -int gn_mgr_contains(bool* result, const char* obj_key) +int +gn_mgr_contains (bool *result, const char *obj_key) { - *result = gn::manager::contains(obj_key); - return gn_success; + *result = gn::manager::contains (obj_key); + return gn_success; } -int gn_mgr_remove(const char* obj_key) +int +gn_mgr_remove (const char *obj_key) { - gn::manager::remove(obj_key); - return gn_success; + gn::manager::remove (obj_key); + return gn_success; } -int gn_mgr_save(char* buf, size_t size, const char* obj_key, const char* filename) +int +gn_mgr_save (char *buf, size_t size, const char *obj_key, const char *filename) { - try { - std::string fn = gn::manager::save(obj_key, filename); - util::fill_string_buffer(fn.data(), fn.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_mgr_save : ", e.what()); + try + { + std::string fn = gn::manager::save (obj_key, filename); + util::fill_string_buffer (fn.data (), fn.size (), buf, size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_mgr_save : ", e.what ()); } } -int gn_mgr_size(size_t* size) +int +gn_mgr_size (size_t *size) { - *size = gn::manager::size(); - return gn_success; + *size = gn::manager::size (); + return gn_success; } -int gn_mgr_to_string(char* buf, size_t size, const char* obj_key) +int +gn_mgr_to_string (char *buf, size_t size, const char *obj_key) { - try { - std::string s = gn::manager::to_string(obj_key); - util::fill_string_buffer(s.data(), s.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_mgr_to_string : ", e.what()); + try + { + std::string s = gn::manager::to_string (obj_key); + util::fill_string_buffer (s.data (), s.size (), buf, size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_mgr_to_string : ", e.what ()); } } -int gn_mgr_type(char* buf, size_t size, const char* obj_key) +int +gn_mgr_type (char *buf, size_t size, const char *obj_key) { - try { - std::string s = gn::manager::type_str(obj_key); - util::fill_string_buffer(s.data(), s.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_mgr_type : ", e.what()); + try + { + std::string s = gn::manager::type_str (obj_key); + util::fill_string_buffer (s.data (), s.size (), buf, size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_mgr_type : ", e.what ()); } } @@ -1404,40 +1866,56 @@ int gn_mgr_type(char* buf, size_t size, const char* obj_key) /* Manager Helpers */ /**************************************************************************/ -int gn_mgr_save_filename_size(size_t* size, const char* obj_key, const char* filename) +int +gn_mgr_save_filename_size (size_t *size, const char *obj_key, + const char *filename) { - try { - util::check_pointer(size); - size_t fn_size = gn::manager::get_filename_from_object_key(obj_key, filename).size(); - *size = util::terminated_size(fn_size); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_mgr_save_filename_size : ", e.what()); + try + { + util::check_pointer (size); + size_t fn_size + = gn::manager::get_filename_from_object_key (obj_key, filename) + .size (); + *size = util::terminated_size (fn_size); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_mgr_save_filename_size : ", + e.what ()); } } -int gn_mgr_to_string_size(size_t* size, const char* obj_key) +int +gn_mgr_to_string_size (size_t *size, const char *obj_key) { - try { - util::check_pointer(size); - *size = util::terminated_size(gn::manager::to_string(obj_key).size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_mgr_to_string_size : ", e.what()); + try + { + util::check_pointer (size); + *size = util::terminated_size (gn::manager::to_string (obj_key).size ()); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_mgr_to_string_size : ", e.what ()); } } -int gn_mgr_type_size(size_t* size, const char* obj_key) +int +gn_mgr_type_size (size_t *size, const char *obj_key) { - try { - util::check_pointer(size); - *size = util::terminated_size(gn::manager::type_str(obj_key).size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_mgr_type_size : ", e.what()); + try + { + util::check_pointer (size); + *size = util::terminated_size (gn::manager::type_str (obj_key).size ()); + return gn_success; + } + catch (const std::exception &e) + { + *size = 0; + return util::return_on_exception ("gn_mgr_type_size : ", e.what ()); } } @@ -1445,190 +1923,244 @@ int gn_mgr_type_size(size_t* size, const char* obj_key) /* Signal Processing */ /**************************************************************************/ -namespace { +namespace +{ - template - int gn_downsamplex(const char* suffix, T* out, size_t out_size, - const T* in, size_t in_size, int ratio, bool interleaved) +template +int +gn_downsamplex (const char *suffix, T *out, size_t out_size, const T *in, + size_t in_size, int ratio, bool interleaved) +{ + try { - try { - gn::downsample(in, in_size, out, out_size, ratio, interleaved); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_downsample", suffix, " : ", e.what()); - } + gn::downsample (in, in_size, out, out_size, ratio, interleaved); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_downsample", suffix, " : ", + e.what ()); } +} - template - int gn_fshiftx(const char* suffix, T* out, size_t out_size, - const T* i, size_t i_size, const T* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) +template +int +gn_fshiftx (const char *suffix, T *out, size_t out_size, const T *i, + size_t i_size, const T *q, size_t q_size, int n, double fs, + double fshift, GnCodeFormat format) +{ + try { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::fshift(i, i_size, q, q_size, out, out_size, n, fs, fshift, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fshift", suffix, " : ", e.what()); - } + gn::CodeFormat f = gn::get_enum (format); + gn::fshift (i, i_size, q, q_size, out, out_size, n, fs, fshift, f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fshift", suffix, " : ", e.what ()); } +} - template - int gn_normalize(const char* suffix, double* out, size_t out_size, - const T* in, size_t in_size, int n, GnCodeFormat format) +template +int +gn_normalize (const char *suffix, double *out, size_t out_size, const T *in, + size_t in_size, int n, GnCodeFormat format) +{ + try { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::normalize(in, in_size, out, out_size, n, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_normalize", suffix, " : ", e.what()); - } + gn::CodeFormat f = gn::get_enum (format); + gn::normalize (in, in_size, out, out_size, n, f); + return gn_success; } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_normalize", suffix, " : ", + e.what ()); + } +} - template - int gn_quantize(const char* suffix, T* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +template +int +gn_quantize (const char *suffix, T *out, size_t out_size, const double *in, + size_t in_size, double fsr, int n, double noise, + GnCodeFormat format) +{ + try { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::quantize(in, in_size, out, out_size, fsr, n, noise, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_quantize", suffix, " : ", e.what()); - } + gn::CodeFormat f = gn::get_enum (format); + gn::quantize (in, in_size, out, out_size, fsr, n, noise, f); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_quantize", suffix, " : ", + e.what ()); } +} } // namespace anonymous -int gn_downsample(double* out, size_t out_size, - const double* in, size_t in_size, int ratio, bool interleaved) +int +gn_downsample (double *out, size_t out_size, const double *in, size_t in_size, + int ratio, bool interleaved) { - return gn_downsamplex("", out, out_size, in, in_size, ratio, interleaved); + return gn_downsamplex ("", out, out_size, in, in_size, ratio, interleaved); } -int gn_downsample16(int16_t* out, size_t out_size, - const int16_t* in, size_t in_size, int ratio, bool interleaved) +int +gn_downsample16 (int16_t *out, size_t out_size, const int16_t *in, + size_t in_size, int ratio, bool interleaved) { - return gn_downsamplex("16", out, out_size, in, in_size, ratio, interleaved); + return gn_downsamplex ("16", out, out_size, in, in_size, ratio, interleaved); } -int gn_downsample32(int32_t* out, size_t out_size, - const int32_t* in, size_t in_size, int ratio, bool interleaved) +int +gn_downsample32 (int32_t *out, size_t out_size, const int32_t *in, + size_t in_size, int ratio, bool interleaved) { - return gn_downsamplex("32", out, out_size, in, in_size, ratio, interleaved); + return gn_downsamplex ("32", out, out_size, in, in_size, ratio, interleaved); } -int gn_downsample64(int64_t* out, size_t out_size, - const int64_t* in, size_t in_size, int ratio, bool interleaved) +int +gn_downsample64 (int64_t *out, size_t out_size, const int64_t *in, + size_t in_size, int ratio, bool interleaved) { - return gn_downsamplex("64", out, out_size, in, in_size, ratio, interleaved); + return gn_downsamplex ("64", out, out_size, in, in_size, ratio, interleaved); } -int gn_fshift(double* out, size_t out_size, - const double* i, size_t i_size, const double* q, size_t q_size, double fs, double fshift) +int +gn_fshift (double *out, size_t out_size, const double *i, size_t i_size, + const double *q, size_t q_size, double fs, double fshift) { - try { - gn::fshift(i, i_size, q, q_size, out, out_size, fs, fshift); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fshift : ", e.what()); + try + { + gn::fshift (i, i_size, q, q_size, out, out_size, fs, fshift); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_fshift : ", e.what ()); } } -int gn_fshift16(int16_t* out, size_t out_size, - const int16_t* i, size_t i_size, const int16_t* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) +int +gn_fshift16 (int16_t *out, size_t out_size, const int16_t *i, size_t i_size, + const int16_t *q, size_t q_size, int n, double fs, double fshift, + GnCodeFormat format) { - return gn_fshiftx("16", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); + return gn_fshiftx ("16", out, out_size, i, i_size, q, q_size, n, fs, fshift, + format); } -int gn_fshift32(int32_t* out, size_t out_size, - const int32_t* i, size_t i_size, const int32_t* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) +int +gn_fshift32 (int32_t *out, size_t out_size, const int32_t *i, size_t i_size, + const int32_t *q, size_t q_size, int n, double fs, double fshift, + GnCodeFormat format) { - return gn_fshiftx("32", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); + return gn_fshiftx ("32", out, out_size, i, i_size, q, q_size, n, fs, fshift, + format); } -int gn_fshift64(int64_t* out, size_t out_size, - const int64_t* i, size_t i_size, const int64_t* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) +int +gn_fshift64 (int64_t *out, size_t out_size, const int64_t *i, size_t i_size, + const int64_t *q, size_t q_size, int n, double fs, double fshift, + GnCodeFormat format) { - return gn_fshiftx("64", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); + return gn_fshiftx ("64", out, out_size, i, i_size, q, q_size, n, fs, fshift, + format); } -int gn_normalize16(double* out, size_t out_size, - const int16_t* in, size_t in_size, int n, GnCodeFormat format) +int +gn_normalize16 (double *out, size_t out_size, const int16_t *in, + size_t in_size, int n, GnCodeFormat format) { - return gn_normalize("16", out, out_size, in, in_size, n, format); + return gn_normalize ("16", out, out_size, in, in_size, n, format); } -int gn_normalize32(double* out, size_t out_size, - const int32_t* in, size_t in_size, int n, GnCodeFormat format) +int +gn_normalize32 (double *out, size_t out_size, const int32_t *in, + size_t in_size, int n, GnCodeFormat format) { - return gn_normalize("32", out, out_size, in, in_size, n, format); + return gn_normalize ("32", out, out_size, in, in_size, n, format); } -int gn_normalize64(double* out, size_t out_size, - const int64_t* in, size_t in_size, int n, GnCodeFormat format) +int +gn_normalize64 (double *out, size_t out_size, const int64_t *in, + size_t in_size, int n, GnCodeFormat format) { - return gn_normalize("64", out, out_size, in, in_size, n, format); + return gn_normalize ("64", out, out_size, in, in_size, n, format); } -int gn_polyval(double* out, size_t out_size, - const double* in, size_t in_size, const double* c, size_t c_size) +int +gn_polyval (double *out, size_t out_size, const double *in, size_t in_size, + const double *c, size_t c_size) { - try { - gn::polyval(in, in_size, out, out_size, c, c_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_polyval : ", e.what()); + try + { + gn::polyval (in, in_size, out, out_size, c, c_size); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_polyval : ", e.what ()); } } -int gn_quantize16(int16_t* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +int +gn_quantize16 (int16_t *out, size_t out_size, const double *in, size_t in_size, + double fsr, int n, double noise, GnCodeFormat format) { - return gn_quantize("16", out, out_size, in, in_size, fsr, n, noise, format); + return gn_quantize ("16", out, out_size, in, in_size, fsr, n, noise, format); } -int gn_quantize32(int32_t* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +int +gn_quantize32 (int32_t *out, size_t out_size, const double *in, size_t in_size, + double fsr, int n, double noise, GnCodeFormat format) { - return gn_quantize("32", out, out_size, in, in_size, fsr, n, noise, format); + return gn_quantize ("32", out, out_size, in, in_size, fsr, n, noise, format); } -int gn_quantize64(int64_t* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +int +gn_quantize64 (int64_t *out, size_t out_size, const double *in, size_t in_size, + double fsr, int n, double noise, GnCodeFormat format) { - return gn_quantize("64", out, out_size, in, in_size, fsr, n, noise, format); + return gn_quantize ("64", out, out_size, in, in_size, fsr, n, noise, format); } /**************************************************************************/ /* Signal Processing Helpers */ /**************************************************************************/ -int gn_downsample_size(size_t* out_size, size_t in_size, int ratio, bool interleaved) +int +gn_downsample_size (size_t *out_size, size_t in_size, int ratio, + bool interleaved) { - try { - util::check_pointer(out_size); - *out_size = gn::downsample_size(in_size, ratio, interleaved); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_downsample_size : ", e.what()); + try + { + util::check_pointer (out_size); + *out_size = gn::downsample_size (in_size, ratio, interleaved); + return gn_success; + } + catch (const std::exception &e) + { + *out_size = 0; + return util::return_on_exception ("gn_downsample_size : ", e.what ()); } } -int gn_fshift_size(size_t* out_size, size_t i_size, size_t q_size) +int +gn_fshift_size (size_t *out_size, size_t i_size, size_t q_size) { - try { - util::check_pointer(out_size); - *out_size = gn::fshift_size(i_size, q_size); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_fshift_size : ", e.what()); + try + { + util::check_pointer (out_size); + *out_size = gn::fshift_size (i_size, q_size); + return gn_success; + } + catch (const std::exception &e) + { + *out_size = 0; + return util::return_on_exception ("gn_fshift_size : ", e.what ()); } } @@ -1636,101 +2168,135 @@ int gn_fshift_size(size_t* out_size, size_t i_size, size_t q_size) /* Waveforms */ /**************************************************************************/ -namespace { +namespace +{ - template - int gn_wf_analysisx(const char* suffix, - char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const T* in, size_t in_size) +template +int +gn_wf_analysisx (const char *suffix, char **rkeys, size_t rkeys_size, + double *rvalues, size_t rvalues_size, const T *in, + size_t in_size) +{ + try { - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::wf_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); - } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - std::map results = gn::wf_analysis(in, in_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_wf_analysis", suffix, " : ", e.what()); + util::check_pointer (rkeys); + util::check_pointer (rvalues); + const std::vector &keys = gn::wf_analysis_ordered_keys (); + if (keys.size () != rkeys_size) + { + throw std::runtime_error ("Size of result key array is wrong"); + } + if (rvalues_size != rkeys_size) + { + throw std::runtime_error ( + "Size of result keys does not match size of result values"); + } + std::map results = gn::wf_analysis (in, in_size); + for (size_t i = 0; i < keys.size (); ++i) + { + const std::string &src = keys[i]; + char *dst = rkeys[i]; + size_t dst_size = util::terminated_size (src.size ()); + util::fill_string_buffer (src.data (), src.size (), dst, dst_size); + rvalues[i] = results.at (src); } + return gn_success; } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_wf_analysis", suffix, " : ", + e.what ()); + } +} } // namespace anonymous -int gn_cos(double* out, size_t size, - double fs, double ampl, double freq, double phase, double td, double tj) +int +gn_cos (double *out, size_t size, double fs, double ampl, double freq, + double phase, double td, double tj) { - try { - gn::cos(out, size, fs, ampl, freq, phase, td, tj); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_cos : ", e.what()); + try + { + gn::cos (out, size, fs, ampl, freq, phase, td, tj); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_cos : ", e.what ()); } } -int gn_gaussian(double* out, size_t size, double mean, double sd) +int +gn_gaussian (double *out, size_t size, double mean, double sd) { - try { - gn::gaussian(out, size, mean, sd); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_gaussian : ", e.what()); + try + { + gn::gaussian (out, size, mean, sd); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_gaussian : ", e.what ()); } } -int gn_ramp(double* out, size_t size, double start, double stop, double noise) +int +gn_ramp (double *out, size_t size, double start, double stop, double noise) { - try { - gn::ramp(out, size, start, stop, noise); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_ramp : ", e.what()); + try + { + gn::ramp (out, size, start, stop, noise); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_ramp : ", e.what ()); } } -int gn_sin(double* out, size_t size, - double fs, double ampl, double freq, double phase, double td, double tj) +int +gn_sin (double *out, size_t size, double fs, double ampl, double freq, + double phase, double td, double tj) { - try { - gn::sin(out, size, fs, ampl, freq, phase, td, tj); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_sin : ", e.what()); + try + { + gn::sin (out, size, fs, ampl, freq, phase, td, tj); + return gn_success; + } + catch (const std::exception &e) + { + return util::return_on_exception ("gn_sin : ", e.what ()); } } -int gn_wf_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const double* in, size_t in_size) +int +gn_wf_analysis (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const double *in, size_t in_size) { - return gn_wf_analysisx("", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); + return gn_wf_analysisx ("", rkeys, rkeys_size, rvalues, rvalues_size, in, + in_size); } -int gn_wf_analysis16(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const int16_t* in, size_t in_size) +int +gn_wf_analysis16 (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const int16_t *in, size_t in_size) { - return gn_wf_analysisx("16", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); + return gn_wf_analysisx ("16", rkeys, rkeys_size, rvalues, rvalues_size, in, + in_size); } -int gn_wf_analysis32(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const int32_t* in, size_t in_size) +int +gn_wf_analysis32 (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const int32_t *in, size_t in_size) { - return gn_wf_analysisx("32", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); + return gn_wf_analysisx ("32", rkeys, rkeys_size, rvalues, rvalues_size, in, + in_size); } -int gn_wf_analysis64(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const int64_t* in, size_t in_size) +int +gn_wf_analysis64 (char **rkeys, size_t rkeys_size, double *rvalues, + size_t rvalues_size, const int64_t *in, size_t in_size) { - return gn_wf_analysisx("64", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); + return gn_wf_analysisx ("64", rkeys, rkeys_size, rvalues, rvalues_size, in, + in_size); } \ No newline at end of file diff --git a/bindings/c/src/cgenalyzer_simplified_beta.cpp b/bindings/c/src/cgenalyzer_simplified_beta.cpp index 264e8ae..527bbb0 100644 --- a/bindings/c/src/cgenalyzer_simplified_beta.cpp +++ b/bindings/c/src/cgenalyzer_simplified_beta.cpp @@ -1,1169 +1,1335 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "cgenalyzer_simplified_beta.h" #include "cgenalyzer_private.h" -extern "C" { - int gn_config_free(gn_config *c) - { - if ((*c)->obj_key){ - gn_mgr_remove((*c)->obj_key); - free((*c)->obj_key); - } - if ((*c)->comp_key){ - gn_fa_remove_comp((*c)->obj_key, (*c)->comp_key); - free((*c)->comp_key); - } - if (((*c)->_fa_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_fa_results_size; i++) - free((*c)->_fa_result_keys[i]); - free((*c)->_fa_result_keys); - free((*c)->_fa_result_key_sizes); - free((*c)->_fa_result_values); - } - if (((*c)->_wfa_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_wfa_results_size; i++) - free((*c)->_wfa_result_keys[i]); - free((*c)->_wfa_result_keys); - free((*c)->_wfa_result_key_sizes); - free((*c)->_wfa_result_values); - } - if (((*c)->_hist_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_hist_results_size; i++) - free((*c)->_hist_result_keys[i]); - free((*c)->_hist_result_keys); - free((*c)->_hist_result_key_sizes); - free((*c)->_hist_result_values); - } - if (((*c)->_dnl_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_dnl_results_size; i++) - free((*c)->_dnl_result_keys[i]); - free((*c)->_dnl_result_keys); - free((*c)->_dnl_result_key_sizes); - free((*c)->_dnl_result_values); - } - if (((*c)->_inl_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_inl_results_size; i++) - free((*c)->_inl_result_keys[i]); - free((*c)->_inl_result_keys); - free((*c)->_inl_result_key_sizes); - free((*c)->_inl_result_values); - } - free(*c); - - return gn_success; - } - - int gn_config_set_ttype(tone_type ttype, gn_config *c) - { - if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) || (ttype == COMPLEX_EXP))) - { - printf("ERROR: Invalid selection of ttype for tone generation\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->ttype = ttype; - - return gn_success; - } - - int gn_config_set_npts(size_t npts, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->npts = npts; - return gn_success; - } - - int gn_config_get_npts(size_t *npts, gn_config *c) - { - if (!(*c)) - { - printf("config struct is NULL\n"); - return gn_failure; - } - *npts = (*c)->npts; - return gn_success; - } - - int gn_config_set_sample_rate(gn::real_t sample_rate, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->sample_rate = sample_rate; - return gn_success; - } - - int gn_config_get_sample_rate(double *sample_rate, gn_config *c) - { - if (!(*c)) - { - printf("config struct is NULL\n"); - return gn_failure; - } - *sample_rate = (*c)->sample_rate; - return gn_success; - } - - int gn_config_set_data_rate(gn::real_t data_rate, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->data_rate = data_rate; - return gn_success; - } - - int gn_config_set_shift_freq(gn::real_t shift_freq, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->shift_freq = shift_freq; - return gn_success; - } - - int gn_config_set_num_tones(size_t num_tones, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->num_tones = num_tones; - return gn_success; - } - - int gn_config_set_tone_freq(gn::real_t *tone_freq, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->tone_freq = tone_freq; - return gn_success; - } - - int gn_config_set_tone_ampl(gn::real_t *tone_ampl, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->tone_ampl = tone_ampl; - return gn_success; - } - - int gn_config_set_tone_phase(gn::real_t *tone_phase, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->tone_phase = tone_phase; - return gn_success; - } - - int gn_config_set_fsr(gn::real_t fsr, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->fsr = fsr; - return gn_success; - } - - int gn_config_set_qres(int qres, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->qres = qres; - return gn_success; - } - - int gn_config_set_noise_rms(gn::real_t noise_rms, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->noise_rms = noise_rms; - return gn_success; - } - - int gn_config_set_code_format(GnCodeFormat code_format, gn_config *c) - { - if (!((code_format == GnCodeFormatOffsetBinary) || (code_format == GnCodeFormatTwosComplement))) - { - printf("ERROR: Invalid selection of code format\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->code_format = code_format; - return gn_success; - } - - int gn_config_set_nfft(size_t nfft, gn_config *c) - { - if (((*c)->nfft) > ((*c)->npts)) - { - printf("ERROR: FFT order cannot be greater than the number of sample points\n"); - return gn_failure; - } - - double rem = 1.0*(((*c)->npts)%((*c)->nfft)); - if (rem > 0) - { - printf("ERROR: FFT order has to be a multiple of the number of sample points\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->nfft = nfft; - (*c)->fft_navg = (*c)->npts/(*c)->nfft; - return gn_success; - } - - int gn_config_get_nfft(size_t *nfft, gn_config *c) - { - if (!(*c)) - { - printf("here - config struct is NULL\n"); - return gn_failure; - } - *nfft = (*c)->nfft; - return gn_success; - } - - int gn_config_set_fft_navg(size_t fft_navg, gn_config *c) - { - if (((*c)->fft_navg) > ((*c)->npts)) - { - printf("ERROR: Number of FFT averages cannot be greater than the number of sample points\n"); - return gn_failure; - } - - double rem = 1.0*(((*c)->npts)%((*c)->fft_navg)); - if (rem > 0) - { - printf("ERROR: Number of FFT averages has to be a multiple of the number of sample points\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->fft_navg = fft_navg; - (*c)->nfft = (*c)->npts/(*c)->fft_navg; - return gn_success; - } - - int gn_config_set_win(GnWindow win, gn_config *c) - { - if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) || (win == GnWindowNoWindow))) - { - printf("ERROR: Invalid selection of window function\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->win = win; - return gn_success; - } - - int gn_config_set_ssb_fund(int ssb_fund, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->ssb_fund = ssb_fund; - return gn_success; - } - - int gn_config_set_ssb_rest(int ssb_rest, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->ssb_rest = ssb_rest; - return gn_success; - } - - int gn_config_set_max_harm_order(int max_harm_order, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->max_harm_order = max_harm_order; - return gn_success; - } - - int gn_config_set_dnla_signal_type(GnDnlSignal dnla_signal_type, gn_config *c) - { - if (!((dnla_signal_type == GnDnlSignalRamp) || (dnla_signal_type == GnDnlSignalTone))) - { - printf("ERROR: Invalid selection of DNL analysis signal type\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->dnla_signal_type = dnla_signal_type; - return gn_success; - } - - int gn_config_set_inla_fit(GnInlLineFit inla_fit, gn_config *c) - { - if (!((inla_fit == GnInlLineFitBestFit) || (inla_fit == GnInlLineFitEndFit) || (inla_fit == GnInlLineFitNoFit))) - { - printf("ERROR: Invalid selection of INL line fit\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->inla_fit = inla_fit; - return gn_success; - } - - int gn_config_set_ramp_start(double ramp_start, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->ramp_start = ramp_start; - return gn_success; - } - - int gn_config_set_ramp_stop(double ramp_stop, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->ramp_stop = ramp_stop; - return gn_success; - } - - int gn_config_get_code_density_size(size_t *code_density_size, gn_config *c) - { - if (!(*c)) - { - printf("config struct is NULL\n"); - return gn_failure; - } - *code_density_size = (*c)->_code_density_size; - return gn_success; - } - - int gn_config_gen_tone(tone_type ttype, size_t npts, gn::real_t sample_rate, size_t num_tones, gn::real_t *tone_freq, gn::real_t *tone_ampl, gn::real_t *tone_phase, gn_config *c) - { - if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) || (ttype == COMPLEX_EXP))) - { - printf("ERROR: Invalid selection of waveform type for tone generation\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->ttype = ttype; - (*c)->npts = npts; - (*c)->sample_rate = sample_rate; - (*c)->num_tones = num_tones; - (*c)->tone_freq = tone_freq; - (*c)->tone_ampl = tone_ampl; - (*c)->tone_phase = tone_phase; - - return gn_success; - } - - int gn_config_gen_ramp(size_t npts, double ramp_start, double ramp_stop, gn_config *c) - { - if (ramp_stop < ramp_start) - { - printf("ERROR: ramp stop value cannot be smaller than ramp start value for ramp generation\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->npts = npts; - (*c)->ramp_start = ramp_start; - (*c)->ramp_stop = ramp_stop; - (*c)->noise_rms = 0.0; - - return gn_success; - } - - int gn_config_quantize(size_t npts, gn::real_t fsr, int qres, gn::real_t noise_rms, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->npts = npts; - (*c)->fsr = fsr; - (*c)->qres = qres; - (*c)->noise_rms = noise_rms; - (*c)->code_format = GnCodeFormatTwosComplement; - - return gn_success; - } - - int gn_config_histz_nla(size_t npts, int qres, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->npts = npts; - (*c)->qres = qres; - (*c)->code_format = GnCodeFormatTwosComplement; - (*c)->inla_fit = GnInlLineFitBestFit; - - return gn_success; - } - - int gn_config_fftz(size_t npts, int qres, size_t fft_navg, size_t nfft, GnWindow win, gn_config *c) - { - if (npts != (fft_navg*nfft)) - { - printf("ERROR: Number of samples points in the waveform has to equal FFT order times number of FFT averages\n"); - return gn_failure; - } - - if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) || (win == GnWindowNoWindow))) - { - printf("ERROR: Invalid selection of window function\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - - (*c)->npts = npts; - (*c)->qres = qres; - (*c)->fft_navg = fft_navg; - (*c)->nfft = nfft; - (*c)->win = win; - (*c)->code_format = GnCodeFormatTwosComplement; - - return gn_success; - } - - int gn_config_fa_auto(uint8_t ssb_width, gn_config *c) - { - int err_code; - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - - if ((*c)->sample_rate <= 0) { - printf("ERROR: Sample rate must be set before configuring Fourier analysis\n"); - return gn_failure; - } - - (*c)->obj_key = (char *)calloc(3, sizeof(char)); - strcpy((*c)->obj_key, "fa"); - (*c)->comp_key = (char *)calloc(2, sizeof(char)); - strcpy((*c)->comp_key, "A"); - - (*c)->ssb_fund = ssb_width; - (*c)->ssb_rest = 0; - (*c)->max_harm_order = 3; - (*c)->axis_type = GnFreqAxisTypeDcCenter; - - // configure object key for Fourier analysis - err_code = gn_fa_create((*c)->obj_key); - - // configure component key for Fourier analysis - err_code += gn_fa_max_tone((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, (*c)->ssb_fund); - - // configure harmonic order for Fourier analysis - err_code += gn_fa_hd((*c)->obj_key, (*c)->max_harm_order); - - // configure single-side bins for Fourier analysis - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDC, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbSignal, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbWO, -1); - - // configure sample-rate, data-rate, shift frequency, and converter offset - err_code += gn_fa_fsample((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fdata((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fshift((*c)->obj_key, 0.0); - err_code += gn_fa_conv_offset((*c)->obj_key, false); - - return (err_code); - } - - - int gn_config_fa(gn::real_t fixed_tone_freq, gn_config *c) - { - int err_code; - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - - if ((*c)->sample_rate <= 0) { - printf("ERROR: Sample rate must be set before configuring Fourier analysis\n"); - return gn_failure; - } - - (*c)->obj_key = (char *)calloc(3, sizeof(char)); - strcpy((*c)->obj_key, "fa"); - (*c)->comp_key = (char *)calloc(2, sizeof(char)); - strcpy((*c)->comp_key, "A"); - - (*c)->ssb_fund = 120; - (*c)->ssb_rest = 0; - (*c)->max_harm_order = 3; - (*c)->axis_type = GnFreqAxisTypeDcCenter; - - // configure object key for Fourier analysis - err_code = gn_fa_create((*c)->obj_key); - - // configure component key for Fourier analysis - err_code += gn_fa_fixed_tone((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, fixed_tone_freq, (*c)->ssb_fund); - - // configure harmonic order for Fourier analysis - err_code += gn_fa_hd((*c)->obj_key, (*c)->max_harm_order); - - // configure single-side bins for Fourier analysis - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDC, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbSignal, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbWO, -1); - - // configure sample-rate, data-rate, shift frequency, and converter offset - err_code += gn_fa_fsample((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fdata((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fshift((*c)->obj_key, 0.0); - err_code += gn_fa_conv_offset((*c)->obj_key, false); - - return (err_code); - } - - // waveform generation - int gn_gen_ramp(gn::real_t **out, gn_config *c) - { - int err_code; - gn::real_t *awf = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - err_code = gn_ramp(awf, (*c)->npts, (*c)->ramp_start, (*c)->ramp_stop, (*c)->noise_rms); - *out = awf; - - return err_code; - } - - int gn_gen_real_tone(gn::real_t **out, gn_config *c) - { - int err_code = 0; - gn::real_t *awf = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - - for (size_t i = 0; i < (*c)->num_tones; i++) - { - gn::real_t *tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - if ((*c)->ttype == REAL_COSINE) - err_code = gn_cos(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - else if ((*c)->ttype == REAL_SINE) - err_code = gn_sin(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - if (!err_code) - { - for (size_t j = 0; j < (*c)->npts; j++) - awf[j] = awf[j] + tmp[j]; - } - } - *out = awf; - - return err_code; - } - - int gn_gen_complex_tone(gn::real_t **outi, gn::real_t **outq, gn_config *c) - { - int err_code = 0; - gn::real_t *awfi = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - gn::real_t *awfq = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - - for (size_t i = 0; i < (*c)->num_tones; i++) { - gn::real_t *tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - err_code = gn_cos(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - if (!err_code) - { - for (size_t j = 0; j < (*c)->npts; j++) - awfi[j] = awfi[j] + tmp[j]; - } - tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - err_code = gn_sin(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - if (!err_code) - { - for (size_t j = 0; j < (*c)->npts; j++) - awfq[j] = awfq[j] + tmp[j]; - } - } - *outi = awfi; - *outq = awfq; - - return err_code; - } - - // processing - int gn_quantize(int32_t **out, const gn::real_t *in, gn_config *c) - { - int err_code; - int32_t *qwf = (int32_t *)calloc((*c)->npts, sizeof(int32_t)); - - err_code = gn_quantize32(qwf, (*c)->npts, in, (*c)->npts, (*c)->fsr, (*c)->qres, (*c)->noise_rms, (*c)->code_format); - *out = qwf; - - return err_code; - } - - int gn_fftz(gn::real_t **out, const int32_t *in_i, const int32_t *in_q, gn_config *c) - { - int err_code; - gn::real_t *fft_of_in = (gn::real_t *)calloc(2*(*c)->nfft, sizeof(gn::real_t)); - - err_code = gn_fft32(fft_of_in, 2*(*c)->nfft, in_i, (*c)->npts, in_q, (*c)->npts, (*c)->qres, (*c)->fft_navg, (*c)->nfft, (*c)->win, (*c)->code_format); - *out = fft_of_in; - - return err_code; - } - - int gn_histz(uint64_t **hist, size_t *hist_len, const int32_t *qwf, gn_config *c) - { - int err_code; - uint64_t *out = NULL; - - err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); - out = (uint64_t *)calloc((*c)->_code_density_size, sizeof(uint64_t)); - err_code += gn_hist32(out, (*c)->_code_density_size, qwf, (*c)->npts, (*c)->qres, (*c)->code_format, false); - *hist = out; - *hist_len = (*c)->_code_density_size; - - return err_code; - } - - int gn_dnlz(double **dnl, size_t *dnl_len, const uint64_t *hist, gn_config *c) - { - int err_code; - double *out = NULL; - - err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); - out = (double *)calloc((*c)->_code_density_size, sizeof(double)); - err_code = gn_dnl(out, (*c)->_code_density_size, hist, (*c)->_code_density_size, (*c)->dnla_signal_type); - *dnl = out; - *dnl_len = (*c)->_code_density_size; - - return err_code; - } - - int gn_inlz(double **inl, size_t *inl_len, const double *dnl, gn_config *c) - { - int err_code; - double *out = NULL; - - err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); - out = (double *)calloc((*c)->_code_density_size, sizeof(double)); - err_code = gn_inl(out, (*c)->_code_density_size, dnl, (*c)->_code_density_size, (*c)->inla_fit); - *inl = out; - *inl_len = (*c)->_code_density_size; - - return err_code; - } - - // Waveform/Histogram/DNL/INL/Fourier Analysis - int gn_get_wfa_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const int32_t *qwf, gn_config *c) - { - int err_code = 0; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_wfa_results_size), GnAnalysisTypeWaveform); - - // allocate memory for result keys and values - (*c)->_wfa_result_keys = (char **)calloc(((*c)->_wfa_results_size), sizeof(char*)); - (*c)->_wfa_result_values = (gn::real_t *)calloc(((*c)->_wfa_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_wfa_result_key_sizes = (size_t *)calloc(((*c)->_wfa_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_wfa_result_key_sizes, (*c)->_wfa_results_size, GnAnalysisTypeWaveform); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) - (*c)->_wfa_result_keys[i] = (char *)calloc((*c)->_wfa_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_wf_analysis32((*c)->_wfa_result_keys, (*c)->_wfa_results_size, (*c)->_wfa_result_values, (*c)->_wfa_results_size, qwf, (*c)->npts); - - // copy keys - *rkeys = (char **)calloc(((*c)->_wfa_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_wfa_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_wfa_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_wfa_result_keys[i]); - (*rvalues)[i] = (*c)->_wfa_result_values[i]; - } - *results_size = (*c)->_wfa_results_size; - - return(err_code); - } - - int gn_get_ha_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const uint64_t *hist, gn_config *c) - { - int err_code = 0; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_hist_results_size), GnAnalysisTypeHistogram); - - // allocate memory for result keys and values - (*c)->_hist_result_keys = (char **)calloc(((*c)->_hist_results_size), sizeof(char*)); - (*c)->_hist_result_values = (gn::real_t *)calloc(((*c)->_hist_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_hist_result_key_sizes = (size_t *)calloc(((*c)->_hist_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_hist_result_key_sizes, (*c)->_hist_results_size, GnAnalysisTypeHistogram); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_hist_results_size; ++i) - (*c)->_hist_result_keys[i] = (char *)calloc((*c)->_hist_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_hist_analysis((*c)->_hist_result_keys, (*c)->_hist_results_size, (*c)->_hist_result_values, (*c)->_hist_results_size, hist, (*c)->_code_density_size); - - // copy keys - *rkeys = (char **)calloc(((*c)->_hist_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_hist_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_hist_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_hist_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_hist_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_hist_result_keys[i]); - (*rvalues)[i] = (*c)->_hist_result_values[i]; - } - *results_size = (*c)->_hist_results_size; - - return(err_code); - } - - int gn_get_dnla_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const gn::real_t *dnl, gn_config *c) - { - int err_code; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_dnl_results_size), GnAnalysisTypeDNL); - - // allocate memory for result keys and values - (*c)->_dnl_result_keys = (char **)calloc(((*c)->_dnl_results_size), sizeof(char*)); - (*c)->_dnl_result_values = (gn::real_t *)calloc(((*c)->_dnl_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_dnl_result_key_sizes = (size_t *)calloc(((*c)->_dnl_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_dnl_result_key_sizes, (*c)->_dnl_results_size, GnAnalysisTypeDNL); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) - (*c)->_dnl_result_keys[i] = (char *)calloc((*c)->_dnl_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_dnl_analysis((*c)->_dnl_result_keys, (*c)->_dnl_results_size, (*c)->_dnl_result_values, (*c)->_dnl_results_size, dnl, (*c)->_code_density_size); - - // copy keys - *rkeys = (char **)calloc(((*c)->_dnl_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_dnl_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_dnl_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_dnl_result_keys[i]); - (*rvalues)[i] = (*c)->_dnl_result_values[i]; - } - *results_size = (*c)->_dnl_results_size; - - return(err_code); - } - - int gn_get_inla_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const gn::real_t *inl, gn_config *c) - { - int err_code; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_inl_results_size), GnAnalysisTypeINL); - - // allocate memory for result keys and values - (*c)->_inl_result_keys = (char **)calloc(((*c)->_inl_results_size), sizeof(char*)); - (*c)->_inl_result_values = (gn::real_t *)calloc(((*c)->_inl_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_inl_result_key_sizes = (size_t *)calloc(((*c)->_inl_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_inl_result_key_sizes, (*c)->_inl_results_size, GnAnalysisTypeINL); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_inl_results_size; ++i) - (*c)->_inl_result_keys[i] = (char *)calloc((*c)->_inl_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_inl_analysis((*c)->_inl_result_keys, (*c)->_inl_results_size, (*c)->_inl_result_values, (*c)->_inl_results_size, inl, (*c)->_code_density_size); - - // copy keys - *rkeys = (char **)calloc(((*c)->_inl_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_inl_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_inl_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_inl_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_inl_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_inl_result_keys[i]); - (*rvalues)[i] = (*c)->_inl_result_values[i]; - } - *results_size = (*c)->_inl_results_size; - - return(err_code); - } - - int gn_get_fa_single_result(gn::real_t *rvalue, const char *metric_name, gn::real_t *fft_ilv, gn_config *c) - { - int err_code; - size_t i; - bool metric_found = false; - size_t results_size; - char **rkeys; - double *rvalues; - - // compute all results - err_code = gn_get_fa_results(&rkeys, &rvalues, &results_size, fft_ilv, &(*c)); - for (i = 0; i < results_size; i++) - { - if (!strcmp(metric_name, rkeys[i])) - { - metric_found = true; - break; - } - } - if (!metric_found) - { - printf("ERROR: Invalid selection of metric\n"); - return gn_failure; - } - *rvalue = rvalues[i]; - - return err_code; - } - - int gn_get_fa_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, gn::real_t *fft_ilv, gn_config *c) - { - int err_code = 0; - size_t *result_key_sizes; - - // get results size - err_code = gn_fft_analysis_results_size(results_size, (*c)->obj_key, 2*(*c)->nfft, (*c)->nfft); - - // allocate memory for result keys and values - *rkeys = (char **)calloc(*results_size, sizeof(char*)); - *rvalues = (gn::real_t *)calloc(*results_size, sizeof(gn::real_t)); - - // get result key sizes - result_key_sizes = (size_t *)calloc(*results_size, sizeof(size_t)); - err_code += gn_fft_analysis_results_key_sizes(result_key_sizes, *results_size, (*c)->obj_key, 2*(*c)->nfft, (*c)->nfft); - - // allocate memory for each result key - for (size_t i = 0; i < *results_size; ++i) - (*rkeys)[i] = (char *)calloc(result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_fft_analysis(*rkeys, *results_size, *rvalues, *results_size, (*c)->obj_key, fft_ilv, 2*(*c)->nfft, (*c)->nfft, (*c)->axis_type); - - return (err_code); - } +extern "C" +{ + int + gn_config_free (gn_config *c) + { + if ((*c)->obj_key) + { + gn_mgr_remove ((*c)->obj_key); + free ((*c)->obj_key); + } + if ((*c)->comp_key) + { + gn_fa_remove_comp ((*c)->obj_key, (*c)->comp_key); + free ((*c)->comp_key); + } + if (((*c)->_fa_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_fa_results_size; i++) + free ((*c)->_fa_result_keys[i]); + free ((*c)->_fa_result_keys); + free ((*c)->_fa_result_key_sizes); + free ((*c)->_fa_result_values); + } + if (((*c)->_wfa_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_wfa_results_size; i++) + free ((*c)->_wfa_result_keys[i]); + free ((*c)->_wfa_result_keys); + free ((*c)->_wfa_result_key_sizes); + free ((*c)->_wfa_result_values); + } + if (((*c)->_hist_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_hist_results_size; i++) + free ((*c)->_hist_result_keys[i]); + free ((*c)->_hist_result_keys); + free ((*c)->_hist_result_key_sizes); + free ((*c)->_hist_result_values); + } + if (((*c)->_dnl_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_dnl_results_size; i++) + free ((*c)->_dnl_result_keys[i]); + free ((*c)->_dnl_result_keys); + free ((*c)->_dnl_result_key_sizes); + free ((*c)->_dnl_result_values); + } + if (((*c)->_inl_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_inl_results_size; i++) + free ((*c)->_inl_result_keys[i]); + free ((*c)->_inl_result_keys); + free ((*c)->_inl_result_key_sizes); + free ((*c)->_inl_result_values); + } + free (*c); + + return gn_success; + } + + int + gn_config_set_ttype (tone_type ttype, gn_config *c) + { + if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) + || (ttype == COMPLEX_EXP))) + { + printf ("ERROR: Invalid selection of ttype for tone generation\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ttype = ttype; + + return gn_success; + } + + int + gn_config_set_npts (size_t npts, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + return gn_success; + } + + int + gn_config_get_npts (size_t *npts, gn_config *c) + { + if (!(*c)) + { + printf ("config struct is NULL\n"); + return gn_failure; + } + *npts = (*c)->npts; + return gn_success; + } + + int + gn_config_set_sample_rate (gn::real_t sample_rate, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->sample_rate = sample_rate; + return gn_success; + } + + int + gn_config_get_sample_rate (double *sample_rate, gn_config *c) + { + if (!(*c)) + { + printf ("config struct is NULL\n"); + return gn_failure; + } + *sample_rate = (*c)->sample_rate; + return gn_success; + } + + int + gn_config_set_data_rate (gn::real_t data_rate, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->data_rate = data_rate; + return gn_success; + } + + int + gn_config_set_shift_freq (gn::real_t shift_freq, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->shift_freq = shift_freq; + return gn_success; + } + + int + gn_config_set_num_tones (size_t num_tones, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->num_tones = num_tones; + return gn_success; + } + + int + gn_config_set_tone_freq (gn::real_t *tone_freq, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->tone_freq = tone_freq; + return gn_success; + } + + int + gn_config_set_tone_ampl (gn::real_t *tone_ampl, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->tone_ampl = tone_ampl; + return gn_success; + } + + int + gn_config_set_tone_phase (gn::real_t *tone_phase, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->tone_phase = tone_phase; + return gn_success; + } + + int + gn_config_set_fsr (gn::real_t fsr, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->fsr = fsr; + return gn_success; + } + + int + gn_config_set_qres (int qres, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->qres = qres; + return gn_success; + } + + int + gn_config_set_noise_rms (gn::real_t noise_rms, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->noise_rms = noise_rms; + return gn_success; + } + + int + gn_config_set_code_format (GnCodeFormat code_format, gn_config *c) + { + if (!((code_format == GnCodeFormatOffsetBinary) + || (code_format == GnCodeFormatTwosComplement))) + { + printf ("ERROR: Invalid selection of code format\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->code_format = code_format; + return gn_success; + } + + int + gn_config_set_nfft (size_t nfft, gn_config *c) + { + if (((*c)->nfft) > ((*c)->npts)) + { + printf ("ERROR: FFT order cannot be greater than the number of sample " + "points\n"); + return gn_failure; + } + + double rem = 1.0 * (((*c)->npts) % ((*c)->nfft)); + if (rem > 0) + { + printf ("ERROR: FFT order has to be a multiple of the number of " + "sample points\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->nfft = nfft; + (*c)->fft_navg = (*c)->npts / (*c)->nfft; + return gn_success; + } + + int + gn_config_get_nfft (size_t *nfft, gn_config *c) + { + if (!(*c)) + { + printf ("here - config struct is NULL\n"); + return gn_failure; + } + *nfft = (*c)->nfft; + return gn_success; + } + + int + gn_config_set_fft_navg (size_t fft_navg, gn_config *c) + { + if (((*c)->fft_navg) > ((*c)->npts)) + { + printf ("ERROR: Number of FFT averages cannot be greater than the " + "number of sample points\n"); + return gn_failure; + } + + double rem = 1.0 * (((*c)->npts) % ((*c)->fft_navg)); + if (rem > 0) + { + printf ("ERROR: Number of FFT averages has to be a multiple of the " + "number of sample points\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->fft_navg = fft_navg; + (*c)->nfft = (*c)->npts / (*c)->fft_navg; + return gn_success; + } + + int + gn_config_set_win (GnWindow win, gn_config *c) + { + if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) + || (win == GnWindowNoWindow))) + { + printf ("ERROR: Invalid selection of window function\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->win = win; + return gn_success; + } + + int + gn_config_set_ssb_fund (int ssb_fund, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ssb_fund = ssb_fund; + return gn_success; + } + + int + gn_config_set_ssb_rest (int ssb_rest, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ssb_rest = ssb_rest; + return gn_success; + } + + int + gn_config_set_max_harm_order (int max_harm_order, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->max_harm_order = max_harm_order; + return gn_success; + } + + int + gn_config_set_dnla_signal_type (GnDnlSignal dnla_signal_type, gn_config *c) + { + if (!((dnla_signal_type == GnDnlSignalRamp) + || (dnla_signal_type == GnDnlSignalTone))) + { + printf ("ERROR: Invalid selection of DNL analysis signal type\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->dnla_signal_type = dnla_signal_type; + return gn_success; + } + + int + gn_config_set_inla_fit (GnInlLineFit inla_fit, gn_config *c) + { + if (!((inla_fit == GnInlLineFitBestFit) || (inla_fit == GnInlLineFitEndFit) + || (inla_fit == GnInlLineFitNoFit))) + { + printf ("ERROR: Invalid selection of INL line fit\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->inla_fit = inla_fit; + return gn_success; + } + + int + gn_config_set_ramp_start (double ramp_start, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ramp_start = ramp_start; + return gn_success; + } + + int + gn_config_set_ramp_stop (double ramp_stop, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ramp_stop = ramp_stop; + return gn_success; + } + + int + gn_config_get_code_density_size (size_t *code_density_size, gn_config *c) + { + if (!(*c)) + { + printf ("config struct is NULL\n"); + return gn_failure; + } + *code_density_size = (*c)->_code_density_size; + return gn_success; + } + + int + gn_config_gen_tone (tone_type ttype, size_t npts, gn::real_t sample_rate, + size_t num_tones, gn::real_t *tone_freq, + gn::real_t *tone_ampl, gn::real_t *tone_phase, + gn_config *c) + { + if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) + || (ttype == COMPLEX_EXP))) + { + printf ( + "ERROR: Invalid selection of waveform type for tone generation\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ttype = ttype; + (*c)->npts = npts; + (*c)->sample_rate = sample_rate; + (*c)->num_tones = num_tones; + (*c)->tone_freq = tone_freq; + (*c)->tone_ampl = tone_ampl; + (*c)->tone_phase = tone_phase; + + return gn_success; + } + + int + gn_config_gen_ramp (size_t npts, double ramp_start, double ramp_stop, + gn_config *c) + { + if (ramp_stop < ramp_start) + { + printf ("ERROR: ramp stop value cannot be smaller than ramp start " + "value for ramp generation\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + (*c)->ramp_start = ramp_start; + (*c)->ramp_stop = ramp_stop; + (*c)->noise_rms = 0.0; + + return gn_success; + } + + int + gn_config_quantize (size_t npts, gn::real_t fsr, int qres, + gn::real_t noise_rms, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + (*c)->fsr = fsr; + (*c)->qres = qres; + (*c)->noise_rms = noise_rms; + (*c)->code_format = GnCodeFormatTwosComplement; + + return gn_success; + } + + int + gn_config_histz_nla (size_t npts, int qres, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + (*c)->qres = qres; + (*c)->code_format = GnCodeFormatTwosComplement; + (*c)->inla_fit = GnInlLineFitBestFit; + + return gn_success; + } + + int + gn_config_fftz (size_t npts, int qres, size_t fft_navg, size_t nfft, + GnWindow win, gn_config *c) + { + if (npts != (fft_navg * nfft)) + { + printf ("ERROR: Number of samples points in the waveform has to equal " + "FFT order times number of FFT averages\n"); + return gn_failure; + } + + if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) + || (win == GnWindowNoWindow))) + { + printf ("ERROR: Invalid selection of window function\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + + (*c)->npts = npts; + (*c)->qres = qres; + (*c)->fft_navg = fft_navg; + (*c)->nfft = nfft; + (*c)->win = win; + (*c)->code_format = GnCodeFormatTwosComplement; + + return gn_success; + } + + int + gn_config_fa_auto (uint8_t ssb_width, gn_config *c) + { + int err_code; + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + + if ((*c)->sample_rate <= 0) + { + printf ("ERROR: Sample rate must be set before configuring Fourier " + "analysis\n"); + return gn_failure; + } + + (*c)->obj_key = (char *)calloc (3, sizeof (char)); + strcpy ((*c)->obj_key, "fa"); + (*c)->comp_key = (char *)calloc (2, sizeof (char)); + strcpy ((*c)->comp_key, "A"); + + (*c)->ssb_fund = ssb_width; + (*c)->ssb_rest = 0; + (*c)->max_harm_order = 3; + (*c)->axis_type = GnFreqAxisTypeDcCenter; + + // configure object key for Fourier analysis + err_code = gn_fa_create ((*c)->obj_key); + + // configure component key for Fourier analysis + err_code += gn_fa_max_tone ((*c)->obj_key, (*c)->comp_key, + GnFACompTagSignal, (*c)->ssb_fund); + + // configure harmonic order for Fourier analysis + err_code += gn_fa_hd ((*c)->obj_key, (*c)->max_harm_order); + + // configure single-side bins for Fourier analysis + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbDC, -1); + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbSignal, -1); + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbWO, -1); + + // configure sample-rate, data-rate, shift frequency, and converter offset + err_code += gn_fa_fsample ((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fdata ((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fshift ((*c)->obj_key, 0.0); + err_code += gn_fa_conv_offset ((*c)->obj_key, false); + + return (err_code); + } + + int + gn_config_fa (gn::real_t fixed_tone_freq, gn_config *c) + { + int err_code; + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc (1, sizeof (*c_p)); + if (!(c_p)) + { + printf ("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + + if ((*c)->sample_rate <= 0) + { + printf ("ERROR: Sample rate must be set before configuring Fourier " + "analysis\n"); + return gn_failure; + } + + (*c)->obj_key = (char *)calloc (3, sizeof (char)); + strcpy ((*c)->obj_key, "fa"); + (*c)->comp_key = (char *)calloc (2, sizeof (char)); + strcpy ((*c)->comp_key, "A"); + + (*c)->ssb_fund = 120; + (*c)->ssb_rest = 0; + (*c)->max_harm_order = 3; + (*c)->axis_type = GnFreqAxisTypeDcCenter; + + // configure object key for Fourier analysis + err_code = gn_fa_create ((*c)->obj_key); + + // configure component key for Fourier analysis + err_code + += gn_fa_fixed_tone ((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, + fixed_tone_freq, (*c)->ssb_fund); + + // configure harmonic order for Fourier analysis + err_code += gn_fa_hd ((*c)->obj_key, (*c)->max_harm_order); + + // configure single-side bins for Fourier analysis + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbDC, -1); + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbSignal, -1); + err_code += gn_fa_ssb ((*c)->obj_key, GnFASsbWO, -1); + + // configure sample-rate, data-rate, shift frequency, and converter offset + err_code += gn_fa_fsample ((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fdata ((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fshift ((*c)->obj_key, 0.0); + err_code += gn_fa_conv_offset ((*c)->obj_key, false); + + return (err_code); + } + + // waveform generation + int + gn_gen_ramp (gn::real_t **out, gn_config *c) + { + int err_code; + gn::real_t *awf = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + err_code = gn_ramp (awf, (*c)->npts, (*c)->ramp_start, (*c)->ramp_stop, + (*c)->noise_rms); + *out = awf; + + return err_code; + } + + int + gn_gen_real_tone (gn::real_t **out, gn_config *c) + { + int err_code = 0; + gn::real_t *awf = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + + for (size_t i = 0; i < (*c)->num_tones; i++) + { + gn::real_t *tmp + = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + if ((*c)->ttype == REAL_COSINE) + err_code + = gn_cos (tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], + (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + else if ((*c)->ttype == REAL_SINE) + err_code + = gn_sin (tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], + (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + if (!err_code) + { + for (size_t j = 0; j < (*c)->npts; j++) + awf[j] = awf[j] + tmp[j]; + } + } + *out = awf; + + return err_code; + } + + int + gn_gen_complex_tone (gn::real_t **outi, gn::real_t **outq, gn_config *c) + { + int err_code = 0; + gn::real_t *awfi = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + gn::real_t *awfq = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + + for (size_t i = 0; i < (*c)->num_tones; i++) + { + gn::real_t *tmp + = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + err_code + = gn_cos (tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], + (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + if (!err_code) + { + for (size_t j = 0; j < (*c)->npts; j++) + awfi[j] = awfi[j] + tmp[j]; + } + tmp = (gn::real_t *)calloc ((*c)->npts, sizeof (gn::real_t)); + err_code + = gn_sin (tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], + (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + if (!err_code) + { + for (size_t j = 0; j < (*c)->npts; j++) + awfq[j] = awfq[j] + tmp[j]; + } + } + *outi = awfi; + *outq = awfq; + + return err_code; + } + + // processing + int + gn_quantize (int32_t **out, const gn::real_t *in, gn_config *c) + { + int err_code; + int32_t *qwf = (int32_t *)calloc ((*c)->npts, sizeof (int32_t)); + + err_code = gn_quantize32 (qwf, (*c)->npts, in, (*c)->npts, (*c)->fsr, + (*c)->qres, (*c)->noise_rms, (*c)->code_format); + *out = qwf; + + return err_code; + } + + int + gn_fftz (gn::real_t **out, const int32_t *in_i, const int32_t *in_q, + gn_config *c) + { + int err_code; + gn::real_t *fft_of_in + = (gn::real_t *)calloc (2 * (*c)->nfft, sizeof (gn::real_t)); + + err_code = gn_fft32 (fft_of_in, 2 * (*c)->nfft, in_i, (*c)->npts, in_q, + (*c)->npts, (*c)->qres, (*c)->fft_navg, (*c)->nfft, + (*c)->win, (*c)->code_format); + *out = fft_of_in; + + return err_code; + } + + int + gn_histz (uint64_t **hist, size_t *hist_len, const int32_t *qwf, + gn_config *c) + { + int err_code; + uint64_t *out = NULL; + + err_code = gn_code_density_size (&((*c)->_code_density_size), (*c)->qres, + (*c)->code_format); + out = (uint64_t *)calloc ((*c)->_code_density_size, sizeof (uint64_t)); + err_code += gn_hist32 (out, (*c)->_code_density_size, qwf, (*c)->npts, + (*c)->qres, (*c)->code_format, false); + *hist = out; + *hist_len = (*c)->_code_density_size; + + return err_code; + } + + int + gn_dnlz (double **dnl, size_t *dnl_len, const uint64_t *hist, gn_config *c) + { + int err_code; + double *out = NULL; + + err_code = gn_code_density_size (&((*c)->_code_density_size), (*c)->qres, + (*c)->code_format); + out = (double *)calloc ((*c)->_code_density_size, sizeof (double)); + err_code = gn_dnl (out, (*c)->_code_density_size, hist, + (*c)->_code_density_size, (*c)->dnla_signal_type); + *dnl = out; + *dnl_len = (*c)->_code_density_size; + + return err_code; + } + + int + gn_inlz (double **inl, size_t *inl_len, const double *dnl, gn_config *c) + { + int err_code; + double *out = NULL; + + err_code = gn_code_density_size (&((*c)->_code_density_size), (*c)->qres, + (*c)->code_format); + out = (double *)calloc ((*c)->_code_density_size, sizeof (double)); + err_code = gn_inl (out, (*c)->_code_density_size, dnl, + (*c)->_code_density_size, (*c)->inla_fit); + *inl = out; + *inl_len = (*c)->_code_density_size; + + return err_code; + } + + // Waveform/Histogram/DNL/INL/Fourier Analysis + int + gn_get_wfa_results (char ***rkeys, gn::real_t **rvalues, + size_t *results_size, const int32_t *qwf, gn_config *c) + { + int err_code = 0; + + // get results size + err_code = gn_analysis_results_size (&((*c)->_wfa_results_size), + GnAnalysisTypeWaveform); + + // allocate memory for result keys and values + (*c)->_wfa_result_keys + = (char **)calloc (((*c)->_wfa_results_size), sizeof (char *)); + (*c)->_wfa_result_values = (gn::real_t *)calloc (((*c)->_wfa_results_size), + sizeof (gn::real_t)); + + // get result key sizes + (*c)->_wfa_result_key_sizes + = (size_t *)calloc (((*c)->_wfa_results_size), sizeof (size_t)); + err_code += gn_analysis_results_key_sizes ((*c)->_wfa_result_key_sizes, + (*c)->_wfa_results_size, + GnAnalysisTypeWaveform); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) + (*c)->_wfa_result_keys[i] + = (char *)calloc ((*c)->_wfa_result_key_sizes[i], sizeof (char)); + + // execute analysis + err_code += gn_wf_analysis32 ( + (*c)->_wfa_result_keys, (*c)->_wfa_results_size, + (*c)->_wfa_result_values, (*c)->_wfa_results_size, qwf, (*c)->npts); + + // copy keys + *rkeys = (char **)calloc (((*c)->_wfa_results_size), sizeof (char *)); + for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) + (*rkeys)[i] + = (char *)calloc ((*c)->_wfa_result_key_sizes[i], sizeof (char)); + + // copy values + *rvalues = (gn::real_t *)calloc (((*c)->_wfa_results_size), + sizeof (gn::real_t)); + for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) + { + strcpy ((*rkeys)[i], (*c)->_wfa_result_keys[i]); + (*rvalues)[i] = (*c)->_wfa_result_values[i]; + } + *results_size = (*c)->_wfa_results_size; + + return (err_code); + } + + int + gn_get_ha_results (char ***rkeys, gn::real_t **rvalues, size_t *results_size, + const uint64_t *hist, gn_config *c) + { + int err_code = 0; + + // get results size + err_code = gn_analysis_results_size (&((*c)->_hist_results_size), + GnAnalysisTypeHistogram); + + // allocate memory for result keys and values + (*c)->_hist_result_keys + = (char **)calloc (((*c)->_hist_results_size), sizeof (char *)); + (*c)->_hist_result_values = (gn::real_t *)calloc ( + ((*c)->_hist_results_size), sizeof (gn::real_t)); + + // get result key sizes + (*c)->_hist_result_key_sizes + = (size_t *)calloc (((*c)->_hist_results_size), sizeof (size_t)); + err_code += gn_analysis_results_key_sizes ((*c)->_hist_result_key_sizes, + (*c)->_hist_results_size, + GnAnalysisTypeHistogram); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_hist_results_size; ++i) + (*c)->_hist_result_keys[i] + = (char *)calloc ((*c)->_hist_result_key_sizes[i], sizeof (char)); + + // execute analysis + err_code += gn_hist_analysis ( + (*c)->_hist_result_keys, (*c)->_hist_results_size, + (*c)->_hist_result_values, (*c)->_hist_results_size, hist, + (*c)->_code_density_size); + + // copy keys + *rkeys = (char **)calloc (((*c)->_hist_results_size), sizeof (char *)); + for (size_t i = 0; i < (*c)->_hist_results_size; ++i) + (*rkeys)[i] + = (char *)calloc ((*c)->_hist_result_key_sizes[i], sizeof (char)); + + // copy values + *rvalues = (gn::real_t *)calloc (((*c)->_hist_results_size), + sizeof (gn::real_t)); + for (size_t i = 0; i < (*c)->_hist_results_size; ++i) + { + strcpy ((*rkeys)[i], (*c)->_hist_result_keys[i]); + (*rvalues)[i] = (*c)->_hist_result_values[i]; + } + *results_size = (*c)->_hist_results_size; + + return (err_code); + } + + int + gn_get_dnla_results (char ***rkeys, gn::real_t **rvalues, + size_t *results_size, const gn::real_t *dnl, + gn_config *c) + { + int err_code; + + // get results size + err_code = gn_analysis_results_size (&((*c)->_dnl_results_size), + GnAnalysisTypeDNL); + + // allocate memory for result keys and values + (*c)->_dnl_result_keys + = (char **)calloc (((*c)->_dnl_results_size), sizeof (char *)); + (*c)->_dnl_result_values = (gn::real_t *)calloc (((*c)->_dnl_results_size), + sizeof (gn::real_t)); + + // get result key sizes + (*c)->_dnl_result_key_sizes + = (size_t *)calloc (((*c)->_dnl_results_size), sizeof (size_t)); + err_code += gn_analysis_results_key_sizes ((*c)->_dnl_result_key_sizes, + (*c)->_dnl_results_size, + GnAnalysisTypeDNL); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) + (*c)->_dnl_result_keys[i] + = (char *)calloc ((*c)->_dnl_result_key_sizes[i], sizeof (char)); + + // execute analysis + err_code + += gn_dnl_analysis ((*c)->_dnl_result_keys, (*c)->_dnl_results_size, + (*c)->_dnl_result_values, (*c)->_dnl_results_size, + dnl, (*c)->_code_density_size); + + // copy keys + *rkeys = (char **)calloc (((*c)->_dnl_results_size), sizeof (char *)); + for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) + (*rkeys)[i] + = (char *)calloc ((*c)->_dnl_result_key_sizes[i], sizeof (char)); + + // copy values + *rvalues = (gn::real_t *)calloc (((*c)->_dnl_results_size), + sizeof (gn::real_t)); + for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) + { + strcpy ((*rkeys)[i], (*c)->_dnl_result_keys[i]); + (*rvalues)[i] = (*c)->_dnl_result_values[i]; + } + *results_size = (*c)->_dnl_results_size; + + return (err_code); + } + + int + gn_get_inla_results (char ***rkeys, gn::real_t **rvalues, + size_t *results_size, const gn::real_t *inl, + gn_config *c) + { + int err_code; + + // get results size + err_code = gn_analysis_results_size (&((*c)->_inl_results_size), + GnAnalysisTypeINL); + + // allocate memory for result keys and values + (*c)->_inl_result_keys + = (char **)calloc (((*c)->_inl_results_size), sizeof (char *)); + (*c)->_inl_result_values = (gn::real_t *)calloc (((*c)->_inl_results_size), + sizeof (gn::real_t)); + + // get result key sizes + (*c)->_inl_result_key_sizes + = (size_t *)calloc (((*c)->_inl_results_size), sizeof (size_t)); + err_code += gn_analysis_results_key_sizes ((*c)->_inl_result_key_sizes, + (*c)->_inl_results_size, + GnAnalysisTypeINL); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_inl_results_size; ++i) + (*c)->_inl_result_keys[i] + = (char *)calloc ((*c)->_inl_result_key_sizes[i], sizeof (char)); + + // execute analysis + err_code + += gn_inl_analysis ((*c)->_inl_result_keys, (*c)->_inl_results_size, + (*c)->_inl_result_values, (*c)->_inl_results_size, + inl, (*c)->_code_density_size); + + // copy keys + *rkeys = (char **)calloc (((*c)->_inl_results_size), sizeof (char *)); + for (size_t i = 0; i < (*c)->_inl_results_size; ++i) + (*rkeys)[i] + = (char *)calloc ((*c)->_inl_result_key_sizes[i], sizeof (char)); + + // copy values + *rvalues = (gn::real_t *)calloc (((*c)->_inl_results_size), + sizeof (gn::real_t)); + for (size_t i = 0; i < (*c)->_inl_results_size; ++i) + { + strcpy ((*rkeys)[i], (*c)->_inl_result_keys[i]); + (*rvalues)[i] = (*c)->_inl_result_values[i]; + } + *results_size = (*c)->_inl_results_size; + + return (err_code); + } + + int + gn_get_fa_single_result (gn::real_t *rvalue, const char *metric_name, + gn::real_t *fft_ilv, gn_config *c) + { + int err_code; + size_t i; + bool metric_found = false; + size_t results_size; + char **rkeys; + double *rvalues; + + // compute all results + err_code + = gn_get_fa_results (&rkeys, &rvalues, &results_size, fft_ilv, &(*c)); + for (i = 0; i < results_size; i++) + { + if (!strcmp (metric_name, rkeys[i])) + { + metric_found = true; + break; + } + } + if (!metric_found) + { + printf ("ERROR: Invalid selection of metric\n"); + return gn_failure; + } + *rvalue = rvalues[i]; + + return err_code; + } + + int + gn_get_fa_results (char ***rkeys, gn::real_t **rvalues, size_t *results_size, + gn::real_t *fft_ilv, gn_config *c) + { + int err_code = 0; + size_t *result_key_sizes; + + // get results size + err_code = gn_fft_analysis_results_size (results_size, (*c)->obj_key, + 2 * (*c)->nfft, (*c)->nfft); + + // allocate memory for result keys and values + *rkeys = (char **)calloc (*results_size, sizeof (char *)); + *rvalues = (gn::real_t *)calloc (*results_size, sizeof (gn::real_t)); + + // get result key sizes + result_key_sizes = (size_t *)calloc (*results_size, sizeof (size_t)); + err_code += gn_fft_analysis_results_key_sizes ( + result_key_sizes, *results_size, (*c)->obj_key, 2 * (*c)->nfft, + (*c)->nfft); + + // allocate memory for each result key + for (size_t i = 0; i < *results_size; ++i) + (*rkeys)[i] = (char *)calloc (result_key_sizes[i], sizeof (char)); + + // execute analysis + err_code += gn_fft_analysis (*rkeys, *results_size, *rvalues, + *results_size, (*c)->obj_key, fft_ilv, + 2 * (*c)->nfft, (*c)->nfft, (*c)->axis_type); + + return (err_code); + } } \ No newline at end of file diff --git a/bindings/python/genalyzer/__init__.py b/bindings/python/genalyzer/__init__.py index 96d18a9..aa194a3 100644 --- a/bindings/python/genalyzer/__init__.py +++ b/bindings/python/genalyzer/__init__.py @@ -1,6 +1,9 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD OR GPL-2.0-or-later + """Python bindings for Genalyzer""" -# Version of the genalyzer bindings (which may be different than the library version) __version__ = "0.1.1" __author__ = "Analog Devices, Inc." diff --git a/bindings/python/genalyzer/helpers/__init__.py b/bindings/python/genalyzer/helpers/__init__.py index 0d382a4..5d38c35 100644 --- a/bindings/python/genalyzer/helpers/__init__.py +++ b/bindings/python/genalyzer/helpers/__init__.py @@ -1,3 +1,7 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD OR GPL-2.0-or-later + try: from .waveform_gen import WaveformGen except ImportError: diff --git a/bindings/python/genalyzer/helpers/waveform_gen.py b/bindings/python/genalyzer/helpers/waveform_gen.py index 883d697..c3598c1 100644 --- a/bindings/python/genalyzer/helpers/waveform_gen.py +++ b/bindings/python/genalyzer/helpers/waveform_gen.py @@ -1,3 +1,7 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD OR GPL-2.0-or-later + from ..simplified_beta import ( config_gen_tone, gen_real_tone, diff --git a/bindings/python/genalyzer/pygenalyzer.py b/bindings/python/genalyzer/pygenalyzer.py index a199690..212dffb 100644 --- a/bindings/python/genalyzer/pygenalyzer.py +++ b/bindings/python/genalyzer/pygenalyzer.py @@ -1,27 +1,11 @@ -""" -* pygenalyzer - genalyzer API header file -* -* Copyright (C) 2022 Analog Devices, Inc. -* Author: Peter Derounian -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -""" +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD OR GPL-2.0-or-later """ Python wrapper for Genalyzer Library (genalyzer_plus_plus) """ + import ctypes as _ctypes from ctypes.util import find_library as _find_library from enum import IntEnum as _IntEnum diff --git a/bindings/python/genalyzer/simplified_beta/__init__.py b/bindings/python/genalyzer/simplified_beta/__init__.py index 89a94fb..d1b6d7f 100644 --- a/bindings/python/genalyzer/simplified_beta/__init__.py +++ b/bindings/python/genalyzer/simplified_beta/__init__.py @@ -1,3 +1,7 @@ +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD OR GPL-2.0-or-later + from .simplified_beta import ( config_free, config_gen_ramp, diff --git a/bindings/python/genalyzer/simplified_beta/simplified_beta.py b/bindings/python/genalyzer/simplified_beta/simplified_beta.py index 1e233b3..49b6d50 100644 --- a/bindings/python/genalyzer/simplified_beta/simplified_beta.py +++ b/bindings/python/genalyzer/simplified_beta/simplified_beta.py @@ -1,23 +1,6 @@ -""" -* cgenalyzer - genalyzer API header file -* -* Copyright (C) 2022 Analog Devices, Inc. -* Author: Srikanth Pagadarai -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -""" +# Copyright (C) 2024 Analog Devices, Inc. +# +# SPDX short identifier: ADIBSD OR GPL-2.0-or-later from dataclasses import dataclass, field diff --git a/cmake/FindBreathe.cmake b/cmake/FindBREATHE.cmake similarity index 80% rename from cmake/FindBreathe.cmake rename to cmake/FindBREATHE.cmake index 239a224..0aed416 100644 --- a/cmake/FindBreathe.cmake +++ b/cmake/FindBREATHE.cmake @@ -7,7 +7,7 @@ if(BREATHE_APIDOC) endif() include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Breathe REQUIRED_VARS BREATHE_APIDOC +find_package_handle_standard_args(BREATHE REQUIRED_VARS BREATHE_APIDOC VERSION_VAR BREATHE_VERSION ) diff --git a/cmake/FindFFTW.cmake b/cmake/FindFFTW.cmake index fb8476d..007c641 100644 --- a/cmake/FindFFTW.cmake +++ b/cmake/FindFFTW.cmake @@ -33,21 +33,21 @@ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# OF THIS SOFTWARE, EVEN ifADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Usage: # find_package(FFTW [REQUIRED] [QUIET] [COMPONENTS component1 ... componentX] ) # # It sets the following variables: -# FFTW_FOUND ... true if fftw is found on the system -# FFTW_[component]_LIB_FOUND ... true if the component is found on the system (see components below) +# FFTW_FOUND ... true iffftw is found on the system +# FFTW_[component]_LIB_FOUND ... true ifthe component is found on the system (see components below) # FFTW_LIBRARIES ... full paths to all found fftw libraries # FFTW_[component]_LIB ... full path to one of the components (see below) # FFTW_INCLUDE_DIRS ... fftw include directory paths # # The following variables will be checked by the function -# FFTW_USE_STATIC_LIBS ... if true, only static libraries are found, otherwise both static and shared. -# FFTW_ROOT ... if set, the libraries are exclusively searched +# FFTW_USE_STATIC_LIBS ... iftrue, only static libraries are found, otherwise both static and shared. +# FFTW_ROOT ... ifset, the libraries are exclusively searched # under this path # # This package supports the following components: @@ -70,7 +70,7 @@ if( NOT FFTW_ROOT AND DEFINED ENV{FFTWDIR} ) set( FFTW_ROOT $ENV{FFTWDIR} ) endif() -# Check if we can use PkgConfig +# Check ifwe can use PkgConfig find_package(PkgConfig) #Determine from PKG @@ -230,113 +230,113 @@ else() PATHS ${PKG_FFTW_INCLUDE_DIRS} ${INCLUDE_INSTALL_DIR} ) -endif( FFTW_ROOT ) +endif() #--------------------------------------- components -if (FFTW_DOUBLE_LIB) +if(FFTW_DOUBLE_LIB) set(FFTW_DOUBLE_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_LIB}) add_library(FFTW::Double INTERFACE IMPORTED) set_target_properties(FFTW::Double PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_LIB}" ) else() set(FFTW_DOUBLE_LIB_FOUND FALSE) endif() -if (FFTW_FLOAT_LIB) +if(FFTW_FLOAT_LIB) set(FFTW_FLOAT_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_LIB}) add_library(FFTW::Float INTERFACE IMPORTED) set_target_properties(FFTW::Float PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_LIB}" ) else() set(FFTW_FLOAT_LIB_FOUND FALSE) endif() -if (FFTW_LONGDOUBLE_LIB) +if(FFTW_LONGDOUBLE_LIB) set(FFTW_LONGDOUBLE_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_LIB}) add_library(FFTW::LongDouble INTERFACE IMPORTED) set_target_properties(FFTW::LongDouble PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_LIB}" ) else() set(FFTW_LONGDOUBLE_LIB_FOUND FALSE) endif() -if (FFTW_DOUBLE_THREADS_LIB) +if(FFTW_DOUBLE_THREADS_LIB) set(FFTW_DOUBLE_THREADS_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_THREADS_LIB}) add_library(FFTW::DoubleThreads INTERFACE IMPORTED) set_target_properties(FFTW::DoubleThreads PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLETHREADS_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLETHREADS_LIB}" ) else() set(FFTW_DOUBLE_THREADS_LIB_FOUND FALSE) endif() -if (FFTW_FLOAT_THREADS_LIB) +if(FFTW_FLOAT_THREADS_LIB) set(FFTW_FLOAT_THREADS_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_THREADS_LIB}) add_library(FFTW::FloatThreads INTERFACE IMPORTED) set_target_properties(FFTW::FloatThreads PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_THREADS_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_THREADS_LIB}" ) else() set(FFTW_FLOAT_THREADS_LIB_FOUND FALSE) endif() -if (FFTW_LONGDOUBLE_THREADS_LIB) +if(FFTW_LONGDOUBLE_THREADS_LIB) set(FFTW_LONGDOUBLE_THREADS_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_THREADS_LIB}) add_library(FFTW::LongDoubleThreads INTERFACE IMPORTED) set_target_properties(FFTW::LongDoubleThreads PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_THREADS_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_THREADS_LIB}" ) else() set(FFTW_LONGDOUBLE_THREADS_LIB_FOUND FALSE) endif() -if (FFTW_DOUBLE_OPENMP_LIB) +if(FFTW_DOUBLE_OPENMP_LIB) set(FFTW_DOUBLE_OPENMP_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_DOUBLE_OPENMP_LIB}) add_library(FFTW::DoubleOpenMP INTERFACE IMPORTED) set_target_properties(FFTW::DoubleOpenMP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_OPENMP_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_DOUBLE_OPENMP_LIB}" ) else() set(FFTW_DOUBLE_OPENMP_LIB_FOUND FALSE) endif() -if (FFTW_FLOAT_OPENMP_LIB) +if(FFTW_FLOAT_OPENMP_LIB) set(FFTW_FLOAT_OPENMP_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_FLOAT_OPENMP_LIB}) add_library(FFTW::FloatOpenMP INTERFACE IMPORTED) set_target_properties(FFTW::FloatOpenMP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_OPENMP_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_FLOAT_OPENMP_LIB}" ) else() set(FFTW_FLOAT_OPENMP_LIB_FOUND FALSE) endif() -if (FFTW_LONGDOUBLE_OPENMP_LIB) +if(FFTW_LONGDOUBLE_OPENMP_LIB) set(FFTW_LONGDOUBLE_OPENMP_LIB_FOUND TRUE) set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTW_LONGDOUBLE_OPENMP_LIB}) add_library(FFTW::LongDoubleOpenMP INTERFACE IMPORTED) set_target_properties(FFTW::LongDoubleOpenMP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FFTW_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_OPENMP_LIB}" + INTERFACE_LINK_LIBRARIES "${FFTW_LONGDOUBLE_OPENMP_LIB}" ) else() set(FFTW_LONGDOUBLE_OPENMP_LIB_FOUND FALSE) diff --git a/cmake/FindSPHINX.cmake b/cmake/FindSPHINX.cmake new file mode 100644 index 0000000..1d37510 --- /dev/null +++ b/cmake/FindSPHINX.cmake @@ -0,0 +1,7 @@ +#Look for an executable called sphinx-build +find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable") + +include(FindPackageHandleStandardArgs) + +#Handle standard arguments to find_package like REQUIRED and QUIET +find_package_handle_standard_args(SPHINX "Failed to find sphinx-build executable" SPHINX_EXECUTABLE) diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake deleted file mode 100644 index 990f979..0000000 --- a/cmake/FindSphinx.cmake +++ /dev/null @@ -1,11 +0,0 @@ -#Look for an executable called sphinx-build -find_program(SPHINX_EXECUTABLE - NAMES sphinx-build - DOC "Path to sphinx-build executable") - -include(FindPackageHandleStandardArgs) - -#Handle standard arguments to find_package like REQUIRED and QUIET -find_package_handle_standard_args(Sphinx - "Failed to find sphinx-build executable" - SPHINX_EXECUTABLE) diff --git a/cmake/Modules/Findgenalyzer_plus_plus.cmake b/cmake/Modules/FindGENALYZER_PLUS_PLUS.cmake similarity index 80% rename from cmake/Modules/Findgenalyzer_plus_plus.cmake rename to cmake/Modules/FindGENALYZER_PLUS_PLUS.cmake index 9b60c2f..9d14a58 100644 --- a/cmake/Modules/Findgenalyzer_plus_plus.cmake +++ b/cmake/Modules/FindGENALYZER_PLUS_PLUS.cmake @@ -1,5 +1,5 @@ if(NOT GENALYZER_PLUS_PLUS_FOUND) - find_path(GENALYZER_PLUS_PLUS_INCLUDE_DIRS + find_path(GENALYZER_PLUS_PLUS_INCLUDE_DIRS NAMES array_ops.hpp code_density.hpp @@ -30,8 +30,8 @@ if(NOT GENALYZER_PLUS_PLUS_FOUND) /usr/local/include/ ) - find_library(GENALYZER_PLUS_PLUS_LIBRARIES - NAMES + find_library(GENALYZER_PLUS_PLUS_LIBRARIES + NAMES genalyzer_plus_plus PATHS /usr/lib @@ -41,11 +41,11 @@ if(NOT GENALYZER_PLUS_PLUS_FOUND) if(GENALYZER_PLUS_PLUS_INCLUDE_DIRS AND GENALYZER_PLUS_PLUS_LIBRARIES) set(GENALYZER_PLUS_PLUS_FOUND TRUE CACHE INTERNAL "libgenalyzer_plus_plus found") message(STATUS "Found libgenalyzer_plus_plus: ${GENALYZER_PLUS_PLUS_INCLUDE_DIRS}, ${GENALYZER_PLUS_PLUS_LIBRARIES}") -else(GENALYZER_PLUS_PLUS_INCLUDE_DIRS AND GENALYZER_PLUS_PLUS_LIBRARIES) +else() set(GENALYZER_PLUS_PLUS_FOUND FALSE CACHE INTERNAL "libgenalyzer_plus_plus found") message(STATUS "libgenalyzer_plus_plus not found.") -endif(GENALYZER_PLUS_PLUS_INCLUDE_DIRS AND GENALYZER_PLUS_PLUS_LIBRARIES) +endif() mark_as_advanced(GENALYZER_PLUS_PLUS_LIBRARIES AND GENALYZER_PLUS_PLUS_INCLUDE_DIRS) -endif(NOT GENALYZER_PLUS_PLUS_FOUND) +endif() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 1676d3a..4a933f6 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -10,10 +10,10 @@ configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}) add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} - DEPENDS ${GENALYZER_PUBLIC_HEADERS} - COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} - MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} - COMMENT "Generating docs") + DEPENDS ${GENALYZER_PUBLIC_HEADERS} + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} + MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} + COMMENT "Generating docs") add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) diff --git a/doc/general_example_noise_configuration.c b/doc/general_example_noise_configuration.c index fe01979..9d73007 100644 --- a/doc/general_example_noise_configuration.c +++ b/doc/general_example_noise_configuration.c @@ -1,12 +1,6 @@ - // configuration - config_noise_meas(&c, - COMPLEX_NOISE, - nfft, - navg, - fs, - fsr, - res, - noise_pwr_lvl, - update_fsample, - update_fdata, - update_fshift); \ No newline at end of file +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +// configuration +config_noise_meas (&c, COMPLEX_NOISE, nfft, navg, fs, fsr, res, noise_pwr_lvl, + update_fsample, update_fdata, update_fshift); \ No newline at end of file diff --git a/doc/general_example_ramp_configuration.c b/doc/general_example_ramp_configuration.c index 8d7adc3..b7e381a 100644 --- a/doc/general_example_ramp_configuration.c +++ b/doc/general_example_ramp_configuration.c @@ -1,10 +1,10 @@ - // configuration - config_ramp_nl_meas(&c, - npts, // # of data points - fs, // sample rate - fsr, // full-scale range - res, // ADC resolution: unused configuration setting - start, - stop, - 0.0 - ); \ No newline at end of file +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +// configuration +config_ramp_nl_meas (&c, + npts, // # of data points + fs, // sample rate + fsr, // full-scale range + res, // ADC resolution: unused configuration setting + start, stop, 0.0); \ No newline at end of file diff --git a/doc/general_example_skelton1.c b/doc/general_example_skelton1.c index 9d9de87..a14753a 100644 --- a/doc/general_example_skelton1.c +++ b/doc/general_example_skelton1.c @@ -1,18 +1,23 @@ -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - // config c = NULL; - - /* configuration */ - // config_tone_meas(...); - - /* waveform generation and quantize */ - // gen_tone(...); - // quantize(...); - - /* compute metrics */ - // fsnr_val = metric(..., "FSNR"); - - return 0; +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +#include "cgenalyzer.h" + +int +main (int argc, char *argv[]) +{ + // opaque config struct that will contain config settings + // config c = NULL; + + /* configuration */ + // config_tone_meas(...); + + /* waveform generation and quantize */ + // gen_tone(...); + // quantize(...); + + /* compute metrics */ + // fsnr_val = metric(..., "FSNR"); + + return 0; } \ No newline at end of file diff --git a/doc/general_example_skelton2.c b/doc/general_example_skelton2.c index df6eaff..5ea2c46 100644 --- a/doc/general_example_skelton2.c +++ b/doc/general_example_skelton2.c @@ -1,17 +1,22 @@ -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - // config c = NULL; - - /* configuration */ - // config_tone_meas(...); - - /* load waveform generation*/ - // read_file_to_array(...); - - /* compute metrics */ - // fsnr_val = metric(..., "FSNR"); - - return 0; +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +#include "cgenalyzer.h" + +int +main (int argc, char *argv[]) +{ + // opaque config struct that will contain config settings + // config c = NULL; + + /* configuration */ + // config_tone_meas(...); + + /* load waveform generation*/ + // read_file_to_array(...); + + /* compute metrics */ + // fsnr_val = metric(..., "FSNR"); + + return 0; } \ No newline at end of file diff --git a/doc/general_example_skelton3.c b/doc/general_example_skelton3.c index d20558b..fe79497 100644 --- a/doc/general_example_skelton3.c +++ b/doc/general_example_skelton3.c @@ -1,21 +1,26 @@ -#include -#include -#include -#include "genalyzer_cwrapper.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - // config c = NULL; - - /* configuration */ - // config_tone_meas(&c, FREQ, ...); - // config_tone_meas(&c, TIME,...); - - /* load waveform generation*/ - // read_file_to_array(...); - - /* compute metrics */ - // fsnr_val = metric(..., "FSNR"); - - return 0; +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +#include "genalyzer_cwrapper.h" +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + // opaque config struct that will contain config settings + // config c = NULL; + + /* configuration */ + // config_tone_meas(&c, FREQ, ...); + // config_tone_meas(&c, TIME,...); + + /* load waveform generation*/ + // read_file_to_array(...); + + /* compute metrics */ + // fsnr_val = metric(..., "FSNR"); + + return 0; } \ No newline at end of file diff --git a/doc/general_example_tone_configuration.c b/doc/general_example_tone_configuration.c index a1c0f87..7aebe39 100644 --- a/doc/general_example_tone_configuration.c +++ b/doc/general_example_tone_configuration.c @@ -1,18 +1,16 @@ - - // configuration - config_tone_meas(&c, - domain_wf, - type_wf, - nfft, // FFT order - navg, // # of FFTs averaged - fs, // sample rate - fsr, // full-scale range - 0, // ADC resolution: unused configuration setting - freq, // tone frequency, # of array elements = num_tones - scale, // tone scale, # of array elements = num_tones - phase, // tone phase, # of array elements = num_tones - num_tones, // # of tones - false, - false, - false - ); \ No newline at end of file + +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +// configuration +config_tone_meas (&c, domain_wf, type_wf, + nfft, // FFT order + navg, // # of FFTs averaged + fs, // sample rate + fsr, // full-scale range + 0, // ADC resolution: unused configuration setting + freq, // tone frequency, # of array elements = num_tones + scale, // tone scale, # of array elements = num_tones + phase, // tone phase, # of array elements = num_tones + num_tones, // # of tones + false, false, false); \ No newline at end of file diff --git a/doc/working_example_tone_instr.c b/doc/working_example_tone_instr.c index 275eb70..94c63ec 100644 --- a/doc/working_example_tone_instr.c +++ b/doc/working_example_tone_instr.c @@ -1,68 +1,70 @@ -#include -#include -#include -#include "test_genalyzer.h" -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // read test waveform - const char *test_filename_ip = argv[1]; - printf("%s\n", test_filename_ip); - - meas_domain domain_wf = atoll(extract_token(test_filename_ip, "domain_wf")); - waveform_type type_wf = atoll(extract_token(test_filename_ip, "type_wf")); - size_t nfft = atoll(extract_token(test_filename_ip, "nfft")); - size_t num_tones = atoll(extract_token(test_filename_ip, "num_tones")); - int res = atoi(extract_token(test_filename_ip, "res")); - int navg = atoi(extract_token(test_filename_ip, "navg")); - double fs = atof(extract_token(test_filename_ip, "fs")); - double fdata = fs, fshift = fs; - double fsr = atof(extract_token(test_filename_ip, "fsr")); - double *freq = (double *)calloc(num_tones, sizeof(double)); - double *scale = (double *)calloc(num_tones, sizeof(double)); - double *phase = (double *)calloc(num_tones, sizeof(double)); - - char tmp_token[10]; - for (int n = 0; n < num_tones; n++) { - sprintf(tmp_token, "freq%d", n); - freq[n] = atof(extract_token(test_filename_ip, tmp_token)); - sprintf(tmp_token, "scale%d", n); - scale[n] = atof(extract_token(test_filename_ip, tmp_token)); - sprintf(tmp_token, "phase%d", n); - phase[n] = atof(extract_token(test_filename_ip, tmp_token)); - } - - size_t npts = 2*nfft*navg; - int qwf[npts]; - config c = NULL; - - // configuration - config_tone_meas(&c, - domain_wf, - type_wf, - nfft, // FFT order - navg, // # of FFTs averaged - fs, // sample rate - fsr, // full-scale range - res, // ADC resolution: unused configuration setting - freq, // tone frequency, # of array elements = num_tones - scale, // tone scale, # of array elements = num_tones - phase, // tone phase, # of array elements = num_tones - num_tones, // # of tones - false, - false, - false - ); - - // read quantized input waveform - read_file_to_array(test_filename_ip, (void *) qwf, INT32); - - // compute metrics - fsnr_val = metric(c, qwf, "FSNR"); - sfdr_val = metric(c, qwf, "SFDR"); - sinad_val = metric(c, qwf, "SINAD"); - - free(awf); - free(qwf); - return 0; +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +#include "cgenalyzer.h" +#include "test_genalyzer.h" +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + // read test waveform + const char *test_filename_ip = argv[1]; + printf ("%s\n", test_filename_ip); + + meas_domain domain_wf + = atoll (extract_token (test_filename_ip, "domain_wf")); + waveform_type type_wf = atoll (extract_token (test_filename_ip, "type_wf")); + size_t nfft = atoll (extract_token (test_filename_ip, "nfft")); + size_t num_tones = atoll (extract_token (test_filename_ip, "num_tones")); + int res = atoi (extract_token (test_filename_ip, "res")); + int navg = atoi (extract_token (test_filename_ip, "navg")); + double fs = atof (extract_token (test_filename_ip, "fs")); + double fdata = fs, fshift = fs; + double fsr = atof (extract_token (test_filename_ip, "fsr")); + double *freq = (double *)calloc (num_tones, sizeof (double)); + double *scale = (double *)calloc (num_tones, sizeof (double)); + double *phase = (double *)calloc (num_tones, sizeof (double)); + + char tmp_token[10]; + for (int n = 0; n < num_tones; n++) + { + sprintf (tmp_token, "freq%d", n); + freq[n] = atof (extract_token (test_filename_ip, tmp_token)); + sprintf (tmp_token, "scale%d", n); + scale[n] = atof (extract_token (test_filename_ip, tmp_token)); + sprintf (tmp_token, "phase%d", n); + phase[n] = atof (extract_token (test_filename_ip, tmp_token)); + } + + size_t npts = 2 * nfft * navg; + int qwf[npts]; + config c = NULL; + + // configuration + config_tone_meas (&c, domain_wf, type_wf, + nfft, // FFT order + navg, // # of FFTs averaged + fs, // sample rate + fsr, // full-scale range + res, // ADC resolution: unused configuration setting + freq, // tone frequency, # of array elements = num_tones + scale, // tone scale, # of array elements = num_tones + phase, // tone phase, # of array elements = num_tones + num_tones, // # of tones + false, false, false); + + // read quantized input waveform + read_file_to_array (test_filename_ip, (void *)qwf, INT32); + + // compute metrics + fsnr_val = metric (c, qwf, "FSNR"); + sfdr_val = metric (c, qwf, "SFDR"); + sinad_val = metric (c, qwf, "SINAD"); + + free (awf); + free (qwf); + return 0; } \ No newline at end of file diff --git a/doc/working_example_tone_sim.c b/doc/working_example_tone_sim.c index be7639e..edfffcb 100644 --- a/doc/working_example_tone_sim.c +++ b/doc/working_example_tone_sim.c @@ -1,66 +1,60 @@ -#include -#include -#include -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // read configuration settings from a file - const char *test_filename = argv[1]; - printf("%s\n", test_filename); - - // variables to hold configuration settings - double *awf; - int *qwf; - size_t nfft = atoll(extract_token(test_filename, "nfft")); - size_t num_tones = atoll(extract_token(test_filename, "num_tones")); - int navg = atoi(extract_token(test_filename, "navg")); - double fs = atof(extract_token(test_filename, "fs")); - double fdata = fs, fshift = fs; - double fsr = atof(extract_token(test_filename, "fsr")); - double *freq = (double *)calloc(num_tones, sizeof(double)); - double *scale = (double *)calloc(num_tones, sizeof(double)); - double *phase = (double *)calloc(num_tones, sizeof(double)); - - char tmp_token[10]; - for (int n = 0; n < num_tones; n++) { - sprintf(tmp_token, "freq%d", n); - freq[n] = atof(extract_token(test_filename, tmp_token)); - sprintf(tmp_token, "scale%d", n); - scale[n] = atof(extract_token(test_filename, tmp_token)); - sprintf(tmp_token, "phase%d", n); - phase[n] = atof(extract_token(test_filename, tmp_token)); - } - - // opaque config struct that will contain config settings - config c = NULL; - - // configuration - config_tone_meas(&c, - FREQ, - COMPLEX_EXP, - nfft, - navg, - fs, - fsr, - res, - &freq, - &scale, - &phase, - 1, - update_fsample, - update_fdata, - update_fshift); - - // waveform generation - gen_tone(c, &awf); - quantize(c, awf, &qwf); - - // compute metrics - fsnr_val = metric(c, qwf, "FSNR"); - sfdr_val = metric(c, qwf, "SFDR"); - sinad_val = metric(c, qwf, "SINAD"); - - free(awf); - free(qwf); - return 0; +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later +#include "cgenalyzer.h" +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + // read configuration settings from a file + const char *test_filename = argv[1]; + printf ("%s\n", test_filename); + + // variables to hold configuration settings + double *awf; + int *qwf; + size_t nfft = atoll (extract_token (test_filename, "nfft")); + size_t num_tones = atoll (extract_token (test_filename, "num_tones")); + int navg = atoi (extract_token (test_filename, "navg")); + double fs = atof (extract_token (test_filename, "fs")); + double fdata = fs, fshift = fs; + double fsr = atof (extract_token (test_filename, "fsr")); + double *freq = (double *)calloc (num_tones, sizeof (double)); + double *scale = (double *)calloc (num_tones, sizeof (double)); + double *phase = (double *)calloc (num_tones, sizeof (double)); + + char tmp_token[10]; + for (int n = 0; n < num_tones; n++) + { + sprintf (tmp_token, "freq%d", n); + freq[n] = atof (extract_token (test_filename, tmp_token)); + sprintf (tmp_token, "scale%d", n); + scale[n] = atof (extract_token (test_filename, tmp_token)); + sprintf (tmp_token, "phase%d", n); + phase[n] = atof (extract_token (test_filename, tmp_token)); + } + + // opaque config struct that will contain config settings + config c = NULL; + + // configuration + config_tone_meas (&c, FREQ, COMPLEX_EXP, nfft, navg, fs, fsr, res, &freq, + &scale, &phase, 1, update_fsample, update_fdata, + update_fshift); + + // waveform generation + gen_tone (c, &awf); + quantize (c, awf, &qwf); + + // compute metrics + fsnr_val = metric (c, qwf, "FSNR"); + sfdr_val = metric (c, qwf, "SFDR"); + sinad_val = metric (c, qwf, "SINAD"); + + free (awf); + free (qwf); + return 0; } \ No newline at end of file diff --git a/examples/do_fa_pluto_example.c b/examples/do_fa_pluto_example.c index ed96e51..9e98f7b 100644 --- a/examples/do_fa_pluto_example.c +++ b/examples/do_fa_pluto_example.c @@ -1,64 +1,75 @@ -#include "cgenalyzer_simplified_beta.h" -#include "../tests/test_genalyzer.h" #include "../tests/cJSON.h" +#include "../tests/test_genalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = "../tests/test_vectors/test_Pluto_DDS_data_1658159639196.json"; - - int err_code; - int32_t *ref_qwfi, *ref_qwfq; - double *fft_out; - double sfdr; + // read test waveform filename + const char *test_filename + = "../tests/test_vectors/test_Pluto_DDS_data_1658159639196.json"; + + int err_code; + int32_t *ref_qwfi, *ref_qwfq; + double *fft_out; + double sfdr; + + // read parameters + tone_type ttype; + int qres; + unsigned long long npts, navg, nfft, tmp_win; + double fs; + GnWindow win; + uint8_t ssb_width = 100; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&ttype), UINT64); + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + err_code = read_scalar_from_json_file (test_filename, "navg", + (void *)(&navg), UINT64); + err_code = read_scalar_from_json_file (test_filename, "fs", (void *)(&fs), + DOUBLE); + err_code = read_scalar_from_json_file (test_filename, "nfft", + (void *)(&nfft), UINT64); + err_code = read_scalar_from_json_file (test_filename, "win", + (void *)(&tmp_win), UINT64); + if (tmp_win == 1) + win = GnWindowBlackmanHarris; + else if (tmp_win == 2) + win = GnWindowHann; + else if (tmp_win == 3) + win = GnWindowNoWindow; + + // read reference waveforms + ref_qwfi = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_qwfi, + INT32, npts); + ref_qwfq = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_qwfq, + INT32, npts); + + // configuration + gn_config c = NULL; + err_code = gn_config_fftz (npts, qres, navg, nfft, win, &c); - // read parameters - tone_type ttype; - int qres; - unsigned long long npts, navg, nfft, tmp_win; - double fs; - GnWindow win; - uint8_t ssb_width = 100; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&ttype), UINT64); - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - err_code = read_scalar_from_json_file(test_filename, "navg", (void*)(&navg), UINT64); - err_code = read_scalar_from_json_file(test_filename, "fs", (void*)(&fs), DOUBLE); - err_code = read_scalar_from_json_file(test_filename, "nfft", (void*)(&nfft), UINT64); - err_code = read_scalar_from_json_file(test_filename, "win", (void*)(&tmp_win), UINT64); - if (tmp_win==1) - win = GnWindowBlackmanHarris; - else if (tmp_win==2) - win = GnWindowHann; - else if (tmp_win==3) - win = GnWindowNoWindow; + // FFT of waveform + err_code = gn_fftz (&fft_out, ref_qwfi, ref_qwfq, &c); + err_code = gn_config_set_sample_rate (fs, &c); - // read reference waveforms - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_qwfi, INT32, npts); - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_qwfq, INT32, npts); + // Configure Fourier analysis + err_code = gn_config_fa_auto (120, &c); - // configuration - gn_config c = NULL; - err_code = gn_config_fftz(npts, qres, navg, nfft, win, &c); + err_code = gn_get_fa_single_result (&sfdr, "sfdr", fft_out, &c); + printf ("SFDR - %20.6f\n", sfdr); - // FFT of waveform - err_code = gn_fftz(&fft_out, ref_qwfi, ref_qwfq, &c); - err_code = gn_config_set_sample_rate(fs, &c); + // free memory + free (ref_qwfi); + free (ref_qwfq); + free (fft_out); + gn_config_free (&c); - // Configure Fourier analysis - err_code = gn_config_fa_auto(120, &c); - - err_code = gn_get_fa_single_result(&sfdr, "sfdr", fft_out, &c); - printf("SFDR - %20.6f\n", sfdr); - - // free memory - free(ref_qwfi); - free(ref_qwfq); - free(fft_out); - gn_config_free(&c); - - return 0; + return 0; } diff --git a/examples/do_fa_pluto_example_all_results.c b/examples/do_fa_pluto_example_all_results.c index 4fef108..2ea8061 100644 --- a/examples/do_fa_pluto_example_all_results.c +++ b/examples/do_fa_pluto_example_all_results.c @@ -1,72 +1,83 @@ -#include "cgenalyzer_simplified_beta.h" -#include "../tests/test_genalyzer.h" #include "../tests/cJSON.h" +#include "../tests/test_genalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = "../tests/test_vectors/test_Pluto_DDS_data_1658159639196.json"; - - int err_code; - int32_t *ref_qwfi, *ref_qwfq; - double *fft_out; - - size_t results_size; - char **rkeys; - double *rvalues; + // read test waveform filename + const char *test_filename + = "../tests/test_vectors/test_Pluto_DDS_data_1658159639196.json"; + + int err_code; + int32_t *ref_qwfi, *ref_qwfq; + double *fft_out; + + size_t results_size; + char **rkeys; + double *rvalues; + + // read parameters + tone_type ttype; + int qres; + unsigned long long npts, navg, nfft, tmp_win; + double fs; + GnWindow win; + uint8_t ssb_width = 100; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&ttype), UINT64); + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + err_code = read_scalar_from_json_file (test_filename, "navg", + (void *)(&navg), UINT64); + err_code = read_scalar_from_json_file (test_filename, "fs", (void *)(&fs), + DOUBLE); + err_code = read_scalar_from_json_file (test_filename, "nfft", + (void *)(&nfft), UINT64); + err_code = read_scalar_from_json_file (test_filename, "win", + (void *)(&tmp_win), UINT64); + if (tmp_win == 1) + win = GnWindowBlackmanHarris; + else if (tmp_win == 2) + win = GnWindowHann; + else if (tmp_win == 3) + win = GnWindowNoWindow; + + // read reference waveforms + ref_qwfi = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_qwfi, + INT32, npts); + ref_qwfq = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_qwfq, + INT32, npts); + + // configuration + gn_config c = NULL; + err_code = gn_config_fftz (npts, qres, navg, nfft, win, &c); + + // FFT of waveform + err_code = gn_fftz (&fft_out, ref_qwfi, ref_qwfq, &c); + err_code = gn_config_set_sample_rate (fs, &c); - // read parameters - tone_type ttype; - int qres; - unsigned long long npts, navg, nfft, tmp_win; - double fs; - GnWindow win; - uint8_t ssb_width = 100; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&ttype), UINT64); - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - err_code = read_scalar_from_json_file(test_filename, "navg", (void*)(&navg), UINT64); - err_code = read_scalar_from_json_file(test_filename, "fs", (void*)(&fs), DOUBLE); - err_code = read_scalar_from_json_file(test_filename, "nfft", (void*)(&nfft), UINT64); - err_code = read_scalar_from_json_file(test_filename, "win", (void*)(&tmp_win), UINT64); - if (tmp_win==1) - win = GnWindowBlackmanHarris; - else if (tmp_win==2) - win = GnWindowHann; - else if (tmp_win==3) - win = GnWindowNoWindow; + // Configure Fourier analysis + err_code = gn_config_fa_auto (120, &c); - // read reference waveforms - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_qwfi, INT32, npts); - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_qwfq, INT32, npts); + err_code = gn_get_fa_results (&rkeys, &rvalues, &results_size, fft_out, &c); + if (err_code != 0) + return err_code; - // configuration - gn_config c = NULL; - err_code = gn_config_fftz(npts, qres, navg, nfft, win, &c); + printf ("\nAll Fourier Analysis Results:\n"); + for (size_t i = 0; i < results_size; i++) + printf ("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - // FFT of waveform - err_code = gn_fftz(&fft_out, ref_qwfi, ref_qwfq, &c); - err_code = gn_config_set_sample_rate(fs, &c); + // free memory + free (ref_qwfi); + free (ref_qwfq); + free (fft_out); + gn_config_free (&c); - // Configure Fourier analysis - err_code = gn_config_fa_auto(120, &c); - - err_code = gn_get_fa_results(&rkeys, &rvalues, &results_size, fft_out, &c); - if (err_code != 0) - return err_code; - - printf("\nAll Fourier Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - // free memory - free(ref_qwfi); - free(ref_qwfq); - free(fft_out); - gn_config_free(&c); - - return 0; + return 0; } diff --git a/examples/do_ha_sim_example.c b/examples/do_ha_sim_example.c index 8e92451..c8cb646 100644 --- a/examples/do_ha_sim_example.c +++ b/examples/do_ha_sim_example.c @@ -1,54 +1,56 @@ #include "cgenalyzer_simplified_beta.h" -#include #include +#include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // parameters - double fsr = 3.0, qnoise = pow(10.0, -60.0 / 20.0), ramp_start = 0, ramp_stop = 2; - int qres = 12; - unsigned long long npts = 8192; - - // waveforms - double *awf; - int32_t *qwf; - - // results - uint64_t *hist; - size_t results_size, hist_len; - char **rkeys; - double *rvalues; - - // configuration - int err_code; - gn_config c = NULL; - err_code = gn_config_gen_ramp(npts, ramp_start, ramp_stop, &c); - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - - // generate waveform - err_code = gn_gen_ramp(&awf, &c); - - // quantize waveform - err_code = gn_quantize(&qwf, awf, &c); - - // compute histogram - err_code = gn_histz(&hist, &hist_len, qwf, &c); - - // do waveform analysis - err_code = gn_get_ha_results(&rkeys, &rvalues, &results_size, hist, &c); - - // print results - printf("All Waveform Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - // free memory - free(qwf); - free(awf); - for (size_t i = 0; i < results_size; i++) - free(rkeys[i]); - free(rkeys); - gn_config_free(&c); - - return 0; + // parameters + double fsr = 3.0, qnoise = pow (10.0, -60.0 / 20.0), ramp_start = 0, + ramp_stop = 2; + int qres = 12; + unsigned long long npts = 8192; + + // waveforms + double *awf; + int32_t *qwf; + + // results + uint64_t *hist; + size_t results_size, hist_len; + char **rkeys; + double *rvalues; + + // configuration + int err_code; + gn_config c = NULL; + err_code = gn_config_gen_ramp (npts, ramp_start, ramp_stop, &c); + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + + // generate waveform + err_code = gn_gen_ramp (&awf, &c); + + // quantize waveform + err_code = gn_quantize (&qwf, awf, &c); + + // compute histogram + err_code = gn_histz (&hist, &hist_len, qwf, &c); + + // do waveform analysis + err_code = gn_get_ha_results (&rkeys, &rvalues, &results_size, hist, &c); + + // print results + printf ("All Waveform Analysis Results:\n"); + for (size_t i = 0; i < results_size; i++) + printf ("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + + // free memory + free (qwf); + free (awf); + for (size_t i = 0; i < results_size; i++) + free (rkeys[i]); + free (rkeys); + gn_config_free (&c); + + return 0; } \ No newline at end of file diff --git a/examples/do_wfa_sim_example.c b/examples/do_wfa_sim_example.c index 8f24277..348cc17 100644 --- a/examples/do_wfa_sim_example.c +++ b/examples/do_wfa_sim_example.c @@ -1,53 +1,55 @@ #include "cgenalyzer_simplified_beta.h" -#include #include +#include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // parameters - tone_type ttype = REAL_COSINE; - double fsr = 3.0, qnoise = pow(10.0, -60.0 / 20.0); - int qres = 12; - double fs = 5000000.0; - unsigned long long npts = 8192, num_tones = 1; - double freq[] = {50000.0}, scale[] = {0.5}, phase[] = {0.2}; - - // waveforms - double *awf; - int32_t *qwf; - - // results - size_t results_size; - char **rkeys; - double *rvalues; - - // configuration - int err_code; - gn_config c = NULL; - err_code = gn_config_gen_tone(ttype, npts, fs, num_tones, freq, scale, phase, &c); - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - - // generate waveform - err_code = gn_gen_real_tone(&awf, &c); - - // quantize waveform - err_code = gn_quantize(&qwf, awf, &c); - - // do waveform analysis - err_code = gn_get_wfa_results(&rkeys, &rvalues, &results_size, qwf, &c); - - // print results - printf("All Waveform Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - // free memory - free(qwf); - free(awf); - for (size_t i = 0; i < results_size; i++) - free(rkeys[i]); - free(rkeys); - gn_config_free(&c); - - return 0; + // parameters + tone_type ttype = REAL_COSINE; + double fsr = 3.0, qnoise = pow (10.0, -60.0 / 20.0); + int qres = 12; + double fs = 5000000.0; + unsigned long long npts = 8192, num_tones = 1; + double freq[] = { 50000.0 }, scale[] = { 0.5 }, phase[] = { 0.2 }; + + // waveforms + double *awf; + int32_t *qwf; + + // results + size_t results_size; + char **rkeys; + double *rvalues; + + // configuration + int err_code; + gn_config c = NULL; + err_code = gn_config_gen_tone (ttype, npts, fs, num_tones, freq, scale, + phase, &c); + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + + // generate waveform + err_code = gn_gen_real_tone (&awf, &c); + + // quantize waveform + err_code = gn_quantize (&qwf, awf, &c); + + // do waveform analysis + err_code = gn_get_wfa_results (&rkeys, &rvalues, &results_size, qwf, &c); + + // print results + printf ("All Waveform Analysis Results:\n"); + for (size_t i = 0; i < results_size; i++) + printf ("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + + // free memory + free (qwf); + free (awf); + for (size_t i = 0; i < results_size; i++) + free (rkeys[i]); + free (rkeys); + gn_config_free (&c); + + return 0; } diff --git a/examples/fft_analysis_genalyzer_advanced.c b/examples/fft_analysis_genalyzer_advanced.c index 42b0a42..899c1ea 100644 --- a/examples/fft_analysis_genalyzer_advanced.c +++ b/examples/fft_analysis_genalyzer_advanced.c @@ -1,299 +1,337 @@ -#include #include +#include -#include #include +#include #include #include #include #define ERROR_BUFFER_SIZE 256 -#define HANDLE_ERROR(x) \ - do { \ - if (0 != x) { \ - gn_error_string(error_buffer, ERROR_BUFFER_SIZE); \ - printf("%s\n", error_buffer); \ - goto cleanup; \ - } \ - } while (0) +#define HANDLE_ERROR(x) \ + do \ + { \ + if (0 != x) \ + { \ + gn_error_string (error_buffer, ERROR_BUFFER_SIZE); \ + printf ("%s\n", error_buffer); \ + goto cleanup; \ + } \ + } \ + while (0) -int main(int argc, char* argv[]) +int +main (int argc, char *argv[]) { - bool save_data = false; - if (1 < argc) { - save_data = !((bool) strcmp(argv[1], "--save-data")); + bool save_data = false; + if (1 < argc) + { + save_data = !((bool)strcmp (argv[1], "--save-data")); } - /* - * Setup - */ - gn_set_string_termination(true); - char error_buffer[ERROR_BUFFER_SIZE]; - bool error_occurred = true; - int result = 0; + /* + * Setup + */ + gn_set_string_termination (true); + char error_buffer[ERROR_BUFFER_SIZE]; + bool error_occurred = true; + int result = 0; - size_t navg = 2; // FFT averaging - size_t nfft = 1024 * 16; // FFT size - double fs = 1e9; // sample rate - double fdata = fs / 1; // data rate - double fshift = 0e6; // shift frequency - double fsr = 2.0; // full-scale range - double ampl_dbfs = -1.0; // input amplitude (dBFS) - double freq = 70e6; // input frequency (Hz) - double phase = 0.110; // input phase (rad) - double td = 0.0; // input delay (s) - double tj = 0.0; // RMS aperature uncertainty (s) - double qpe = (atan(1.0) * 2) * 1e-5; // quadrature phase error (pi/2 * x) - double poco[] = {0.0, 1.0, 0.0, 0.003}; // distortion polynomial coefficients - int qres = 12; // quantizer resolution - double qnoise_dbfs = -63.0; // quantizer noise (dBFS) - GnCodeFormat code_fmt = GnCodeFormatTwosComplement; - GnFreqAxisFormat axis_fmt = GnFreqAxisFormatFreq; - GnFreqAxisType axis_type = GnFreqAxisTypeDcCenter; - GnWindow window = GnWindowNoWindow; + size_t navg = 2; // FFT averaging + size_t nfft = 1024 * 16; // FFT size + double fs = 1e9; // sample rate + double fdata = fs / 1; // data rate + double fshift = 0e6; // shift frequency + double fsr = 2.0; // full-scale range + double ampl_dbfs = -1.0; // input amplitude (dBFS) + double freq = 70e6; // input frequency (Hz) + double phase = 0.110; // input phase (rad) + double td = 0.0; // input delay (s) + double tj = 0.0; // RMS aperature uncertainty (s) + double qpe = (atan (1.0) * 2) * 1e-5; // quadrature phase error (pi/2 * x) + double poco[] + = { 0.0, 1.0, 0.0, 0.003 }; // distortion polynomial coefficients + int qres = 12; // quantizer resolution + double qnoise_dbfs = -63.0; // quantizer noise (dBFS) + GnCodeFormat code_fmt = GnCodeFormatTwosComplement; + GnFreqAxisFormat axis_fmt = GnFreqAxisFormatFreq; + GnFreqAxisType axis_type = GnFreqAxisTypeDcCenter; + GnWindow window = GnWindowNoWindow; - int dsr = (int) (fs / fdata); - size_t npts = navg * nfft * dsr; - double ampl = (fsr / 2) * pow(10.0, ampl_dbfs / 20.0); - double qnoise = pow(10.0, qnoise_dbfs / 20.0); - int ssb_fund = 4; - int ssb_rest = 3; + int dsr = (int)(fs / fdata); + size_t npts = navg * nfft * dsr; + double ampl = (fsr / 2) * pow (10.0, ampl_dbfs / 20.0); + double qnoise = pow (10.0, qnoise_dbfs / 20.0); + int ssb_fund = 4; + int ssb_rest = 3; - /* - * Pointers for allocated memory - */ - double* awfi = NULL; // in-phase analog waveform - double* awfq = NULL; // quadrature analog waveform - int16_t* qwfi = NULL; // in-phase quantized waveform - int16_t* qwfq = NULL; // quadrature quantized waveform - int16_t* xwf = NULL; // frequency-shifted waveform - int16_t* ywf = NULL; // downsampled waveform - double* fft_cplx = NULL; // FFT complex data - double* fft_db = NULL; // FFT magnitude data - double* freq_axis = NULL; // frequency axis - char* fa_preview = NULL; // FFT analysis configuration preview - char* fa_carrier = NULL; // FFT analysis carrier key - char* fa_maxspur = NULL; // FFT analysis maxspur key - char** fft_rkeys = NULL; // FFT analysis keys - double* fft_rvalues = NULL; // FFT analysis values - size_t* fft_rkey_sizes = NULL; // FFT analysis key sizes - double* fft_select_rvalues = NULL; // FFT analysis select values + /* + * Pointers for allocated memory + */ + double *awfi = NULL; // in-phase analog waveform + double *awfq = NULL; // quadrature analog waveform + int16_t *qwfi = NULL; // in-phase quantized waveform + int16_t *qwfq = NULL; // quadrature quantized waveform + int16_t *xwf = NULL; // frequency-shifted waveform + int16_t *ywf = NULL; // downsampled waveform + double *fft_cplx = NULL; // FFT complex data + double *fft_db = NULL; // FFT magnitude data + double *freq_axis = NULL; // frequency axis + char *fa_preview = NULL; // FFT analysis configuration preview + char *fa_carrier = NULL; // FFT analysis carrier key + char *fa_maxspur = NULL; // FFT analysis maxspur key + char **fft_rkeys = NULL; // FFT analysis keys + double *fft_rvalues = NULL; // FFT analysis values + size_t *fft_rkey_sizes = NULL; // FFT analysis key sizes + double *fft_select_rvalues = NULL; // FFT analysis select values - size_t fft_results_size = 0; + size_t fft_results_size = 0; - /* - * Allocate memory - */ - size_t xwf_size = npts * 2; - size_t ywf_size = 0; - size_t fft_cplx_size = nfft * 2; - result += gn_downsample_size(&ywf_size, xwf_size, dsr, true); - HANDLE_ERROR(result); - awfi = malloc(npts * sizeof(double)); - awfq = malloc(npts * sizeof(double)); - qwfi = malloc(npts * sizeof(int16_t)); - qwfq = malloc(npts * sizeof(int16_t)); - xwf = malloc(xwf_size * sizeof(int16_t)); - ywf = malloc(ywf_size * sizeof(int16_t)); - fft_cplx = malloc(fft_cplx_size * sizeof(double)); + /* + * Allocate memory + */ + size_t xwf_size = npts * 2; + size_t ywf_size = 0; + size_t fft_cplx_size = nfft * 2; + result += gn_downsample_size (&ywf_size, xwf_size, dsr, true); + HANDLE_ERROR (result); + awfi = malloc (npts * sizeof (double)); + awfq = malloc (npts * sizeof (double)); + qwfi = malloc (npts * sizeof (int16_t)); + qwfq = malloc (npts * sizeof (int16_t)); + xwf = malloc (xwf_size * sizeof (int16_t)); + ywf = malloc (ywf_size * sizeof (int16_t)); + fft_cplx = malloc (fft_cplx_size * sizeof (double)); - /* - * Signal generation and processing - */ - if (GnWindowNoWindow == window) { - result += gn_coherent(&freq, nfft, fdata, freq); - HANDLE_ERROR(result); - double fbin = fdata / nfft; - fshift = round(fshift / fbin) * fbin; - ssb_fund = 0; - ssb_rest = 0; + /* + * Signal generation and processing + */ + if (GnWindowNoWindow == window) + { + result += gn_coherent (&freq, nfft, fdata, freq); + HANDLE_ERROR (result); + double fbin = fdata / nfft; + fshift = round (fshift / fbin) * fbin; + ssb_fund = 0; + ssb_rest = 0; } - result += gn_cos(awfi, npts, fs, ampl, freq, phase, td, tj); - result += gn_sin(awfq, npts, fs, ampl, freq, phase + qpe, td, tj); - result += gn_polyval(awfi, npts, awfi, npts, poco, (sizeof poco) / sizeof(double)); - result += gn_polyval(awfq, npts, awfq, npts, poco, (sizeof poco) / sizeof(double)); - result += gn_quantize16(qwfi, npts, awfi, npts, fsr, qres, qnoise, code_fmt); - result += gn_quantize16(qwfq, npts, awfq, npts, fsr, qres, qnoise, code_fmt); - result += gn_fshift16(xwf, xwf_size, qwfi, npts, qwfq, npts, qres, fs, fshift, code_fmt); - result += gn_downsample16(ywf, ywf_size, xwf, xwf_size, dsr, true); - result += gn_fft16(fft_cplx, fft_cplx_size, ywf, ywf_size, NULL, 0, qres, navg, nfft, window, code_fmt); - HANDLE_ERROR(result); + result += gn_cos (awfi, npts, fs, ampl, freq, phase, td, tj); + result += gn_sin (awfq, npts, fs, ampl, freq, phase + qpe, td, tj); + result += gn_polyval (awfi, npts, awfi, npts, poco, + (sizeof poco) / sizeof (double)); + result += gn_polyval (awfq, npts, awfq, npts, poco, + (sizeof poco) / sizeof (double)); + result + += gn_quantize16 (qwfi, npts, awfi, npts, fsr, qres, qnoise, code_fmt); + result + += gn_quantize16 (qwfq, npts, awfq, npts, fsr, qres, qnoise, code_fmt); + result += gn_fshift16 (xwf, xwf_size, qwfi, npts, qwfq, npts, qres, fs, + fshift, code_fmt); + result += gn_downsample16 (ywf, ywf_size, xwf, xwf_size, dsr, true); + result += gn_fft16 (fft_cplx, fft_cplx_size, ywf, ywf_size, NULL, 0, qres, + navg, nfft, window, code_fmt); + HANDLE_ERROR (result); - /* - * Fourier analysis configuration - */ - char* key = "fa"; - result += gn_fa_create(key); - result += gn_fa_fixed_tone(key, "A", GnFACompTagSignal, freq, ssb_fund); - result += gn_fa_hd(key, 3); - result += gn_fa_ssb(key, GnFASsbDefault, ssb_rest); - result += gn_fa_ssb(key, GnFASsbDC, -1); - result += gn_fa_ssb(key, GnFASsbSignal, -1); - result += gn_fa_ssb(key, GnFASsbWO, -1); - result += gn_fa_fsample(key, fs); - result += gn_fa_fdata(key, fdata); - result += gn_fa_fshift(key, fshift); - result += gn_fa_conv_offset(key, 0.0 != fshift); - HANDLE_ERROR(result); - size_t fa_preview_size = 0; - result += gn_fa_preview_size(&fa_preview_size, key, true); - fa_preview = malloc(fa_preview_size); - result += gn_fa_preview(fa_preview, fa_preview_size, key, true); - HANDLE_ERROR(result); - printf("%s\n", fa_preview); + /* + * Fourier analysis configuration + */ + char *key = "fa"; + result += gn_fa_create (key); + result += gn_fa_fixed_tone (key, "A", GnFACompTagSignal, freq, ssb_fund); + result += gn_fa_hd (key, 3); + result += gn_fa_ssb (key, GnFASsbDefault, ssb_rest); + result += gn_fa_ssb (key, GnFASsbDC, -1); + result += gn_fa_ssb (key, GnFASsbSignal, -1); + result += gn_fa_ssb (key, GnFASsbWO, -1); + result += gn_fa_fsample (key, fs); + result += gn_fa_fdata (key, fdata); + result += gn_fa_fshift (key, fshift); + result += gn_fa_conv_offset (key, 0.0 != fshift); + HANDLE_ERROR (result); + size_t fa_preview_size = 0; + result += gn_fa_preview_size (&fa_preview_size, key, true); + fa_preview = malloc (fa_preview_size); + result += gn_fa_preview (fa_preview, fa_preview_size, key, true); + HANDLE_ERROR (result); + printf ("%s\n", fa_preview); - /* - * Fourier analysis with all results - */ - // 1. Get results size - result += gn_fft_analysis_results_size(&fft_results_size, key, fft_cplx_size, nfft); - // 2. Allocate memory for result keys and values - fft_rkeys = malloc(fft_results_size * sizeof(char*)); - fft_rvalues = malloc(fft_results_size * sizeof(double)); - // 3. Get result key sizes - fft_rkey_sizes = malloc(fft_results_size * sizeof(size_t)); - result += gn_fft_analysis_results_key_sizes(fft_rkey_sizes, fft_results_size, key, fft_cplx_size, nfft); - HANDLE_ERROR(result); - // 4. Allocate memory for each result key - for (size_t i = 0; i < fft_results_size; ++i) { - fft_rkeys[i] = malloc(fft_rkey_sizes[i]); + /* + * Fourier analysis with all results + */ + // 1. Get results size + result += gn_fft_analysis_results_size (&fft_results_size, key, + fft_cplx_size, nfft); + // 2. Allocate memory for result keys and values + fft_rkeys = malloc (fft_results_size * sizeof (char *)); + fft_rvalues = malloc (fft_results_size * sizeof (double)); + // 3. Get result key sizes + fft_rkey_sizes = malloc (fft_results_size * sizeof (size_t)); + result += gn_fft_analysis_results_key_sizes ( + fft_rkey_sizes, fft_results_size, key, fft_cplx_size, nfft); + HANDLE_ERROR (result); + // 4. Allocate memory for each result key + for (size_t i = 0; i < fft_results_size; ++i) + { + fft_rkeys[i] = malloc (fft_rkey_sizes[i]); } - // 5. Execute analysis - result += gn_fft_analysis(fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, - key, fft_cplx, fft_cplx_size, nfft, axis_type); - HANDLE_ERROR(result); + // 5. Execute analysis + result += gn_fft_analysis (fft_rkeys, fft_results_size, fft_rvalues, + fft_results_size, key, fft_cplx, fft_cplx_size, + nfft, axis_type); + HANDLE_ERROR (result); - /* - * Fourier analysis with single result - */ - double fsnr = 0.0; - double a_mag_dbfs = 0.0; - result += gn_fft_analysis_single(&fsnr, key, "fsnr", fft_cplx, fft_cplx_size, nfft, axis_type); - result += gn_fft_analysis_single(&a_mag_dbfs, key, "A:mag_dbfs", fft_cplx, fft_cplx_size, nfft, axis_type); - HANDLE_ERROR(result); + /* + * Fourier analysis with single result + */ + double fsnr = 0.0; + double a_mag_dbfs = 0.0; + result += gn_fft_analysis_single (&fsnr, key, "fsnr", fft_cplx, + fft_cplx_size, nfft, axis_type); + result += gn_fft_analysis_single (&a_mag_dbfs, key, "A:mag_dbfs", fft_cplx, + fft_cplx_size, nfft, axis_type); + HANDLE_ERROR (result); - /* - * Fourier analysis with select results - */ - const char* fft_select_rkeys[] = {"sfdr", "-3A:mag_dbc"}; - size_t fft_select_results_size = (sizeof fft_select_rkeys) / sizeof(char*); - fft_select_rvalues = malloc(fft_select_results_size * sizeof(double)); - result = gn_fft_analysis_select(fft_select_rvalues, fft_select_results_size, - key, fft_select_rkeys, fft_select_results_size, fft_cplx, fft_cplx_size, nfft, axis_type); - HANDLE_ERROR(result); + /* + * Fourier analysis with select results + */ + const char *fft_select_rkeys[] = { "sfdr", "-3A:mag_dbc" }; + size_t fft_select_results_size = (sizeof fft_select_rkeys) / sizeof (char *); + fft_select_rvalues = malloc (fft_select_results_size * sizeof (double)); + result = gn_fft_analysis_select ( + fft_select_rvalues, fft_select_results_size, key, fft_select_rkeys, + fft_select_results_size, fft_cplx, fft_cplx_size, nfft, axis_type); + HANDLE_ERROR (result); - /* - * Carrier and MaxSpur keys (requires all results) - */ - size_t fa_result_string_size = 0; - result = gn_fa_result_string_size(&fa_result_string_size, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "carrierindex"); - HANDLE_ERROR(result); - fa_carrier = malloc(fa_result_string_size); - result = gn_fa_result_string(fa_carrier, fa_result_string_size, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "carrierindex"); - HANDLE_ERROR(result); - result = gn_fa_result_string_size(&fa_result_string_size, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "maxspurindex"); - HANDLE_ERROR(result); - fa_maxspur = malloc(fa_result_string_size); - result = gn_fa_result_string(fa_maxspur, fa_result_string_size, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "maxspurindex"); - HANDLE_ERROR(result); + /* + * Carrier and MaxSpur keys (requires all results) + */ + size_t fa_result_string_size = 0; + result = gn_fa_result_string_size ( + &fa_result_string_size, (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "carrierindex"); + HANDLE_ERROR (result); + fa_carrier = malloc (fa_result_string_size); + result = gn_fa_result_string (fa_carrier, fa_result_string_size, + (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "carrierindex"); + HANDLE_ERROR (result); + result = gn_fa_result_string_size ( + &fa_result_string_size, (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "maxspurindex"); + HANDLE_ERROR (result); + fa_maxspur = malloc (fa_result_string_size); + result = gn_fa_result_string (fa_maxspur, fa_result_string_size, + (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "maxspurindex"); + HANDLE_ERROR (result); - /* - * Print results - */ - printf("\nAll Fourier Analysis Results:\n"); - for (size_t i = 0; i < fft_results_size; ++i) { - printf("%4zu%20s%20.6f\n", i, fft_rkeys[i], fft_rvalues[i]); + /* + * Print results + */ + printf ("\nAll Fourier Analysis Results:\n"); + for (size_t i = 0; i < fft_results_size; ++i) + { + printf ("%4zu%20s%20.6f\n", i, fft_rkeys[i], fft_rvalues[i]); } - // gn_fa_result extracts specified result from key-value arrays - double snr = 0.0; - double a_freq = 0.0; - double a_ffinal = 0.0; - result = gn_fa_result(&snr, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "snr"); - result = gn_fa_result(&a_freq, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "A:freq"); - result = gn_fa_result(&a_ffinal, - (const char**)fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, "A:ffinal"); - HANDLE_ERROR(result); - printf(" %s = %.3f\n", "snr", snr); - printf(" %s = %.3f MHz\n", "A:freq", a_freq / 1e6); - printf(" %s = %.3f MHz\n", "A:ffinal", a_ffinal / 1e6); - printf(" %s = %s\n", "Carrier", fa_carrier); - printf(" %s = %s\n", "MaxSpur", fa_maxspur); + // gn_fa_result extracts specified result from key-value arrays + double snr = 0.0; + double a_freq = 0.0; + double a_ffinal = 0.0; + result = gn_fa_result (&snr, (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "snr"); + result = gn_fa_result (&a_freq, (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "A:freq"); + result = gn_fa_result (&a_ffinal, (const char **)fft_rkeys, fft_results_size, + fft_rvalues, fft_results_size, "A:ffinal"); + HANDLE_ERROR (result); + printf (" %s = %.3f\n", "snr", snr); + printf (" %s = %.3f MHz\n", "A:freq", a_freq / 1e6); + printf (" %s = %.3f MHz\n", "A:ffinal", a_ffinal / 1e6); + printf (" %s = %s\n", "Carrier", fa_carrier); + printf (" %s = %s\n", "MaxSpur", fa_maxspur); - printf("\nSingle Fourier Analysis Results:\n"); - printf("%20s = %20.6f\n", "fsnr", fsnr); - printf("%20s = %20.6f\n", "A::mag_dbfs", a_mag_dbfs); + printf ("\nSingle Fourier Analysis Results:\n"); + printf ("%20s = %20.6f\n", "fsnr", fsnr); + printf ("%20s = %20.6f\n", "A::mag_dbfs", a_mag_dbfs); - printf("\nSelect Fourier Analysis Results:\n"); - for (size_t i = 0; i < fft_select_results_size; ++i) { - printf("%20s = %20.6f\n", fft_select_rkeys[i], fft_select_rvalues[i]); + printf ("\nSelect Fourier Analysis Results:\n"); + for (size_t i = 0; i < fft_select_results_size; ++i) + { + printf ("%20s = %20.6f\n", fft_select_rkeys[i], fft_select_rvalues[i]); } - /* - * Save data - */ - if (save_data) { - const char* fn = "fft.txt"; - FILE* fp = fopen(fn, "w"); - if (fp) { - fft_db = malloc(nfft * sizeof(double)); - result += gn_db(fft_db, nfft, fft_cplx, fft_cplx_size); - if (GnFreqAxisTypeDcCenter == axis_type) { - gn_fftshift(fft_db, nfft, fft_db, nfft); + /* + * Save data + */ + if (save_data) + { + const char *fn = "fft.txt"; + FILE *fp = fopen (fn, "w"); + if (fp) + { + fft_db = malloc (nfft * sizeof (double)); + result += gn_db (fft_db, nfft, fft_cplx, fft_cplx_size); + if (GnFreqAxisTypeDcCenter == axis_type) + { + gn_fftshift (fft_db, nfft, fft_db, nfft); } - for (size_t i = 0; i < nfft; ++i) { - fprintf(fp, "%.6f\n", fft_db[i]); + for (size_t i = 0; i < nfft; ++i) + { + fprintf (fp, "%.6f\n", fft_db[i]); } - fclose(fp); - printf("\nWrote FFT magnitude data to %s\n", fn); + fclose (fp); + printf ("\nWrote FFT magnitude data to %s\n", fn); } - fn = "fft_axis.txt"; - fp = fopen(fn, "w"); - if (fp) { - freq_axis = malloc(nfft * sizeof(double)); - result += gn_freq_axis(freq_axis, nfft, nfft, axis_type, fdata, axis_fmt); - for (size_t i = 0; i < nfft; ++i) { - fprintf(fp, "%.6f\n", freq_axis[i]); + fn = "fft_axis.txt"; + fp = fopen (fn, "w"); + if (fp) + { + freq_axis = malloc (nfft * sizeof (double)); + result += gn_freq_axis (freq_axis, nfft, nfft, axis_type, fdata, + axis_fmt); + for (size_t i = 0; i < nfft; ++i) + { + fprintf (fp, "%.6f\n", freq_axis[i]); } - fclose(fp); - printf("Wrote FFT x-axis data to %s\n", fn); + fclose (fp); + printf ("Wrote FFT x-axis data to %s\n", fn); } } - error_occurred = false; + error_occurred = false; cleanup: - if (error_occurred) { - printf("\nError occurred, freeing memory\n"); - } else { - printf("\nFreeing memory\n"); + if (error_occurred) + { + printf ("\nError occurred, freeing memory\n"); + } + else + { + printf ("\nFreeing memory\n"); } - free(fft_select_rvalues); - if (fft_rkeys) { - for (size_t i = 0; i < fft_results_size; ++i) { - free(fft_rkeys[i]); + free (fft_select_rvalues); + if (fft_rkeys) + { + for (size_t i = 0; i < fft_results_size; ++i) + { + free (fft_rkeys[i]); } } - free(fft_rkey_sizes); - free(fft_rvalues); - free(fft_rkeys); - free(fa_maxspur); - free(fa_carrier); - free(fa_preview); - free(freq_axis); - free(fft_db); - free(fft_cplx); - free(ywf); - free(xwf); - free(qwfq); - free(qwfi); - free(awfq); - free(awfi); + free (fft_rkey_sizes); + free (fft_rvalues); + free (fft_rkeys); + free (fa_maxspur); + free (fa_carrier); + free (fa_preview); + free (freq_axis); + free (fft_db); + free (fft_cplx); + free (ywf); + free (xwf); + free (qwfq); + free (qwfi); + free (awfq); + free (awfi); - return 0; + return 0; } \ No newline at end of file diff --git a/examples/fft_analysis_genalyzer_advanced_debug.c b/examples/fft_analysis_genalyzer_advanced_debug.c new file mode 100644 index 0000000..7cd505c --- /dev/null +++ b/examples/fft_analysis_genalyzer_advanced_debug.c @@ -0,0 +1,251 @@ +#include "../tests/cJSON.h" +#include "../tests/test_genalyzer.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERROR_BUFFER_SIZE 256 + +#define HANDLE_ERROR(x) \ + do \ + { \ + if (0 != x) \ + { \ + gn_error_string (error_buffer, ERROR_BUFFER_SIZE); \ + printf ("%s\n", error_buffer); \ + goto cleanup; \ + } \ + } \ + while (0) + +int +main (int argc, char *argv[]) +{ + bool save_data = false; + if (1 < argc) + { + save_data = !((bool)strcmp (argv[1], "--save-data")); + } + + /* + * Setup + */ + gn_set_string_termination (true); + char error_buffer[ERROR_BUFFER_SIZE]; + bool error_occurred = true; + int result = 0; + + size_t navg = 1; // FFT averaging + size_t nfft = 32768; // FFT size + double fs = 3e6; // sample rate + double fdata = fs / 1; // data rate + double fshift = 0e6; // shift frequency + double fsr = 2.0; // full-scale range + double ampl_dbfs = -1.0; // input amplitude (dBFS) + double freq = 100000; // input frequency (Hz) + double phase = 0.0; // input phase (rad) + double td = 0.0; // input delay (s) + double tj = 0.0; // RMS aperature uncertainty (s) + double qpe = 0.0; // (atan(1.0) * 2) * 1e-5; // quadrature phase error + // (pi/2 * x) + double poco[] + = { 0.0, 1.0, 0.0, 0.003 }; // distortion polynomial coefficients + int qres = 12; // quantizer resolution + double qnoise_dbfs = -63.0; // quantizer noise (dBFS) + GnCodeFormat code_fmt = GnCodeFormatTwosComplement; + GnFreqAxisFormat axis_fmt = GnFreqAxisFormatFreq; + GnFreqAxisType axis_type = GnFreqAxisTypeDcCenter; + GnWindow window = GnWindowNoWindow; + + int dsr = (int)(fs / fdata); + size_t npts = navg * nfft * dsr; + double ampl = (fsr / 2) * pow (10.0, ampl_dbfs / 20.0); + double qnoise = pow (10.0, qnoise_dbfs / 20.0); + int ssb_fund = 4; + int ssb_rest = 3; + const char *test_filename + = "../tests/test_vectors/test_Pluto_DDS_data_1658159639196.json"; + + /* + * Pointers for allocated memory + */ + double *awfi = NULL; // in-phase analog waveform + double *awfq = NULL; // quadrature analog waveform + int16_t *qwfi = NULL; // in-phase quantized waveform + int16_t *qwfq = NULL; // quadrature quantized waveform + int16_t *xwf = NULL; // frequency-shifted waveform + int16_t *ywf = NULL; // downsampled waveform + double *fft_cplx = NULL; // FFT complex data + double *fft_db = NULL; // FFT magnitude data + double *freq_axis = NULL; // frequency axis + char *fa_preview = NULL; // FFT analysis configuration preview + char *fa_carrier = NULL; // FFT analysis carrier key + char *fa_maxspur = NULL; // FFT analysis maxspur key + char **fft_rkeys = NULL; // FFT analysis keys + double *fft_rvalues = NULL; // FFT analysis values + size_t *fft_rkey_sizes = NULL; // FFT analysis key sizes + double *fft_select_rvalues = NULL; // FFT analysis select values + + size_t fft_results_size = 0; + + /* + * Allocate memory + */ + size_t xwf_size = npts * 2; + size_t ywf_size = 0; + size_t fft_cplx_size = nfft * 2; + result += gn_downsample_size (&ywf_size, xwf_size, dsr, true); + HANDLE_ERROR (result); + awfi = malloc (npts * sizeof (double)); + awfq = malloc (npts * sizeof (double)); + qwfi = malloc (npts * sizeof (int16_t)); + qwfq = malloc (npts * sizeof (int16_t)); + xwf = malloc (xwf_size * sizeof (int16_t)); + ywf = malloc (ywf_size * sizeof (int16_t)); + fft_cplx = malloc (fft_cplx_size * sizeof (double)); + + /* + * Signal generation and processing + */ + if (GnWindowNoWindow == window) + { + result += gn_coherent (&freq, nfft, fdata, freq); + HANDLE_ERROR (result); + double fbin = fdata / nfft; + fshift = round (fshift / fbin) * fbin; + ssb_fund = 50; + ssb_rest = 3; + } + + /* + result += gn_cos(awfi, npts, fs, ampl, freq, phase, td, tj); + result += gn_sin(awfq, npts, fs, ampl, freq, phase + qpe, td, tj); + result += gn_polyval(awfi, npts, awfi, npts, poco, (sizeof poco) / + sizeof(double)); result += gn_polyval(awfq, npts, awfq, npts, poco, (sizeof + poco) / sizeof(double)); result += gn_quantize16(qwfi, npts, awfi, npts, fsr, + qres, qnoise, code_fmt); result += gn_quantize16(qwfq, npts, awfq, npts, fsr, + qres, qnoise, code_fmt); + */ + result += read_array_from_json_file (test_filename, "test_vec_i", qwfi, + INT16, npts); + result += read_array_from_json_file (test_filename, "test_vec_q", qwfq, + INT16, npts); + // result += read_array_from_json_file_int32(test_filename, "test_vec_i", + // qwfi, npts); result += read_array_from_json_file_int32(test_filename, + // "test_vec_q", qwfq, npts); result += gn_fshift16(xwf, xwf_size, qwfi, + // npts, qwfq, npts, qres, fs, fshift, code_fmt); result += + // gn_downsample16(ywf, ywf_size, xwf, xwf_size, dsr, true); + /* + printf("qwf---------\n"); + for (int ii = 0; ii < 10; ii++) + printf("%d\t%d\n", qwfi[ii], qwfq[ii]); + */ + ProfilerStart ("profile.log"); + result += gn_fft16 (fft_cplx, fft_cplx_size, qwfi, npts, qwfq, npts, qres, + navg, nfft, window, code_fmt); + /* + printf("xwf---------\n"); + for (int ii = 0; ii < 10; ii++) + printf("%d\n", xwf[ii]); + */ + // result += gn_fft16(fft_cplx, fft_cplx_size, xwf, 2*npts, NULL, 0, qres, + // navg, nfft, window, code_fmt); return 0; + + /* + FILE *fp1 = fopen("fft_data_debug.txt", "w"); + for (int i =0; i < fft_cplx_size; i++) + fprintf(fp1, "%f\n", fft_cplx[i]); + fclose(fp1); + HANDLE_ERROR(result); + */ + + /* + * Fourier analysis configuration + */ + char *key = "fa"; + result += gn_fa_create (key); + result += gn_fa_fixed_tone (key, "A", GnFACompTagSignal, freq, ssb_fund); + result += gn_fa_hd (key, 3); + result += gn_fa_ssb (key, GnFASsbDefault, ssb_rest); + result += gn_fa_ssb (key, GnFASsbDC, -1); + result += gn_fa_ssb (key, GnFASsbSignal, -1); + result += gn_fa_ssb (key, GnFASsbWO, -1); + result += gn_fa_fsample (key, fs); + result += gn_fa_fdata (key, fdata); + result += gn_fa_fshift (key, fshift); + result += gn_fa_conv_offset (key, 0.0 != fshift); + HANDLE_ERROR (result); + size_t fa_preview_size = 0; + result += gn_fa_preview_size (&fa_preview_size, key, true); + fa_preview = malloc (fa_preview_size); + result += gn_fa_preview (fa_preview, fa_preview_size, key, true); + HANDLE_ERROR (result); + // printf("%s\n", fa_preview); + + /* + * Fourier analysis with all results + */ + // 1. Get results size + result += gn_fft_analysis_results_size (&fft_results_size, key, + fft_cplx_size, nfft); + // 2. Allocate memory for result keys and values + fft_rkeys = malloc (fft_results_size * sizeof (char *)); + fft_rvalues = malloc (fft_results_size * sizeof (double)); + // 3. Get result key sizes + fft_rkey_sizes = malloc (fft_results_size * sizeof (size_t)); + result += gn_fft_analysis_results_key_sizes ( + fft_rkey_sizes, fft_results_size, key, fft_cplx_size, nfft); + HANDLE_ERROR (result); + // 4. Allocate memory for each result key + for (size_t i = 0; i < fft_results_size; ++i) + { + fft_rkeys[i] = malloc (fft_rkey_sizes[i]); + } + // 5. Execute analysis + result += gn_fft_analysis (fft_rkeys, fft_results_size, fft_rvalues, + fft_results_size, key, fft_cplx, fft_cplx_size, + nfft, axis_type); + HANDLE_ERROR (result); + // return 0; + ProfilerStop (); + +cleanup: + if (error_occurred) + { + printf ("\nError occurred, freeing memory\n"); + } + else + { + printf ("\nFreeing memory\n"); + } + free (fft_select_rvalues); + if (fft_rkeys) + { + for (size_t i = 0; i < fft_results_size; ++i) + { + free (fft_rkeys[i]); + } + } + free (fft_rkey_sizes); + free (fft_rvalues); + free (fft_rkeys); + free (fa_maxspur); + free (fa_carrier); + free (fa_preview); + free (freq_axis); + free (fft_db); + free (fft_cplx); + free (ywf); + free (xwf); + // free(qwfq); + // free(qwfi); + // free(awfq); + // free(awfi); + + return 0; +} \ No newline at end of file diff --git a/examples/real_analysis_genalyzer_advanced.c b/examples/real_analysis_genalyzer_advanced.c index 74c0c1f..6644ef1 100644 --- a/examples/real_analysis_genalyzer_advanced.c +++ b/examples/real_analysis_genalyzer_advanced.c @@ -1,395 +1,457 @@ -#include #include +#include -#include #include +#include #include #include #include #define ERROR_BUFFER_SIZE 256 -#define HANDLE_ERROR(x) \ - do { \ - if (0 != x) { \ - gn_error_string(error_buffer, ERROR_BUFFER_SIZE); \ - printf("%s\n", error_buffer); \ - goto cleanup; \ - } \ - } while (0) +#define HANDLE_ERROR(x) \ + do \ + { \ + if (0 != x) \ + { \ + gn_error_string (error_buffer, ERROR_BUFFER_SIZE); \ + printf ("%s\n", error_buffer); \ + goto cleanup; \ + } \ + } \ + while (0) -int main(int argc, char* argv[]) +int +main (int argc, char *argv[]) { - bool save_data = false; - if (1 < argc) { - save_data = !((bool) strcmp(argv[1], "--save-data")); + bool save_data = false; + if (1 < argc) + { + save_data = !((bool)strcmp (argv[1], "--save-data")); } - /* - * Setup - */ - gn_set_string_termination(true); - char error_buffer[ERROR_BUFFER_SIZE]; - bool error_occurred = true; - int result = 0; + /* + * Setup + */ + gn_set_string_termination (true); + char error_buffer[ERROR_BUFFER_SIZE]; + bool error_occurred = true; + int result = 0; - size_t navg = 2; // FFT averaging - size_t nfft = 1024 * 256; // FFT size - double fs = 1e9; // sample rate - double fsr = 2.0; // full-scale range - double ampl_dbfs = -1.0; // input amplitude (dBFS) - double freq = 10e6; // input frequency (Hz) - double phase = 0.110; // input phase (rad) - double td = 0.0; // input delay (s) - double tj = 0.0; // RMS aperature uncertainty (s) - double poco[] = {0.0, 1.0, 0.0, 0.003}; // distortion polynomial coefficients - int qres = 12; // quantizer resolution - double qnoise_dbfs = -63.0; // quantizer noise (dBFS) - GnCodeFormat code_fmt = GnCodeFormatTwosComplement; - GnDnlSignal sig_type = GnDnlSignalTone; - GnInlLineFit inl_fit = GnInlLineFitBestFit; - GnRfftScale rfft_scale = GnRfftScaleDbfsSin; - GnWindow window = GnWindowNoWindow; + size_t navg = 2; // FFT averaging + size_t nfft = 1024 * 256; // FFT size + double fs = 1e9; // sample rate + double fsr = 2.0; // full-scale range + double ampl_dbfs = -1.0; // input amplitude (dBFS) + double freq = 10e6; // input frequency (Hz) + double phase = 0.110; // input phase (rad) + double td = 0.0; // input delay (s) + double tj = 0.0; // RMS aperature uncertainty (s) + double poco[] + = { 0.0, 1.0, 0.0, 0.003 }; // distortion polynomial coefficients + int qres = 12; // quantizer resolution + double qnoise_dbfs = -63.0; // quantizer noise (dBFS) + GnCodeFormat code_fmt = GnCodeFormatTwosComplement; + GnDnlSignal sig_type = GnDnlSignalTone; + GnInlLineFit inl_fit = GnInlLineFitBestFit; + GnRfftScale rfft_scale = GnRfftScaleDbfsSin; + GnWindow window = GnWindowNoWindow; - size_t npts = navg * nfft; - double ampl = (fsr / 2) * pow(10.0, ampl_dbfs / 20.0); - double qnoise = pow(10.0, qnoise_dbfs / 20.0); - int ssb_fund = 4; - int ssb_rest = 3; + size_t npts = navg * nfft; + double ampl = (fsr / 2) * pow (10.0, ampl_dbfs / 20.0); + double qnoise = pow (10.0, qnoise_dbfs / 20.0); + int ssb_fund = 4; + int ssb_rest = 3; - /* - * Pointers for allocated memory - */ - double* awf = NULL; // analog waveform - int16_t* qwf = NULL; // quantized waveform - uint64_t* hist = NULL; // histogram data - double* dnl = NULL; // DNL data - double* inl = NULL; // INL data - double* code_axis = NULL; // code density axis - double* fft_cplx = NULL; // FFT complex data - double* fft_db = NULL; // FFT magnitude data - double* freq_axis = NULL; // frequency axis - char* fa_preview = NULL; // FFT configuration preview - char** wf_rkeys = NULL; // waveform analysis keys - double* wf_rvalues = NULL; // waveform analysis values - size_t* wf_rkey_sizes = NULL; // waveform analysis key sizes - char** hist_rkeys = NULL; // histogram analysis keys - double* hist_rvalues = NULL; // histogram analysis values - size_t* hist_rkey_sizes = NULL; // histogram analysis key sizes - char** dnl_rkeys = NULL; // DNL analysis keys - double* dnl_rvalues = NULL; // DNL analysis values - size_t* dnl_rkey_sizes = NULL; // DNL analysis key sizes - char** inl_rkeys = NULL; // INL analysis keys - double* inl_rvalues = NULL; // INL analysis values - size_t* inl_rkey_sizes = NULL; // INL analysis key sizes - char** fft_rkeys = NULL; // FFT analysis keys - double* fft_rvalues = NULL; // FFT analysis values - size_t* fft_rkey_sizes = NULL; // FFT analysis key sizes + /* + * Pointers for allocated memory + */ + double *awf = NULL; // analog waveform + int16_t *qwf = NULL; // quantized waveform + uint64_t *hist = NULL; // histogram data + double *dnl = NULL; // DNL data + double *inl = NULL; // INL data + double *code_axis = NULL; // code density axis + double *fft_cplx = NULL; // FFT complex data + double *fft_db = NULL; // FFT magnitude data + double *freq_axis = NULL; // frequency axis + char *fa_preview = NULL; // FFT configuration preview + char **wf_rkeys = NULL; // waveform analysis keys + double *wf_rvalues = NULL; // waveform analysis values + size_t *wf_rkey_sizes = NULL; // waveform analysis key sizes + char **hist_rkeys = NULL; // histogram analysis keys + double *hist_rvalues = NULL; // histogram analysis values + size_t *hist_rkey_sizes = NULL; // histogram analysis key sizes + char **dnl_rkeys = NULL; // DNL analysis keys + double *dnl_rvalues = NULL; // DNL analysis values + size_t *dnl_rkey_sizes = NULL; // DNL analysis key sizes + char **inl_rkeys = NULL; // INL analysis keys + double *inl_rvalues = NULL; // INL analysis values + size_t *inl_rkey_sizes = NULL; // INL analysis key sizes + char **fft_rkeys = NULL; // FFT analysis keys + double *fft_rvalues = NULL; // FFT analysis values + size_t *fft_rkey_sizes = NULL; // FFT analysis key sizes - size_t wf_results_size = 0; - size_t hist_results_size = 0; - size_t dnl_results_size = 0; - size_t inl_results_size = 0; - size_t fft_results_size = 0; + size_t wf_results_size = 0; + size_t hist_results_size = 0; + size_t dnl_results_size = 0; + size_t inl_results_size = 0; + size_t fft_results_size = 0; - /* - * Allocate memory - */ - size_t cd_size = 0; // cd = code density - size_t fft_cplx_size = 0; - result += gn_code_density_size(&cd_size, qres, code_fmt); - result += gn_rfft_size(&fft_cplx_size, npts, navg, nfft); - HANDLE_ERROR(result); - awf = malloc(npts * sizeof(double)); - qwf = malloc(npts * sizeof(int16_t)); - hist = malloc(cd_size * sizeof(uint64_t)); - dnl = malloc(cd_size * sizeof(double)); - inl = malloc(cd_size * sizeof(double)); - fft_cplx = malloc(fft_cplx_size * sizeof(double)); + /* + * Allocate memory + */ + size_t cd_size = 0; // cd = code density + size_t fft_cplx_size = 0; + result += gn_code_density_size (&cd_size, qres, code_fmt); + result += gn_rfft_size (&fft_cplx_size, npts, navg, nfft); + HANDLE_ERROR (result); + awf = malloc (npts * sizeof (double)); + qwf = malloc (npts * sizeof (int16_t)); + hist = malloc (cd_size * sizeof (uint64_t)); + dnl = malloc (cd_size * sizeof (double)); + inl = malloc (cd_size * sizeof (double)); + fft_cplx = malloc (fft_cplx_size * sizeof (double)); - /* - * Signal generation and processing - */ - if (GnWindowNoWindow == window) { - result += gn_coherent(&freq, nfft, fs, freq); - HANDLE_ERROR(result); - ssb_fund = 0; - ssb_rest = 0; + /* + * Signal generation and processing + */ + if (GnWindowNoWindow == window) + { + result += gn_coherent (&freq, nfft, fs, freq); + HANDLE_ERROR (result); + ssb_fund = 0; + ssb_rest = 0; } - result += gn_cos(awf, npts, fs, ampl, freq, phase, td, tj); - result += gn_polyval(awf, npts, awf, npts, poco, (sizeof poco) / sizeof(double)); - result += gn_quantize16(qwf, npts, awf, npts, fsr, qres, qnoise, code_fmt); - result += gn_hist16(hist, cd_size, qwf, npts, qres, code_fmt, false); - result += gn_dnl(dnl, cd_size, hist, cd_size, sig_type); - result += gn_inl(inl, cd_size, dnl, cd_size, inl_fit); - result += gn_rfft16(fft_cplx, fft_cplx_size, qwf, npts, qres, navg, nfft, window, code_fmt, rfft_scale); - HANDLE_ERROR(result); + result += gn_cos (awf, npts, fs, ampl, freq, phase, td, tj); + result += gn_polyval (awf, npts, awf, npts, poco, + (sizeof poco) / sizeof (double)); + result += gn_quantize16 (qwf, npts, awf, npts, fsr, qres, qnoise, code_fmt); + result += gn_hist16 (hist, cd_size, qwf, npts, qres, code_fmt, false); + result += gn_dnl (dnl, cd_size, hist, cd_size, sig_type); + result += gn_inl (inl, cd_size, dnl, cd_size, inl_fit); + result += gn_rfft16 (fft_cplx, fft_cplx_size, qwf, npts, qres, navg, nfft, + window, code_fmt, rfft_scale); + HANDLE_ERROR (result); - /* - * Fourier analysis configuration - */ - char* key = "fa"; - result += gn_fa_create(key); - result += gn_fa_fixed_tone(key, "A", GnFACompTagSignal, freq, ssb_fund); - result += gn_fa_hd(key, 3); - result += gn_fa_ssb(key, GnFASsbDefault, ssb_rest); - result += gn_fa_ssb(key, GnFASsbDC, -1); - result += gn_fa_ssb(key, GnFASsbSignal, -1); - result += gn_fa_ssb(key, GnFASsbWO, -1); - result += gn_fa_fsample(key, fs); - HANDLE_ERROR(result); - size_t fa_preview_size = 0; - result += gn_fa_preview_size(&fa_preview_size, key, false); - fa_preview = malloc(fa_preview_size); - result += gn_fa_preview(fa_preview, fa_preview_size, key, false); - HANDLE_ERROR(result); - printf("%s\n", fa_preview); + /* + * Fourier analysis configuration + */ + char *key = "fa"; + result += gn_fa_create (key); + result += gn_fa_fixed_tone (key, "A", GnFACompTagSignal, freq, ssb_fund); + result += gn_fa_hd (key, 3); + result += gn_fa_ssb (key, GnFASsbDefault, ssb_rest); + result += gn_fa_ssb (key, GnFASsbDC, -1); + result += gn_fa_ssb (key, GnFASsbSignal, -1); + result += gn_fa_ssb (key, GnFASsbWO, -1); + result += gn_fa_fsample (key, fs); + HANDLE_ERROR (result); + size_t fa_preview_size = 0; + result += gn_fa_preview_size (&fa_preview_size, key, false); + fa_preview = malloc (fa_preview_size); + result += gn_fa_preview (fa_preview, fa_preview_size, key, false); + HANDLE_ERROR (result); + printf ("%s\n", fa_preview); - // To do an analysis: - // 1. Get results size - // 2. Allocate memory for result keys and values - // 3. Get result key sizes - // 4. Allocate memory for each result key - // 5. Execute analysis + // To do an analysis: + // 1. Get results size + // 2. Allocate memory for result keys and values + // 3. Get result key sizes + // 4. Allocate memory for each result key + // 5. Execute analysis - /* - * Waveform analysis - */ - // 1. - result += gn_analysis_results_size(&wf_results_size, GnAnalysisTypeWaveform); - // 2. - wf_rkeys = malloc(wf_results_size * sizeof(char*)); - wf_rvalues = malloc(wf_results_size * sizeof(double)); - // 3. - wf_rkey_sizes = malloc(wf_results_size * sizeof(size_t)); - result += gn_analysis_results_key_sizes(wf_rkey_sizes, wf_results_size, GnAnalysisTypeWaveform); - HANDLE_ERROR(result); - // 4. - for (size_t i = 0; i < wf_results_size; ++i) { - wf_rkeys[i] = malloc(wf_rkey_sizes[i]); + /* + * Waveform analysis + */ + // 1. + result + += gn_analysis_results_size (&wf_results_size, GnAnalysisTypeWaveform); + // 2. + wf_rkeys = malloc (wf_results_size * sizeof (char *)); + wf_rvalues = malloc (wf_results_size * sizeof (double)); + // 3. + wf_rkey_sizes = malloc (wf_results_size * sizeof (size_t)); + result += gn_analysis_results_key_sizes (wf_rkey_sizes, wf_results_size, + GnAnalysisTypeWaveform); + HANDLE_ERROR (result); + // 4. + for (size_t i = 0; i < wf_results_size; ++i) + { + wf_rkeys[i] = malloc (wf_rkey_sizes[i]); } - // 5. - result += gn_wf_analysis16(wf_rkeys, wf_results_size, wf_rvalues, wf_results_size, qwf, npts); - HANDLE_ERROR(result); + // 5. + result += gn_wf_analysis16 (wf_rkeys, wf_results_size, wf_rvalues, + wf_results_size, qwf, npts); + HANDLE_ERROR (result); - /* - * Histogram analysis - */ - result += gn_analysis_results_size(&hist_results_size, GnAnalysisTypeHistogram); - hist_rkeys = malloc(hist_results_size * sizeof(char*)); - hist_rvalues = malloc(hist_results_size * sizeof(double)); - hist_rkey_sizes = malloc(hist_results_size * sizeof(size_t)); - result += gn_analysis_results_key_sizes(hist_rkey_sizes, hist_results_size, GnAnalysisTypeHistogram); - HANDLE_ERROR(result); - for (size_t i = 0; i < hist_results_size; ++i) { - hist_rkeys[i] = malloc(hist_rkey_sizes[i]); + /* + * Histogram analysis + */ + result += gn_analysis_results_size (&hist_results_size, + GnAnalysisTypeHistogram); + hist_rkeys = malloc (hist_results_size * sizeof (char *)); + hist_rvalues = malloc (hist_results_size * sizeof (double)); + hist_rkey_sizes = malloc (hist_results_size * sizeof (size_t)); + result += gn_analysis_results_key_sizes (hist_rkey_sizes, hist_results_size, + GnAnalysisTypeHistogram); + HANDLE_ERROR (result); + for (size_t i = 0; i < hist_results_size; ++i) + { + hist_rkeys[i] = malloc (hist_rkey_sizes[i]); } - result += gn_hist_analysis(hist_rkeys, hist_results_size, hist_rvalues, hist_results_size, hist, cd_size); - HANDLE_ERROR(result); + result += gn_hist_analysis (hist_rkeys, hist_results_size, hist_rvalues, + hist_results_size, hist, cd_size); + HANDLE_ERROR (result); - /* - * DNL analysis - */ - result += gn_analysis_results_size(&dnl_results_size, GnAnalysisTypeDNL); - dnl_rkeys = malloc(dnl_results_size * sizeof(char*)); - dnl_rvalues = malloc(dnl_results_size * sizeof(double)); - dnl_rkey_sizes = malloc(dnl_results_size * sizeof(size_t)); - result += gn_analysis_results_key_sizes(dnl_rkey_sizes, dnl_results_size, GnAnalysisTypeDNL); - HANDLE_ERROR(result); - for (size_t i = 0; i < dnl_results_size; ++i) { - dnl_rkeys[i] = malloc(dnl_rkey_sizes[i]); + /* + * DNL analysis + */ + result += gn_analysis_results_size (&dnl_results_size, GnAnalysisTypeDNL); + dnl_rkeys = malloc (dnl_results_size * sizeof (char *)); + dnl_rvalues = malloc (dnl_results_size * sizeof (double)); + dnl_rkey_sizes = malloc (dnl_results_size * sizeof (size_t)); + result += gn_analysis_results_key_sizes (dnl_rkey_sizes, dnl_results_size, + GnAnalysisTypeDNL); + HANDLE_ERROR (result); + for (size_t i = 0; i < dnl_results_size; ++i) + { + dnl_rkeys[i] = malloc (dnl_rkey_sizes[i]); } - result += gn_dnl_analysis(dnl_rkeys, dnl_results_size, dnl_rvalues, dnl_results_size, dnl, cd_size); - HANDLE_ERROR(result); + result += gn_dnl_analysis (dnl_rkeys, dnl_results_size, dnl_rvalues, + dnl_results_size, dnl, cd_size); + HANDLE_ERROR (result); - /* - * INL analysis - */ - result += gn_analysis_results_size(&inl_results_size, GnAnalysisTypeINL); - inl_rkeys = malloc(inl_results_size * sizeof(char*)); - inl_rvalues = malloc(inl_results_size * sizeof(double)); - inl_rkey_sizes = malloc(inl_results_size * sizeof(size_t)); - result += gn_analysis_results_key_sizes(inl_rkey_sizes, inl_results_size, GnAnalysisTypeINL); - HANDLE_ERROR(result); - for (size_t i = 0; i < inl_results_size; ++i) { - inl_rkeys[i] = malloc(inl_rkey_sizes[i]); + /* + * INL analysis + */ + result += gn_analysis_results_size (&inl_results_size, GnAnalysisTypeINL); + inl_rkeys = malloc (inl_results_size * sizeof (char *)); + inl_rvalues = malloc (inl_results_size * sizeof (double)); + inl_rkey_sizes = malloc (inl_results_size * sizeof (size_t)); + result += gn_analysis_results_key_sizes (inl_rkey_sizes, inl_results_size, + GnAnalysisTypeINL); + HANDLE_ERROR (result); + for (size_t i = 0; i < inl_results_size; ++i) + { + inl_rkeys[i] = malloc (inl_rkey_sizes[i]); } - result += gn_inl_analysis(inl_rkeys, inl_results_size, inl_rvalues, inl_results_size, inl, cd_size); - HANDLE_ERROR(result); + result += gn_inl_analysis (inl_rkeys, inl_results_size, inl_rvalues, + inl_results_size, inl, cd_size); + HANDLE_ERROR (result); - /* - * Fourier analysis - */ - result += gn_fft_analysis_results_size(&fft_results_size, key, fft_cplx_size, nfft); - HANDLE_ERROR(result); - fft_rkeys = malloc(fft_results_size * sizeof(char*)); - fft_rvalues = malloc(fft_results_size * sizeof(double)); - fft_rkey_sizes = malloc(fft_results_size * sizeof(size_t)); - result += gn_fft_analysis_results_key_sizes(fft_rkey_sizes, fft_results_size, key, fft_cplx_size, nfft); - HANDLE_ERROR(result); - for (size_t i = 0; i < fft_results_size; ++i) { - fft_rkeys[i] = malloc(fft_rkey_sizes[i]); + /* + * Fourier analysis + */ + result += gn_fft_analysis_results_size (&fft_results_size, key, + fft_cplx_size, nfft); + HANDLE_ERROR (result); + fft_rkeys = malloc (fft_results_size * sizeof (char *)); + fft_rvalues = malloc (fft_results_size * sizeof (double)); + fft_rkey_sizes = malloc (fft_results_size * sizeof (size_t)); + result += gn_fft_analysis_results_key_sizes ( + fft_rkey_sizes, fft_results_size, key, fft_cplx_size, nfft); + HANDLE_ERROR (result); + for (size_t i = 0; i < fft_results_size; ++i) + { + fft_rkeys[i] = malloc (fft_rkey_sizes[i]); } - result += gn_fft_analysis(fft_rkeys, fft_results_size, fft_rvalues, fft_results_size, - key, fft_cplx, fft_cplx_size, nfft, GnFreqAxisTypeReal); - HANDLE_ERROR(result); + result += gn_fft_analysis (fft_rkeys, fft_results_size, fft_rvalues, + fft_results_size, key, fft_cplx, fft_cplx_size, + nfft, GnFreqAxisTypeReal); + HANDLE_ERROR (result); - /* - * Print results - */ - printf("\nWaveform Analysis Results:\n"); - for (size_t i = 0; i < wf_results_size; ++i) { - printf("%4zu%16s%16.6f\n", i, wf_rkeys[i], wf_rvalues[i]); + /* + * Print results + */ + printf ("\nWaveform Analysis Results:\n"); + for (size_t i = 0; i < wf_results_size; ++i) + { + printf ("%4zu%16s%16.6f\n", i, wf_rkeys[i], wf_rvalues[i]); } - printf("\nHistogram Analysis Results:\n"); - for (size_t i = 0; i < hist_results_size; ++i) { - printf("%4zu%16s%16.6f\n", i, hist_rkeys[i], hist_rvalues[i]); + printf ("\nHistogram Analysis Results:\n"); + for (size_t i = 0; i < hist_results_size; ++i) + { + printf ("%4zu%16s%16.6f\n", i, hist_rkeys[i], hist_rvalues[i]); } - printf("\nDNL Analysis Results:\n"); - for (size_t i = 0; i < dnl_results_size; ++i) { - printf("%4zu%16s%16.6f\n", i, dnl_rkeys[i], dnl_rvalues[i]); + printf ("\nDNL Analysis Results:\n"); + for (size_t i = 0; i < dnl_results_size; ++i) + { + printf ("%4zu%16s%16.6f\n", i, dnl_rkeys[i], dnl_rvalues[i]); } - printf("\nINL Analysis Results:\n"); - for (size_t i = 0; i < inl_results_size; ++i) { - printf("%4zu%16s%16.6f\n", i, inl_rkeys[i], inl_rvalues[i]); + printf ("\nINL Analysis Results:\n"); + for (size_t i = 0; i < inl_results_size; ++i) + { + printf ("%4zu%16s%16.6f\n", i, inl_rkeys[i], inl_rvalues[i]); } - printf("\nFourier Analysis Results:\n"); - for (size_t i = 0; i < fft_results_size; ++i) { - printf("%4zu%20s%20.6f\n", i, fft_rkeys[i], fft_rvalues[i]); + printf ("\nFourier Analysis Results:\n"); + for (size_t i = 0; i < fft_results_size; ++i) + { + printf ("%4zu%20s%20.6f\n", i, fft_rkeys[i], fft_rvalues[i]); } - /* - * Save data - */ - if (save_data) { - const char* fn = "qwf.txt"; - FILE* fp = fopen(fn, "w"); - if (fp) { - for (size_t i = 0; i < npts; ++i) { - fprintf(fp, "%d\n", qwf[i]); + /* + * Save data + */ + if (save_data) + { + const char *fn = "qwf.txt"; + FILE *fp = fopen (fn, "w"); + if (fp) + { + for (size_t i = 0; i < npts; ++i) + { + fprintf (fp, "%d\n", qwf[i]); } - fclose(fp); - printf("\nWrote quantized waveform data to %s\n", fn); + fclose (fp); + printf ("\nWrote quantized waveform data to %s\n", fn); } - fn = "hist.txt"; - fp = fopen(fn, "w"); - if (fp) { - for (size_t i = 0; i < cd_size; ++i) { - fprintf(fp, "%zu\n", hist[i]); + fn = "hist.txt"; + fp = fopen (fn, "w"); + if (fp) + { + for (size_t i = 0; i < cd_size; ++i) + { + fprintf (fp, "%zu\n", hist[i]); } - fclose(fp); - printf("Wrote histogram data to %s\n", fn); + fclose (fp); + printf ("Wrote histogram data to %s\n", fn); } - fn = "dnl.txt"; - fp = fopen(fn, "w"); - if (fp) { - for (size_t i = 0; i < cd_size; ++i) { - fprintf(fp, "%.9f\n", dnl[i]); + fn = "dnl.txt"; + fp = fopen (fn, "w"); + if (fp) + { + for (size_t i = 0; i < cd_size; ++i) + { + fprintf (fp, "%.9f\n", dnl[i]); } - fclose(fp); - printf("Wrote DNL data to %s\n", fn); + fclose (fp); + printf ("Wrote DNL data to %s\n", fn); } - fn = "inl.txt"; - fp = fopen(fn, "w"); - if (fp) { - for (size_t i = 0; i < cd_size; ++i) { - fprintf(fp, "%.9f\n", inl[i]); + fn = "inl.txt"; + fp = fopen (fn, "w"); + if (fp) + { + for (size_t i = 0; i < cd_size; ++i) + { + fprintf (fp, "%.9f\n", inl[i]); } - fclose(fp); - printf("Wrote INL data to %s\n", fn); + fclose (fp); + printf ("Wrote INL data to %s\n", fn); } - fn = "code_axis.txt"; - fp = fopen(fn, "w"); - if (fp) { - code_axis = malloc(cd_size * sizeof(double)); - result += gn_code_axis(code_axis, cd_size, qres, code_fmt); - for (size_t i = 0; i < cd_size; ++i) { - fprintf(fp, "%.0f\n", code_axis[i]); + fn = "code_axis.txt"; + fp = fopen (fn, "w"); + if (fp) + { + code_axis = malloc (cd_size * sizeof (double)); + result += gn_code_axis (code_axis, cd_size, qres, code_fmt); + for (size_t i = 0; i < cd_size; ++i) + { + fprintf (fp, "%.0f\n", code_axis[i]); } - fclose(fp); - printf("Wrote code density axis data to %s\n", fn); + fclose (fp); + printf ("Wrote code density axis data to %s\n", fn); } - fn = "rfft.txt"; - fp = fopen(fn, "w"); - if (fp) { - fft_db = malloc((fft_cplx_size / 2) * sizeof(double)); - result += gn_db(fft_db, (fft_cplx_size / 2), fft_cplx, fft_cplx_size); - for (size_t i = 0; i < (fft_cplx_size / 2); ++i) { - fprintf(fp, "%.9f\n", fft_db[i]); + fn = "rfft.txt"; + fp = fopen (fn, "w"); + if (fp) + { + fft_db = malloc ((fft_cplx_size / 2) * sizeof (double)); + result + += gn_db (fft_db, (fft_cplx_size / 2), fft_cplx, fft_cplx_size); + for (size_t i = 0; i < (fft_cplx_size / 2); ++i) + { + fprintf (fp, "%.9f\n", fft_db[i]); } - fclose(fp); - printf("Wrote FFT magnitude data to %s\n", fn); + fclose (fp); + printf ("Wrote FFT magnitude data to %s\n", fn); } - fn = "rfft_axis.txt"; - fp = fopen(fn, "w"); - if (fp) { - freq_axis = malloc((fft_cplx_size / 2) * sizeof(double)); - result = gn_freq_axis(freq_axis, (fft_cplx_size / 2), nfft, GnFreqAxisTypeReal, fs, GnFreqAxisFormatFreq); - for (size_t i = 0; i < (fft_cplx_size / 2); ++i) { - fprintf(fp, "%.6f\n", freq_axis[i]); + fn = "rfft_axis.txt"; + fp = fopen (fn, "w"); + if (fp) + { + freq_axis = malloc ((fft_cplx_size / 2) * sizeof (double)); + result = gn_freq_axis (freq_axis, (fft_cplx_size / 2), nfft, + GnFreqAxisTypeReal, fs, GnFreqAxisFormatFreq); + for (size_t i = 0; i < (fft_cplx_size / 2); ++i) + { + fprintf (fp, "%.6f\n", freq_axis[i]); } - fclose(fp); - printf("Wrote FFT x-axis data to %s\n", fn); + fclose (fp); + printf ("Wrote FFT x-axis data to %s\n", fn); } } - error_occurred = false; + error_occurred = false; cleanup: - if (error_occurred) { - printf("\nError occurred, freeing memory\n"); - } else { - printf("\nFreeing memory\n"); + if (error_occurred) + { + printf ("\nError occurred, freeing memory\n"); + } + else + { + printf ("\nFreeing memory\n"); } - if (fft_rkeys) { - for (size_t i = 0; i < fft_results_size; ++i) { - free(fft_rkeys[i]); + if (fft_rkeys) + { + for (size_t i = 0; i < fft_results_size; ++i) + { + free (fft_rkeys[i]); } } - free(fft_rkey_sizes); - free(fft_rvalues); - free(fft_rkeys); - if (inl_rkeys) { - for (size_t i = 0; i < inl_results_size; ++i) { - free(inl_rkeys[i]); + free (fft_rkey_sizes); + free (fft_rvalues); + free (fft_rkeys); + if (inl_rkeys) + { + for (size_t i = 0; i < inl_results_size; ++i) + { + free (inl_rkeys[i]); } } - free(inl_rkey_sizes); - free(inl_rvalues); - free(inl_rkeys); - if (dnl_rkeys) { - for (size_t i = 0; i < dnl_results_size; ++i) { - free(dnl_rkeys[i]); + free (inl_rkey_sizes); + free (inl_rvalues); + free (inl_rkeys); + if (dnl_rkeys) + { + for (size_t i = 0; i < dnl_results_size; ++i) + { + free (dnl_rkeys[i]); } } - free(dnl_rkey_sizes); - free(dnl_rvalues); - free(dnl_rkeys); - if (hist_rkeys) { - for (size_t i = 0; i < hist_results_size; ++i) { - free(hist_rkeys[i]); + free (dnl_rkey_sizes); + free (dnl_rvalues); + free (dnl_rkeys); + if (hist_rkeys) + { + for (size_t i = 0; i < hist_results_size; ++i) + { + free (hist_rkeys[i]); } } - free(hist_rkey_sizes); - free(hist_rvalues); - free(hist_rkeys); - if (wf_rkeys) { - for (size_t i = 0; i < wf_results_size; ++i) { - free(wf_rkeys[i]); + free (hist_rkey_sizes); + free (hist_rvalues); + free (hist_rkeys); + if (wf_rkeys) + { + for (size_t i = 0; i < wf_results_size; ++i) + { + free (wf_rkeys[i]); } } - free(wf_rkey_sizes); - free(wf_rvalues); - free(wf_rkeys); - free(fa_preview); - free(freq_axis); - free(fft_db); - free(fft_cplx); - free(code_axis); - free(inl); - free(dnl); - free(hist); - free(qwf); - free(awf); + free (wf_rkey_sizes); + free (wf_rvalues); + free (wf_rkeys); + free (fa_preview); + free (freq_axis); + free (fft_db); + free (fft_cplx); + free (code_axis); + free (inl); + free (dnl); + free (hist); + free (qwf); + free (awf); - return 0; + return 0; } \ No newline at end of file diff --git a/include/array_ops.hpp b/include/array_ops.hpp index 5f24aa5..a687100 100644 --- a/include/array_ops.hpp +++ b/include/array_ops.hpp @@ -1,21 +1,31 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_ARRAY_OPS_HPP #define GENALYZER_IMPL_ARRAY_OPS_HPP #include "type_aliases.hpp" -namespace genalyzer_impl { +namespace genalyzer_impl +{ - void abs(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void abs (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - void angle(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void angle (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - void db(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void db (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - void db10(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void db10 (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - void db20(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void db20 (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - void norm(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void norm (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); } // namespace genalyzer_impl diff --git a/include/code_density.hpp b/include/code_density.hpp index 9cb1fa2..9bfe4b5 100644 --- a/include/code_density.hpp +++ b/include/code_density.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_CODE_DENSITY_HPP #define GENALYZER_IMPL_CODE_DENSITY_HPP @@ -6,65 +9,42 @@ #include -namespace genalyzer_impl { - - size_t code_density_size(int n, CodeFormat format); - - size_t code_densityx_size(int64_t min, int64_t max); - - void code_axis(real_t* data, size_t size, int n, CodeFormat format); - - void code_axisx(real_t* data, size_t size, int64_t min, int64_t max); - - void dnl( - real_t* dnl_data, - size_t dnl_size, - const uint64_t* hist_data, - size_t hist_size, - DnlSignal type - ); - - std::map dnl_analysis(const real_t* data, size_t size); - - const std::vector& dnl_analysis_ordered_keys(); - - template - void hist( - uint64_t* hist_data, - size_t hist_size, - const T* wf_data, - size_t wf_size, - int n, - CodeFormat format, - bool preserve - ); - - template - void histx( - uint64_t* hist_data, - size_t hist_size, - const T* wf_data, - size_t wf_size, - int64_t min, - int64_t max, - bool preserve - ); - - std::map hist_analysis(const uint64_t* data, size_t size); - - const std::vector& hist_analysis_ordered_keys(); - - void inl( - real_t* inl_data, - size_t inl_size, - const real_t* dnl_data, - size_t dnl_size, - InlLineFit fit - ); - - std::map inl_analysis(const real_t* data, size_t size); - - const std::vector& inl_analysis_ordered_keys(); +namespace genalyzer_impl +{ + +size_t code_density_size (int n, CodeFormat format); + +size_t code_densityx_size (int64_t min, int64_t max); + +void code_axis (real_t *data, size_t size, int n, CodeFormat format); + +void code_axisx (real_t *data, size_t size, int64_t min, int64_t max); + +void dnl (real_t *dnl_data, size_t dnl_size, const uint64_t *hist_data, + size_t hist_size, DnlSignal type); + +std::map dnl_analysis (const real_t *data, size_t size); + +const std::vector &dnl_analysis_ordered_keys (); + +template +void hist (uint64_t *hist_data, size_t hist_size, const T *wf_data, + size_t wf_size, int n, CodeFormat format, bool preserve); + +template +void histx (uint64_t *hist_data, size_t hist_size, const T *wf_data, + size_t wf_size, int64_t min, int64_t max, bool preserve); + +std::map hist_analysis (const uint64_t *data, size_t size); + +const std::vector &hist_analysis_ordered_keys (); + +void inl (real_t *inl_data, size_t inl_size, const real_t *dnl_data, + size_t dnl_size, InlLineFit fit); + +std::map inl_analysis (const real_t *data, size_t size); + +const std::vector &inl_analysis_ordered_keys (); } // namespace genalyzer_impl diff --git a/include/constants.hpp b/include/constants.hpp index 500f65d..9202571 100644 --- a/include/constants.hpp +++ b/include/constants.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_CONSTANTS_HPP #define GENALYZER_IMPL_CONSTANTS_HPP @@ -5,29 +8,30 @@ #include -namespace genalyzer_impl { - - const real_t k_half = 0.5; - const real_t k_one = 1.0; - const real_t k_two = 2.0; - const real_t k_sqrt2 = std::sqrt(k_two); - const real_t k_inv_sqrt2 = std::sqrt(k_half); - const real_t k_pi4 = std::atan(k_one); - const real_t k_pi2 = k_two * k_pi4; - const real_t k_pi = k_two * k_pi2; - const real_t k_2pi = k_two * k_pi; - - const int k_abs_min_code_width = 1; - const int k_abs_max_code_width = 30; - - const size_t k_abs_max_fft_navg = 256; - - const real_t k_abs_max_db = 400.0; - const real_t k_abs_min_db = -400.0; - const real_t k_abs_max_rms = std::pow(10.0, k_abs_max_db / 20.0); - const real_t k_abs_min_rms = std::pow(10.0, k_abs_min_db / 20.0); - const real_t k_abs_max_msq = k_abs_max_rms * k_abs_max_rms; - const real_t k_abs_min_msq = k_abs_min_rms * k_abs_min_rms; +namespace genalyzer_impl +{ + +const real_t k_half = 0.5; +const real_t k_one = 1.0; +const real_t k_two = 2.0; +const real_t k_sqrt2 = std::sqrt (k_two); +const real_t k_inv_sqrt2 = std::sqrt (k_half); +const real_t k_pi4 = std::atan (k_one); +const real_t k_pi2 = k_two * k_pi4; +const real_t k_pi = k_two * k_pi2; +const real_t k_2pi = k_two * k_pi; + +const int k_abs_min_code_width = 1; +const int k_abs_max_code_width = 30; + +const size_t k_abs_max_fft_navg = 256; + +const real_t k_abs_max_db = 400.0; +const real_t k_abs_min_db = -400.0; +const real_t k_abs_max_rms = std::pow (10.0, k_abs_max_db / 20.0); +const real_t k_abs_min_rms = std::pow (10.0, k_abs_min_db / 20.0); +const real_t k_abs_max_msq = k_abs_max_rms * k_abs_max_rms; +const real_t k_abs_min_msq = k_abs_min_rms * k_abs_min_rms; } // namespace genalyzer_impl diff --git a/include/enum_map.hpp b/include/enum_map.hpp index b71861b..ac1c127 100644 --- a/include/enum_map.hpp +++ b/include/enum_map.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_ENUM_MAP_HPP #define GENALYZER_IMPL_ENUM_MAP_HPP @@ -7,75 +10,75 @@ #include #include -namespace genalyzer_impl { - - class enum_map - { - public: - - using itos_map_t = std::map; - using stoi_map_t = std::map; - using const_iterator = itos_map_t::const_iterator; - - public: - - enum_map(const char* name, std::initializer_list> list); - - public: - - ~enum_map() = default; - - public: // Element Access - - const str_t& at(int i) const - { - contains(i, true); - return m_itos.at(i); - } - - int at(const str_t& s) const - { - contains(s, true); - return m_stoi.at(s); - } - - public: // Iterators - - const_iterator begin() const - { - return m_itos.begin(); - } - - const_iterator end() const - { - return m_itos.end(); - } - - public: // Lookup - - bool contains(int i, bool throw_if_not_found = false) const; - - bool contains(const str_t& s, bool throw_if_not_found = false) const; - - public: // Other Member Functions - - const str_t& name() const - { - return m_name; - } - - size_t size() const - { - return m_itos.size(); - } - - private: - - str_t m_name; - itos_map_t m_itos; // int to string - stoi_map_t m_stoi; // string to int - - }; // class enum_map +namespace genalyzer_impl +{ + +class enum_map +{ +public: + using itos_map_t = std::map; + using stoi_map_t = std::map; + using const_iterator = itos_map_t::const_iterator; + +public: + enum_map (const char *name, + std::initializer_list > list); + +public: + ~enum_map () = default; + +public: // Element Access + const str_t & + at (int i) const + { + contains (i, true); + return m_itos.at (i); + } + + int + at (const str_t &s) const + { + contains (s, true); + return m_stoi.at (s); + } + +public: // Iterators + const_iterator + begin () const + { + return m_itos.begin (); + } + + const_iterator + end () const + { + return m_itos.end (); + } + +public: // Lookup + bool contains (int i, bool throw_if_not_found = false) const; + + bool contains (const str_t &s, bool throw_if_not_found = false) const; + +public: // Other Member Functions + const str_t & + name () const + { + return m_name; + } + + size_t + size () const + { + return m_itos.size (); + } + +private: + str_t m_name; + itos_map_t m_itos; // int to string + stoi_map_t m_stoi; // string to int + +}; // class enum_map } // namespace genalyzer_impl diff --git a/include/enum_maps.hpp b/include/enum_maps.hpp index 889bfbd..e8e8ed0 100644 --- a/include/enum_maps.hpp +++ b/include/enum_maps.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_ENUM_MAPS_HPP #define GENALYZER_IMPL_ENUM_MAPS_HPP @@ -5,160 +8,156 @@ #include "enums.hpp" #include "utils.hpp" -namespace genalyzer_impl { - - int enum_value(const str_t& enumeration, const str_t& enumerator); - - template - E get_enum(int); - - const enum_map analysis_type_map ("AnalysisType", { - { to_int(AnalysisType::DNL) , "DNL" }, - { to_int(AnalysisType::Fourier) , "Fourier" }, - { to_int(AnalysisType::Histogram) , "Histogram" }, - { to_int(AnalysisType::INL) , "INL" }, - { to_int(AnalysisType::Waveform) , "Waveform" }} - ); - - const enum_map code_format_map ("CodeFormat", { - { to_int(CodeFormat::OffsetBinary) , "OffsetBinary" }, - { to_int(CodeFormat::TwosComplement) , "TwosComplement" }} - ); - - const enum_map dnl_signal_map ("DnlSignal", { - { to_int(DnlSignal::Ramp) , "Ramp" }, - { to_int(DnlSignal::Tone) , "Tone" }} - ); - - const enum_map fa_comp_tag_map ("FACompTag", { - { to_int(FACompTag::DC) , "DC" }, - { to_int(FACompTag::Signal) , "Signal" }, - { to_int(FACompTag::HD) , "HD" }, - { to_int(FACompTag::IMD) , "IMD" }, - { to_int(FACompTag::ILOS) , "ILOS" }, - { to_int(FACompTag::ILGT) , "ILGT" }, - { to_int(FACompTag::CLK) , "CLK" }, - { to_int(FACompTag::UserDist) , "UserDist" }, - { to_int(FACompTag::Noise) , "Noise" }} - ); - - const enum_map fa_ssb_map ("FASsb", { - { to_int(FASsb::Default) , "Default" }, - { to_int(FASsb::DC) , "DC" }, - { to_int(FASsb::Signal) , "Signal" }, - { to_int(FASsb::WO) , "WO" }} - ); - - const enum_map freq_axis_format_map ("FreqAxisFormat", { - { to_int(FreqAxisFormat::Bins) , "Bins" }, - { to_int(FreqAxisFormat::Freq) , "Freq" }, - { to_int(FreqAxisFormat::Norm) , "Norm" }} - ); - - const enum_map freq_axis_type_map ("FreqAxisType", { - { to_int(FreqAxisType::DcCenter) , "DcCenter" }, - { to_int(FreqAxisType::DcLeft) , "DcLeft" }, - { to_int(FreqAxisType::Real) , "Real" }} - ); - - const enum_map inl_line_fit_map ("InlLineFit", { - { to_int(InlLineFit::NoFit) , "NoFit" }, - { to_int(InlLineFit::BestFit) , "BestFit" }, - { to_int(InlLineFit::EndFit) , "EndFit" }} - ); - - const enum_map rfft_scale_map ("RfftScale", { - { to_int(RfftScale::DbfsDc) , "DbfsDc" }, - { to_int(RfftScale::DbfsSin) , "DbfsSin" }, - { to_int(RfftScale::Native) , "Native" }} - ); - - const enum_map window_map ("Window", { - { to_int(Window::NoWindow) , "NoWindow" }, - { to_int(Window::BlackmanHarris) , "BlackmanHarris" }, - { to_int(Window::Hann) , "Hann" }} - ); - +namespace genalyzer_impl +{ + +int enum_value (const str_t &enumeration, const str_t &enumerator); + +template E get_enum (int); + +const enum_map + analysis_type_map ("AnalysisType", + { { to_int (AnalysisType::DNL), "DNL" }, + { to_int (AnalysisType::Fourier), "Fourier" }, + { to_int (AnalysisType::Histogram), "Histogram" }, + { to_int (AnalysisType::INL), "INL" }, + { to_int (AnalysisType::Waveform), "Waveform" } }); + +const enum_map code_format_map ( + "CodeFormat", + { { to_int (CodeFormat::OffsetBinary), "OffsetBinary" }, + { to_int (CodeFormat::TwosComplement), "TwosComplement" } }); + +const enum_map dnl_signal_map ("DnlSignal", + { { to_int (DnlSignal::Ramp), "Ramp" }, + { to_int (DnlSignal::Tone), "Tone" } }); + +const enum_map fa_comp_tag_map ("FACompTag", + { { to_int (FACompTag::DC), "DC" }, + { to_int (FACompTag::Signal), "Signal" }, + { to_int (FACompTag::HD), "HD" }, + { to_int (FACompTag::IMD), "IMD" }, + { to_int (FACompTag::ILOS), "ILOS" }, + { to_int (FACompTag::ILGT), "ILGT" }, + { to_int (FACompTag::CLK), "CLK" }, + { to_int (FACompTag::UserDist), "UserDist" }, + { to_int (FACompTag::Noise), "Noise" } }); + +const enum_map fa_ssb_map ("FASsb", { { to_int (FASsb::Default), "Default" }, + { to_int (FASsb::DC), "DC" }, + { to_int (FASsb::Signal), "Signal" }, + { to_int (FASsb::WO), "WO" } }); + +const enum_map + freq_axis_format_map ("FreqAxisFormat", + { { to_int (FreqAxisFormat::Bins), "Bins" }, + { to_int (FreqAxisFormat::Freq), "Freq" }, + { to_int (FreqAxisFormat::Norm), "Norm" } }); + +const enum_map + freq_axis_type_map ("FreqAxisType", + { { to_int (FreqAxisType::DcCenter), "DcCenter" }, + { to_int (FreqAxisType::DcLeft), "DcLeft" }, + { to_int (FreqAxisType::Real), "Real" } }); + +const enum_map + inl_line_fit_map ("InlLineFit", + { { to_int (InlLineFit::NoFit), "NoFit" }, + { to_int (InlLineFit::BestFit), "BestFit" }, + { to_int (InlLineFit::EndFit), "EndFit" } }); + +const enum_map rfft_scale_map ("RfftScale", + { { to_int (RfftScale::DbfsDc), "DbfsDc" }, + { to_int (RfftScale::DbfsSin), "DbfsSin" }, + { to_int (RfftScale::Native), "Native" } }); + +const enum_map + window_map ("Window", + { { to_int (Window::NoWindow), "NoWindow" }, + { to_int (Window::BlackmanHarris), "BlackmanHarris" }, + { to_int (Window::Hann), "Hann" } }); + } // namespace genalyzer_impl -namespace genalyzer_impl { - - const enum_map fa_comp_type_map ("FACompType", { - { to_int(FACompType::DC) , "DC" }, - { to_int(FACompType::FixedTone) , "FixedTone" }, - { to_int(FACompType::MaxTone) , "MaxTone" }, - { to_int(FACompType::WOTone) , "WOTone" }} - ); - - const enum_map fa_result_map ("FAResult", { - { to_int(FAResult::AnalysisType) , "analysistype" }, - { to_int(FAResult::SignalType) , "signaltype" }, - { to_int(FAResult::NFFT) , "nfft" }, - { to_int(FAResult::DataSize) , "datasize" }, - { to_int(FAResult::FBin) , "fbin" }, - { to_int(FAResult::FData) , "fdata" }, - { to_int(FAResult::FSample) , "fsample" }, - { to_int(FAResult::FShift) , "fshift" }, - { to_int(FAResult::FSNR) , "fsnr" }, - { to_int(FAResult::SNR) , "snr" }, - { to_int(FAResult::SINAD) , "sinad" }, - { to_int(FAResult::SFDR) , "sfdr" }, - { to_int(FAResult::ABN) , "abn" }, - { to_int(FAResult::NSD) , "nsd" }, - { to_int(FAResult::CarrierIndex) , "carrierindex" }, - { to_int(FAResult::MaxSpurIndex) , "maxspurindex" }, - { to_int(FAResult::AB_Width) , "ab_width" }, - { to_int(FAResult::AB_I1) , "ab_i1" }, - { to_int(FAResult::AB_I2) , "ab_i2" }, - { to_int(FAResult::AB_NBins) , "ab_nbins" }, - { to_int(FAResult::AB_RSS) , "ab_rss" }, - { to_int(FAResult::Signal_NBins) , "signal_nbins" }, - { to_int(FAResult::Signal_RSS) , "signal_rss" }, - { to_int(FAResult::CLK_NBins) , "clk_nbins" }, - { to_int(FAResult::CLK_RSS) , "clk_rss" }, - { to_int(FAResult::HD_NBins) , "hd_nbins" }, - { to_int(FAResult::HD_RSS) , "hd_rss" }, - { to_int(FAResult::ILOS_NBins) , "ilos_nbins" }, - { to_int(FAResult::ILOS_RSS) , "ilos_rss" }, - { to_int(FAResult::ILGT_NBins) , "ilgt_nbins" }, - { to_int(FAResult::ILGT_RSS) , "ilgt_rss" }, - { to_int(FAResult::IMD_NBins) , "imd_nbins" }, - { to_int(FAResult::IMD_RSS) , "imd_rss" }, - { to_int(FAResult::UserDist_NBins) , "userdist_nbins" }, - { to_int(FAResult::UserDist_RSS) , "userdist_rss" }, - { to_int(FAResult::THD_NBins) , "thd_nbins" }, - { to_int(FAResult::THD_RSS) , "thd_rss" }, - { to_int(FAResult::ILV_NBins) , "ilv_nbins" }, - { to_int(FAResult::ILV_RSS) , "ilv_rss" }, - { to_int(FAResult::Dist_NBins) , "dist_nbins" }, - { to_int(FAResult::Dist_RSS) , "dist_rss" }, - { to_int(FAResult::Noise_NBins) , "noise_nbins" }, - { to_int(FAResult::Noise_RSS) , "noise_rss" }, - { to_int(FAResult::NAD_NBins) , "nad_nbins" }, - { to_int(FAResult::NAD_RSS) , "nad_rss" }} - ); - - const enum_map fa_tone_result_map ("FAToneResult", { - { to_int(FAToneResult::OrderIndex) , "orderindex" }, - { to_int(FAToneResult::Tag) , "tag" }, - { to_int(FAToneResult::Freq) , "freq" }, - { to_int(FAToneResult::FFinal) , "ffinal" }, - { to_int(FAToneResult::FWAvg) , "fwavg" }, - { to_int(FAToneResult::I1) , "i1" }, - { to_int(FAToneResult::I2) , "i2" }, - { to_int(FAToneResult::NBins) , "nbins" }, - { to_int(FAToneResult::InBand) , "inband" }, - { to_int(FAToneResult::Mag) , "mag" }, - { to_int(FAToneResult::Mag_dBFS) , "mag_dbfs" }, - { to_int(FAToneResult::Mag_dBc) , "mag_dbc" }, - { to_int(FAToneResult::Phase) , "phase" }, - { to_int(FAToneResult::Phase_c) , "phase_c" }} - ); - - const enum_map object_type_map ("ObjectType", { - { to_int(ObjectType::FourierAnalysis) , "FourierAnalysis" }} - ); - +namespace genalyzer_impl +{ + +const enum_map + fa_comp_type_map ("FACompType", + { { to_int (FACompType::DC), "DC" }, + { to_int (FACompType::FixedTone), "FixedTone" }, + { to_int (FACompType::MaxTone), "MaxTone" }, + { to_int (FACompType::WOTone), "WOTone" } }); + +const enum_map + fa_result_map ("FAResult", + { { to_int (FAResult::AnalysisType), "analysistype" }, + { to_int (FAResult::SignalType), "signaltype" }, + { to_int (FAResult::NFFT), "nfft" }, + { to_int (FAResult::DataSize), "datasize" }, + { to_int (FAResult::FBin), "fbin" }, + { to_int (FAResult::FData), "fdata" }, + { to_int (FAResult::FSample), "fsample" }, + { to_int (FAResult::FShift), "fshift" }, + { to_int (FAResult::FSNR), "fsnr" }, + { to_int (FAResult::SNR), "snr" }, + { to_int (FAResult::SINAD), "sinad" }, + { to_int (FAResult::SFDR), "sfdr" }, + { to_int (FAResult::ABN), "abn" }, + { to_int (FAResult::NSD), "nsd" }, + { to_int (FAResult::CarrierIndex), "carrierindex" }, + { to_int (FAResult::MaxSpurIndex), "maxspurindex" }, + { to_int (FAResult::AB_Width), "ab_width" }, + { to_int (FAResult::AB_I1), "ab_i1" }, + { to_int (FAResult::AB_I2), "ab_i2" }, + { to_int (FAResult::AB_NBins), "ab_nbins" }, + { to_int (FAResult::AB_RSS), "ab_rss" }, + { to_int (FAResult::Signal_NBins), "signal_nbins" }, + { to_int (FAResult::Signal_RSS), "signal_rss" }, + { to_int (FAResult::CLK_NBins), "clk_nbins" }, + { to_int (FAResult::CLK_RSS), "clk_rss" }, + { to_int (FAResult::HD_NBins), "hd_nbins" }, + { to_int (FAResult::HD_RSS), "hd_rss" }, + { to_int (FAResult::ILOS_NBins), "ilos_nbins" }, + { to_int (FAResult::ILOS_RSS), "ilos_rss" }, + { to_int (FAResult::ILGT_NBins), "ilgt_nbins" }, + { to_int (FAResult::ILGT_RSS), "ilgt_rss" }, + { to_int (FAResult::IMD_NBins), "imd_nbins" }, + { to_int (FAResult::IMD_RSS), "imd_rss" }, + { to_int (FAResult::UserDist_NBins), "userdist_nbins" }, + { to_int (FAResult::UserDist_RSS), "userdist_rss" }, + { to_int (FAResult::THD_NBins), "thd_nbins" }, + { to_int (FAResult::THD_RSS), "thd_rss" }, + { to_int (FAResult::ILV_NBins), "ilv_nbins" }, + { to_int (FAResult::ILV_RSS), "ilv_rss" }, + { to_int (FAResult::Dist_NBins), "dist_nbins" }, + { to_int (FAResult::Dist_RSS), "dist_rss" }, + { to_int (FAResult::Noise_NBins), "noise_nbins" }, + { to_int (FAResult::Noise_RSS), "noise_rss" }, + { to_int (FAResult::NAD_NBins), "nad_nbins" }, + { to_int (FAResult::NAD_RSS), "nad_rss" } }); + +const enum_map + fa_tone_result_map ("FAToneResult", + { { to_int (FAToneResult::OrderIndex), "orderindex" }, + { to_int (FAToneResult::Tag), "tag" }, + { to_int (FAToneResult::Freq), "freq" }, + { to_int (FAToneResult::FFinal), "ffinal" }, + { to_int (FAToneResult::FWAvg), "fwavg" }, + { to_int (FAToneResult::I1), "i1" }, + { to_int (FAToneResult::I2), "i2" }, + { to_int (FAToneResult::NBins), "nbins" }, + { to_int (FAToneResult::InBand), "inband" }, + { to_int (FAToneResult::Mag), "mag" }, + { to_int (FAToneResult::Mag_dBFS), "mag_dbfs" }, + { to_int (FAToneResult::Mag_dBc), "mag_dbc" }, + { to_int (FAToneResult::Phase), "phase" }, + { to_int (FAToneResult::Phase_c), "phase_c" } }); + +const enum_map object_type_map ("ObjectType", + { { to_int (ObjectType::FourierAnalysis), + "FourierAnalysis" } }); + } // namespace genalyzer_impl #endif // GENALYZER_IMPL_ENUM_MAPS_HPP \ No newline at end of file diff --git a/include/enums.hpp b/include/enums.hpp index c56bc1e..e01dbd6 100644 --- a/include/enums.hpp +++ b/include/enums.hpp @@ -1,178 +1,198 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_ENUMS_HPP #define GENALYZER_IMPL_ENUMS_HPP /* * Enumerations that are part of the API (exposed as type int) */ -namespace genalyzer_impl { - - enum class AnalysisType : int { - DNL, - Fourier, - Histogram, - INL, - Waveform - }; - - enum class CodeFormat : int { - OffsetBinary, - TwosComplement - }; - - enum class DnlSignal : int { - Ramp, - Tone - }; - - // Noise means not DC and not Signal and not Distortion - enum class FACompTag : int { // Fourier Analysis Component Tag - DC, // DC component (always Bin 0) - Signal, // Signal component - HD, // Harmonic distortion - IMD, // Intermodulation distortion - ILOS, // Interleaving offset component - ILGT, // Interleaving gain/timing/BW component - CLK, // Clock component - UserDist, // User-designated distortion - Noise // Noise component (e.g. WorstOther) - }; - - enum class FASsb : int { - Default, // Default SSB (applies to auto-generated components) - DC, // SSB for DC component - Signal, // SSB for Signal components - WO, // SSB for WorstOther components - }; - - enum class FreqAxisFormat : int { - Bins, - Freq, - Norm - }; - - enum class FreqAxisType : int { - DcCenter, - DcLeft, - Real - }; - - enum class InlLineFit : int { - BestFit, - EndFit, - NoFit - }; - - enum class RfftScale : int { - DbfsDc, // Full-scale sinusoid measures -3 dBFS - DbfsSin, // Full-scale sinusoid measures 0 dBFS - Native // Full-scale sinusoid measures -6 dBFS - }; - - enum class Window : int { - BlackmanHarris, - Hann, - NoWindow - }; +namespace genalyzer_impl +{ + +enum class AnalysisType : int +{ + DNL, + Fourier, + Histogram, + INL, + Waveform +}; + +enum class CodeFormat : int +{ + OffsetBinary, + TwosComplement +}; + +enum class DnlSignal : int +{ + Ramp, + Tone +}; + +// Noise means not DC and not Signal and not Distortion +enum class FACompTag : int +{ // Fourier Analysis Component Tag + DC, // DC component (always Bin 0) + Signal, // Signal component + HD, // Harmonic distortion + IMD, // Intermodulation distortion + ILOS, // Interleaving offset component + ILGT, // Interleaving gain/timing/BW component + CLK, // Clock component + UserDist, // User-designated distortion + Noise // Noise component (e.g. WorstOther) +}; + +enum class FASsb : int +{ + Default, // Default SSB (applies to auto-generated components) + DC, // SSB for DC component + Signal, // SSB for Signal components + WO, // SSB for WorstOther components +}; + +enum class FreqAxisFormat : int +{ + Bins, + Freq, + Norm +}; + +enum class FreqAxisType : int +{ + DcCenter, + DcLeft, + Real +}; + +enum class InlLineFit : int +{ + BestFit, + EndFit, + NoFit +}; + +enum class RfftScale : int +{ + DbfsDc, // Full-scale sinusoid measures -3 dBFS + DbfsSin, // Full-scale sinusoid measures 0 dBFS + Native // Full-scale sinusoid measures -6 dBFS +}; + +enum class Window : int +{ + BlackmanHarris, + Hann, + NoWindow +}; } // namespace genalyzer_impl /* * Enumerations only used internally */ -namespace genalyzer_impl { - - enum class FACompType : int { // Fourier Analysis Component Type - DC, // DC component (always Bin 0) - FixedTone, // Tone with fixed, user-defined location - MaxTone, // Next largest tone - WOTone // Worst other tone - }; - - enum class FAResult : int { // Fourier Analysis Results - // Meta Data - AnalysisType = 0, // Analysis type - SignalType, // Signal type: 0=Real, 1=Cplx - NFFT, // FFT size - DataSize, // Data size - FBin, // Frequency resolution (Hz) - FData, // Data rate (S/s) - FSample, // Sample rate (S/s) - FShift, // Shift frequency (Hz) - // Primary Measurements - FSNR, // Full-Scale-to-Noise ratio, a.k.a "SNRFS" (dB) - SNR, // Signal-to-Noise ratio (dB) - SINAD, // Signal-to-Noise-and-Distortion ratio (dB) - SFDR, // Spurious-Free Dynamic Range (dB) - ABN, // Average Bin Noise (dBFS) - NSD, // Noise Spectral Density (dBFS/Hz) - // Carrier and MaxSpur - CarrierIndex, // Order index of Carrier tone - MaxSpurIndex, // Order index of MaxSpur tone - // Analysis Band Info - AB_Width, // Width (Hz) - AB_I1, // Index 1 - AB_I2, // Index 2 - AB_NBins, // Number of bins - AB_RSS, // Root-sum-square - // In-Band Tag Info - Signal_NBins, - Signal_RSS, - CLK_NBins, - CLK_RSS, - HD_NBins, - HD_RSS, - ILOS_NBins, - ILOS_RSS, - ILGT_NBins, - ILGT_RSS, - IMD_NBins, - IMD_RSS, - UserDist_NBins, - UserDist_RSS, - // In-Band Composite Info - THD_NBins, // HD + IMD (total harmonic distortion) - THD_RSS, - ILV_NBins, // ILOS + ILGT (total interleaving) - ILV_RSS, - Dist_NBins, // Distortion - Dist_RSS, - Noise_NBins, // Noise - Noise_RSS, - NAD_NBins, // Noise + Distortion - NAD_RSS, - // - __SIZE__ - }; - - enum class FAToneResult : int { // Fourier Analysis Tone Results - OrderIndex = 0, - Tag, - Freq, - FFinal, - FWAvg, - I1, - I2, - NBins, - InBand, - Mag, - Mag_dBFS, - Mag_dBc, - Phase, - Phase_c, - // - __SIZE__ - }; - - enum class FPFormat { // Floating-point format - Auto, - Eng, - Fix, - Sci - }; - - enum class ObjectType { - FourierAnalysis - }; +namespace genalyzer_impl +{ + +enum class FACompType : int +{ // Fourier Analysis Component Type + DC, // DC component (always Bin 0) + FixedTone, // Tone with fixed, user-defined location + MaxTone, // Next largest tone + WOTone // Worst other tone +}; + +enum class FAResult : int +{ // Fourier Analysis Results + // Meta Data + AnalysisType = 0, // Analysis type + SignalType, // Signal type: 0=Real, 1=Cplx + NFFT, // FFT size + DataSize, // Data size + FBin, // Frequency resolution (Hz) + FData, // Data rate (S/s) + FSample, // Sample rate (S/s) + FShift, // Shift frequency (Hz) + // Primary Measurements + FSNR, // Full-Scale-to-Noise ratio, a.k.a "SNRFS" (dB) + SNR, // Signal-to-Noise ratio (dB) + SINAD, // Signal-to-Noise-and-Distortion ratio (dB) + SFDR, // Spurious-Free Dynamic Range (dB) + ABN, // Average Bin Noise (dBFS) + NSD, // Noise Spectral Density (dBFS/Hz) + // Carrier and MaxSpur + CarrierIndex, // Order index of Carrier tone + MaxSpurIndex, // Order index of MaxSpur tone + // Analysis Band Info + AB_Width, // Width (Hz) + AB_I1, // Index 1 + AB_I2, // Index 2 + AB_NBins, // Number of bins + AB_RSS, // Root-sum-square + // In-Band Tag Info + Signal_NBins, + Signal_RSS, + CLK_NBins, + CLK_RSS, + HD_NBins, + HD_RSS, + ILOS_NBins, + ILOS_RSS, + ILGT_NBins, + ILGT_RSS, + IMD_NBins, + IMD_RSS, + UserDist_NBins, + UserDist_RSS, + // In-Band Composite Info + THD_NBins, // HD + IMD (total harmonic distortion) + THD_RSS, + ILV_NBins, // ILOS + ILGT (total interleaving) + ILV_RSS, + Dist_NBins, // Distortion + Dist_RSS, + Noise_NBins, // Noise + Noise_RSS, + NAD_NBins, // Noise + Distortion + NAD_RSS, + // + __SIZE__ +}; + +enum class FAToneResult : int +{ // Fourier Analysis Tone Results + OrderIndex = 0, + Tag, + Freq, + FFinal, + FWAvg, + I1, + I2, + NBins, + InBand, + Mag, + Mag_dBFS, + Mag_dBc, + Phase, + Phase_c, + // + __SIZE__ +}; + +enum class FPFormat +{ // Floating-point format + Auto, + Eng, + Fix, + Sci +}; + +enum class ObjectType +{ + FourierAnalysis +}; } // namespace genalyzer_impl diff --git a/include/error.h b/include/error.h new file mode 100644 index 0000000..76a3b7a --- /dev/null +++ b/include/error.h @@ -0,0 +1,10 @@ +#ifndef ERROR_H +#define ERROR_H + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY (x) +#define LOCATION __FILE__ ":" TOSTRING (__LINE__) + +void error (const char *location, const char *msg); + +#endif // ERROR_H \ No newline at end of file diff --git a/include/exceptions.hpp b/include/exceptions.hpp index 9eb2006..f443d35 100644 --- a/include/exceptions.hpp +++ b/include/exceptions.hpp @@ -1,19 +1,23 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_EXCEPTIONS_HPP #define GENALYZER_IMPL_EXCEPTIONS_HPP #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - class logic_error final : public std::logic_error - { - using std::logic_error::logic_error; - }; +class logic_error final : public std::logic_error +{ + using std::logic_error::logic_error; +}; - class runtime_error final : public std::runtime_error - { - using std::runtime_error::runtime_error; - }; +class runtime_error final : public std::runtime_error +{ + using std::runtime_error::runtime_error; +}; } // namespace genalyzer_impl diff --git a/include/expression.hpp b/include/expression.hpp index 1f95228..38f4806 100644 --- a/include/expression.hpp +++ b/include/expression.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_EXPRESSION_HPP #define GENALYZER_IMPL_EXPRESSION_HPP @@ -8,47 +11,45 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - struct expression_token; +struct expression_token; - class expression - { - public: +class expression +{ +public: + using token_ptr = std::unique_ptr; + using token_vector = std::vector; + using var_map = std::map; + using var_set = std::set; - using token_ptr = std::unique_ptr; - using token_vector = std::vector; - using var_map = std::map; - using var_set = std::set; +public: + expression (const str_t &infix_string); - public: + ~expression (); - expression(const str_t& infix_string); +public: + // Returns true if expression depends on one or more variables in vars + bool depends_on (const var_set &vars) const; - ~expression(); - - public: + real_t evaluate (const var_map &vars = var_map ()) const; - // Returns true if expression depends on one or more variables in vars - bool depends_on(const var_set& vars) const; + str_t to_postfix_string (FPFormat fmt = FPFormat::Auto, + int max_prec = -1) const; - real_t evaluate(const var_map& vars = var_map()) const; + str_t to_string (FPFormat fmt = FPFormat::Auto, int max_prec = -1) const; - str_t to_postfix_string(FPFormat fmt = FPFormat::Auto, int max_prec = -1) const; - - str_t to_string(FPFormat fmt = FPFormat::Auto, int max_prec = -1) const; + // Returns the variables expression depends on + var_set vars () const; - // Returns the variables expression depends on - var_set vars() const; + // Returns the first expression variable not found in vars + str_t vars_defined (const var_map &vars) const; - // Returns the first expression variable not found in vars - str_t vars_defined(const var_map& vars) const; - - private: +private: + token_vector m_infix_tokens; - token_vector m_infix_tokens; - - }; // class expression +}; // class expression } // namespace genalyzer_impl diff --git a/include/formatted_data.hpp b/include/formatted_data.hpp index 1032b27..63a4b9f 100644 --- a/include/formatted_data.hpp +++ b/include/formatted_data.hpp @@ -1,17 +1,17 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FORMATTED_DATA_HPP #define GENALYZER_IMPL_FORMATTED_DATA_HPP #include "type_aliases.hpp" -namespace genalyzer_impl { +namespace genalyzer_impl +{ - str_t table( - const std::vector& header_rows, - const std::vector& data_rows, - int col_margin, - bool show_border, - bool show_col_sep - ); +str_t table (const std::vector &header_rows, + const std::vector &data_rows, int col_margin, + bool show_border, bool show_col_sep); } // namespace genalyzer_impl diff --git a/include/fourier_analysis.hpp b/include/fourier_analysis.hpp index 0e8d0ae..6addeed 100644 --- a/include/fourier_analysis.hpp +++ b/include/fourier_analysis.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FOURIER_ANALYSIS_HPP #define GENALYZER_IMPL_FOURIER_ANALYSIS_HPP @@ -14,217 +17,256 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ + +class fourier_analysis final : public object +{ +public: + using mask_map = std::map; + using min_max_def_t = std::tuple; + using var_map = expression::var_map; + +public: + static std::shared_ptr + create () + { + return std::make_shared (); + } + + static std::shared_ptr load (const str_t &filename); + + static const min_max_def_t mmd_hd; + static const min_max_def_t mmd_imd; + static const min_max_def_t mmd_wo; + static const min_max_def_t mmd_ssb; + +public: // Constructors, Destructor, and Assignment + fourier_analysis (); + + fourier_analysis (const fourier_analysis &); + + fourier_analysis (fourier_analysis &&); + + ~fourier_analysis () = default; + + fourier_analysis &operator= (const fourier_analysis &); + + fourier_analysis &operator= (fourier_analysis &&); + +public: // Analysis + fourier_analysis_results analyze (const real_t *in_data, + const size_t in_size, const size_t nfft, + FreqAxisType axis_type) const; + +public: // Component Definition + void add_fixed_tone (const str_t &key, FACompTag tag, const str_t &freq, + int ssb); + + void add_max_tone (const str_t &key, FACompTag tag, const str_t ¢er, + const str_t &width, int ssb); + + void remove_comp (const str_t &key); + +public: // Configuration Getters + str_t + ab_center () const + { + return m_ab_center; + }; + str_t + ab_width () const + { + return m_ab_width; + }; + std::set + clk () const + { + return m_clk; + }; + str_t + fdata () const + { + return m_fdata; + }; + str_t + fsample () const + { + return m_fdata; + }; + str_t + fshift () const + { + return m_fdata; + }; + int + hd () const + { + return m_hd; + }; + std::set + ilv () const + { + return m_ilv; + }; + int + imd () const + { + return m_imd; + }; + int + wo () const + { + return m_wo; + }; - class fourier_analysis final : public object - { - public: + int ssb (FASsb group) const; + +public: // Configuration Setters + void set_analysis_band (const str_t ¢er, const str_t &width); + + void set_clk (const std::set &clk); + + void set_fdata (const str_t &expr); + + void set_fsample (const str_t &expr); - using mask_map = std::map; - using min_max_def_t = std::tuple; - using var_map = expression::var_map; + void set_fshift (const str_t &expr); - public: + void set_hd (int n); - static std::shared_ptr create() - { - return std::make_shared(); - } + void set_ilv (const std::set &ilv); - static std::shared_ptr load(const str_t& filename); + void set_imd (int n); - static const min_max_def_t mmd_hd; - static const min_max_def_t mmd_imd; - static const min_max_def_t mmd_wo; - static const min_max_def_t mmd_ssb; + void set_ssb (FASsb group, int ssb); - public: // Constructors, Destructor, and Assignment + void set_var (const str_t &key, real_t x); + + void set_wo (int n); + +public: // Key Queries + static bool is_reserved (const str_t &key); + + static bool is_valid (const str_t &key); + + bool + is_available (const str_t &key) const + { + return !is_reserved (key) && !is_comp (key) && !is_var (key) + && is_valid (key); + } + + bool + is_comp (const str_t &key) const + { + return !(m_user_comps.find (key) == m_user_comps.end ()); + } + + bool + is_var (const str_t &key) const + { + return !(m_user_vars.find (key) == m_user_vars.end ()); + } + +public: // Other Member Functions + static str_t flat_tone_key (const str_t &key, int result_index); + + static std::pair split_key (const str_t &key); + + str_t preview (bool cplx) const; + + void reset (); + + std::vector result_key_lengths (size_t in_size, size_t nfft) const; + + size_t results_size (size_t in_size, size_t nfft) const; + +private: + static const str_t key_pattern; + static const str_t wo_pattern; + static const std::set reserved_keys; + static const str_vector reserved_patterns; + static const str_t flat_key_coupler; + +private: // Virtual Function Overrides + bool equals_impl (const object &that) const override; + + ObjectType + object_type_impl () const override + { + return ObjectType::FourierAnalysis; + } - fourier_analysis(); + void save_impl (const str_t &filename) const override; - fourier_analysis(const fourier_analysis&); + str_t to_string_impl () const override; - fourier_analysis(fourier_analysis&&); +private: + using comp_ptr = std::unique_ptr; + using comp_map = std::map; + using comp_data_t = std::tuple >; - ~fourier_analysis() = default; + static void add_comp (str_vector &keys, comp_map &comps, const str_t &k, + comp_ptr c); - fourier_analysis& operator=(const fourier_analysis&); + static int limit_ssb (int ssb, int lower_limit); - fourier_analysis& operator=(fourier_analysis&&); + comp_data_t generate_comps (bool cplx) const; - public: // Analysis + void if_key_not_available_throw (const str_t &key) const; - fourier_analysis_results analyze(const real_t* in_data, const size_t in_size, - const size_t nfft, FreqAxisType axis_type) const; +private: // Analysis and related subroutines + static mask_map initialize_masks (bool cplx, size_t size); - public: // Component Definition + fourier_analysis_results analyze_impl ( + const real_t *msq_data, // mean-square FFT magnitude data + const size_t msq_size, // size of ms_data + const size_t nfft, // FFT size + FreqAxisType axis_type, // + const cplx_t *fft_data + = nullptr, // complex FFT data; if provided, results include phase + const size_t fft_size = 0 // size of fft_data; if fft_data is not Null, + ) const; // fft_size should equal msq_size - void add_fixed_tone(const str_t& key, FACompTag tag, const str_t& freq, int ssb); + void finalize_masks (mask_map &masks) const; - void add_max_tone(const str_t& key, FACompTag tag, const str_t& center, const str_t& width, int ssb); + var_map initialize_vars (size_t nfft) const; - void remove_comp(const str_t& key); + void setup_analysis_band (bool cplx, fourier_analysis_comp_mask &mask, + var_map &vars) const; - public: // Configuration Getters +public: // Public configuration parameters + bool clk_as_noise; // Treat CLK components as noise + bool dc_as_dist; // Treat DC component as distortion + bool en_conv_offset; // Enable converter offset component + bool en_fund_images; // Enable fundamental image component(s) + bool en_quad_errors; // Enable quadrature error tone components + bool ilv_as_noise; // Treat ILV components as noise + +private: // Private configuration parameters + int m_hd; // Order of harmonic distortion + int m_imd; // Order of intermodulation distortion + int m_wo; // Number of worst others + int m_ssb_def; // Default SSB (for auto-generated tone components) + int m_ssb_dc; // SSB for DC + int m_ssb_sig; // SSB for Signals + int m_ssb_wo; // SSB for WO + str_t m_ab_center; // Analysis band center + str_t m_ab_width; // Analysis band width + str_t m_fdata; // Data rate + str_t m_fsample; // Sample rate + str_t m_fshift; // Shift frequency (sum of frequency translations after + // sampling) + std::set m_clk; // Clock sub-harmonic divisors + std::set m_ilv; // Interleaving factors - str_t ab_center() const { return m_ab_center; }; - str_t ab_width() const { return m_ab_width; }; - std::set clk() const { return m_clk; }; - str_t fdata() const { return m_fdata; }; - str_t fsample() const { return m_fdata; }; - str_t fshift() const { return m_fdata; }; - int hd() const { return m_hd; }; - std::set ilv() const { return m_ilv; }; - int imd() const { return m_imd; }; - int wo() const { return m_wo; }; + // User-defined components and variables + str_vector m_user_keys; + comp_map m_user_comps; + var_map m_user_vars; - int ssb(FASsb group) const; - - public: // Configuration Setters - - void set_analysis_band(const str_t& center, const str_t& width); - - void set_clk(const std::set& clk); - - void set_fdata(const str_t& expr); - - void set_fsample(const str_t& expr); - - void set_fshift(const str_t& expr); - - void set_hd(int n); - - void set_ilv(const std::set& ilv); - - void set_imd(int n); - - void set_ssb(FASsb group, int ssb); - - void set_var(const str_t& key, real_t x); - - void set_wo(int n); - - public: // Key Queries - - static bool is_reserved(const str_t& key); - - static bool is_valid(const str_t& key); - - bool is_available(const str_t& key) const - { - return !is_reserved(key) && !is_comp(key) && !is_var(key) && is_valid(key); - } - - bool is_comp(const str_t& key) const - { - return !(m_user_comps.find(key) == m_user_comps.end()); - } - - bool is_var(const str_t& key) const - { - return !(m_user_vars.find(key) == m_user_vars.end()); - } - - public: // Other Member Functions - - static str_t flat_tone_key(const str_t& key, int result_index); - - static std::pair split_key(const str_t& key); - - str_t preview(bool cplx) const; - - void reset(); - - std::vector result_key_lengths(size_t in_size, size_t nfft) const; - - size_t results_size(size_t in_size, size_t nfft) const; - - private: - - static const str_t key_pattern; - static const str_t wo_pattern; - static const std::set reserved_keys; - static const str_vector reserved_patterns; - static const str_t flat_key_coupler; - - private: // Virtual Function Overrides - - bool equals_impl(const object& that) const override; - - ObjectType object_type_impl() const override - { - return ObjectType::FourierAnalysis; - } - - void save_impl(const str_t& filename) const override; - - str_t to_string_impl() const override; - - private: - - using comp_ptr = std::unique_ptr; - using comp_map = std::map; - using comp_data_t = std::tuple>; - - static void add_comp(str_vector& keys, comp_map& comps, const str_t& k, comp_ptr c); - - static int limit_ssb(int ssb, int lower_limit); - - comp_data_t generate_comps(bool cplx) const; - - void if_key_not_available_throw(const str_t& key) const; - - private: // Analysis and related subroutines - - static mask_map initialize_masks(bool cplx, size_t size); - - fourier_analysis_results analyze_impl( - const real_t* msq_data, // mean-square FFT magnitude data - const size_t msq_size, // size of ms_data - const size_t nfft, // FFT size - FreqAxisType axis_type, // - const cplx_t* fft_data = nullptr, // complex FFT data; if provided, results include phase - const size_t fft_size = 0 // size of fft_data; if fft_data is not Null, - ) const; // fft_size should equal msq_size - - void finalize_masks(mask_map& masks) const; - - var_map initialize_vars(size_t nfft) const; - - void setup_analysis_band(bool cplx, fourier_analysis_comp_mask& mask, var_map& vars) const; - - public: // Public configuration parameters - - bool clk_as_noise; // Treat CLK components as noise - bool dc_as_dist; // Treat DC component as distortion - bool en_conv_offset; // Enable converter offset component - bool en_fund_images; // Enable fundamental image component(s) - bool en_quad_errors; // Enable quadrature error tone components - bool ilv_as_noise; // Treat ILV components as noise - - private: // Private configuration parameters - - int m_hd; // Order of harmonic distortion - int m_imd; // Order of intermodulation distortion - int m_wo; // Number of worst others - int m_ssb_def; // Default SSB (for auto-generated tone components) - int m_ssb_dc; // SSB for DC - int m_ssb_sig; // SSB for Signals - int m_ssb_wo; // SSB for WO - str_t m_ab_center; // Analysis band center - str_t m_ab_width; // Analysis band width - str_t m_fdata; // Data rate - str_t m_fsample; // Sample rate - str_t m_fshift; // Shift frequency (sum of frequency translations after sampling) - std::set m_clk; // Clock sub-harmonic divisors - std::set m_ilv; // Interleaving factors - - // User-defined components and variables - str_vector m_user_keys; - comp_map m_user_comps; - var_map m_user_vars; - - }; // class fourier_analysis +}; // class fourier_analysis } // namespace genalyzer_impl diff --git a/include/fourier_analysis_comp_mask.hpp b/include/fourier_analysis_comp_mask.hpp index cd6cd39..dd857ca 100644 --- a/include/fourier_analysis_comp_mask.hpp +++ b/include/fourier_analysis_comp_mask.hpp @@ -1,194 +1,205 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FOURIER_ANALYSIS_COMP_MASK_HPP #define GENALYZER_IMPL_FOURIER_ANALYSIS_COMP_MASK_HPP -#include #include "type_aliases.hpp" +#include -namespace genalyzer_impl { - - // Ranges are set as [first, last], i.e., inclusive-inclusive, - // but are stored [first, last+1) like STL, i.e., inclusive-exclusive - class fourier_analysis_comp_mask - { - public: - - enum BoundaryMode { Stop, Wrap }; - - public: - - fourier_analysis_comp_mask(bool cplx, size_t array_size) - : m_mode {cplx ? Wrap : Stop}, - m_ufirst {0}, - m_ulast {array_size - 1}, - m_usize {array_size}, - m_first {0}, - m_last {static_cast(array_size - 1)}, - m_size {static_cast(array_size)}, - m_data {} - {} - - fourier_analysis_comp_mask(bool cplx, size_t array_size, const std::vector& init); - - fourier_analysis_comp_mask(const fourier_analysis_comp_mask& m) - : m_mode {m.m_mode}, - m_ufirst {m.m_ufirst}, - m_ulast {m.m_ulast}, - m_usize {m.m_usize}, - m_first {m.m_first}, - m_last {m.m_last}, - m_size {m.m_size}, - m_data (m.m_data) - {} - - fourier_analysis_comp_mask(fourier_analysis_comp_mask&& m) - : m_mode {m.m_mode}, - m_ufirst {m.m_ufirst}, - m_ulast {m.m_ulast}, - m_usize {m.m_usize}, - m_first {m.m_first}, - m_last {m.m_last}, - m_size {m.m_size}, - m_data (std::move(m.m_data)) - {} - - ~fourier_analysis_comp_mask() = default; - - public: - - fourier_analysis_comp_mask& operator=(const fourier_analysis_comp_mask& m) - { - if (&m != this) { - fourier_analysis_comp_mask the_copy (m); - std::swap(the_copy, *this); - } - return *this; - } - - fourier_analysis_comp_mask& operator=(fourier_analysis_comp_mask&& m) - { - std::swap(this->m_mode , m.m_mode); - std::swap(this->m_ufirst , m.m_ufirst); - std::swap(this->m_ulast , m.m_ulast); - std::swap(this->m_usize , m.m_usize); - std::swap(this->m_first , m.m_first); - std::swap(this->m_last , m.m_last); - std::swap(this->m_size , m.m_size); - std::swap(this->m_data , m.m_data); - return *this; - } - - fourier_analysis_comp_mask& operator&=(fourier_analysis_comp_mask m); - - fourier_analysis_comp_mask& operator|=(const fourier_analysis_comp_mask& m); - - public: - - void clear() - { - m_data.clear(); - } - - // Returns the number of elements in the ranges - size_t count() const; - - real_t count_r() const - { - return static_cast(count()); - } - - const std::vector& data() const - { - return m_data; - } - - bool equals(const fourier_analysis_comp_mask& that) const - { - return (this->m_usize == that.m_usize) && (this->m_data == that.m_data); - } - - // <0> = index of max element (-1 if not found) - // <1> = last contiguous free index to the left - // <2> = last contiguous free index to the right - std::tuple find_max_index(const real_t* data, size_t size) const; - - // Returns Index1, Index2, Number of Bins - std::tuple get_indexes() const; - - void invert(); - - BoundaryMode mode() const - { - return m_mode; - } - - size_t num_ranges() const - { - return m_data.size() / 2; - } - - // Returns true if [left, right] overlaps any ranges - bool overlaps(size_t left, size_t right) const; // inclusive-inclusive - - void set(std::vector init) - { - fourier_analysis_comp_mask new_mask ((Wrap == this->m_mode), this->m_usize, init); - std::swap(new_mask, *this); - } - - void set_all() - { - m_data = {0, m_usize}; - } - - void set_range(diff_t left, diff_t right); // inclusive-inclusive - - size_t size() const - { - return m_usize; - } - - real_t root_sum(const real_t* data, size_t size) const - { - return std::sqrt(sum(data, size)); - } - - // Returns the sum of the data in the ranges - real_t sum(const real_t* data, size_t size) const; - - void unset_ranges(const fourier_analysis_comp_mask& m); - - private: - - // Returns the index of the first element greater than 'value' - size_t get_index(size_t value) const; - - void if_not_compat_then_throw(const fourier_analysis_comp_mask& m); - - // Document the pre-conditions that make this 'safe' - void set_range_safe(size_t left, size_t right); // inclusive-inclusive - - private: - - BoundaryMode m_mode; - size_t m_ufirst; - size_t m_ulast; - size_t m_usize; - diff_t m_first; - diff_t m_last; - diff_t m_size; - std::vector m_data; - - }; // class fourier_analysis_comp_mask - - inline bool operator==(const fourier_analysis_comp_mask& a, const fourier_analysis_comp_mask& b) - { - return a.equals(b); - } - - inline bool operator!=(const fourier_analysis_comp_mask& a, const fourier_analysis_comp_mask& b) - { - return !a.equals(b); - } +namespace genalyzer_impl +{ + +// Ranges are set as [first, last], i.e., inclusive-inclusive, +// but are stored [first, last+1) like STL, i.e., inclusive-exclusive +class fourier_analysis_comp_mask +{ +public: + enum BoundaryMode + { + Stop, + Wrap + }; + +public: + fourier_analysis_comp_mask (bool cplx, size_t array_size) + : m_mode{ cplx ? Wrap : Stop }, m_ufirst{ 0 }, m_ulast{ array_size - 1 }, + m_usize{ array_size }, m_first{ 0 }, + m_last{ static_cast (array_size - 1) }, + m_size{ static_cast (array_size) }, m_data{} + { + } + + fourier_analysis_comp_mask (bool cplx, size_t array_size, + const std::vector &init); + + fourier_analysis_comp_mask (const fourier_analysis_comp_mask &m) + : m_mode{ m.m_mode }, m_ufirst{ m.m_ufirst }, m_ulast{ m.m_ulast }, + m_usize{ m.m_usize }, m_first{ m.m_first }, m_last{ m.m_last }, + m_size{ m.m_size }, m_data (m.m_data) + { + } + + fourier_analysis_comp_mask (fourier_analysis_comp_mask &&m) + : m_mode{ m.m_mode }, m_ufirst{ m.m_ufirst }, m_ulast{ m.m_ulast }, + m_usize{ m.m_usize }, m_first{ m.m_first }, m_last{ m.m_last }, + m_size{ m.m_size }, m_data (std::move (m.m_data)) + { + } + + ~fourier_analysis_comp_mask () = default; + +public: + fourier_analysis_comp_mask & + operator= (const fourier_analysis_comp_mask &m) + { + if (&m != this) + { + fourier_analysis_comp_mask the_copy (m); + std::swap (the_copy, *this); + } + return *this; + } + + fourier_analysis_comp_mask & + operator= (fourier_analysis_comp_mask &&m) + { + std::swap (this->m_mode, m.m_mode); + std::swap (this->m_ufirst, m.m_ufirst); + std::swap (this->m_ulast, m.m_ulast); + std::swap (this->m_usize, m.m_usize); + std::swap (this->m_first, m.m_first); + std::swap (this->m_last, m.m_last); + std::swap (this->m_size, m.m_size); + std::swap (this->m_data, m.m_data); + return *this; + } + + fourier_analysis_comp_mask &operator&= (fourier_analysis_comp_mask m); + + fourier_analysis_comp_mask &operator|= (const fourier_analysis_comp_mask &m); + +public: + void + clear () + { + m_data.clear (); + } + + // Returns the number of elements in the ranges + size_t count () const; + + real_t + count_r () const + { + return static_cast (count ()); + } + + const std::vector & + data () const + { + return m_data; + } + + bool + equals (const fourier_analysis_comp_mask &that) const + { + return (this->m_usize == that.m_usize) && (this->m_data == that.m_data); + } + + // <0> = index of max element (-1 if not found) + // <1> = last contiguous free index to the left + // <2> = last contiguous free index to the right + std::tuple find_max_index (const real_t *data, + size_t size) const; + + // Returns Index1, Index2, Number of Bins + std::tuple get_indexes () const; + + void invert (); + + BoundaryMode + mode () const + { + return m_mode; + } + + size_t + num_ranges () const + { + return m_data.size () / 2; + } + + // Returns true if [left, right] overlaps any ranges + bool overlaps (size_t left, size_t right) const; // inclusive-inclusive + + void + set (std::vector init) + { + fourier_analysis_comp_mask new_mask ((Wrap == this->m_mode), this->m_usize, + init); + std::swap (new_mask, *this); + } + + void + set_all () + { + m_data = { 0, m_usize }; + } + + void set_range (diff_t left, diff_t right); // inclusive-inclusive + + size_t + size () const + { + return m_usize; + } + + real_t + root_sum (const real_t *data, size_t size) const + { + return std::sqrt (sum (data, size)); + } + + // Returns the sum of the data in the ranges + real_t sum (const real_t *data, size_t size) const; + + void unset_ranges (const fourier_analysis_comp_mask &m); + +private: + // Returns the index of the first element greater than 'value' + size_t get_index (size_t value) const; + + void if_not_compat_then_throw (const fourier_analysis_comp_mask &m); + + // Document the pre-conditions that make this 'safe' + void set_range_safe (size_t left, size_t right); // inclusive-inclusive + +private: + BoundaryMode m_mode; + size_t m_ufirst; + size_t m_ulast; + size_t m_usize; + diff_t m_first; + diff_t m_last; + diff_t m_size; + std::vector m_data; + +}; // class fourier_analysis_comp_mask + +inline bool +operator== (const fourier_analysis_comp_mask &a, + const fourier_analysis_comp_mask &b) +{ + return a.equals (b); +} + +inline bool +operator!= (const fourier_analysis_comp_mask &a, + const fourier_analysis_comp_mask &b) +{ + return !a.equals (b); +} } // namespace genalyzer_impl diff --git a/include/fourier_analysis_component.hpp b/include/fourier_analysis_component.hpp index db4f56c..dfc0632 100644 --- a/include/fourier_analysis_component.hpp +++ b/include/fourier_analysis_component.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FOURIER_ANALYSIS_COMPONENT_HPP #define GENALYZER_IMPL_FOURIER_ANALYSIS_COMPONENT_HPP @@ -6,216 +9,236 @@ #include -namespace genalyzer_impl { - - struct fourier_analysis_component - { - using pointer = std::unique_ptr; - - fourier_analysis_component(FACompType _type, FACompTag _tag) - : type (_type), - tag (_tag) - {} - - virtual ~fourier_analysis_component() = default; - - pointer clone() const - { - return clone_impl(); - } - - bool equals(const fourier_analysis_component& that) const - { - return this->equals_impl(that); - } - - str_t spec() const - { - return spec_impl(); - } - - const FACompType type; - const FACompTag tag; - - private: - - virtual pointer clone_impl() const = 0; - - virtual bool equals_impl(const fourier_analysis_component& that) const = 0; - - virtual str_t spec_impl() const = 0; - - }; // class fourier_analysis_component - - struct fa_dc final : public fourier_analysis_component - { - static pointer create(int ssb) - { - return std::make_unique(ssb); - } - - fa_dc(int _ssb) - : fourier_analysis_component(FACompType::DC, FACompTag::DC), - ssb (_ssb) - {} - - ~fa_dc() = default; - - const int ssb; - - private: - - pointer clone_impl() const override - { - return std::make_unique(*this); - } - - bool equals_impl(const fourier_analysis_component& that_obj) const override - { - bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); - if (!equal) { - return false; - } - auto& that = static_cast(that_obj); - return this->ssb == that.ssb; - } - - str_t spec_impl() const override - { - return "SSB= " + std::to_string(ssb); - } - - }; // class fa_dc - - struct fa_fixed_tone final : public fourier_analysis_component - { - static pointer create(FACompTag tag, const str_t& freq, int ssb) - { - return std::make_unique(tag, freq, ssb); - } - - fa_fixed_tone(FACompTag tag, const str_t& _freq, int _ssb) - : fourier_analysis_component(FACompType::FixedTone, tag), - freq (_freq), - ssb (_ssb) - {} - - ~fa_fixed_tone() = default; - - const str_t freq; - const int ssb; - - private: - - pointer clone_impl() const override - { - return std::make_unique(*this); - } - - bool equals_impl(const fourier_analysis_component& that_obj) const override - { - bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); - if (!equal) { - return false; - } - auto& that = static_cast(that_obj); - return (this->freq == that.freq) && (this->ssb == that.ssb); - } - - str_t spec_impl() const override - { - return "F= " + freq + " , SSB= " + std::to_string(ssb); - } - - }; // class fa_fixed_tone - - struct fa_max_tone final : public fourier_analysis_component - { - static pointer create(FACompTag tag, const str_t& center, const str_t& width, int ssb) - { - return std::make_unique(tag, center, width, ssb); - } - - fa_max_tone(FACompTag tag, const str_t& _center, const str_t& _width, int _ssb) - : fourier_analysis_component(FACompType::MaxTone, tag), - center (_center), - width (_width), - ssb (_ssb) - {} - - ~fa_max_tone() = default; - - const str_t center; - const str_t width; - const int ssb; - - private: - - pointer clone_impl() const override - { - return std::make_unique(*this); - } - - bool equals_impl(const fourier_analysis_component& that_obj) const override - { - bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); - if (!equal) { - return false; - } - auto& that = static_cast(that_obj); - return (this->center == that.center) && - (this->width == that.width ) && - (this->ssb == that.ssb ); - } - - str_t spec_impl() const override - { - // May implement search band in the future. - // return "C= " + center + " , W= " + width + " , SSB= " + std::to_string(ssb); - return "SSB= " + std::to_string(ssb); - } - - }; // class fa_max_tone - - struct fa_wo_tone final : public fourier_analysis_component - { - static pointer create(int ssb) - { - return std::make_unique(ssb); - } - - fa_wo_tone(int _ssb) - : fourier_analysis_component(FACompType::WOTone, FACompTag::Noise), - ssb (_ssb) - {} - - ~fa_wo_tone() = default; - - const int ssb; - - private: - - pointer clone_impl() const override - { - return std::make_unique(*this); - } - - bool equals_impl(const fourier_analysis_component& that_obj) const override - { - bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); - if (!equal) { - return false; - } - auto& that = static_cast(that_obj); - return this->ssb == that.ssb; - } - - str_t spec_impl() const override - { - return "SSB= " + std::to_string(ssb); - } - - }; // class fa_wo_tone +namespace genalyzer_impl +{ + +struct fourier_analysis_component +{ + using pointer = std::unique_ptr; + + fourier_analysis_component (FACompType _type, FACompTag _tag) + : type (_type), tag (_tag) + { + } + + virtual ~fourier_analysis_component () = default; + + pointer + clone () const + { + return clone_impl (); + } + + bool + equals (const fourier_analysis_component &that) const + { + return this->equals_impl (that); + } + + str_t + spec () const + { + return spec_impl (); + } + + const FACompType type; + const FACompTag tag; + +private: + virtual pointer clone_impl () const = 0; + + virtual bool equals_impl (const fourier_analysis_component &that) const = 0; + + virtual str_t spec_impl () const = 0; + +}; // class fourier_analysis_component + +struct fa_dc final : public fourier_analysis_component +{ + static pointer + create (int ssb) + { + return std::make_unique (ssb); + } + + fa_dc (int _ssb) + : fourier_analysis_component (FACompType::DC, FACompTag::DC), ssb (_ssb) + { + } + + ~fa_dc () = default; + + const int ssb; + +private: + pointer + clone_impl () const override + { + return std::make_unique (*this); + } + + bool + equals_impl (const fourier_analysis_component &that_obj) const override + { + bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); + if (!equal) + { + return false; + } + auto &that = static_cast (that_obj); + return this->ssb == that.ssb; + } + + str_t + spec_impl () const override + { + return "SSB= " + std::to_string (ssb); + } + +}; // class fa_dc + +struct fa_fixed_tone final : public fourier_analysis_component +{ + static pointer + create (FACompTag tag, const str_t &freq, int ssb) + { + return std::make_unique (tag, freq, ssb); + } + + fa_fixed_tone (FACompTag tag, const str_t &_freq, int _ssb) + : fourier_analysis_component (FACompType::FixedTone, tag), freq (_freq), + ssb (_ssb) + { + } + + ~fa_fixed_tone () = default; + + const str_t freq; + const int ssb; + +private: + pointer + clone_impl () const override + { + return std::make_unique (*this); + } + + bool + equals_impl (const fourier_analysis_component &that_obj) const override + { + bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); + if (!equal) + { + return false; + } + auto &that = static_cast (that_obj); + return (this->freq == that.freq) && (this->ssb == that.ssb); + } + + str_t + spec_impl () const override + { + return "F= " + freq + " , SSB= " + std::to_string (ssb); + } + +}; // class fa_fixed_tone + +struct fa_max_tone final : public fourier_analysis_component +{ + static pointer + create (FACompTag tag, const str_t ¢er, const str_t &width, int ssb) + { + return std::make_unique (tag, center, width, ssb); + } + + fa_max_tone (FACompTag tag, const str_t &_center, const str_t &_width, + int _ssb) + : fourier_analysis_component (FACompType::MaxTone, tag), + center (_center), width (_width), ssb (_ssb) + { + } + + ~fa_max_tone () = default; + + const str_t center; + const str_t width; + const int ssb; + +private: + pointer + clone_impl () const override + { + return std::make_unique (*this); + } + + bool + equals_impl (const fourier_analysis_component &that_obj) const override + { + bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); + if (!equal) + { + return false; + } + auto &that = static_cast (that_obj); + return (this->center == that.center) && (this->width == that.width) + && (this->ssb == that.ssb); + } + + str_t + spec_impl () const override + { + // May implement search band in the future. + // return "C= " + center + " , W= " + width + " , SSB= " + + // std::to_string(ssb); + return "SSB= " + std::to_string (ssb); + } + +}; // class fa_max_tone + +struct fa_wo_tone final : public fourier_analysis_component +{ + static pointer + create (int ssb) + { + return std::make_unique (ssb); + } + + fa_wo_tone (int _ssb) + : fourier_analysis_component (FACompType::WOTone, FACompTag::Noise), + ssb (_ssb) + { + } + + ~fa_wo_tone () = default; + + const int ssb; + +private: + pointer + clone_impl () const override + { + return std::make_unique (*this); + } + + bool + equals_impl (const fourier_analysis_component &that_obj) const override + { + bool equal = (this->type == that_obj.type) && (this->tag == that_obj.tag); + if (!equal) + { + return false; + } + auto &that = static_cast (that_obj); + return this->ssb == that.ssb; + } + + str_t + spec_impl () const override + { + return "SSB= " + std::to_string (ssb); + } + +}; // class fa_wo_tone } // namespace genalyzer_impl diff --git a/include/fourier_analysis_results.hpp b/include/fourier_analysis_results.hpp index adf48b6..00ac8d9 100644 --- a/include/fourier_analysis_results.hpp +++ b/include/fourier_analysis_results.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FOURIER_ANALYSIS_RESULTS_HPP #define GENALYZER_IMPL_FOURIER_ANALYSIS_RESULTS_HPP @@ -7,86 +10,109 @@ #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - struct fa_tone_results - { - real_t get(FAToneResult key) const - { - if (results.find(key) == results.end()) { - throw runtime_error("fa_tone_results::get : key not found"); - } - return results.at(key); - } +struct fa_tone_results +{ + real_t + get (FAToneResult key) const + { + if (results.find (key) == results.end ()) + { + throw runtime_error ("fa_tone_results::get : key not found"); + } + return results.at (key); + } - void set(FAToneResult key, real_t value) - { - results[key] = value; - if (FAToneResult::I1 == key) { - i1 = static_cast(value); - } else if (FAToneResult::I2 == key) { - i2 = static_cast(value); - } else if (FAToneResult::NBins == key) { - nbins = static_cast(value); - } else if (FAToneResult::InBand == key) { - inband = static_cast(value); - } - } + void + set (FAToneResult key, real_t value) + { + results[key] = value; + if (FAToneResult::I1 == key) + { + i1 = static_cast (value); + } + else if (FAToneResult::I2 == key) + { + i2 = static_cast (value); + } + else if (FAToneResult::NBins == key) + { + nbins = static_cast (value); + } + else if (FAToneResult::InBand == key) + { + inband = static_cast (value); + } + } - void set_mag(real_t ms_value) - { - results[FAToneResult::Mag] = std::sqrt(ms_value); - results[FAToneResult::Mag_dBFS] = bounded_db10(ms_value); - } + void + set_mag (real_t ms_value) + { + results[FAToneResult::Mag] = std::sqrt (ms_value); + results[FAToneResult::Mag_dBFS] = bounded_db10 (ms_value); + } - std::map results; - size_t i1; - size_t i2; - size_t nbins; - bool inband; - }; + std::map results; + size_t i1; + size_t i2; + size_t nbins; + bool inband; +}; - struct fourier_analysis_results - { - real_t get(FAResult key) const - { - if (results.find(key) == results.end()) { - throw runtime_error("fourier_analysis_results::get : key not found"); - } - return results.at(key); - } +struct fourier_analysis_results +{ + real_t + get (FAResult key) const + { + if (results.find (key) == results.end ()) + { + throw runtime_error ("fourier_analysis_results::get : key not found"); + } + return results.at (key); + } - void set(FAResult key, real_t value) - { - results[key] = value; - } + void + set (FAResult key, real_t value) + { + results[key] = value; + } - bool contains_tone(const str_t& key) const - { - return tone_results.find(key) != tone_results.end(); - } + bool + contains_tone (const str_t &key) const + { + return tone_results.find (key) != tone_results.end (); + } - void add_tone(const str_t& key, fa_tone_results tr) - { - if (!contains_tone(key)) { - tone_keys.push_back(key); - tone_results.emplace(key, std::move(tr)); - } - } + void + add_tone (const str_t &key, fa_tone_results tr) + { + if (!contains_tone (key)) + { + tone_keys.push_back (key); + tone_results.emplace (key, std::move (tr)); + } + } - const fa_tone_results& get_tone(const str_t& key) const - { - if (contains_tone(key)) { - return tone_results.at(key); - } else { - throw runtime_error("fourier_analysis_results::get_tone : key not found"); - } - } + const fa_tone_results & + get_tone (const str_t &key) const + { + if (contains_tone (key)) + { + return tone_results.at (key); + } + else + { + throw runtime_error ( + "fourier_analysis_results::get_tone : key not found"); + } + } - std::map results; - str_vector tone_keys; - std::map tone_results; - }; + std::map results; + str_vector tone_keys; + std::map tone_results; +}; } // namespace genalyzer_impl diff --git a/include/fourier_transforms.hpp b/include/fourier_transforms.hpp index 951a50e..ff7b9a9 100644 --- a/include/fourier_transforms.hpp +++ b/include/fourier_transforms.hpp @@ -1,66 +1,36 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FOURIER_TRANSFORMS_HPP #define GENALYZER_IMPL_FOURIER_TRANSFORMS_HPP #include "enums.hpp" #include "type_aliases.hpp" -namespace genalyzer_impl { +namespace genalyzer_impl +{ - void fft( - const real_t* i_data, - size_t i_size, - const real_t* q_data, - size_t q_size, - real_t* out_data, - size_t out_size, - size_t navg, - size_t nfft, - Window window - ); +void fft (const real_t *i_data, size_t i_size, const real_t *q_data, + size_t q_size, real_t *out_data, size_t out_size, size_t navg, + size_t nfft, Window window); - template - void fft( - const T* i_data, - size_t i_size, - const T* q_data, - size_t q_size, - real_t* out_data, - size_t out_size, - int n, - size_t navg, - size_t nfft, - Window window, - CodeFormat format - ); +template +void fft (const T *i_data, size_t i_size, const T *q_data, size_t q_size, + real_t *out_data, size_t out_size, int n, size_t navg, size_t nfft, + Window window, CodeFormat format); - size_t fft_size(size_t i_size, size_t q_size, size_t& navg, size_t& nfft); +size_t fft_size (size_t i_size, size_t q_size, size_t &navg, size_t &nfft); - void rfft( - const real_t* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - size_t navg, - size_t nfft, - Window window, - RfftScale scale - ); +void rfft (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size, size_t navg, size_t nfft, Window window, + RfftScale scale); - template - void rfft( - const T* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - int n, - size_t navg, - size_t nfft, - Window window, - CodeFormat format, - RfftScale scale - ); +template +void rfft (const T *in_data, size_t in_size, real_t *out_data, size_t out_size, + int n, size_t navg, size_t nfft, Window window, CodeFormat format, + RfftScale scale); - size_t rfft_size(size_t in_size, size_t& navg, size_t& nfft); +size_t rfft_size (size_t in_size, size_t &navg, size_t &nfft); } // namespace genalyzer_impl diff --git a/include/fourier_utilities.hpp b/include/fourier_utilities.hpp index 8498a94..9b4e3a5 100644 --- a/include/fourier_utilities.hpp +++ b/include/fourier_utilities.hpp @@ -1,29 +1,29 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_FOURIER_UTILITIES_HPP #define GENALYZER_IMPL_FOURIER_UTILITIES_HPP #include "enums.hpp" #include "type_aliases.hpp" -namespace genalyzer_impl { +namespace genalyzer_impl +{ - real_t alias(real_t fs, real_t freq, FreqAxisType axis_type); +real_t alias (real_t fs, real_t freq, FreqAxisType axis_type); - real_t coherent(size_t nfft, real_t fs, real_t freq); +real_t coherent (size_t nfft, real_t fs, real_t freq); - void fftshift(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void fftshift (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - void freq_axis( - real_t* data, - size_t size, - size_t nfft, - FreqAxisType axis_type, - real_t fs, - FreqAxisFormat axis_format - ); +void freq_axis (real_t *data, size_t size, size_t nfft, FreqAxisType axis_type, + real_t fs, FreqAxisFormat axis_format); - void ifftshift(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size); +void ifftshift (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size); - size_t freq_axis_size(size_t nfft, FreqAxisType axis_type); +size_t freq_axis_size (size_t nfft, FreqAxisType axis_type); } // namespace genalyzer_impl diff --git a/include/json.hpp b/include/json.hpp index d2b7438..5c949e1 100644 --- a/include/json.hpp +++ b/include/json.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ diff --git a/include/manager.hpp b/include/manager.hpp index f1d8883..d316101 100644 --- a/include/manager.hpp +++ b/include/manager.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_MANAGER_HPP #define GENALYZER_IMPL_MANAGER_HPP @@ -8,40 +11,42 @@ /* * Part of the API */ -namespace genalyzer_impl::manager { +namespace genalyzer_impl::manager +{ - void clear(); +void clear (); - bool contains(const str_t& key, bool throw_if_not_found = false); +bool contains (const str_t &key, bool throw_if_not_found = false); - bool equal(const str_t& key1, const str_t& key2); +bool equal (const str_t &key1, const str_t &key2); - void remove(const str_t& key); +void remove (const str_t &key); - str_t save(const str_t& key, const str_t& filename = ""); +str_t save (const str_t &key, const str_t &filename = ""); - size_t size(); +size_t size (); - str_t to_string(const str_t& key = ""); +str_t to_string (const str_t &key = ""); - str_t type_str(const str_t& key); +str_t type_str (const str_t &key); } // namespace genalyzer_impl::manager /* * Internal use only */ -namespace genalyzer_impl::manager { +namespace genalyzer_impl::manager +{ - static const str_t key_pattern = "[[:alpha:]][[:alnum:]._]*"; +static const str_t key_pattern = "[[:alpha:]][[:alnum:]._]*"; - void add_object(const str_t& key, object::pointer obj, bool replace); +void add_object (const str_t &key, object::pointer obj, bool replace); - str_t get_filename_from_object_key(const str_t& key, str_t filename); +str_t get_filename_from_object_key (const str_t &key, str_t filename); - object::pointer get_object(const str_t& key); +object::pointer get_object (const str_t &key); - ObjectType type(const str_t& key); +ObjectType type (const str_t &key); } // namespace genalyzer_impl::manager diff --git a/include/object.hpp b/include/object.hpp index 4489d18..9829df8 100644 --- a/include/object.hpp +++ b/include/object.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_OBJECT_HPP #define GENALYZER_IMPL_OBJECT_HPP @@ -6,51 +9,52 @@ #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - class object - { - public: +class object +{ +public: + using pointer = std::shared_ptr; - using pointer = std::shared_ptr; +public: + virtual ~object () = default; - public: +public: + bool + equals (const object &that) const + { + return this->equals_impl (that); + } - virtual ~object() = default; + ObjectType + object_type () const + { + return object_type_impl (); + } - public: + void + save (const str_t &filename) const + { + save_impl (filename); + } - bool equals(const object& that) const - { - return this->equals_impl(that); - } + str_t + to_string () const + { + return to_string_impl (); + } - ObjectType object_type() const - { - return object_type_impl(); - } +private: + virtual bool equals_impl (const object &that) const = 0; - void save(const str_t& filename) const - { - save_impl(filename); - } + virtual ObjectType object_type_impl () const = 0; - str_t to_string() const - { - return to_string_impl(); - } + virtual void save_impl (const str_t &filename) const = 0; - private: + virtual str_t to_string_impl () const = 0; - virtual bool equals_impl(const object& that) const = 0; - - virtual ObjectType object_type_impl() const = 0; - - virtual void save_impl(const str_t& filename) const = 0; - - virtual str_t to_string_impl() const = 0; - - }; // class object +}; // class object } // namespace genalyzer_impl diff --git a/include/processes.hpp b/include/processes.hpp index 2703c64..a0777ae 100644 --- a/include/processes.hpp +++ b/include/processes.hpp @@ -1,80 +1,43 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_PROCESSES_HPP #define GENALYZER_IMPL_PROCESSES_HPP #include "enums.hpp" #include "type_aliases.hpp" -namespace genalyzer_impl { - - template - void downsample( - const T* in_data, - size_t in_size, - T* out_data, - size_t out_size, - int ratio, - bool interleaved - ); +namespace genalyzer_impl +{ - size_t downsample_size(size_t in_size, int ratio, bool interleaved); +template +void downsample (const T *in_data, size_t in_size, T *out_data, + size_t out_size, int ratio, bool interleaved); - void fshift( - const real_t* i_data, - size_t i_size, - const real_t* q_data, - size_t q_size, - real_t* out_data, - size_t out_size, - real_t fs, - real_t _fshift - ); - - template - void fshift( - const T* i_data, - size_t i_size, - const T* q_data, - size_t q_size, - T* out_data, - size_t out_size, - int n, - real_t fs, - real_t _fshift, - CodeFormat format - ); - - size_t fshift_size(size_t i_size, size_t q_size); - - template - void normalize( - const T* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - int n, - CodeFormat format - ); - - void polyval( - const real_t* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - const real_t* c_data, - size_t c_size - ); - - template - void quantize( - const real_t* in_data, - size_t in_size, - T* out_data, - size_t out_size, - real_t fsr, - int n, - real_t noise, - CodeFormat format - ); +size_t downsample_size (size_t in_size, int ratio, bool interleaved); + +void fshift (const real_t *i_data, size_t i_size, const real_t *q_data, + size_t q_size, real_t *out_data, size_t out_size, real_t fs, + real_t _fshift); + +template +void fshift (const T *i_data, size_t i_size, const T *q_data, size_t q_size, + T *out_data, size_t out_size, int n, real_t fs, real_t _fshift, + CodeFormat format); + +size_t fshift_size (size_t i_size, size_t q_size); + +template +void normalize (const T *in_data, size_t in_size, real_t *out_data, + size_t out_size, int n, CodeFormat format); + +void polyval (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size, const real_t *c_data, size_t c_size); + +template +void quantize (const real_t *in_data, size_t in_size, T *out_data, + size_t out_size, real_t fsr, int n, real_t noise, + CodeFormat format); } // namespace genalyzer_impl diff --git a/include/reductions.hpp b/include/reductions.hpp index f6af07b..4f52d91 100644 --- a/include/reductions.hpp +++ b/include/reductions.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_REDUCTIONS_HPP #define GENALYZER_IMPL_REDUCTIONS_HPP @@ -5,56 +8,58 @@ #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - struct std_reduce_t - { - std_reduce_t(size_t size) - : min {0.0}, - max {0.0}, - sum {0.0}, - sumsq {0.0}, - min_index {size}, - max_index {size} - {} - real_t min; - real_t max; - real_t sum; - real_t sumsq; - size_t min_index; - size_t max_index; - }; +struct std_reduce_t +{ + std_reduce_t (size_t size) + : min{ 0.0 }, max{ 0.0 }, sum{ 0.0 }, sumsq{ 0.0 }, min_index{ size }, + max_index{ size } + { + } + real_t min; + real_t max; + real_t sum; + real_t sumsq; + size_t min_index; + size_t max_index; +}; - template - std_reduce_t std_reduce( - const T* data, // pointer to array - const size_t size, // array size - const size_t i1, // index of first element - const size_t i2 // one past the last element - ) +template +std_reduce_t +std_reduce (const T *data, // pointer to array + const size_t size, // array size + const size_t i1, // index of first element + const size_t i2 // one past the last element +) +{ + std_reduce_t r (size); + if (i1 < i2 && i2 <= size) { - std_reduce_t r (size); - if (i1 < i2 && i2 <= size) { - r.min = static_cast(data[i1]); - r.max = static_cast(data[i1]); - r.min_index = i1; - r.max_index = i1; - for (size_t i = i1 + 1; i < i2; ++i) { - const real_t x = static_cast(data[i]); - if (x < r.min) { - r.min = x; - r.min_index = i; - } - if (r.max < x) { - r.max = x; - r.max_index = i; - } - r.sum += x; - r.sumsq += x * x; + r.min = static_cast (data[i1]); + r.max = static_cast (data[i1]); + r.min_index = i1; + r.max_index = i1; + for (size_t i = i1 + 1; i < i2; ++i) + { + const real_t x = static_cast (data[i]); + if (x < r.min) + { + r.min = x; + r.min_index = i; + } + if (r.max < x) + { + r.max = x; + r.max_index = i; } + r.sum += x; + r.sumsq += x * x; } - return r; } + return r; +} } // namespace genalyzer_impl diff --git a/include/type_aliases.hpp b/include/type_aliases.hpp index fd0de4d..4ef9c41 100644 --- a/include/type_aliases.hpp +++ b/include/type_aliases.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_TYPE_ALIASES_HPP #define GENALYZER_IMPL_TYPE_ALIASES_HPP @@ -8,27 +11,28 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - using diff_t = std::ptrdiff_t; - using size_t = std::size_t; - using int16_t = std::int_least16_t; - using int32_t = std::int_least32_t; - using int64_t = std::int_least64_t; - using uint16_t = std::uint_least16_t; - using uint32_t = std::uint_least32_t; - using uint64_t = std::uint_least64_t; - using real_t = double; - using cplx_t = std::complex; - using str_t = std::string; +using diff_t = std::ptrdiff_t; +using size_t = std::size_t; +using int16_t = std::int_least16_t; +using int32_t = std::int_least32_t; +using int64_t = std::int_least64_t; +using uint16_t = std::uint_least16_t; +using uint32_t = std::uint_least32_t; +using uint64_t = std::uint_least64_t; +using real_t = double; +using cplx_t = std::complex; +using str_t = std::string; - // pairs - using diff_p = std::pair; - using size_p = std::pair; - using real_p = std::pair; +// pairs +using diff_p = std::pair; +using size_p = std::pair; +using real_p = std::pair; - // vectors - using str_vector = std::vector; +// vectors +using str_vector = std::vector; } // namespace genalyzer_impl diff --git a/include/utils.hpp b/include/utils.hpp index 4e0a6d9..b2cb201 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_UTILS_HPP #define GENALYZER_IMPL_UTILS_HPP @@ -11,145 +14,168 @@ #include #include -namespace genalyzer_impl { - - inline real_t bounded_db10(real_t msq_value) - { - return 10 * std::log10(std::clamp(msq_value, k_abs_min_msq, k_abs_max_msq)); - } - - inline real_t bounded_db20(real_t rms_value) - { - return 20 * std::log10(std::clamp(rms_value, k_abs_min_rms, k_abs_max_rms)); - } - - inline real_t bounded_db(const cplx_t& cplx_value) - { - return bounded_db10(std::norm(cplx_value)); - } - - template - bool is_even(T n) - { - return 0 == n % 2; - } - - template - bool is_odd(T n) +namespace genalyzer_impl +{ + +inline real_t +bounded_db10 (real_t msq_value) +{ + return 10 + * std::log10 (std::clamp (msq_value, k_abs_min_msq, k_abs_max_msq)); +} + +inline real_t +bounded_db20 (real_t rms_value) +{ + return 20 + * std::log10 (std::clamp (rms_value, k_abs_min_rms, k_abs_max_rms)); +} + +inline real_t +bounded_db (const cplx_t &cplx_value) +{ + return bounded_db10 (std::norm (cplx_value)); +} + +template +bool +is_even (T n) +{ + return 0 == n % 2; +} + +template +bool +is_odd (T n) +{ + return 1 == n % 2; +} + +template +bool +is_pow2 (T n) +{ + return (n < 1) ? false : (0 == (n & (n - 1))); +} + +template +int +to_int (E e) +{ + static_assert (std::is_enum_v, "Requires enum type"); + return static_cast (e); +} + +template +void +assert_eq (const char *trace, const char *name1, T val1, const char *name2, + T val2) +{ + if (val1 != val2) { - return 1 == n % 2; + throw runtime_error (str_t (trace) + name1 + " != " + name2); } +} - template - bool is_pow2(T n) +template +void +assert_gt0 (const char *trace, const char *name, T val) +{ + if (!(static_cast (0) < val)) { - return (n < 1) ? false : (0 == (n & (n - 1))); + throw runtime_error (str_t (trace) + name + " <= 0"); } +} - template - int to_int(E e) +template +void +assert_ptr_not_null (const char *trace, const char *name, const T *p) +{ + if (nullptr == p) { - static_assert(std::is_enum_v, "Requires enum type"); - return static_cast(e); + throw runtime_error (str_t (trace) + "pointer to " + name + " is NULL"); } - - template - void assert_eq(const char* trace, const char* name1, T val1, const char* name2, T val2) +} + +template +void +check_array (const char *trace, const char *name, const T *p, size_t size, + bool interleaved = false) +{ + assert_ptr_not_null (trace, name, p); + str_t n = str_t (name) + " size"; + assert_gt0 (trace, n.c_str (), size); + if (interleaved && is_odd (size)) { - if (val1 != val2) { - throw runtime_error(str_t(trace) + name1 + " != " + name2); - } + throw runtime_error (str_t (trace) + " must be even if interleaved"); } - - template - void assert_gt0(const char* trace, const char* name, T val) +} + +template +void +check_array_pair (const char *trace, const char *name1, const T1 *p1, + size_t size1, const char *name2, const T2 *p2, size_t size2, + bool interleaved = false) +{ + check_array (trace, name1, p1, size1); + check_array (trace, name2, p2, size2); + str_t n1 = str_t (name1) + " size"; + str_t n2 = str_t (name2) + " size"; + assert_eq (trace, n1.c_str (), size1, n2.c_str (), size2); + if (interleaved && is_odd (size1)) { - if (!(static_cast(0) < val)) { - throw runtime_error(str_t(trace) + name + " <= 0"); - } + throw runtime_error (str_t (trace) + " must be even if interleaved"); } +} - template - void assert_ptr_not_null(const char* trace, const char* name, const T* p) +inline void +check_code_width (const char *trace, int n) +{ + if (n < k_abs_min_code_width || k_abs_max_code_width < n) { - if (nullptr == p) { - throw runtime_error(str_t(trace) + "pointer to " + name + " is NULL"); - } + throw runtime_error ( + str_t (trace) + "resolution outside absolute code width limits : [" + + std::to_string (k_abs_min_code_width) + ", " + + std::to_string (k_abs_max_code_width) + "]"); } - - template - void check_array( - const char* trace, const char* name, const T* p, size_t size, bool interleaved = false) +} + +template +T +check_type_absolute_value (const char *trace, int64_t n) +{ + static_assert (sizeof (T) <= sizeof (int64_t), "T is bigger than int64_t"); + static_assert (std::is_signed_v, "T must be signed"); + constexpr int64_t min + = static_cast (std::numeric_limits::min ()); + constexpr int64_t max + = static_cast (std::numeric_limits::max ()); + if (n < min || max < n) { - assert_ptr_not_null(trace, name, p); - str_t n = str_t(name) + " size"; - assert_gt0(trace, n.c_str(), size); - if (interleaved && is_odd(size)) { - throw runtime_error(str_t(trace) + " must be even if interleaved"); - } + throw runtime_error (str_t (trace) + "value exceeds type limits"); } - - template - void check_array_pair( - const char* trace, - const char* name1, - const T1* p1, - size_t size1, - const char* name2, - const T2* p2, - size_t size2, - bool interleaved = false - ) - { - check_array(trace, name1, p1, size1); - check_array(trace, name2, p2, size2); - str_t n1 = str_t(name1) + " size"; - str_t n2 = str_t(name2) + " size"; - assert_eq(trace, n1.c_str(), size1, n2.c_str(), size2); - if (interleaved && is_odd(size1)) { - throw runtime_error(str_t(trace) + " must be even if interleaved"); - } - } - - inline void check_code_width(const char* trace, int n) - { - if (n < k_abs_min_code_width || k_abs_max_code_width < n) { - throw runtime_error(str_t(trace) + "resolution outside absolute code width limits : [" - + std::to_string(k_abs_min_code_width) + ", " - + std::to_string(k_abs_max_code_width) + "]"); - } - } - - template - T check_type_absolute_value(const char* trace, int64_t n) - { - static_assert(sizeof(T) <= sizeof(int64_t), "T is bigger than int64_t"); - static_assert(std::is_signed_v, "T must be signed"); - constexpr int64_t min = static_cast(std::numeric_limits::min()); - constexpr int64_t max = static_cast(std::numeric_limits::max()); - if (n < min || max < n) { - throw runtime_error(str_t(trace) + "value exceeds type limits"); - } - return static_cast(n); - } - - template - std::pair resolution_to_minmax(int n, CodeFormat format) + return static_cast (n); +} + +template +std::pair +resolution_to_minmax (int n, CodeFormat format) +{ + const char *trace = "resolution_to_minmax : "; + check_code_width (trace, n); // for example, let n = 8 + int64_t min64 = -(static_cast (1) << (n - 1)); // min = -128 + int64_t max64 = -1 - min64; // max = +127 + if (CodeFormat::OffsetBinary == format) { - const char* trace = "resolution_to_minmax : "; - check_code_width(trace, n); // for example, let n = 8 - int64_t min64 = -(static_cast(1) << (n - 1)); // min = -128 - int64_t max64 = -1 - min64; // max = +127 - if (CodeFormat::OffsetBinary == format) { - max64 -= min64; // max = 255 - min64 = 0; // min = 0 - } - T min = check_type_absolute_value(trace, min64); - T max = check_type_absolute_value(trace, max64); - return std::make_pair(min, max); + max64 -= min64; // max = 255 + min64 = 0; // min = 0 } + T min = check_type_absolute_value (trace, min64); + T max = check_type_absolute_value (trace, max64); + return std::make_pair (min, max); +} - str_t to_string(real_t n, FPFormat fmt = FPFormat::Auto, int max_prec = -1); +str_t to_string (real_t n, FPFormat fmt = FPFormat::Auto, int max_prec = -1); } // namespace genalyzer_impl diff --git a/include/version.h b/include/version.h index 435b215..b0360ad 100644 --- a/include/version.h +++ b/include/version.h @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #define GENALYZER_VERSION_MAJOR 1 #define GENALYZER_VERSION_MINOR 0 #define GENALYZER_VERSION_PATCH 0 \ No newline at end of file diff --git a/include/version.hpp b/include/version.hpp index 1f2611c..8e453cd 100644 --- a/include/version.hpp +++ b/include/version.hpp @@ -1,12 +1,16 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_VERSION_HPP #define GENALYZER_IMPL_VERSION_HPP #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ + +std::string_view version_string (); - std::string_view version_string(); - } // namespace genalyzer_impl #endif // GENALYZER_IMPL_VERSION_HPP \ No newline at end of file diff --git a/include/waveforms.hpp b/include/waveforms.hpp index 7e0787e..432013e 100644 --- a/include/waveforms.hpp +++ b/include/waveforms.hpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #ifndef GENALYZER_IMPL_WAVEFORMS_HPP #define GENALYZER_IMPL_WAVEFORMS_HPP @@ -5,38 +8,23 @@ #include -namespace genalyzer_impl { - - void cos( - real_t* data, - size_t size, - real_t fs, - real_t ampl, - real_t freq, - real_t phase, - real_t td, - real_t tj - ); - - void gaussian(real_t* data, size_t size, real_t mean, real_t sd); - - void ramp(real_t* data, size_t size, real_t start, real_t stop, real_t noise); - - void sin( - real_t* data, - size_t size, - real_t fs, - real_t ampl, - real_t freq, - real_t phase, - real_t td, - real_t tj - ); - - template - std::map wf_analysis(const T* wf_data, size_t wf_size); - - const std::vector& wf_analysis_ordered_keys(); +namespace genalyzer_impl +{ + +void cos (real_t *data, size_t size, real_t fs, real_t ampl, real_t freq, + real_t phase, real_t td, real_t tj); + +void gaussian (real_t *data, size_t size, real_t mean, real_t sd); + +void ramp (real_t *data, size_t size, real_t start, real_t stop, real_t noise); + +void sin (real_t *data, size_t size, real_t fs, real_t ampl, real_t freq, + real_t phase, real_t td, real_t tj); + +template +std::map wf_analysis (const T *wf_data, size_t wf_size); + +const std::vector &wf_analysis_ordered_keys (); } // namespace genalyzer_impl diff --git a/requirements_test.txt b/requirements_test.txt index dc7f412..f8046a5 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -7,4 +7,7 @@ numpy setuptools matplotlib tabulate -brokenaxes \ No newline at end of file +brokenaxes +pre-commit +cmakelint +clang-format \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7cdd5bc..8d05aab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ file(GLOB HEADER_LIST CONFIGURE_DEPENDS - "${PROJECT_SOURCE_DIR}/include/*.hpp") + "${PROJECT_SOURCE_DIR}/include/*.hpp") add_definitions(-DEXPORT_API) @@ -33,14 +33,14 @@ set_target_properties(genalyzer_plus_plus PROPERTIES VERSION ${CMAKE_PROJECT_VERSION} SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR} FRAMEWORK TRUE - PUBLIC_HEADER "${HEADER_LIST}" - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED ON - CXX_EXTENSIONS OFF + PUBLIC_HEADER "${HEADER_LIST}" + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF ) set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" - CACHE PATH "Installation directory for libraries") + CACHE PATH "Installation directory for libraries") if(APPLE) find_package(PkgConfig) @@ -53,10 +53,10 @@ if(APPLE OR WIN32) endif() install(TARGETS genalyzer_plus_plus - ARCHIVE DESTINATION lib - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" - RUNTIME DESTINATION bin - FRAMEWORK DESTINATION lib - PUBLIC_HEADER DESTINATION include) + ARCHIVE DESTINATION lib + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" + RUNTIME DESTINATION bin + FRAMEWORK DESTINATION lib + PUBLIC_HEADER DESTINATION include) include(GNUInstallDirs) diff --git a/src/array_ops.cpp b/src/array_ops.cpp index 68c7891..18522bb 100644 --- a/src/array_ops.cpp +++ b/src/array_ops.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "array_ops.hpp" #include "utils.hpp" @@ -5,67 +8,71 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - namespace { +namespace +{ - void c2r( - const real_t* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - real_t(*func)(const cplx_t&) - ) - { - assert_eq("", "input array size", in_size, "2 * output array size", 2 * out_size); - const cplx_t* cin_data = reinterpret_cast(in_data); - size_t cin_size = in_size / 2; - check_array_pair("", "input array", cin_data, cin_size, "output array", out_data, out_size); - std::transform(cin_data, cin_data + cin_size, out_data, func); - } +void +c2r (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size, + real_t (*func) (const cplx_t &)) +{ + assert_eq ("", "input array size", in_size, "2 * output array size", + 2 * out_size); + const cplx_t *cin_data = reinterpret_cast (in_data); + size_t cin_size = in_size / 2; + check_array_pair ("", "input array", cin_data, cin_size, "output array", + out_data, out_size); + std::transform (cin_data, cin_data + cin_size, out_data, func); +} - void r2r( - const real_t* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - real_t(*func)(real_t) - ) - { - check_array_pair("", "input array", in_data, in_size, "output array", out_data, out_size); - std::transform(in_data, in_data + in_size, out_data, func); - } +void +r2r (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size, + real_t (*func) (real_t)) +{ + check_array_pair ("", "input array", in_data, in_size, "output array", + out_data, out_size); + std::transform (in_data, in_data + in_size, out_data, func); +} - } // namespace anonymous +} // namespace anonymous - void abs(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) - { - c2r(in_data, in_size, out_data, out_size, std::abs); - } +void +abs (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size) +{ + c2r (in_data, in_size, out_data, out_size, std::abs); +} - void angle(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) - { - c2r(in_data, in_size, out_data, out_size, std::arg); - } +void +angle (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size) +{ + c2r (in_data, in_size, out_data, out_size, std::arg); +} - void db(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) - { - c2r(in_data, in_size, out_data, out_size, bounded_db); - } +void +db (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size) +{ + c2r (in_data, in_size, out_data, out_size, bounded_db); +} - void db10(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) - { - r2r(in_data, in_size, out_data, out_size, bounded_db10); - } +void +db10 (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size) +{ + r2r (in_data, in_size, out_data, out_size, bounded_db10); +} - void db20(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) - { - r2r(in_data, in_size, out_data, out_size, bounded_db20); - } +void +db20 (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size) +{ + r2r (in_data, in_size, out_data, out_size, bounded_db20); +} - void norm(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) - { - c2r(in_data, in_size, out_data, out_size, std::norm); - } +void +norm (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size) +{ + c2r (in_data, in_size, out_data, out_size, std::norm); +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/code_density.cpp b/src/code_density.cpp index 144e146..3b0e5f9 100644 --- a/src/code_density.cpp +++ b/src/code_density.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "code_density.hpp" #include "constants.hpp" @@ -10,435 +13,504 @@ #include #include -namespace genalyzer_impl { - - namespace { +namespace genalyzer_impl +{ - // Returns first and last non-zero indices - size_p first_and_last_nz(const uint64_t* data, size_t size) - { - size_t first = 0; - while (0 == data[first]) { - ++first; - if (first == size) { - return size_p(size, size); // no nz bins - } - } - size_t last = size - 1; - while (0 == data[last] && first < last) { - --last; - } - return size_p(first, last); - } +namespace +{ - void dnl_ramp(const uint64_t* hist_data, real_t* dnl_data, size_t size) +// Returns first and last non-zero indices +size_p +first_and_last_nz (const uint64_t *data, size_t size) +{ + size_t first = 0; + while (0 == data[first]) + { + ++first; + if (first == size) { - const size_p nz = first_and_last_nz(hist_data, size); - real_t sum = 0.0; - for (size_t i = nz.first + 1; i < nz.second; ++i) { // exclude first and last NZ bins - sum += static_cast(hist_data[i]); - } - if (0.0 == sum) { - std::fill(dnl_data, dnl_data + size, -1.0); - return; - } - const real_t avg_count = sum / (static_cast(nz.second - nz.first) - 1.0); - std::fill(dnl_data, dnl_data + nz.first + 1, -1.0); - for (size_t i = nz.first + 1; i < nz.second; ++i) { - dnl_data[i] = hist_data[i] / avg_count - 1.0; - } - std::fill(dnl_data + nz.second, dnl_data + size, -1.0); + return size_p (size, size); // no nz bins } + } + size_t last = size - 1; + while (0 == data[last] && first < last) + { + --last; + } + return size_p (first, last); +} - void dnl_tone(const uint64_t* hist_data, real_t* dnl_data, size_t size) - { - // 0. Check for minimum data - const size_p nz = first_and_last_nz(hist_data, size); - if (!(nz.first + 1 < nz.second)) { - std::fill(dnl_data, dnl_data + size, -1.0); - return; - } - // dnl_data stores the result of each of the following steps. - // 1a. Cumulative histogram - dnl_data[0] = static_cast(hist_data[0]); - for (size_t i = 1; i < size; ++i) { - dnl_data[i] = dnl_data[i - 1] + static_cast(hist_data[i]); - } - const real_t total_count = dnl_data[size - 1]; - // 1b. Find histogram peaks - size_t median_index = 0; - const real_t median_count = total_count * 0.5; - while (dnl_data[median_index] < median_count) { - ++median_index; - } - // find left peak in [nz.first, median_index] - size_t left_peak_index = nz.first; - uint64_t peak = hist_data[left_peak_index]; - for (size_t i = nz.first + 1; i <= median_index; ++i) { - if (peak < hist_data[i]) { // Note the less-than: if multiple bins contain the - peak = hist_data[i]; // peak count, get the leftmost - left_peak_index = i; - } - } - // find right peak in [median_index, nz.second] - size_t right_peak_index = median_index; - peak = hist_data[right_peak_index]; - for (size_t i = median_index; i <= nz.second; ++i) { - if (peak <= hist_data[i]) { // Note the less-than-or-equal: if multiple bins - peak = hist_data[i]; // contain the same peak count, get the rightmost - right_peak_index = i; - } - } - // Ensure plausible results: - if (!(left_peak_index < median_index && median_index < right_peak_index)) { - std::fill(dnl_data, dnl_data + size, -1.0); - throw runtime_error("dnl : unable to locate histogram peaks"); - } - // 2. Code transition points - const real_t k1 = k_pi / total_count; - for (size_t i = 0; i < size; ++i) { - dnl_data[i] = -std::cos(k1 * dnl_data[i]); - } - // 3. Code widths - size_t left_dnl_index = left_peak_index; - if (nz.first == left_dnl_index) { // exclude first NZ bin - left_dnl_index += 1; // certain: 0 < left_dnl_index <= median_index - } - size_t right_dnl_index = right_peak_index; - if (nz.second == right_dnl_index) { // exclude last NZ bin - right_dnl_index -= 1; // certain: median_index <= right_peak_index < size - 1 - } - real_t code_width_sum = 0.0; - // width of code n is the difference between transition points of n and n-1 - for (size_t i = right_dnl_index; left_dnl_index <= i; --i) { - dnl_data[i] -= dnl_data[i - 1]; - code_width_sum += dnl_data[i]; - } - size_t num_dnl_codes = (right_dnl_index - left_dnl_index) + 1; - const real_t avg_code_width = code_width_sum / static_cast(num_dnl_codes); - if (avg_code_width <= 0.0) { // not sure how this can happen, but just in case... - throw runtime_error("dnl : avg_code_width <= 0.0"); - } - std::fill(dnl_data, dnl_data + left_dnl_index, 0.0); - std::fill(dnl_data + right_dnl_index + 1, dnl_data + size, 0.0); - // 4. DNL - const real_t k2 = 1 / avg_code_width; - for (size_t i = 0; i < size; ++i) { - dnl_data[i] = std::fma(k2, dnl_data[i], -1.0); - } - } - - } // namespace anonymous - - size_t code_density_size(int n, CodeFormat format) +void +dnl_ramp (const uint64_t *hist_data, real_t *dnl_data, size_t size) +{ + const size_p nz = first_and_last_nz (hist_data, size); + real_t sum = 0.0; + for (size_t i = nz.first + 1; i < nz.second; ++i) + { // exclude first and last NZ bins + sum += static_cast (hist_data[i]); + } + if (0.0 == sum) + { + std::fill (dnl_data, dnl_data + size, -1.0); + return; + } + const real_t avg_count + = sum / (static_cast (nz.second - nz.first) - 1.0); + std::fill (dnl_data, dnl_data + nz.first + 1, -1.0); + for (size_t i = nz.first + 1; i < nz.second; ++i) { - std::pair mm = resolution_to_minmax(n, format); - return code_densityx_size(mm.first, mm.second); + dnl_data[i] = hist_data[i] / avg_count - 1.0; } + std::fill (dnl_data + nz.second, dnl_data + size, -1.0); +} - size_t code_densityx_size(int64_t min, int64_t max) +void +dnl_tone (const uint64_t *hist_data, real_t *dnl_data, size_t size) +{ + // 0. Check for minimum data + const size_p nz = first_and_last_nz (hist_data, size); + if (!(nz.first + 1 < nz.second)) { - str_t trace = "code_densityx_size : "; - if (max < min) { - throw runtime_error(trace + "max < min"); - } - const int64_t abs_max_range = static_cast(1) << k_abs_max_code_width; - const int64_t abs_min = -(abs_max_range >> 1); - const int64_t abs_max = abs_max_range - 1; - if (min < abs_min) { - throw runtime_error(trace + "min < absolute min"); - } - if (abs_max < max) { - throw runtime_error(trace + "absolute max < max"); + std::fill (dnl_data, dnl_data + size, -1.0); + return; + } + // dnl_data stores the result of each of the following steps. + // 1a. Cumulative histogram + dnl_data[0] = static_cast (hist_data[0]); + for (size_t i = 1; i < size; ++i) + { + dnl_data[i] = dnl_data[i - 1] + static_cast (hist_data[i]); + } + const real_t total_count = dnl_data[size - 1]; + // 1b. Find histogram peaks + size_t median_index = 0; + const real_t median_count = total_count * 0.5; + while (dnl_data[median_index] < median_count) + { + ++median_index; + } + // find left peak in [nz.first, median_index] + size_t left_peak_index = nz.first; + uint64_t peak = hist_data[left_peak_index]; + for (size_t i = nz.first + 1; i <= median_index; ++i) + { + if (peak < hist_data[i]) + { // Note the less-than: if multiple bins contain the + peak = hist_data[i]; // peak count, get the leftmost + left_peak_index = i; } - // now it is safe to calculate range - const int64_t range = (max - min) + 1; - if (abs_max_range < range) { - throw runtime_error(trace + "range exceeds absolute max"); + } + // find right peak in [median_index, nz.second] + size_t right_peak_index = median_index; + peak = hist_data[right_peak_index]; + for (size_t i = median_index; i <= nz.second; ++i) + { + if (peak <= hist_data[i]) + { // Note the less-than-or-equal: if multiple bins + peak + = hist_data[i]; // contain the same peak count, get the rightmost + right_peak_index = i; } - return static_cast(range); } + // Ensure plausible results: + if (!(left_peak_index < median_index && median_index < right_peak_index)) + { + std::fill (dnl_data, dnl_data + size, -1.0); + throw runtime_error ("dnl : unable to locate histogram peaks"); + } + // 2. Code transition points + const real_t k1 = k_pi / total_count; + for (size_t i = 0; i < size; ++i) + { + dnl_data[i] = -std::cos (k1 * dnl_data[i]); + } + // 3. Code widths + size_t left_dnl_index = left_peak_index; + if (nz.first == left_dnl_index) + { // exclude first NZ bin + left_dnl_index += 1; // certain: 0 < left_dnl_index <= median_index + } + size_t right_dnl_index = right_peak_index; + if (nz.second == right_dnl_index) + { // exclude last NZ bin + right_dnl_index + -= 1; // certain: median_index <= right_peak_index < size - 1 + } + real_t code_width_sum = 0.0; + // width of code n is the difference between transition points of n and n-1 + for (size_t i = right_dnl_index; left_dnl_index <= i; --i) + { + dnl_data[i] -= dnl_data[i - 1]; + code_width_sum += dnl_data[i]; + } + size_t num_dnl_codes = (right_dnl_index - left_dnl_index) + 1; + const real_t avg_code_width + = code_width_sum / static_cast (num_dnl_codes); + if (avg_code_width <= 0.0) + { // not sure how this can happen, but just in case... + throw runtime_error ("dnl : avg_code_width <= 0.0"); + } + std::fill (dnl_data, dnl_data + left_dnl_index, 0.0); + std::fill (dnl_data + right_dnl_index + 1, dnl_data + size, 0.0); + // 4. DNL + const real_t k2 = 1 / avg_code_width; + for (size_t i = 0; i < size; ++i) + { + dnl_data[i] = std::fma (k2, dnl_data[i], -1.0); + } +} + +} // namespace anonymous + +size_t +code_density_size (int n, CodeFormat format) +{ + std::pair mm = resolution_to_minmax (n, format); + return code_densityx_size (mm.first, mm.second); +} + +size_t +code_densityx_size (int64_t min, int64_t max) +{ + str_t trace = "code_densityx_size : "; + if (max < min) + { + throw runtime_error (trace + "max < min"); + } + const int64_t abs_max_range = static_cast (1) + << k_abs_max_code_width; + const int64_t abs_min = -(abs_max_range >> 1); + const int64_t abs_max = abs_max_range - 1; + if (min < abs_min) + { + throw runtime_error (trace + "min < absolute min"); + } + if (abs_max < max) + { + throw runtime_error (trace + "absolute max < max"); + } + // now it is safe to calculate range + const int64_t range = (max - min) + 1; + if (abs_max_range < range) + { + throw runtime_error (trace + "range exceeds absolute max"); + } + return static_cast (range); +} - void code_axis(real_t* data, size_t size, int n, CodeFormat format) +void +code_axis (real_t *data, size_t size, int n, CodeFormat format) +{ + std::pair mm = resolution_to_minmax (n, format); + code_axisx (data, size, mm.first, mm.second); +} + +void +code_axisx (real_t *data, size_t size, int64_t min, int64_t max) +{ + const char *trace = "code_axisx : "; + check_array (trace, "array", data, size); + size_t size_expected = code_densityx_size (min, max); + assert_eq (trace, "array size", size, "expected", size_expected); + real_t x = static_cast (min); + for (size_t i = 0; i < size; ++i) { - std::pair mm = resolution_to_minmax(n, format); - code_axisx(data, size, mm.first, mm.second); + data[i] = x; + x += 1.0; } +} - void code_axisx(real_t* data, size_t size, int64_t min, int64_t max) - { - const char* trace = "code_axisx : "; - check_array(trace, "array", data, size); - size_t size_expected = code_densityx_size(min, max); - assert_eq(trace, "array size", size, "expected", size_expected); - real_t x = static_cast(min); - for (size_t i = 0; i < size; ++i) { - data[i] = x; - x += 1.0; - } +void +dnl (real_t *dnl_data, size_t dnl_size, const uint64_t *hist_data, + size_t hist_size, DnlSignal type) +{ + check_array_pair ("dnl : ", "hist array", hist_data, hist_size, "dnl array", + dnl_data, dnl_size); + switch (type) + { + case DnlSignal::Ramp: + dnl_ramp (hist_data, dnl_data, dnl_size); + return; + case DnlSignal::Tone: + dnl_tone (hist_data, dnl_data, dnl_size); + return; + default: + throw runtime_error ("dnl : DNL not implemented for signal type"); } +} - void dnl( - real_t* dnl_data, - size_t dnl_size, - const uint64_t* hist_data, - size_t hist_size, - DnlSignal type - ) - { - check_array_pair("dnl : ", "hist array", hist_data, hist_size, "dnl array", dnl_data, dnl_size); - switch (type) +std::map +dnl_analysis (const real_t *data, size_t size) +{ + check_array ("", "dnl array", data, size); + // First and last non-missing codes + size_t first_nm_index = 0; + while (first_nm_index < size) + { + if (-1.0 < data[first_nm_index++]) { - case DnlSignal::Ramp: - dnl_ramp(hist_data, dnl_data, dnl_size); - return; - case DnlSignal::Tone: - dnl_tone(hist_data, dnl_data, dnl_size); - return; - default: - throw runtime_error("dnl : DNL not implemented for signal type"); + break; } } - - std::map dnl_analysis(const real_t* data, size_t size) - { - check_array("", "dnl array", data, size); - // First and last non-missing codes - size_t first_nm_index = 0; - while (first_nm_index < size) { - if (-1.0 < data[first_nm_index++]) { - break; - } - } - size_t last_nm_index = size - 1; - real_t num_codes = 0.0; - if (first_nm_index < size) { // if there are any non-missing codes - while (first_nm_index < last_nm_index) { - if (-1.0 < data[last_nm_index--]) { - break; - } + size_t last_nm_index = size - 1; + real_t num_codes = 0.0; + if (first_nm_index < size) + { // if there are any non-missing codes + while (first_nm_index < last_nm_index) + { + if (-1.0 < data[last_nm_index--]) + { + break; } - num_codes = 1.0 + static_cast(last_nm_index - first_nm_index); - } else { - last_nm_index = first_nm_index; - } - // Results - std_reduce_t r (size); - real_t avg = 0.0; - real_t rms = 0.0; - if (0.0 < num_codes) { - r = std_reduce(data, size, first_nm_index, last_nm_index + 1); - avg = r.sum / num_codes; - rms = std::sqrt(r.sumsq / num_codes); - } else { - r.min = -1.0; - r.max = -1.0; - avg = -1.0; - rms = 1.0; } - std::vector keys = dnl_analysis_ordered_keys(); - return std::map { - { keys[0] , r.min }, - { keys[1] , r.max }, - { keys[2] , avg }, - { keys[3] , rms }, - { keys[4] , static_cast(r.min_index) }, - { keys[5] , static_cast(r.max_index) }, - { keys[6] , static_cast(first_nm_index) }, - { keys[7] , static_cast(last_nm_index) }, - { keys[8] , num_codes }}; + num_codes = 1.0 + static_cast (last_nm_index - first_nm_index); } - - const std::vector& dnl_analysis_ordered_keys() - { - // first_nm_index, last_nm_index - static const std::vector keys { - "min", // min DNL value - "max", // max DNL value - "avg", // average DNL value - "rms", // RMS DNL value - "min_index", // index of min DNL value - "max_index", // index of max DNL value - "first_nm_index", // index of first non-missing code - "last_nm_index", // index of last non-missing code - "nm_range" // non-missing code range - }; - return keys; + else + { + last_nm_index = first_nm_index; } - - template - void hist( - uint64_t* hist_data, - size_t hist_size, - const T* wf_data, - size_t wf_size, - int n, - CodeFormat format, - bool preserve - ) - { - std::pair mm = resolution_to_minmax(n, format); - histx(hist_data, hist_size, wf_data, wf_size, mm.first, mm.second, preserve); + // Results + std_reduce_t r (size); + real_t avg = 0.0; + real_t rms = 0.0; + if (0.0 < num_codes) + { + r = std_reduce (data, size, first_nm_index, last_nm_index + 1); + avg = r.sum / num_codes; + rms = std::sqrt (r.sumsq / num_codes); + } + else + { + r.min = -1.0; + r.max = -1.0; + avg = -1.0; + rms = 1.0; } + std::vector keys = dnl_analysis_ordered_keys (); + return std::map{ + { keys[0], r.min }, + { keys[1], r.max }, + { keys[2], avg }, + { keys[3], rms }, + { keys[4], static_cast (r.min_index) }, + { keys[5], static_cast (r.max_index) }, + { keys[6], static_cast (first_nm_index) }, + { keys[7], static_cast (last_nm_index) }, + { keys[8], num_codes } + }; +} - template void hist(uint64_t*, size_t, const int16_t*, size_t, int, CodeFormat, bool); - template void hist(uint64_t*, size_t, const int32_t*, size_t, int, CodeFormat, bool); - template void hist(uint64_t*, size_t, const int64_t*, size_t, int, CodeFormat, bool); +const std::vector & +dnl_analysis_ordered_keys () +{ + // first_nm_index, last_nm_index + static const std::vector keys{ + "min", // min DNL value + "max", // max DNL value + "avg", // average DNL value + "rms", // RMS DNL value + "min_index", // index of min DNL value + "max_index", // index of max DNL value + "first_nm_index", // index of first non-missing code + "last_nm_index", // index of last non-missing code + "nm_range" // non-missing code range + }; + return keys; +} - template - void histx( - uint64_t* hist_data, - size_t hist_size, - const T* wf_data, - size_t wf_size, - int64_t min, - int64_t max, - bool preserve - ) - { - check_array("histx : ", "hist array", hist_data, hist_size); - check_array("histx : ", "waveform array", wf_data, wf_size); - size_t size_expected = code_densityx_size(min, max); - assert_eq("histx : ", "hist array size", hist_size, "expected", size_expected); - if (!preserve) { - std::fill(hist_data, hist_data + hist_size, 0); - } - for (size_t i = 0; i < wf_size; ++i) { - if (min <= wf_data[i] && wf_data[i] <= max) { - ++hist_data[wf_data[i] - min]; - } +template +void +hist (uint64_t *hist_data, size_t hist_size, const T *wf_data, size_t wf_size, + int n, CodeFormat format, bool preserve) +{ + std::pair mm = resolution_to_minmax (n, format); + histx (hist_data, hist_size, wf_data, wf_size, mm.first, mm.second, + preserve); +} + +template void hist (uint64_t *, size_t, const int16_t *, size_t, int, + CodeFormat, bool); +template void hist (uint64_t *, size_t, const int32_t *, size_t, int, + CodeFormat, bool); +template void hist (uint64_t *, size_t, const int64_t *, size_t, int, + CodeFormat, bool); + +template +void +histx (uint64_t *hist_data, size_t hist_size, const T *wf_data, size_t wf_size, + int64_t min, int64_t max, bool preserve) +{ + check_array ("histx : ", "hist array", hist_data, hist_size); + check_array ("histx : ", "waveform array", wf_data, wf_size); + size_t size_expected = code_densityx_size (min, max); + assert_eq ("histx : ", "hist array size", hist_size, "expected", + size_expected); + if (!preserve) + { + std::fill (hist_data, hist_data + hist_size, 0); + } + for (size_t i = 0; i < wf_size; ++i) + { + if (min <= wf_data[i] && wf_data[i] <= max) + { + ++hist_data[wf_data[i] - min]; } } +} - template void histx(uint64_t*, size_t, const int16_t*, size_t, int64_t, int64_t, bool); - template void histx(uint64_t*, size_t, const int32_t*, size_t, int64_t, int64_t, bool); - template void histx(uint64_t*, size_t, const int64_t*, size_t, int64_t, int64_t, bool); +template void histx (uint64_t *, size_t, const int16_t *, size_t, int64_t, + int64_t, bool); +template void histx (uint64_t *, size_t, const int32_t *, size_t, int64_t, + int64_t, bool); +template void histx (uint64_t *, size_t, const int64_t *, size_t, int64_t, + int64_t, bool); - std::map hist_analysis(const uint64_t* data, size_t size) - { - check_array("", "hist array", data, size); - // Cummulative Histogram - std::vector chist (size); - chist[0] = static_cast(data[0]); - for (size_t i = 1; i < size; ++i) { - chist[i] = chist[i - 1] + static_cast(data[i]); - } - // First and last non-zero indexes - size_t first_nz_index = 0; - while (first_nz_index < size) { - if (0 < data[first_nz_index++]) { - break; - } +std::map +hist_analysis (const uint64_t *data, size_t size) +{ + check_array ("", "hist array", data, size); + // Cummulative Histogram + std::vector chist (size); + chist[0] = static_cast (data[0]); + for (size_t i = 1; i < size; ++i) + { + chist[i] = chist[i - 1] + static_cast (data[i]); + } + // First and last non-zero indexes + size_t first_nz_index = 0; + while (first_nz_index < size) + { + if (0 < data[first_nz_index++]) + { + break; } - size_t last_nz_index = size - 1; - real_t num_bins = 0.0; - if (first_nz_index < size) { // if there are any non-zero bins - while (first_nz_index < last_nz_index) { - if (0 < data[last_nz_index--]) { - break; - } + } + size_t last_nz_index = size - 1; + real_t num_bins = 0.0; + if (first_nz_index < size) + { // if there are any non-zero bins + while (first_nz_index < last_nz_index) + { + if (0 < data[last_nz_index--]) + { + break; } - num_bins = 1.0 + static_cast(last_nz_index - first_nz_index); - } else { - last_nz_index = first_nz_index; } - // Results - std::vector keys = hist_analysis_ordered_keys(); - return std::map { - { keys[0] , chist.back() }, - { keys[1] , static_cast(first_nz_index) }, - { keys[2] , static_cast(last_nz_index) }, - { keys[3] , num_bins }}; + num_bins = 1.0 + static_cast (last_nz_index - first_nz_index); } - - const std::vector& hist_analysis_ordered_keys() + else { - static const std::vector keys { - "sum", // total histogram hits - "first_nz_index", // index of first non-zero bin - "last_nz_index", // index of last non-zero bin - "nz_range" // non-zero bin range - }; - return keys; + last_nz_index = first_nz_index; } + // Results + std::vector keys = hist_analysis_ordered_keys (); + return std::map{ + { keys[0], chist.back () }, + { keys[1], static_cast (first_nz_index) }, + { keys[2], static_cast (last_nz_index) }, + { keys[3], num_bins } + }; +} - void inl( - real_t* inl_data, - size_t inl_size, - const real_t* dnl_data, - size_t dnl_size, - InlLineFit fit - ) - { - check_array_pair("inl : ", "dnl array", dnl_data, dnl_size, "inl array", inl_data, inl_size); - size_t first = 0; - while (dnl_data[first] <= -1.0) { - inl_data[first++] = 0.0; - if (first == dnl_size) { - return; // all missing codes - } - } - size_t last = dnl_size - 1; - while (dnl_data[last] <= -1.0 && first < last) { - inl_data[last--] = 0.0; - } - std::partial_sum(dnl_data + first, dnl_data + last + 1, inl_data + first); - real_t m = 0.0; - real_t b = 0.0; - switch (fit) +const std::vector & +hist_analysis_ordered_keys () +{ + static const std::vector keys{ + "sum", // total histogram hits + "first_nz_index", // index of first non-zero bin + "last_nz_index", // index of last non-zero bin + "nz_range" // non-zero bin range + }; + return keys; +} + +void +inl (real_t *inl_data, size_t inl_size, const real_t *dnl_data, + size_t dnl_size, InlLineFit fit) +{ + check_array_pair ("inl : ", "dnl array", dnl_data, dnl_size, "inl array", + inl_data, inl_size); + size_t first = 0; + while (dnl_data[first] <= -1.0) + { + inl_data[first++] = 0.0; + if (first == dnl_size) { - case InlLineFit::NoFit: - return; - case InlLineFit::BestFit: { - // https://en.wikipedia.org/wiki/Ordinary_least_squares - real_t n = static_cast(last - first) + 1.0; - real_t sx = 0.0; - real_t sy = 0.0; - real_t sxx = 0.0; - real_t sxy = 0.0; - for (size_t i = first; i <= last; ++i) { - real_t x = static_cast(i); - sx += x; - sy += inl_data[i]; - sxx += x * x; - sxy += x * inl_data[i]; - } - m = (n * sxy - sx * sy) / (n * sxx - sx * sx); - b = (sy - m * sx) / n; - break; - } case InlLineFit::EndFit: { - m = (inl_data[last] - inl_data[first]) / static_cast(last - first); - b = inl_data[first] - m * static_cast(first); - break; - } default: - throw runtime_error("inl : line fit not implemented"); - } - for (size_t i = first; i <= last; ++i) { - inl_data[i] -= m * static_cast(i) + b; + return; // all missing codes } } - - std::map inl_analysis(const real_t* data, size_t size) + size_t last = dnl_size - 1; + while (dnl_data[last] <= -1.0 && first < last) { - check_array("", "inl array", data, size); - std_reduce_t r = std_reduce(data, size, 0, size); - std::vector keys = inl_analysis_ordered_keys(); - return std::map { - { keys[0] , r.min }, - { keys[1] , r.max }, - { keys[2] , static_cast(r.min_index) }, - { keys[3] , static_cast(r.max_index) }}; + inl_data[last--] = 0.0; } - - const std::vector& inl_analysis_ordered_keys() + std::partial_sum (dnl_data + first, dnl_data + last + 1, inl_data + first); + real_t m = 0.0; + real_t b = 0.0; + switch (fit) + { + case InlLineFit::NoFit: + return; + case InlLineFit::BestFit: + { + // https://en.wikipedia.org/wiki/Ordinary_least_squares + real_t n = static_cast (last - first) + 1.0; + real_t sx = 0.0; + real_t sy = 0.0; + real_t sxx = 0.0; + real_t sxy = 0.0; + for (size_t i = first; i <= last; ++i) + { + real_t x = static_cast (i); + sx += x; + sy += inl_data[i]; + sxx += x * x; + sxy += x * inl_data[i]; + } + m = (n * sxy - sx * sy) / (n * sxx - sx * sx); + b = (sy - m * sx) / n; + break; + } + case InlLineFit::EndFit: + { + m = (inl_data[last] - inl_data[first]) + / static_cast (last - first); + b = inl_data[first] - m * static_cast (first); + break; + } + default: + throw runtime_error ("inl : line fit not implemented"); + } + for (size_t i = first; i <= last; ++i) { - static const std::vector keys { - "min", // min INL value - "max", // max INL value - "min_index", // index of min INL value - "max_index" // index of max INL value - }; - return keys; + inl_data[i] -= m * static_cast (i) + b; } +} + +std::map +inl_analysis (const real_t *data, size_t size) +{ + check_array ("", "inl array", data, size); + std_reduce_t r = std_reduce (data, size, 0, size); + std::vector keys = inl_analysis_ordered_keys (); + return std::map{ + { keys[0], r.min }, + { keys[1], r.max }, + { keys[2], static_cast (r.min_index) }, + { keys[3], static_cast (r.max_index) } + }; +} + +const std::vector & +inl_analysis_ordered_keys () +{ + static const std::vector keys{ + "min", // min INL value + "max", // max INL value + "min_index", // index of min INL value + "max_index" // index of max INL value + }; + return keys; +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/enum_map.cpp b/src/enum_map.cpp index dee6cb8..6ecf489 100644 --- a/src/enum_map.cpp +++ b/src/enum_map.cpp @@ -1,49 +1,63 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "enum_map.hpp" -namespace genalyzer_impl { +namespace genalyzer_impl +{ - enum_map::enum_map(const char* name, std::initializer_list> list) - : m_name (name), - m_itos {}, - m_stoi {} +enum_map::enum_map (const char *name, + std::initializer_list > list) + : m_name (name), m_itos{}, m_stoi{} +{ + if (m_name.empty ()) { - if (m_name.empty()) { - throw runtime_error("enum_map : enumeration name is required"); + throw runtime_error ("enum_map : enumeration name is required"); + } + for (const auto &es : list) + { + int i = es.first; + const str_t &s = es.second; + if (s.empty ()) + { + throw runtime_error ("enum_map : enumerator name is required"); + } + bool success = false; + std::tie (std::ignore, success) = m_itos.emplace (i, s); + if (!success) + { + throw runtime_error ("enum_map : enumerator already exists"); } - for (const auto& es : list) { - int i = es.first; - const str_t& s = es.second; - if (s.empty()) { - throw runtime_error("enum_map : enumerator name is required"); - } - bool success = false; - std::tie(std::ignore, success) = m_itos.emplace(i, s); - if (!success) { - throw runtime_error("enum_map : enumerator already exists"); - } - std::tie(std::ignore, success) = m_stoi.emplace(s, i); - if (!success) { - throw runtime_error("enum_map : enumerator name already exists"); - } + std::tie (std::ignore, success) = m_stoi.emplace (s, i); + if (!success) + { + throw runtime_error ("enum_map : enumerator name already exists"); } } +} - bool enum_map::contains(int i, bool throw_if_not_found) const +bool +enum_map::contains (int i, bool throw_if_not_found) const +{ + bool not_found = m_itos.end () == m_itos.find (i); + if (not_found && throw_if_not_found) { - bool not_found = m_itos.end() == m_itos.find(i); - if (not_found && throw_if_not_found) { - throw runtime_error("enum_map : " + m_name + " does not contain value " + std::to_string(i)); - } - return !not_found; + throw runtime_error ("enum_map : " + m_name + " does not contain value " + + std::to_string (i)); } + return !not_found; +} - bool enum_map::contains(const str_t& s, bool throw_if_not_found) const +bool +enum_map::contains (const str_t &s, bool throw_if_not_found) const +{ + bool not_found = m_stoi.end () == m_stoi.find (s); + if (not_found && throw_if_not_found) { - bool not_found = m_stoi.end() == m_stoi.find(s); - if (not_found && throw_if_not_found) { - throw runtime_error("enum_map : " + m_name + " : does not contain enumerator " + s); - } - return !not_found; + throw runtime_error ("enum_map : " + m_name + + " : does not contain enumerator " + s); } + return !not_found; +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/enum_maps.cpp b/src/enum_maps.cpp index 0d88893..af4e3a5 100644 --- a/src/enum_maps.cpp +++ b/src/enum_maps.cpp @@ -1,100 +1,116 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "enum_maps.hpp" #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - const std::map> enumeration_map = { - { analysis_type_map.name() , std::cref(analysis_type_map) }, - { code_format_map.name() , std::cref(code_format_map) }, - { dnl_signal_map.name() , std::cref(dnl_signal_map) }, - { fa_comp_tag_map.name() , std::cref(fa_comp_tag_map) }, - { fa_ssb_map.name() , std::cref(fa_ssb_map) }, - { freq_axis_format_map.name() , std::cref(freq_axis_format_map) }, - { freq_axis_type_map.name() , std::cref(freq_axis_type_map) }, - { inl_line_fit_map.name() , std::cref(inl_line_fit_map) }, - { rfft_scale_map.name() , std::cref(rfft_scale_map) }, - { window_map.name() , std::cref(window_map) } - }; +const std::map > enumeration_map + = { { analysis_type_map.name (), std::cref (analysis_type_map) }, + { code_format_map.name (), std::cref (code_format_map) }, + { dnl_signal_map.name (), std::cref (dnl_signal_map) }, + { fa_comp_tag_map.name (), std::cref (fa_comp_tag_map) }, + { fa_ssb_map.name (), std::cref (fa_ssb_map) }, + { freq_axis_format_map.name (), std::cref (freq_axis_format_map) }, + { freq_axis_type_map.name (), std::cref (freq_axis_type_map) }, + { inl_line_fit_map.name (), std::cref (inl_line_fit_map) }, + { rfft_scale_map.name (), std::cref (rfft_scale_map) }, + { window_map.name (), std::cref (window_map) } }; - int enum_value(const str_t& enumeration, const str_t& enumerator) +int +enum_value (const str_t &enumeration, const str_t &enumerator) +{ + if (enumeration_map.find (enumeration) == enumeration_map.end ()) { - if (enumeration_map.find(enumeration) == enumeration_map.end()) { - throw runtime_error("enum_value : unknown enumeration, '" + enumeration + "'"); - } - const enum_map& em = enumeration_map.at(enumeration); - em.contains(enumerator, true); - return em.at(enumerator); + throw runtime_error ("enum_value : unknown enumeration, '" + enumeration + + "'"); } + const enum_map &em = enumeration_map.at (enumeration); + em.contains (enumerator, true); + return em.at (enumerator); +} - template<> - AnalysisType get_enum(int i) - { - analysis_type_map.contains(i, true); - return static_cast(i); - } +template <> +AnalysisType +get_enum (int i) +{ + analysis_type_map.contains (i, true); + return static_cast (i); +} - template<> - CodeFormat get_enum(int i) - { - code_format_map.contains(i, true); - return static_cast(i); - } +template <> +CodeFormat +get_enum (int i) +{ + code_format_map.contains (i, true); + return static_cast (i); +} - template<> - DnlSignal get_enum(int i) - { - dnl_signal_map.contains(i, true); - return static_cast(i); - } +template <> +DnlSignal +get_enum (int i) +{ + dnl_signal_map.contains (i, true); + return static_cast (i); +} - template<> - FACompTag get_enum(int i) - { - fa_comp_tag_map.contains(i, true); - return static_cast(i); - } +template <> +FACompTag +get_enum (int i) +{ + fa_comp_tag_map.contains (i, true); + return static_cast (i); +} - template<> - FASsb get_enum(int i) - { - fa_ssb_map.contains(i, true); - return static_cast(i); - } +template <> +FASsb +get_enum (int i) +{ + fa_ssb_map.contains (i, true); + return static_cast (i); +} - template<> - FreqAxisFormat get_enum(int i) - { - freq_axis_format_map.contains(i, true); - return static_cast(i); - } +template <> +FreqAxisFormat +get_enum (int i) +{ + freq_axis_format_map.contains (i, true); + return static_cast (i); +} - template<> - FreqAxisType get_enum(int i) - { - freq_axis_type_map.contains(i, true); - return static_cast(i); - } +template <> +FreqAxisType +get_enum (int i) +{ + freq_axis_type_map.contains (i, true); + return static_cast (i); +} - template<> - InlLineFit get_enum(int i) - { - inl_line_fit_map.contains(i, true); - return static_cast(i); - } +template <> +InlLineFit +get_enum (int i) +{ + inl_line_fit_map.contains (i, true); + return static_cast (i); +} - template<> - RfftScale get_enum(int i) - { - rfft_scale_map.contains(i, true); - return static_cast(i); - } +template <> +RfftScale +get_enum (int i) +{ + rfft_scale_map.contains (i, true); + return static_cast (i); +} - template<> - Window get_enum(int i) - { - window_map.contains(i, true); - return static_cast(i); - } +template <> +Window +get_enum (int i) +{ + window_map.contains (i, true); + return static_cast (i); +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/error.cpp b/src/error.cpp new file mode 100644 index 0000000..49bc556 --- /dev/null +++ b/src/error.cpp @@ -0,0 +1,8 @@ +#include "error.h" +#include + +void +error (const char *location, const char *msg) +{ + printf ("error at %s: %s\n", location, msg); +} \ No newline at end of file diff --git a/src/expression.cpp b/src/expression.cpp index 13251b9..4658548 100644 --- a/src/expression.cpp +++ b/src/expression.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "expression.hpp" #include "exceptions.hpp" @@ -9,671 +12,877 @@ #include #include -namespace genalyzer_impl { // expression tokens +namespace genalyzer_impl +{ // expression tokens + +enum class TokenType +{ + Number, + Operator, + Parenthesis, + Variable +}; + +enum class OpType +{ + Add, + Sub, + Mul, + Div, + Mod, + UPlus, + UMinus, + Exp +}; + +enum class OpArity +{ + Unary, + Binary +}; + +enum class OpAssoc +{ + Left, + Right +}; + +enum OpProps +{ + OpPropsSymbol = 0, + OpPropsPrec, + OpPropsArity, + OpPropsAssoc +}; + +enum class ParenType +{ + Left, + Right +}; + +struct expression_token +{ + using pointer = std::unique_ptr; + + virtual ~expression_token () = default; + + virtual pointer clone () const = 0; + + virtual TokenType type () const = 0; +}; + +struct num_token final : public expression_token +{ + num_token (real_t n) : num{ n } {} + + pointer + clone () const override + { + return std::make_unique (*this); + } + + TokenType + type () const override + { + return TokenType::Number; + } + + real_t num; +}; + +struct op_token final : public expression_token +{ + op_token (OpType o) : op{ o } + { + std::tuple props; + switch (op) + { + case OpType::Add: + props = std::make_tuple ('+', 0, OpArity::Binary, OpAssoc::Left); + break; + case OpType::Sub: + props = std::make_tuple ('-', 0, OpArity::Binary, OpAssoc::Left); + break; + case OpType::Mul: + props = std::make_tuple ('*', 1, OpArity::Binary, OpAssoc::Left); + break; + case OpType::Div: + props = std::make_tuple ('/', 1, OpArity::Binary, OpAssoc::Left); + break; + case OpType::Mod: + props = std::make_tuple ('%', 1, OpArity::Binary, OpAssoc::Left); + break; + case OpType::UPlus: + props = std::make_tuple ('+', 2, OpArity::Unary, OpAssoc::Right); + break; + case OpType::UMinus: + props = std::make_tuple ('-', 2, OpArity::Unary, OpAssoc::Right); + break; + case OpType::Exp: + props = std::make_tuple ('^', 2, OpArity::Binary, OpAssoc::Right); + break; + } + symbol = std::get<0> (props); + prec = std::get<1> (props); + arity = std::get<2> (props); + assoc = std::get<3> (props); + } + + pointer + clone () const override + { + return std::make_unique (*this); + } + + TokenType + type () const override + { + return TokenType::Operator; + } + + bool + operator< (const op_token &that) const + { + return this->prec < that.prec; + } + + bool + operator<= (const op_token &that) const + { + return this->prec <= that.prec; + } + + OpType op; + char symbol; + int prec; + OpArity arity; + OpAssoc assoc; +}; + +struct paren_token final : public expression_token +{ + paren_token (ParenType p) + : paren{ p }, pchar{ ParenType::Left == paren ? '(' : ')' } + { + } + + pointer + clone () const override + { + return std::make_unique (*this); + } + + TokenType + type () const override + { + return TokenType::Parenthesis; + } + + ParenType paren; + char pchar; +}; + +struct var_token final : public expression_token +{ + + var_token (const str_t &v) : var{ v } {} + + pointer + clone () const override + { + return std::make_unique (*this); + } + + TokenType + type () const override + { + return TokenType::Variable; + } + + str_t var; +}; - enum class TokenType { - Number, Operator, Parenthesis, Variable - }; - - enum class OpType { - Add, Sub, Mul, Div, Mod, UPlus, UMinus, Exp - }; - - enum class OpArity { - Unary, Binary - }; - - enum class OpAssoc { - Left, Right - }; - - enum OpProps { - OpPropsSymbol = 0, - OpPropsPrec, - OpPropsArity, - OpPropsAssoc - }; - - enum class ParenType { - Left, Right - }; - - struct expression_token - { - using pointer = std::unique_ptr; - - virtual ~expression_token() = default; - - virtual pointer clone() const = 0; - - virtual TokenType type() const = 0; - }; - - struct num_token final : public expression_token - { - num_token(real_t n) - : num {n} - {} - - pointer clone() const override - { - return std::make_unique(*this); - } - - TokenType type() const override - { - return TokenType::Number; - } - - real_t num; - }; +} // genalyzer_impl - struct op_token final : public expression_token +namespace genalyzer_impl +{ + +bool +is_binary_operator (char c) +{ + return ('*' == c) || ('/' == c) || ('%' == c) || ('^' == c); +} + +bool +is_operator (char c) +{ + return ('+' == c) || ('-' == c) || ('*' == c) || ('/' == c) || ('%' == c) + || ('^' == c); +} + +bool +is_variable (const str_t &s) +{ + static const std::regex re ("[[:alpha:]][[:alnum:]_]*"); + return std::regex_match (s, re); +} + +void +operator<< (expression::token_vector &tokens, real_t n) +{ + tokens.push_back (std::make_unique (n)); +} + +void +operator<< (expression::token_vector &tokens, OpType o) +{ + tokens.push_back (std::make_unique (o)); +} + +void +operator<< (expression::token_vector &tokens, ParenType p) +{ + tokens.push_back (std::make_unique (p)); +} + +void +operator<< (expression::token_vector &tokens, const str_t &v) +{ + tokens.push_back (std::make_unique (v)); +} + +void +push_back_operator (expression::token_vector &tokens, char c, OpArity arity) +{ + OpType op = OpType::Add; + switch (c) { - op_token(OpType o) - : op {o} - { - std::tuple props; - switch (op) - { - case OpType::Add : props = std::make_tuple('+', 0, OpArity::Binary, OpAssoc::Left ); break; - case OpType::Sub : props = std::make_tuple('-', 0, OpArity::Binary, OpAssoc::Left ); break; - case OpType::Mul : props = std::make_tuple('*', 1, OpArity::Binary, OpAssoc::Left ); break; - case OpType::Div : props = std::make_tuple('/', 1, OpArity::Binary, OpAssoc::Left ); break; - case OpType::Mod : props = std::make_tuple('%', 1, OpArity::Binary, OpAssoc::Left ); break; - case OpType::UPlus : props = std::make_tuple('+', 2, OpArity::Unary, OpAssoc::Right); break; - case OpType::UMinus : props = std::make_tuple('-', 2, OpArity::Unary, OpAssoc::Right); break; - case OpType::Exp : props = std::make_tuple('^', 2, OpArity::Binary, OpAssoc::Right); break; - } - symbol = std::get<0>(props); - prec = std::get<1>(props); - arity = std::get<2>(props); - assoc = std::get<3>(props); - } - - pointer clone() const override - { - return std::make_unique(*this); - } - - TokenType type() const override - { - return TokenType::Operator; - } - - bool operator<(const op_token& that) const - { - return this->prec < that.prec; - } - - bool operator<=(const op_token& that) const - { - return this->prec <= that.prec; - } - - OpType op; - char symbol; - int prec; - OpArity arity; - OpAssoc assoc; - }; - - struct paren_token final : public expression_token + case '+': + op = (OpArity::Unary == arity) ? OpType::UPlus : OpType::Add; + break; + case '-': + op = (OpArity::Unary == arity) ? OpType::UMinus : OpType::Sub; + break; + case '*': + op = OpType::Mul; + break; + case '/': + op = OpType::Div; + break; + case '%': + op = OpType::Mod; + break; + case '^': + op = OpType::Exp; + break; + } + tokens << op; +} + +expression::var_set +get_vars (const expression::token_vector &tokens) +{ + expression::var_set vars; + for (const expression::token_ptr &token : tokens) { - paren_token(ParenType p) - : paren {p}, - pchar {ParenType::Left == paren ? '(' : ')'} - {} - - pointer clone() const override - { - return std::make_unique(*this); - } - - TokenType type() const override + if (TokenType::Variable == token->type ()) { - return TokenType::Parenthesis; + auto &v = static_cast (*token); + vars.insert (v.var); } - - ParenType paren; - char pchar; - }; - - struct var_token final : public expression_token + } + return vars; +} + +void +validate_postfix (const expression::token_vector &tokens) +{ + str_t msg = "validate_postfix : "; + std::stack operands; + for (const expression::token_ptr &token : tokens) { - - var_token(const str_t& v) - : var {v} - {} - - pointer clone() const override - { - return std::make_unique(*this); - } - - TokenType type() const override + switch (token->type ()) { - return TokenType::Variable; + case TokenType::Number: + case TokenType::Variable: + operands.push (0.0); + break; + case TokenType::Operator: + { + auto &op = static_cast (*token); + if (OpArity::Unary == op.arity) + { + if (operands.size () < 1) + { + throw runtime_error (msg + "stack underflow"); + } + } + else + { + if (operands.size () < 2) + { + throw runtime_error (msg + "stack underflow"); + } + else + { + operands.pop (); + } + } + break; + } + case TokenType::Parenthesis: + throw runtime_error (msg + "parenthesis found in postfix"); } - - str_t var; - }; - -} // genalyzer_impl - -namespace genalyzer_impl { - - bool is_binary_operator(char c) - { - return ('*' == c) || ('/' == c) || ('%' == c) || ('^' == c); } - - bool is_operator(char c) + if (1 < operands.size ()) { - return ('+' == c) || ('-' == c) || ('*' == c) || ('/' == c) || ('%' == c) || ('^' == c); + throw runtime_error (msg + "stack overflow"); } - - bool is_variable(const str_t& s) - { - static const std::regex re ("[[:alpha:]][[:alnum:]_]*"); - return std::regex_match(s, re); - } - - void operator<<(expression::token_vector& tokens, real_t n) - { - tokens.push_back(std::make_unique(n)); - } - - void operator<<(expression::token_vector& tokens, OpType o) +} + +expression::token_vector +infix_to_postfix (const expression::token_vector &infix_tokens) +{ + /* + * Uses Edsger Dijkstra's Shunting Yard algorithm to convert infix to postfix + * https://en.wikipedia.org/wiki/Shunting-yard_algorithm + * https://www.chris-j.co.uk/parsing.php + */ + expression::token_vector postfix_tokens; + if (infix_tokens.empty ()) { - tokens.push_back(std::make_unique(o)); + return postfix_tokens; } - - void operator<<(expression::token_vector& tokens, ParenType p) + std::stack op_stack; + for (const expression::token_ptr &token : infix_tokens) { - tokens.push_back(std::make_unique(p)); + switch (token->type ()) + { + case TokenType::Number: + case TokenType::Variable: + postfix_tokens.push_back (token->clone ()); + break; + case TokenType::Operator: + { + auto &op1 = static_cast (*token); + while (!op_stack.empty ()) + { + if (TokenType::Parenthesis == op_stack.top ()->type ()) + { + break; + } + auto &op2 = static_cast (*op_stack.top ()); + if ((OpAssoc::Left == op1.assoc && op1 <= op2) + || (OpAssoc::Right == op1.assoc && op1 < op2)) + { + postfix_tokens.push_back (op_stack.top ()->clone ()); + op_stack.pop (); + } + else + { + break; + } + } + op_stack.push (token->clone ()); + break; + } + case TokenType::Parenthesis: + { + auto &p1 = static_cast (*token); + if (ParenType::Left == p1.paren) + { + op_stack.push (token->clone ()); + } + else + { + while (!op_stack.empty ()) + { + if (TokenType::Parenthesis == op_stack.top ()->type ()) + { + auto &p2 = static_cast ( + *op_stack.top ()); + if (ParenType::Left == p2.paren) + { + op_stack.pop (); + break; + } + } + postfix_tokens.push_back (op_stack.top ()->clone ()); + op_stack.pop (); + } + } + break; + } + } } - - void operator<<(expression::token_vector& tokens, const str_t& v) + while (!op_stack.empty ()) { - tokens.push_back(std::make_unique(v)); + postfix_tokens.push_back (op_stack.top ()->clone ()); + op_stack.pop (); } - - void push_back_operator(expression::token_vector& tokens, char c, OpArity arity) + validate_postfix (postfix_tokens); + return postfix_tokens; +} + +str_t +to_string (const expression::token_vector &tokens, FPFormat fmt, int prec) +{ + std::ostringstream ss; + for (const expression::token_ptr &token : tokens) { - OpType op = OpType::Add; - switch (c) + switch (token->type ()) { - case '+' : op = (OpArity::Unary == arity) ? OpType::UPlus : OpType::Add; break; - case '-' : op = (OpArity::Unary == arity) ? OpType::UMinus : OpType::Sub; break; - case '*' : op = OpType::Mul; break; - case '/' : op = OpType::Div; break; - case '%' : op = OpType::Mod; break; - case '^' : op = OpType::Exp; break; - } - tokens << op; - } - - expression::var_set get_vars(const expression::token_vector& tokens) - { - expression::var_set vars; - for (const expression::token_ptr& token : tokens) { - if (TokenType::Variable == token->type()) { - auto& v = static_cast(*token); - vars.insert(v.var); - } + case TokenType::Number: + { + auto &t = static_cast (*token); + ss << genalyzer_impl::to_string (t.num, fmt, prec); + break; + } + case TokenType::Operator: + { + auto &t = static_cast (*token); + ss << t.symbol; + break; + } + case TokenType::Parenthesis: + { + auto &t = static_cast (*token); + ss << t.pchar; + break; + } + case TokenType::Variable: + { + auto &t = static_cast (*token); + ss << t.var; + break; + } } - return vars; } - - void validate_postfix(const expression::token_vector& tokens) + return ss.str (); +} + +expression::token_vector +tokenize_infix (const str_t &infix_string) +{ + expression::token_vector tokens; + char c = 0; + std::istringstream ss (infix_string); + int open_parens = 0; + const char *syntax_error = "tokenize_infix : syntax error"; + while (ss >> c) { - str_t msg = "validate_postfix : "; - std::stack operands; - for (const expression::token_ptr& token : tokens) { - switch (token->type()) + // Number + if (std::isdigit (c) || '.' == c) + { + if (!tokens.empty ()) { - case TokenType::Number : - case TokenType::Variable : - operands.push(0.0); - break; - case TokenType::Operator : { - auto& op = static_cast(*token); - if (OpArity::Unary == op.arity) { - if (operands.size() < 1) { - throw runtime_error(msg + "stack underflow"); - } - } else { - if (operands.size() < 2) { - throw runtime_error(msg + "stack underflow"); - } else { - operands.pop(); - } + TokenType previous = tokens.back ()->type (); + if (TokenType::Number == previous + || TokenType::Variable == previous) + { + tokens.clear (); + throw runtime_error (syntax_error); + } + else if (TokenType::Parenthesis == previous) + { + auto &p = static_cast (*tokens.back ()); + if (ParenType::Right == p.paren) + { + tokens << OpType::Mul; } - break; } - case TokenType::Parenthesis : - throw runtime_error(msg + "parenthesis found in postfix"); } - } - if (1 < operands.size()) { - throw runtime_error(msg + "stack overflow"); - } - } + ss.unget (); + real_t num = 0.0; + ss >> num; - expression::token_vector infix_to_postfix(const expression::token_vector& infix_tokens) - { - /* - * Uses Edsger Dijkstra's Shunting Yard algorithm to convert infix to postfix - * https://en.wikipedia.org/wiki/Shunting-yard_algorithm - * https://www.chris-j.co.uk/parsing.php - */ - expression::token_vector postfix_tokens; - if (infix_tokens.empty()) { - return postfix_tokens; - } - std::stack op_stack; - for (const expression::token_ptr& token : infix_tokens) { - switch (token->type()) +#if defined(__APPLE__) + if (!ss) { - case TokenType::Number : - case TokenType::Variable : - postfix_tokens.push_back(token->clone()); - break; - case TokenType::Operator : { - auto& op1 = static_cast(*token); - while (!op_stack.empty()) { - if (TokenType::Parenthesis == op_stack.top()->type()) { - break; - } - auto& op2 = static_cast(*op_stack.top()); - if ((OpAssoc::Left == op1.assoc && op1 <= op2) || - (OpAssoc::Right == op1.assoc && op1 < op2)) { - postfix_tokens.push_back(op_stack.top()->clone()); - op_stack.pop(); - } else { - break; - } - } - op_stack.push(token->clone()); - break; - } case TokenType::Parenthesis : { - auto& p1 = static_cast(*token); - if (ParenType::Left == p1.paren) { - op_stack.push(token->clone()); - } else { - while (!op_stack.empty()) { - if (TokenType::Parenthesis == op_stack.top()->type()) { - auto& p2 = static_cast(*op_stack.top()); - if (ParenType::Left == p2.paren) { - op_stack.pop(); - break; - } - } - postfix_tokens.push_back(op_stack.top()->clone()); - op_stack.pop(); - } - } - break; + // Clang doesn't support stringstream to double if contains + // characters Need to manually convert + std::string tmp = ss.str (); + ss.clear (); // clear error flags + // Remove all non-numeric characters + tmp.erase (std::remove_if (tmp.begin (), tmp.end (), + [] (char c) { + return !(std::isdigit (c) + || c == '.'); + }), + tmp.end ()); + if (tmp.empty ()) + { + throw runtime_error ( + "tokenize_infix : invalid numeric value"); } + num = std::stod (tmp); } - } - while (!op_stack.empty()) { - postfix_tokens.push_back(op_stack.top()->clone()); - op_stack.pop(); - } - validate_postfix(postfix_tokens); - return postfix_tokens; - } - - str_t to_string(const expression::token_vector& tokens, FPFormat fmt, int prec) - { - std::ostringstream ss; - for (const expression::token_ptr& token : tokens) { - switch (token->type()) +#endif + if (ss) { - case TokenType::Number : { - auto& t = static_cast(*token); - ss << genalyzer_impl::to_string(t.num, fmt, prec); - break; - } - case TokenType::Operator : { - auto& t = static_cast(*token); - ss << t.symbol; - break; - } - case TokenType::Parenthesis : { - auto& t = static_cast(*token); - ss << t.pchar; - break; - } - case TokenType::Variable : { - auto& t = static_cast(*token); - ss << t.var; - break; - } + tokens << num; + } + else + { + throw runtime_error ("tokenize_infix : invalid numeric value"); } } - return ss.str(); - } - - expression::token_vector tokenize_infix(const str_t& infix_string) - { - expression::token_vector tokens; - char c = 0; - std::istringstream ss (infix_string); - int open_parens = 0; - const char* syntax_error = "tokenize_infix : syntax error"; - while (ss >> c) { - // Number - if (std::isdigit(c) || '.' == c) { - if (!tokens.empty()) { - TokenType previous = tokens.back()->type(); - if (TokenType::Number == previous || TokenType::Variable == previous) { - tokens.clear(); - throw runtime_error(syntax_error); - } else if (TokenType::Parenthesis == previous) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Right == p.paren) { - tokens << OpType::Mul; - } - } + // Operator + else if (is_operator (c)) + { + if (is_binary_operator (c)) + { + if (tokens.empty ()) + { + throw runtime_error (syntax_error); } - ss.unget(); - real_t num = 0.0; - ss >> num; - -#if defined(__APPLE__) - if (!ss){ - // Clang doesn't support stringstream to double if contains characters - // Need to manually convert - std::string tmp = ss.str(); - ss.clear(); // clear error flags - // Remove all non-numeric characters - tmp.erase(std::remove_if(tmp.begin(), tmp.end(), [](char c) { return !(std::isdigit(c) || c == '.'); }), tmp.end()); - if (tmp.empty()) { - throw runtime_error("tokenize_infix : invalid numeric value"); - } - num = std::stod(tmp); + TokenType previous = tokens.back ()->type (); + if (TokenType::Operator == previous) + { + tokens.clear (); + throw runtime_error (syntax_error); } -#endif - if (ss) { - tokens << num; - } else { - throw runtime_error("tokenize_infix : invalid numeric value"); + else if (TokenType::Parenthesis == previous) + { + auto &p = static_cast (*tokens.back ()); + if (ParenType::Left == p.paren) + { + tokens.clear (); + throw runtime_error (syntax_error); + } } + push_back_operator (tokens, c, OpArity::Binary); } - // Operator - else if (is_operator(c)) { - if (is_binary_operator(c)) { - if (tokens.empty()) { - throw runtime_error(syntax_error); + else + { + OpArity arity = OpArity::Unary; + if (!tokens.empty ()) + { + TokenType previous = tokens.back ()->type (); + if (TokenType::Number == previous + || TokenType::Variable == previous) + { + arity = OpArity::Binary; } - TokenType previous = tokens.back()->type(); - if (TokenType::Operator == previous) { - tokens.clear(); - throw runtime_error(syntax_error); - } else if (TokenType::Parenthesis == previous) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Left == p.paren) { - tokens.clear(); - throw runtime_error(syntax_error); + else if (TokenType::Parenthesis == previous) + { + auto &p + = static_cast (*tokens.back ()); + if (ParenType::Right == p.paren) + { + arity = OpArity::Binary; } } - push_back_operator(tokens, c, OpArity::Binary); - } else { - OpArity arity = OpArity::Unary; - if (!tokens.empty()) { - TokenType previous = tokens.back()->type(); - if (TokenType::Number == previous || TokenType::Variable == previous) { - arity = OpArity::Binary; - } else if (TokenType::Parenthesis == previous) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Right == p.paren) { - arity = OpArity::Binary; - } - } else if (TokenType::Operator == previous) { - auto& o = static_cast(*tokens.back()); - if ('+' == o.symbol || '-' == o.symbol) { - tokens.clear(); - throw runtime_error(syntax_error); - } + else if (TokenType::Operator == previous) + { + auto &o + = static_cast (*tokens.back ()); + if ('+' == o.symbol || '-' == o.symbol) + { + tokens.clear (); + throw runtime_error (syntax_error); } } - push_back_operator(tokens, c, arity); } + push_back_operator (tokens, c, arity); } - // Left Parenthesis - else if ('(' == c) { - if (!tokens.empty()) { - TokenType previous = tokens.back()->type(); - if (TokenType::Number == previous || TokenType::Variable == previous) { - tokens << OpType::Mul; - } else if (TokenType::Parenthesis == previous) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Right == p.paren) { - tokens << OpType::Mul; - } + } + // Left Parenthesis + else if ('(' == c) + { + if (!tokens.empty ()) + { + TokenType previous = tokens.back ()->type (); + if (TokenType::Number == previous + || TokenType::Variable == previous) + { + tokens << OpType::Mul; + } + else if (TokenType::Parenthesis == previous) + { + auto &p = static_cast (*tokens.back ()); + if (ParenType::Right == p.paren) + { + tokens << OpType::Mul; } } - tokens << ParenType::Left; - open_parens += 1; } - // Right Parenthesis - else if (')' == c) { - if (tokens.empty()) { - throw runtime_error(syntax_error); - } - TokenType previous = tokens.back()->type(); - if (TokenType::Operator == previous) { - tokens.clear(); - throw runtime_error(syntax_error); - } else if (TokenType::Parenthesis == previous) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Left == p.paren) { - tokens.clear(); - throw runtime_error(syntax_error); - } + tokens << ParenType::Left; + open_parens += 1; + } + // Right Parenthesis + else if (')' == c) + { + if (tokens.empty ()) + { + throw runtime_error (syntax_error); + } + TokenType previous = tokens.back ()->type (); + if (TokenType::Operator == previous) + { + tokens.clear (); + throw runtime_error (syntax_error); + } + else if (TokenType::Parenthesis == previous) + { + auto &p = static_cast (*tokens.back ()); + if (ParenType::Left == p.paren) + { + tokens.clear (); + throw runtime_error (syntax_error); } - tokens << ParenType::Right; - open_parens -= 1; } - // Variable - else if (std::isalpha(c)) { - if (!tokens.empty()) { - TokenType previous = tokens.back()->type(); - if (TokenType::Number == previous) { - tokens << OpType::Mul; - } else if (TokenType::Parenthesis == previous) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Right == p.paren) { - tokens << OpType::Mul; - } - } else if (TokenType::Variable == previous) { - tokens.clear(); - throw runtime_error(syntax_error); - } + tokens << ParenType::Right; + open_parens -= 1; + } + // Variable + else if (std::isalpha (c)) + { + if (!tokens.empty ()) + { + TokenType previous = tokens.back ()->type (); + if (TokenType::Number == previous) + { + tokens << OpType::Mul; } - str_t var (1, c); - while (ss.get(c)) { - if (std::isalnum(c) || '_' == c) { - var.push_back(c); - } else { - ss.unget(); - break; + else if (TokenType::Parenthesis == previous) + { + auto &p = static_cast (*tokens.back ()); + if (ParenType::Right == p.paren) + { + tokens << OpType::Mul; } } - if (is_variable(var)) { - tokens << var; - } else { - throw runtime_error("tokenize_infix : invalid variable name"); + else if (TokenType::Variable == previous) + { + tokens.clear (); + throw runtime_error (syntax_error); + } + } + str_t var (1, c); + while (ss.get (c)) + { + if (std::isalnum (c) || '_' == c) + { + var.push_back (c); + } + else + { + ss.unget (); + break; } } - // Invalid - else { - tokens.clear(); - throw runtime_error("tokenize_infix : invalid token"); + if (is_variable (var)) + { + tokens << var; + } + else + { + throw runtime_error ("tokenize_infix : invalid variable name"); } } - // Check for unmatched parentheses - if (0 != open_parens) { - throw runtime_error("tokenize_infix : expression has unmatched parentheses"); + // Invalid + else + { + tokens.clear (); + throw runtime_error ("tokenize_infix : invalid token"); } - // Last token must not be an operator or left parenthesis - if (tokens.empty()) { - throw runtime_error("tokenize_infix : expression has no tokens"); - } else { - TokenType last = tokens.back()->type(); - if (TokenType::Operator == last) { - tokens.clear(); - throw runtime_error(syntax_error); - } else if (TokenType::Parenthesis == last) { - auto& p = static_cast(*tokens.back()); - if (ParenType::Left == p.paren) { - tokens.clear(); - throw runtime_error("tokenize_infix : expression has unmatched parentheses"); - } + } + // Check for unmatched parentheses + if (0 != open_parens) + { + throw runtime_error ( + "tokenize_infix : expression has unmatched parentheses"); + } + // Last token must not be an operator or left parenthesis + if (tokens.empty ()) + { + throw runtime_error ("tokenize_infix : expression has no tokens"); + } + else + { + TokenType last = tokens.back ()->type (); + if (TokenType::Operator == last) + { + tokens.clear (); + throw runtime_error (syntax_error); + } + else if (TokenType::Parenthesis == last) + { + auto &p = static_cast (*tokens.back ()); + if (ParenType::Left == p.paren) + { + tokens.clear (); + throw runtime_error ( + "tokenize_infix : expression has unmatched parentheses"); } } - return tokens; } + return tokens; +} } // namespace genalyzer_impl -namespace genalyzer_impl { // expression class +namespace genalyzer_impl +{ // expression class - expression::expression(const str_t& infix_string) - : m_infix_tokens (tokenize_infix(infix_string)) - {} +expression::expression (const str_t &infix_string) + : m_infix_tokens (tokenize_infix (infix_string)) +{ +} - expression::~expression() = default; +expression::~expression () = default; - bool expression::depends_on(const var_set& vars) const +bool +expression::depends_on (const var_set &vars) const +{ + var_set expr_vars = get_vars (m_infix_tokens); + for (const str_t &v : vars) { - var_set expr_vars = get_vars(m_infix_tokens); - for (const str_t& v : vars) { - if (expr_vars.find(v) != expr_vars.end()) { - return true; - } + if (expr_vars.find (v) != expr_vars.end ()) + { + return true; } - return false; } - - real_t expression::evaluate(const var_map& vars) const + return false; +} + +real_t +expression::evaluate (const var_map &vars) const +{ + str_t msg = "expression::evaluate : "; + str_t missing_var = vars_defined (vars); + if (!missing_var.empty ()) { - str_t msg = "expression::evaluate : "; - str_t missing_var = vars_defined(vars); - if (!missing_var.empty()) { - throw runtime_error(msg + "expression depends on undefined variable, '" + missing_var + "'"); - } - token_vector postfix_tokens = infix_to_postfix(m_infix_tokens); - if (postfix_tokens.empty()) { - throw runtime_error(msg + "empty expression"); - } - std::stack operands; - for (const token_ptr& token : postfix_tokens) { - switch (token->type()) - { - case TokenType::Number : { - auto& t = static_cast(*token); - operands.push(t.num); + throw runtime_error (msg + "expression depends on undefined variable, '" + + missing_var + "'"); + } + token_vector postfix_tokens = infix_to_postfix (m_infix_tokens); + if (postfix_tokens.empty ()) + { + throw runtime_error (msg + "empty expression"); + } + std::stack operands; + for (const token_ptr &token : postfix_tokens) + { + switch (token->type ()) + { + case TokenType::Number: + { + auto &t = static_cast (*token); + operands.push (t.num); + break; + } + case TokenType::Variable: + { + auto &t = static_cast (*token); + operands.push (vars.at (t.var)); + break; + } + case TokenType::Operator: + { + auto &t = static_cast (*token); + real_t result = 0.0; + if (OpArity::Unary == t.arity) + { + real_t value = operands.top (); + operands.pop (); + switch (t.op) + { + case OpType::UPlus: + result = value; break; - } - case TokenType::Variable : { - auto& t = static_cast(*token); - operands.push(vars.at(t.var)); + case OpType::UMinus: + result = -value; break; - } - case TokenType::Operator : { - auto& t = static_cast(*token); - real_t result = 0.0; - if (OpArity::Unary == t.arity) { - real_t value = operands.top(); - operands.pop(); - switch (t.op) - { - case OpType::UPlus : - result = value; - break; - case OpType::UMinus : - result = -value; - break; - default: - break; - } - } else { - real_t rval = operands.top(); - operands.pop(); - real_t lval = operands.top(); - operands.pop(); - switch (t.op) - { - case OpType::Add : - result = lval + rval; - break; - case OpType::Sub : - result = lval - rval; - break; - case OpType::Mul : - result = lval * rval; - break; - case OpType::Div : - if (0.0 == rval) { - throw runtime_error(msg + "divide by 0"); - } - result = lval / rval; - break; - case OpType::Mod : - if (0.0 == rval) { - throw runtime_error(msg + "divide by 0"); - } - result = std::fmod(lval, rval); - break; - case OpType::Exp : - result = std::pow(lval, rval); - break; - default: - break; - } - } - operands.push(result); + default: break; - } - default: + } + } + else + { + real_t rval = operands.top (); + operands.pop (); + real_t lval = operands.top (); + operands.pop (); + switch (t.op) + { + case OpType::Add: + result = lval + rval; break; - } - } - if (1 != operands.size()) { - throw runtime_error(msg + "stack error"); + case OpType::Sub: + result = lval - rval; + break; + case OpType::Mul: + result = lval * rval; + break; + case OpType::Div: + if (0.0 == rval) + { + throw runtime_error (msg + "divide by 0"); + } + result = lval / rval; + break; + case OpType::Mod: + if (0.0 == rval) + { + throw runtime_error (msg + "divide by 0"); + } + result = std::fmod (lval, rval); + break; + case OpType::Exp: + result = std::pow (lval, rval); + break; + default: + break; + } + } + operands.push (result); + break; + } + default: + break; } - return operands.top(); - } - - str_t expression::to_postfix_string(FPFormat fmt, int prec) const - { - token_vector postfix_tokens = infix_to_postfix(m_infix_tokens); - return genalyzer_impl::to_string(postfix_tokens, fmt, prec); - } - - str_t expression::to_string(FPFormat fmt, int prec) const - { - return genalyzer_impl::to_string(m_infix_tokens, fmt, prec); } - - expression::var_set expression::vars() const + if (1 != operands.size ()) { - return get_vars(m_infix_tokens); + throw runtime_error (msg + "stack error"); } - - str_t expression::vars_defined(const var_map& vars) const + return operands.top (); +} + +str_t +expression::to_postfix_string (FPFormat fmt, int prec) const +{ + token_vector postfix_tokens = infix_to_postfix (m_infix_tokens); + return genalyzer_impl::to_string (postfix_tokens, fmt, prec); +} + +str_t +expression::to_string (FPFormat fmt, int prec) const +{ + return genalyzer_impl::to_string (m_infix_tokens, fmt, prec); +} + +expression::var_set +expression::vars () const +{ + return get_vars (m_infix_tokens); +} + +str_t +expression::vars_defined (const var_map &vars) const +{ + var_set expr_vars = get_vars (m_infix_tokens); + for (const str_t &v : expr_vars) { - var_set expr_vars = get_vars(m_infix_tokens); - for (const str_t& v : expr_vars) { - if (vars.end() == vars.find(v)) { - return v; - } + if (vars.end () == vars.find (v)) + { + return v; } - return ""; } - + return ""; +} + } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/formatted_data.cpp b/src/formatted_data.cpp index a084680..76b8fca 100644 --- a/src/formatted_data.cpp +++ b/src/formatted_data.cpp @@ -1,71 +1,81 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "formatted_data.hpp" #include #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - str_t table( - const std::vector& header_rows, - const std::vector& data_rows, - int col_margin, - bool show_border, - bool show_col_sep - ) +str_t +table (const std::vector &header_rows, + const std::vector &data_rows, int col_margin, + bool show_border, bool show_col_sep) +{ + std::vector all_rows (header_rows); + all_rows.insert (all_rows.end (), data_rows.begin (), data_rows.end ()); + // Determine number of columns + size_t ncols = 0; + for (const str_vector &row : all_rows) { - std::vector all_rows (header_rows); - all_rows.insert(all_rows.end(), data_rows.begin(), data_rows.end()); - // Determine number of columns - size_t ncols = 0; - for (const str_vector& row : all_rows) { - ncols = std::max(ncols, row.size()); - } - if (0 == ncols) { - return ""; - } - // Determine max data width in each column - std::vector col_widths (ncols, 0); - for (str_vector& row : all_rows) { - for (size_t col = 0; col < row.size(); ++col) { - col_widths[col] = std::max(col_widths[col], row[col].size()); - } - // Add missing columns to row - row.resize(ncols, ""); + ncols = std::max (ncols, row.size ()); + } + if (0 == ncols) + { + return ""; + } + // Determine max data width in each column + std::vector col_widths (ncols, 0); + for (str_vector &row : all_rows) + { + for (size_t col = 0; col < row.size (); ++col) + { + col_widths[col] = std::max (col_widths[col], row[col].size ()); } - // Setup - col_margin = std::max(0, std::min(col_margin, 9)); - str_t col_pad = str_t(static_cast(col_margin), ' '); - str_t col_div = col_pad + (show_col_sep ? '|' : ' ') + col_pad; - str_t left_border = (show_border ? '|' : ' ') + col_pad; - str_t right_border = col_pad + (show_border ? '|' : ' '); - size_t total_width = left_border.size() + (ncols - 1) * col_div.size() + right_border.size(); - for (size_t w : col_widths) { - total_width += w; + // Add missing columns to row + row.resize (ncols, ""); + } + // Setup + col_margin = std::max (0, std::min (col_margin, 9)); + str_t col_pad = str_t (static_cast (col_margin), ' '); + str_t col_div = col_pad + (show_col_sep ? '|' : ' ') + col_pad; + str_t left_border = (show_border ? '|' : ' ') + col_pad; + str_t right_border = col_pad + (show_border ? '|' : ' '); + size_t total_width = left_border.size () + (ncols - 1) * col_div.size () + + right_border.size (); + for (size_t w : col_widths) + { + total_width += w; + } + str_t h_border = show_border ? (str_t (total_width, '=') + '\n') : ""; + str_t h_div = header_rows.empty () ? "" : (str_t (total_width, '=') + '\n'); + // Generate table + std::ostringstream ss; + ss << h_border; + for (size_t row = 0; row < all_rows.size (); ++row) + { + if (header_rows.size () == row) + { + ss << h_div; } - str_t h_border = show_border ? (str_t(total_width, '=') + '\n') : ""; - str_t h_div = header_rows.empty() ? "" : (str_t(total_width, '=') + '\n'); - // Generate table - std::ostringstream ss; - ss << h_border; - for (size_t row = 0; row < all_rows.size(); ++row) { - if (header_rows.size() == row) { - ss << h_div; - } - ss << left_border; - const str_vector& data = all_rows[row]; - for (size_t col = 0; col < ncols; ++col) { - ss << std::setw(static_cast(col_widths[col])) - << std::left - << data[col]; - if (col + 1 < ncols) { - ss << col_div; - } + ss << left_border; + const str_vector &data = all_rows[row]; + for (size_t col = 0; col < ncols; ++col) + { + ss << std::setw (static_cast (col_widths[col])) << std::left + << data[col]; + if (col + 1 < ncols) + { + ss << col_div; } - ss << right_border << '\n'; } - ss << h_border; - return ss.str(); + ss << right_border << '\n'; } + ss << h_border; + return ss.str (); +} } // namespace genalyzer_impl diff --git a/src/fourier_analysis.cpp b/src/fourier_analysis.cpp index 9833b5b..b52d557 100644 --- a/src/fourier_analysis.cpp +++ b/src/fourier_analysis.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "fourier_analysis.hpp" #include "array_ops.hpp" @@ -12,840 +15,1013 @@ #include #include -namespace genalyzer_impl { - - namespace { - - struct fraction - { - int num; - int den; - str_t term; - - fraction(int n, int d, const str_t& var = "") - { - if (!(1 <= n && 1 <= d && n < d)) { - throw runtime_error("Invalid fraction"); - } - int gcd = std::gcd(n, d); - num = n / gcd; - den = d / gcd; - if (1 == num && !var.empty()) { - term = var; - } else { - term = std::to_string(num) + var; - } - term += '/' + std::to_string(den); - } - - }; // struct fraction - - bool operator<(const fraction& lhs, const fraction& rhs) - { - // Based on numeric value, this operator would: - // return lhs.num * rhs.den < lhs.den * rhs.num; - // But in this implementation of Fourier analysis, fractions are grouped by - // denominator, in increasing order: - if (lhs.den < rhs.den) { - return true; - } else { - return (lhs.den == rhs.den) && (lhs.num < rhs.num); - } - } +namespace genalyzer_impl +{ + +namespace +{ + +struct fraction +{ + int num; + int den; + str_t term; + + fraction (int n, int d, const str_t &var = "") + { + if (!(1 <= n && 1 <= d && n < d)) + { + throw runtime_error ("Invalid fraction"); + } + int gcd = std::gcd (n, d); + num = n / gcd; + den = d / gcd; + if (1 == num && !var.empty ()) + { + term = var; + } + else + { + term = std::to_string (num) + var; + } + term += '/' + std::to_string (den); + } + +}; // struct fraction + +bool +operator< (const fraction &lhs, const fraction &rhs) +{ + // Based on numeric value, this operator would: + // return lhs.num * rhs.den < lhs.den * rhs.num; + // But in this implementation of Fourier analysis, fractions are grouped by + // denominator, in increasing order: + if (lhs.den < rhs.den) + { + return true; + } + else + { + return (lhs.den == rhs.den) && (lhs.num < rhs.num); + } +} - str_t negate(const str_t& expr, bool neg) - { - return neg ? ("-(" + expr + ')') : expr; - } +str_t +negate (const str_t &expr, bool neg) +{ + return neg ? ("-(" + expr + ')') : expr; +} - } // namespace anonymous +} // namespace anonymous - const fourier_analysis::min_max_def_t fourier_analysis::mmd_hd = { 1, 99, 6 }; - const fourier_analysis::min_max_def_t fourier_analysis::mmd_imd = { 1, 9, 3 }; - const fourier_analysis::min_max_def_t fourier_analysis::mmd_wo = { 1, 9, 1 }; - const fourier_analysis::min_max_def_t fourier_analysis::mmd_ssb = { 0, 1 << 29, 0 }; +const fourier_analysis::min_max_def_t fourier_analysis::mmd_hd = { 1, 99, 6 }; +const fourier_analysis::min_max_def_t fourier_analysis::mmd_imd = { 1, 9, 3 }; +const fourier_analysis::min_max_def_t fourier_analysis::mmd_wo = { 1, 9, 1 }; +const fourier_analysis::min_max_def_t fourier_analysis::mmd_ssb + = { 0, 1 << 29, 0 }; } // namespace genalyzer_impl -namespace genalyzer_impl { // Constructors, Destructor, and Assignment - - fourier_analysis::fourier_analysis() - : object {}, - // Parameters - clk_as_noise (false), - dc_as_dist (false), - en_conv_offset (false), - en_fund_images (true), - en_quad_errors (false), - ilv_as_noise (false), - m_hd (std::get<2>(mmd_hd)), - m_imd (std::get<2>(mmd_imd)), - m_wo (std::get<2>(mmd_wo)), - m_ssb_def (std::get<2>(mmd_ssb)), - m_ssb_dc (-1), - m_ssb_sig (-1), - m_ssb_wo (-1), - m_ab_center ("0"), - m_ab_width ("fdata"), - m_fdata ("fs"), - m_fsample ("1"), - m_fshift ("0"), - m_clk (), - m_ilv (), - // Components - m_user_keys (), - m_user_comps (), - // Variables - m_user_vars () - {} - - fourier_analysis::fourier_analysis(const fourier_analysis& obj) - : object {}, - // Parameters - clk_as_noise (obj.clk_as_noise), - dc_as_dist (obj.dc_as_dist), - en_conv_offset (obj.en_conv_offset), - en_fund_images (obj.en_fund_images), - en_quad_errors (obj.en_quad_errors), - ilv_as_noise (obj.ilv_as_noise), - m_hd (obj.m_hd), - m_imd (obj.m_imd), - m_wo (obj.m_wo), - m_ssb_def (obj.m_ssb_def), - m_ssb_dc (obj.m_ssb_dc), - m_ssb_sig (obj.m_ssb_sig), - m_ssb_wo (obj.m_ssb_wo), - m_ab_center (obj.m_ab_center), - m_ab_width (obj.m_ab_width), - m_fdata (obj.m_fdata), - m_fsample (obj.m_fsample), - m_fshift (obj.m_fshift), - m_clk (obj.m_clk), - m_ilv (obj.m_ilv), - // Components - m_user_keys (obj.m_user_keys), - m_user_comps (), - // Variables - m_user_vars (obj.m_user_vars) - { - for (const str_t& key : m_user_keys) { - m_user_comps[key] = obj.m_user_comps.at(key)->clone(); - } +namespace genalyzer_impl +{ // Constructors, Destructor, and Assignment + +fourier_analysis::fourier_analysis () + : object{}, + // Parameters + clk_as_noise (false), dc_as_dist (false), en_conv_offset (false), + en_fund_images (true), en_quad_errors (false), ilv_as_noise (false), + m_hd (std::get<2> (mmd_hd)), m_imd (std::get<2> (mmd_imd)), + m_wo (std::get<2> (mmd_wo)), m_ssb_def (std::get<2> (mmd_ssb)), + m_ssb_dc (-1), m_ssb_sig (-1), m_ssb_wo (-1), m_ab_center ("0"), + m_ab_width ("fdata"), m_fdata ("fs"), m_fsample ("1"), m_fshift ("0"), + m_clk (), m_ilv (), + // Components + m_user_keys (), m_user_comps (), + // Variables + m_user_vars () +{ +} + +fourier_analysis::fourier_analysis (const fourier_analysis &obj) + : object{}, + // Parameters + clk_as_noise (obj.clk_as_noise), dc_as_dist (obj.dc_as_dist), + en_conv_offset (obj.en_conv_offset), en_fund_images (obj.en_fund_images), + en_quad_errors (obj.en_quad_errors), ilv_as_noise (obj.ilv_as_noise), + m_hd (obj.m_hd), m_imd (obj.m_imd), m_wo (obj.m_wo), + m_ssb_def (obj.m_ssb_def), m_ssb_dc (obj.m_ssb_dc), + m_ssb_sig (obj.m_ssb_sig), m_ssb_wo (obj.m_ssb_wo), + m_ab_center (obj.m_ab_center), m_ab_width (obj.m_ab_width), + m_fdata (obj.m_fdata), m_fsample (obj.m_fsample), + m_fshift (obj.m_fshift), m_clk (obj.m_clk), m_ilv (obj.m_ilv), + // Components + m_user_keys (obj.m_user_keys), m_user_comps (), + // Variables + m_user_vars (obj.m_user_vars) +{ + for (const str_t &key : m_user_keys) + { + m_user_comps[key] = obj.m_user_comps.at (key)->clone (); } - - fourier_analysis::fourier_analysis(fourier_analysis&& obj) - : object {}, - // Parameters - clk_as_noise (obj.clk_as_noise), - dc_as_dist (obj.dc_as_dist), - en_conv_offset (obj.en_conv_offset), - en_fund_images (obj.en_fund_images), - en_quad_errors (obj.en_quad_errors), - ilv_as_noise (obj.ilv_as_noise), - m_hd (obj.m_hd), - m_imd (obj.m_imd), - m_wo (obj.m_wo), - m_ssb_def (obj.m_ssb_def), - m_ssb_dc (obj.m_ssb_dc), - m_ssb_sig (obj.m_ssb_sig), - m_ssb_wo (obj.m_ssb_wo), - m_ab_center (obj.m_ab_center), - m_ab_width (obj.m_ab_width), - m_fdata (obj.m_fdata), - m_fsample (obj.m_fsample), - m_fshift (obj.m_fshift), - m_clk (std::move(obj.m_clk)), - m_ilv (std::move(obj.m_ilv)), - // Components - m_user_keys (std::move(obj.m_user_keys)), - m_user_comps (std::move(obj.m_user_comps)), - // Variables - m_user_vars (std::move(obj.m_user_vars)) - {} - - fourier_analysis& fourier_analysis::operator=(const fourier_analysis& obj) - { - if (&obj != this) { - fourier_analysis the_copy (obj); - std::swap(the_copy, *this); - } - return *this; - } - - fourier_analysis& fourier_analysis::operator=(fourier_analysis&& obj) - { - // Parameters - std::swap(clk_as_noise , obj.clk_as_noise); - std::swap(dc_as_dist , obj.dc_as_dist); - std::swap(en_conv_offset , obj.en_conv_offset); - std::swap(en_fund_images , obj.en_fund_images); - std::swap(en_quad_errors , obj.en_quad_errors); - std::swap(ilv_as_noise , obj.ilv_as_noise); - std::swap(m_hd , obj.m_hd); - std::swap(m_imd , obj.m_imd); - std::swap(m_wo , obj.m_wo); - std::swap(m_ssb_def , obj.m_ssb_def); - std::swap(m_ssb_dc , obj.m_ssb_dc); - std::swap(m_ssb_sig , obj.m_ssb_sig); - std::swap(m_ssb_wo , obj.m_ssb_wo); - std::swap(m_ab_center , obj.m_ab_center); - std::swap(m_ab_width , obj.m_ab_width); - std::swap(m_fdata , obj.m_fdata); - std::swap(m_fsample , obj.m_fsample); - std::swap(m_fshift , obj.m_fshift); - std::swap(m_clk , obj.m_clk); - std::swap(m_ilv , obj.m_ilv); - // Components - std::swap(m_user_keys , obj.m_user_keys); - std::swap(m_user_comps , obj.m_user_comps); - // Variables - std::swap(m_user_vars , obj.m_user_vars); - return *this; +} + +fourier_analysis::fourier_analysis (fourier_analysis &&obj) + : object{}, + // Parameters + clk_as_noise (obj.clk_as_noise), dc_as_dist (obj.dc_as_dist), + en_conv_offset (obj.en_conv_offset), en_fund_images (obj.en_fund_images), + en_quad_errors (obj.en_quad_errors), ilv_as_noise (obj.ilv_as_noise), + m_hd (obj.m_hd), m_imd (obj.m_imd), m_wo (obj.m_wo), + m_ssb_def (obj.m_ssb_def), m_ssb_dc (obj.m_ssb_dc), + m_ssb_sig (obj.m_ssb_sig), m_ssb_wo (obj.m_ssb_wo), + m_ab_center (obj.m_ab_center), m_ab_width (obj.m_ab_width), + m_fdata (obj.m_fdata), m_fsample (obj.m_fsample), + m_fshift (obj.m_fshift), m_clk (std::move (obj.m_clk)), + m_ilv (std::move (obj.m_ilv)), + // Components + m_user_keys (std::move (obj.m_user_keys)), + m_user_comps (std::move (obj.m_user_comps)), + // Variables + m_user_vars (std::move (obj.m_user_vars)) +{ +} + +fourier_analysis & +fourier_analysis::operator= (const fourier_analysis &obj) +{ + if (&obj != this) + { + fourier_analysis the_copy (obj); + std::swap (the_copy, *this); } + return *this; +} + +fourier_analysis & +fourier_analysis::operator= (fourier_analysis &&obj) +{ + // Parameters + std::swap (clk_as_noise, obj.clk_as_noise); + std::swap (dc_as_dist, obj.dc_as_dist); + std::swap (en_conv_offset, obj.en_conv_offset); + std::swap (en_fund_images, obj.en_fund_images); + std::swap (en_quad_errors, obj.en_quad_errors); + std::swap (ilv_as_noise, obj.ilv_as_noise); + std::swap (m_hd, obj.m_hd); + std::swap (m_imd, obj.m_imd); + std::swap (m_wo, obj.m_wo); + std::swap (m_ssb_def, obj.m_ssb_def); + std::swap (m_ssb_dc, obj.m_ssb_dc); + std::swap (m_ssb_sig, obj.m_ssb_sig); + std::swap (m_ssb_wo, obj.m_ssb_wo); + std::swap (m_ab_center, obj.m_ab_center); + std::swap (m_ab_width, obj.m_ab_width); + std::swap (m_fdata, obj.m_fdata); + std::swap (m_fsample, obj.m_fsample); + std::swap (m_fshift, obj.m_fshift); + std::swap (m_clk, obj.m_clk); + std::swap (m_ilv, obj.m_ilv); + // Components + std::swap (m_user_keys, obj.m_user_keys); + std::swap (m_user_comps, obj.m_user_comps); + // Variables + std::swap (m_user_vars, obj.m_user_vars); + return *this; +} } // namespace genalyzer_impl - Constructors, Destructor, and Assignment -namespace genalyzer_impl { // Analysis - - fourier_analysis_results fourier_analysis::analyze( - const real_t* in_data, - const size_t in_size, - const size_t nfft, - FreqAxisType axis_type - ) const - { - check_array("", "input array", in_data, in_size); - std::vector msq; // used only if in_data is complex - const real_t* msq_data = nullptr; - size_t msq_size = 0; - const cplx_t* fft_data = nullptr; - size_t fft_size = 0; - if (in_size == nfft || // Real data, complex analysis - in_size == nfft / 2 + 1) { // Real data, real analysis - // input array is mean-square FFT data (phase not available) - msq_data = in_data; - msq_size = in_size; - } else if (in_size == nfft * 2 || // Complex data, complex analysis - in_size == (nfft / 2 + 1) * 2) { // Complex data, real analysis - // input array is interleaved Re/Im FFT data - msq_size = in_size / 2; - msq = std::vector(msq_size); - norm(in_data, in_size, msq.data(), msq.size()); - msq_data = msq.data(); - fft_data = reinterpret_cast(in_data); - fft_size = in_size / 2; - } else { - throw runtime_error("Mismatch between data size and NFFT"); - } - fourier_analysis_results results = analyze_impl(msq_data, msq_size, nfft, axis_type, fft_data, fft_size); - return results; +namespace genalyzer_impl +{ // Analysis + +fourier_analysis_results +fourier_analysis::analyze (const real_t *in_data, const size_t in_size, + const size_t nfft, FreqAxisType axis_type) const +{ + check_array ("", "input array", in_data, in_size); + std::vector msq; // used only if in_data is complex + const real_t *msq_data = nullptr; + size_t msq_size = 0; + const cplx_t *fft_data = nullptr; + size_t fft_size = 0; + if (in_size == nfft || // Real data, complex analysis + in_size == nfft / 2 + 1) + { // Real data, real analysis + // input array is mean-square FFT data (phase not available) + msq_data = in_data; + msq_size = in_size; } + else if (in_size == nfft * 2 || // Complex data, complex analysis + in_size == (nfft / 2 + 1) * 2) + { // Complex data, real analysis + // input array is interleaved Re/Im FFT data + msq_size = in_size / 2; + msq = std::vector (msq_size); + norm (in_data, in_size, msq.data (), msq.size ()); + msq_data = msq.data (); + fft_data = reinterpret_cast (in_data); + fft_size = in_size / 2; + } + else + { + throw runtime_error ("Mismatch between data size and NFFT"); + } + fourier_analysis_results results + = analyze_impl (msq_data, msq_size, nfft, axis_type, fft_data, fft_size); + return results; +} } // namespace genalyzer_impl - Analysis -namespace genalyzer_impl { // Component Definition - - void fourier_analysis::add_fixed_tone( - const str_t& key, FACompTag tag, const str_t& freq, int ssb) - { - if_key_not_available_throw(key); - expression fe (freq); - ssb = limit_ssb(ssb, -1); - m_user_keys.push_back(key); - m_user_comps.insert({key, std::make_unique( - tag, fe.to_string(FPFormat::Eng), ssb)}); - } - - void fourier_analysis::add_max_tone( - const str_t& key, FACompTag tag, const str_t& center, const str_t& width, int ssb) - { - if (FACompTag::Signal == tag || FACompTag::UserDist == tag || FACompTag::Noise == tag) { - if_key_not_available_throw(key); - expression ce (center); - expression we (width); - ssb = limit_ssb(ssb, -1); - m_user_keys.push_back(key); - m_user_comps.insert({key, std::make_unique( - tag, ce.to_string(FPFormat::Eng), we.to_string(FPFormat::Eng), ssb)}); - } else { - throw runtime_error("tag must be one of {" - + fa_comp_tag_map.at(to_int(FACompTag::Signal)) + ", " - + fa_comp_tag_map.at(to_int(FACompTag::UserDist)) + ", " - + fa_comp_tag_map.at(to_int(FACompTag::Noise)) + '}'); - } +namespace genalyzer_impl +{ // Component Definition + +void +fourier_analysis::add_fixed_tone (const str_t &key, FACompTag tag, + const str_t &freq, int ssb) +{ + if_key_not_available_throw (key); + expression fe (freq); + ssb = limit_ssb (ssb, -1); + m_user_keys.push_back (key); + m_user_comps.insert ({ key, std::make_unique ( + tag, fe.to_string (FPFormat::Eng), ssb) }); +} + +void +fourier_analysis::add_max_tone (const str_t &key, FACompTag tag, + const str_t ¢er, const str_t &width, + int ssb) +{ + if (FACompTag::Signal == tag || FACompTag::UserDist == tag + || FACompTag::Noise == tag) + { + if_key_not_available_throw (key); + expression ce (center); + expression we (width); + ssb = limit_ssb (ssb, -1); + m_user_keys.push_back (key); + m_user_comps.insert ({ key, std::make_unique ( + tag, ce.to_string (FPFormat::Eng), + we.to_string (FPFormat::Eng), ssb) }); } + else + { + throw runtime_error ( + "tag must be one of {" + + fa_comp_tag_map.at (to_int (FACompTag::Signal)) + ", " + + fa_comp_tag_map.at (to_int (FACompTag::UserDist)) + ", " + + fa_comp_tag_map.at (to_int (FACompTag::Noise)) + '}'); + } +} - void fourier_analysis::remove_comp(const str_t& key) +void +fourier_analysis::remove_comp (const str_t &key) +{ + if (is_comp (key)) { - if (is_comp(key)) { - m_user_comps.erase(key); - m_user_keys.erase(std::remove(m_user_keys.begin(), m_user_keys.end(), key), m_user_keys.end()); - } + m_user_comps.erase (key); + m_user_keys.erase ( + std::remove (m_user_keys.begin (), m_user_keys.end (), key), + m_user_keys.end ()); } +} } // namespace genalyzer_impl - Component Definition -namespace genalyzer_impl { // Configuration - - namespace { - - void fa_set_expr(const str_t& name, str_t& m_expr, const str_t& expr, const expression::var_set& disallowed) - { - expression e (expr); - if (e.depends_on(disallowed)) { - std::ostringstream ss (name); - ss << " may not depend on"; - for (const str_t& s : disallowed) { - ss << " '" << s << "',"; - } - ss.seekp(-1, std::ios_base::end); - throw runtime_error(ss.str()); - } else { - m_expr = e.to_string(FPFormat::Eng); - } - } +namespace genalyzer_impl +{ // Configuration - } // namespace anonymous +namespace +{ - int fourier_analysis::ssb(FASsb group) const +void +fa_set_expr (const str_t &name, str_t &m_expr, const str_t &expr, + const expression::var_set &disallowed) +{ + expression e (expr); + if (e.depends_on (disallowed)) { - switch (group) + std::ostringstream ss (name); + ss << " may not depend on"; + for (const str_t &s : disallowed) { - case FASsb::DC : - return m_ssb_dc; - case FASsb::Signal : - return m_ssb_sig; - case FASsb::WO : - return m_ssb_wo; - default : - return m_ssb_def; + ss << " '" << s << "',"; } + ss.seekp (-1, std::ios_base::end); + throw runtime_error (ss.str ()); } - - void fourier_analysis::set_analysis_band(const str_t& center, const str_t& width) + else { - fa_set_expr("ab_center", m_ab_center, center, {}); - fa_set_expr("ab_width", m_ab_width, width, {}); + m_expr = e.to_string (FPFormat::Eng); } +} + +} // namespace anonymous - void fourier_analysis::set_clk(const std::set& clk) +int +fourier_analysis::ssb (FASsb group) const +{ + switch (group) { - m_clk.clear(); - for (int n : clk) { - if (2 <= n && n <= 256) { - m_clk.insert(n); - } - } + case FASsb::DC: + return m_ssb_dc; + case FASsb::Signal: + return m_ssb_sig; + case FASsb::WO: + return m_ssb_wo; + default: + return m_ssb_def; } - - void fourier_analysis::set_fdata(const str_t& expr) +} + +void +fourier_analysis::set_analysis_band (const str_t ¢er, const str_t &width) +{ + fa_set_expr ("ab_center", m_ab_center, center, {}); + fa_set_expr ("ab_width", m_ab_width, width, {}); +} + +void +fourier_analysis::set_clk (const std::set &clk) +{ + m_clk.clear (); + for (int n : clk) { - expression::var_set disallowed {"fbin", "fdata", "fshift"}; - fa_set_expr("fdata", m_fdata, expr, disallowed); + if (2 <= n && n <= 256) + { + m_clk.insert (n); + } } - - void fourier_analysis::set_fsample(const str_t& expr) +} + +void +fourier_analysis::set_fdata (const str_t &expr) +{ + expression::var_set disallowed{ "fbin", "fdata", "fshift" }; + fa_set_expr ("fdata", m_fdata, expr, disallowed); +} + +void +fourier_analysis::set_fsample (const str_t &expr) +{ + expression::var_set disallowed{ "fbin", "fdata", "fs", "fshift" }; + fa_set_expr ("fsample", m_fsample, expr, disallowed); +} + +void +fourier_analysis::set_fshift (const str_t &expr) +{ + expression::var_set disallowed{ "fshift" }; + fa_set_expr ("fshift", m_fshift, expr, disallowed); +} + +void +fourier_analysis::set_hd (int n) +{ + m_hd = std::clamp (n, std::get<0> (mmd_hd), std::get<1> (mmd_hd)); +} + +void +fourier_analysis::set_ilv (const std::set &ilv) +{ + m_ilv.clear (); + for (int n : ilv) { - expression::var_set disallowed {"fbin", "fdata", "fs", "fshift"}; - fa_set_expr("fsample", m_fsample, expr, disallowed); + if (2 <= n && n <= 64) + { + m_ilv.insert (n); + } } - - void fourier_analysis::set_fshift(const str_t& expr) +} + +void +fourier_analysis::set_imd (int n) +{ + m_imd = std::clamp (n, std::get<0> (mmd_imd), std::get<1> (mmd_imd)); +} + +void +fourier_analysis::set_ssb (FASsb group, int ssb) +{ + switch (group) { - expression::var_set disallowed {"fshift"}; - fa_set_expr("fshift", m_fshift, expr, disallowed); + case FASsb::DC: + m_ssb_dc = limit_ssb (ssb, -1); + break; + case FASsb::Signal: + m_ssb_sig = limit_ssb (ssb, -1); + break; + case FASsb::WO: + m_ssb_wo = limit_ssb (ssb, -1); + break; + default: + m_ssb_def = limit_ssb (ssb, std::get<0> (mmd_ssb)); + break; } +} - void fourier_analysis::set_hd(int n) +void +fourier_analysis::set_var (const str_t &key, real_t x) +{ + if (!is_var (key)) { - m_hd = std::clamp(n, std::get<0>(mmd_hd), std::get<1>(mmd_hd)); + if_key_not_available_throw (key); } - - void fourier_analysis::set_ilv(const std::set& ilv) + if (!std::isfinite (x)) { - m_ilv.clear(); - for (int n : ilv) { - if (2 <= n && n <= 64) { - m_ilv.insert(n); - } - } + throw runtime_error ("got non-finite value"); } + m_user_vars[key] = x; +} + +void +fourier_analysis::set_wo (int n) +{ + m_wo = std::clamp (n, std::get<0> (mmd_wo), std::get<1> (mmd_wo)); +} - void fourier_analysis::set_imd(int n) +} // namespace genalyzer_impl - Configuration + +namespace genalyzer_impl +{ // Key Queries + +bool +fourier_analysis::is_reserved (const str_t &key) +{ + if (reserved_keys.end () != reserved_keys.find (key)) { - m_imd = std::clamp(n, std::get<0>(mmd_imd), std::get<1>(mmd_imd)); + return true; } - - void fourier_analysis::set_ssb(FASsb group, int ssb) + for (const str_t &pat : reserved_patterns) { - switch (group) + std::regex re (pat); + if (std::regex_match (key, re)) { - case FASsb::DC : - m_ssb_dc = limit_ssb(ssb, -1); - break; - case FASsb::Signal : - m_ssb_sig = limit_ssb(ssb, -1); - break; - case FASsb::WO : - m_ssb_wo = limit_ssb(ssb, -1); - break; - default : - m_ssb_def = limit_ssb(ssb, std::get<0>(mmd_ssb)); - break; + return true; } } + return false; +} + +bool +fourier_analysis::is_valid (const str_t &key) +{ + std::regex re (key_pattern); + return std::regex_match (key, re); +} - void fourier_analysis::set_var(const str_t& key, real_t x) +} // namespace genalyzer_impl - Key Queries + +namespace genalyzer_impl +{ // Other Member Functions + +str_t +fourier_analysis::flat_tone_key (const str_t &key, int result_index) +{ + fa_tone_result_map.contains (result_index, true); + return key + flat_key_coupler + fa_tone_result_map.at (result_index); +} + +std::pair +fourier_analysis::split_key (const str_t &key) +{ + std::pair keys{ "", "" }; + size_t pos = key.find (flat_key_coupler); + if (std::string::npos == pos) { - if (!is_var(key)) { - if_key_not_available_throw(key); - } - if (!std::isfinite(x)) { - throw runtime_error("got non-finite value"); - } - m_user_vars[key] = x; + keys.first = key; } - - void fourier_analysis::set_wo(int n) + else { - m_wo = std::clamp(n, std::get<0>(mmd_wo), std::get<1>(mmd_wo)); + keys.first = key.substr (0, pos); + keys.second = key.substr (pos + flat_key_coupler.length ()); } - -} // namespace genalyzer_impl - Configuration - -namespace genalyzer_impl { // Key Queries - - bool fourier_analysis::is_reserved(const str_t& key) + return keys; +} + +str_t +fourier_analysis::preview (bool cplx) const +{ + const comp_data_t comp_data = generate_comps (cplx); + const str_vector &keys = std::get<0> (comp_data); + const comp_map &comps = std::get<1> (comp_data); + std::vector header{ { "Index", "Key", "Type", "Tag", "Spec" } }; + std::vector data; + int i = 0; + for (const str_t &key : keys) { - if (reserved_keys.end() != reserved_keys.find(key)) { - return true; - } - for (const str_t& pat : reserved_patterns) { - std::regex re (pat); - if (std::regex_match(key, re)) { - return true; - } - } - return false; + const comp_ptr &comp = comps.at (key); + str_vector row{ std::to_string (i), key }; + row.push_back (fa_comp_type_map.at (to_int (comp->type))); + row.push_back (fa_comp_tag_map.at (to_int (comp->tag))); + row.push_back (comp->spec ()); + data.push_back (row); + ++i; } - - bool fourier_analysis::is_valid(const str_t& key) + return table (header, data, 2, true, true); +} + +void +fourier_analysis::reset () +{ + fourier_analysis new_obj{}; + std::swap (new_obj, *this); +} + +namespace +{ + +bool +is_cplx_analysis (size_t in_size, size_t nfft) +{ + bool cplx = false; + if (in_size == nfft || in_size == nfft * 2) { - std::regex re (key_pattern); - return std::regex_match(key, re); + cplx = true; } - -} // namespace genalyzer_impl - Key Queries - -namespace genalyzer_impl { // Other Member Functions - - str_t fourier_analysis::flat_tone_key(const str_t& key, int result_index) + else if (!(in_size == nfft / 2 + 1 || in_size == (nfft / 2 + 1) * 2)) { - fa_tone_result_map.contains(result_index, true); - return key + flat_key_coupler + fa_tone_result_map.at(result_index); + throw runtime_error ("Invalid combination of data size and NFFT"); } - - std::pair fourier_analysis::split_key(const str_t& key) + return cplx; +} + +} // namespace anonymous + +std::vector +fourier_analysis::result_key_lengths (size_t in_size, size_t nfft) const +{ + bool cplx = is_cplx_analysis (in_size, nfft); + const comp_data_t comp_data = generate_comps (cplx); + const str_vector &comp_keys = std::get<0> (comp_data); + const size_t num_result_keys = static_cast (FAResult::__SIZE__); + const size_t num_tone_result_keys + = static_cast (FAToneResult::__SIZE__); + size_t total_keys + = num_result_keys + num_tone_result_keys * comp_keys.size (); + std::vector key_lengths (total_keys); + size_t i = 0; + for (int j = 0; j < static_cast (num_result_keys); ++j) { - std::pair keys {"", ""}; - size_t pos = key.find(flat_key_coupler); - if (std::string::npos == pos) { - keys.first = key; - } else { - keys.first = key.substr(0, pos); - keys.second = key.substr(pos + flat_key_coupler.length()); - } - return keys; - } - - str_t fourier_analysis::preview(bool cplx) const - { - const comp_data_t comp_data = generate_comps(cplx); - const str_vector& keys = std::get<0>(comp_data); - const comp_map& comps = std::get<1>(comp_data); - std::vector header {{"Index", "Key", "Type", "Tag", "Spec"}}; - std::vector data; - int i = 0; - for (const str_t& key : keys) { - const comp_ptr& comp = comps.at(key); - str_vector row {std::to_string(i), key}; - row.push_back(fa_comp_type_map.at(to_int(comp->type))); - row.push_back(fa_comp_tag_map.at(to_int(comp->tag))); - row.push_back(comp->spec()); - data.push_back(row); - ++i; - } - return table(header, data, 2, true, true); + key_lengths[i] = fa_result_map.at (j).length (); + i += 1; } - - void fourier_analysis::reset() + size_t key_coupler_len = flat_key_coupler.length (); + std::vector tone_result_key_lengths (num_tone_result_keys, + key_coupler_len); + for (int j = 0; j < static_cast (num_tone_result_keys); ++j) { - fourier_analysis new_obj {}; - std::swap(new_obj, *this); + tone_result_key_lengths[j] += fa_tone_result_map.at (j).length (); } - - namespace { - - bool is_cplx_analysis(size_t in_size, size_t nfft) + for (const str_t &ckey : comp_keys) + { + const size_t ckey_len = ckey.length (); + for (size_t rkey_len : tone_result_key_lengths) { - bool cplx = false; - if (in_size == nfft || in_size == nfft * 2) { - cplx = true; - } else if (!(in_size == nfft / 2 + 1 || in_size == (nfft / 2 + 1) * 2)) { - throw runtime_error("Invalid combination of data size and NFFT"); - } - return cplx; + key_lengths[i] = ckey_len + rkey_len; + i += 1; } - - } // namespace anonymous - - std::vector fourier_analysis::result_key_lengths(size_t in_size, size_t nfft) const - { - bool cplx = is_cplx_analysis(in_size, nfft); - const comp_data_t comp_data = generate_comps(cplx); - const str_vector& comp_keys = std::get<0>(comp_data); - const size_t num_result_keys = static_cast(FAResult::__SIZE__); - const size_t num_tone_result_keys = static_cast(FAToneResult::__SIZE__); - size_t total_keys = num_result_keys + num_tone_result_keys * comp_keys.size(); - std::vector key_lengths (total_keys); - size_t i = 0; - for (int j = 0; j < static_cast(num_result_keys); ++j) { - key_lengths[i] = fa_result_map.at(j).length(); - i += 1; - } - size_t key_coupler_len = flat_key_coupler.length(); - std::vector tone_result_key_lengths (num_tone_result_keys, key_coupler_len); - for (int j = 0; j < static_cast(num_tone_result_keys); ++j) { - tone_result_key_lengths[j] += fa_tone_result_map.at(j).length(); - } - for (const str_t& ckey : comp_keys) { - const size_t ckey_len = ckey.length(); - for (size_t rkey_len : tone_result_key_lengths) { - key_lengths[i] = ckey_len + rkey_len; - i += 1; - } - } - return key_lengths; - } - - size_t fourier_analysis::results_size(size_t in_size, size_t nfft) const - { - bool cplx = is_cplx_analysis(in_size, nfft); - const comp_data_t comp_data = generate_comps(cplx); - const str_vector& keys = std::get<0>(comp_data); - size_t size = fa_result_map.size(); - size += fa_tone_result_map.size() * keys.size(); - return size; } + return key_lengths; +} + +size_t +fourier_analysis::results_size (size_t in_size, size_t nfft) const +{ + bool cplx = is_cplx_analysis (in_size, nfft); + const comp_data_t comp_data = generate_comps (cplx); + const str_vector &keys = std::get<0> (comp_data); + size_t size = fa_result_map.size (); + size += fa_tone_result_map.size () * keys.size (); + return size; +} } // namespace genalyzer_impl - Other Member Functions -namespace genalyzer_impl { // Virtual Function Overrides +namespace genalyzer_impl +{ // Virtual Function Overrides - bool fourier_analysis::equals_impl(const object& that_obj) const +bool +fourier_analysis::equals_impl (const object &that_obj) const +{ + if (ObjectType::FourierAnalysis != that_obj.object_type ()) { - if (ObjectType::FourierAnalysis != that_obj.object_type()) { - return false; - } - auto& that = static_cast(that_obj); - if ( (this->clk_as_noise != that.clk_as_noise ) || - (this->dc_as_dist != that.dc_as_dist ) || - (this->en_conv_offset != that.en_conv_offset) || - (this->en_fund_images != that.en_fund_images) || - (this->en_quad_errors != that.en_quad_errors) || - (this->ilv_as_noise != that.ilv_as_noise ) ) { - return false; - } - if ( (this->m_hd != that.m_hd ) || - (this->m_imd != that.m_imd ) || - (this->m_wo != that.m_wo ) || - (this->m_ssb_def != that.m_ssb_def ) || - (this->m_ssb_dc != that.m_ssb_dc ) || - (this->m_ssb_sig != that.m_ssb_sig ) || - (this->m_ssb_wo != that.m_ssb_wo ) ) { - return false; - } - if ( (this->m_ab_center != that.m_ab_center ) || - (this->m_ab_width != that.m_ab_width ) || - (this->m_fdata != that.m_fdata ) || - (this->m_fsample != that.m_fsample ) || - (this->m_fshift != that.m_fshift ) ) { - return false; - } - if ( (this->m_clk != that.m_clk ) || - (this->m_ilv != that.m_ilv ) || - (this->m_user_keys != that.m_user_keys ) || - (this->m_user_vars != that.m_user_vars ) ) { - return false; - } - for (const str_t& key : m_user_keys) { - const fourier_analysis_component& this_comp = *this->m_user_comps.at(key); - const fourier_analysis_component& that_comp = *that.m_user_comps.at(key); - if (!this_comp.equals(that_comp)) { - return false; - } - } - return true; + return false; } - - str_t fourier_analysis::to_string_impl() const + auto &that = static_cast (that_obj); + if ((this->clk_as_noise != that.clk_as_noise) + || (this->dc_as_dist != that.dc_as_dist) + || (this->en_conv_offset != that.en_conv_offset) + || (this->en_fund_images != that.en_fund_images) + || (this->en_quad_errors != that.en_quad_errors) + || (this->ilv_as_noise != that.ilv_as_noise)) + { + return false; + } + if ((this->m_hd != that.m_hd) || (this->m_imd != that.m_imd) + || (this->m_wo != that.m_wo) || (this->m_ssb_def != that.m_ssb_def) + || (this->m_ssb_dc != that.m_ssb_dc) + || (this->m_ssb_sig != that.m_ssb_sig) + || (this->m_ssb_wo != that.m_ssb_wo)) + { + return false; + } + if ((this->m_ab_center != that.m_ab_center) + || (this->m_ab_width != that.m_ab_width) + || (this->m_fdata != that.m_fdata) || (this->m_fsample != that.m_fsample) + || (this->m_fshift != that.m_fshift)) { - return "=====\nFIXME\n=====\n"; + return false; } - + if ((this->m_clk != that.m_clk) || (this->m_ilv != that.m_ilv) + || (this->m_user_keys != that.m_user_keys) + || (this->m_user_vars != that.m_user_vars)) + { + return false; + } + for (const str_t &key : m_user_keys) + { + const fourier_analysis_component &this_comp + = *this->m_user_comps.at (key); + const fourier_analysis_component &that_comp + = *that.m_user_comps.at (key); + if (!this_comp.equals (that_comp)) + { + return false; + } + } + return true; +} + +str_t +fourier_analysis::to_string_impl () const +{ + return "=====\nFIXME\n=====\n"; +} + } // namespace genalyzer_impl -namespace genalyzer_impl { // Non-Public +namespace genalyzer_impl +{ // Non-Public - const str_t fourier_analysis::key_pattern = "[[:alpha:]][[:alnum:]_]*"; +const str_t fourier_analysis::key_pattern = "[[:alpha:]][[:alnum:]_]*"; - const str_t fourier_analysis::wo_pattern = "^wo[1-9]?$"; +const str_t fourier_analysis::wo_pattern = "^wo[1-9]?$"; - const std::set fourier_analysis::reserved_keys = { - "co", // comp/var : converter offset - "dc", // comp : DC - "fbin", // var : frequency bin size - "fdata", // var : data rate - "fs", // var : sample rate - "fshift" // var : shift frequency - }; +const std::set fourier_analysis::reserved_keys = { + "co", // comp/var : converter offset + "dc", // comp : DC + "fbin", // var : frequency bin size + "fdata", // var : data rate + "fs", // var : sample rate + "fshift" // var : shift frequency +}; - const str_vector fourier_analysis::reserved_patterns = { - fourier_analysis::wo_pattern - }; +const str_vector fourier_analysis::reserved_patterns + = { fourier_analysis::wo_pattern }; - const str_t fourier_analysis::flat_key_coupler = ":"; +const str_t fourier_analysis::flat_key_coupler = ":"; - void fourier_analysis::add_comp(str_vector& keys, comp_map& comps, const str_t& k, comp_ptr c) +void +fourier_analysis::add_comp (str_vector &keys, comp_map &comps, const str_t &k, + comp_ptr c) +{ + if (comps.find (k) != comps.end ()) { - if (comps.find(k) != comps.end()) { - throw runtime_error("fourier_analysis::add_comp : key '" + k + "' already exists"); - } - keys.push_back(k); - comps.insert({k, std::move(c)}); - } - - int fourier_analysis::limit_ssb(int ssb, int lower_limit) { - lower_limit = (lower_limit < 0) ? -1 : std::get<0>(mmd_ssb); - return std::clamp(ssb, lower_limit, std::get<1>(mmd_ssb)); - } - - fourier_analysis::comp_data_t fourier_analysis::generate_comps(bool cplx) const - { - bool find_fi = en_fund_images && cplx; - bool find_qe = en_quad_errors && cplx; - comp_data_t comp_data; - str_vector& keys = std::get<0>(comp_data); - comp_map& comps = std::get<1>(comp_data); - std::set& ilos_clk_keys = std::get<2>(comp_data); - str_t key = ""; - int ssb = 0; - // DC and Converter Offset Components - ssb = (m_ssb_dc < 0) ? m_ssb_def : m_ssb_dc; - add_comp(keys, comps, "dc", fa_dc::create(ssb)); - if (en_conv_offset) { - add_comp(keys, comps, "co", fa_fixed_tone::create(FACompTag::UserDist, "0", ssb)); + throw runtime_error ("fourier_analysis::add_comp : key '" + k + + "' already exists"); + } + keys.push_back (k); + comps.insert ({ k, std::move (c) }); +} + +int +fourier_analysis::limit_ssb (int ssb, int lower_limit) +{ + lower_limit = (lower_limit < 0) ? -1 : std::get<0> (mmd_ssb); + return std::clamp (ssb, lower_limit, std::get<1> (mmd_ssb)); +} + +fourier_analysis::comp_data_t +fourier_analysis::generate_comps (bool cplx) const +{ + bool find_fi = en_fund_images && cplx; + bool find_qe = en_quad_errors && cplx; + comp_data_t comp_data; + str_vector &keys = std::get<0> (comp_data); + comp_map &comps = std::get<1> (comp_data); + std::set &ilos_clk_keys = std::get<2> (comp_data); + str_t key = ""; + int ssb = 0; + // DC and Converter Offset Components + ssb = (m_ssb_dc < 0) ? m_ssb_def : m_ssb_dc; + add_comp (keys, comps, "dc", fa_dc::create (ssb)); + if (en_conv_offset) + { + add_comp (keys, comps, "co", + fa_fixed_tone::create (FACompTag::UserDist, "0", ssb)); + } + // Interleaving Offset and Clock Components + std::set ilos_clk_terms; + std::set ilv_terms; + for (int x : m_ilv) + { + for (int i = 1; i <= x / 2; ++i) + { + ilv_terms.emplace (i, x, "fs"); + ilos_clk_terms.emplace (i, x, "fs"); } - // Interleaving Offset and Clock Components - std::set ilos_clk_terms; - std::set ilv_terms; - for (int x : m_ilv) { - for (int i = 1; i <= x / 2; ++i) { - ilv_terms.emplace(i, x, "fs"); - ilos_clk_terms.emplace(i, x, "fs"); + } + std::set clk_terms; + for (int x : m_clk) + { + for (int i = 1; i <= x / 2; ++i) + { + if (1 == std::gcd (i, x)) + { + clk_terms.emplace (i, x, "fs"); + ilos_clk_terms.emplace (i, x, "fs"); } } - std::set clk_terms; - for (int x : m_clk) + } + for (const fraction &f : ilos_clk_terms) + { + key = f.term; + if (ilv_terms.end () != ilv_terms.find (f)) { - for (int i = 1; i <= x / 2; ++i) { - if (1 == std::gcd(i, x)) { - clk_terms.emplace(i, x, "fs"); - ilos_clk_terms.emplace(i, x, "fs"); + bool is_also_clk = clk_terms.end () != clk_terms.find (f); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::ILOS, key, m_ssb_def)); + if (is_also_clk) + { + ilos_clk_keys.insert (key); + } + if (cplx && "fs/2" != key) + { + key.insert (0, 1, '-'); + add_comp ( + keys, comps, key, + fa_fixed_tone::create (FACompTag::ILOS, key, m_ssb_def)); + if (is_also_clk) + { + ilos_clk_keys.insert (key); } } } - for (const fraction& f : ilos_clk_terms) { - key = f.term; - if (ilv_terms.end() != ilv_terms.find(f)) { - bool is_also_clk = clk_terms.end() != clk_terms.find(f); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::ILOS, key, m_ssb_def)); - if (is_also_clk) { - ilos_clk_keys.insert(key); - } - if (cplx && "fs/2" != key) { - key.insert(0, 1, '-'); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::ILOS, key, m_ssb_def)); - if (is_also_clk) { - ilos_clk_keys.insert(key); - } - } - } else { - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::CLK, key, m_ssb_def)); - if (cplx && "fs/2" != key) { - key.insert(0, 1, '-'); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::CLK, key, m_ssb_def)); - } + else + { + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::CLK, key, m_ssb_def)); + if (cplx && "fs/2" != key) + { + key.insert (0, 1, '-'); + add_comp ( + keys, comps, key, + fa_fixed_tone::create (FACompTag::CLK, key, m_ssb_def)); } } - // User and Auto Components - str_vector fund_keys; - int def_sig_ssb = (m_ssb_sig < 0) ? m_ssb_def : m_ssb_sig; - for (const str_t& ukey : m_user_keys) { - const comp_ptr& comp = m_user_comps.at(ukey); - int def_user_ssb = (FACompTag::Signal == comp->tag) ? def_sig_ssb : m_ssb_def; - if (FACompType::FixedTone == comp->type) { - const auto& c = static_cast(*comp); - ssb = (c.ssb < 0) ? def_user_ssb : c.ssb; - add_comp(keys, comps, ukey, fa_fixed_tone::create(c.tag, c.freq, ssb)); - } else if (FACompType::MaxTone == comp->type) { - const auto& c = static_cast(*comp); - ssb = (c.ssb < 0) ? def_user_ssb : c.ssb; - add_comp(keys, comps, ukey, fa_max_tone::create(c.tag, c.center, c.width, ssb)); - } else { - throw runtime_error("fourier_analysis::generate_comps : unsupported component type"); + } + // User and Auto Components + str_vector fund_keys; + int def_sig_ssb = (m_ssb_sig < 0) ? m_ssb_def : m_ssb_sig; + for (const str_t &ukey : m_user_keys) + { + const comp_ptr &comp = m_user_comps.at (ukey); + int def_user_ssb + = (FACompTag::Signal == comp->tag) ? def_sig_ssb : m_ssb_def; + if (FACompType::FixedTone == comp->type) + { + const auto &c = static_cast (*comp); + ssb = (c.ssb < 0) ? def_user_ssb : c.ssb; + add_comp (keys, comps, ukey, + fa_fixed_tone::create (c.tag, c.freq, ssb)); + } + else if (FACompType::MaxTone == comp->type) + { + const auto &c = static_cast (*comp); + ssb = (c.ssb < 0) ? def_user_ssb : c.ssb; + add_comp (keys, comps, ukey, + fa_max_tone::create (c.tag, c.center, c.width, ssb)); + } + else + { + throw runtime_error ( + "fourier_analysis::generate_comps : unsupported component type"); + } + if (FACompTag::Signal != comp->tag) + { + continue; + } + fund_keys.push_back (ukey); + ssb = m_ssb_def; + // Fundamental Image Component + if (find_fi) + { + key = '-' + ukey; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::HD, key, ssb)); + } + // Harmonic Distortion Components + for (int i = 2; i <= m_hd; ++i) + { + if (is_even (i)) + { + // even order + key = std::to_string (i) + ukey; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::HD, key, ssb)); + if (cplx) + { + key.insert (0, 1, '-'); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::HD, key, ssb)); + } } - if (FACompTag::Signal != comp->tag) { - continue; + else + { + // odd order + // real data: j = +i + // cplx data: j = -i for 3, 7, 11... + // j = +i for 5, 9, 13... + int j = (cplx && is_odd (i / 2)) ? -i : i; + key = std::to_string (j) + ukey; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::HD, key, ssb)); + if (find_qe) + { + key = std::to_string (-j) + ukey; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::HD, key, ssb)); + } } - fund_keys.push_back(ukey); - ssb = m_ssb_def; - // Fundamental Image Component - if (find_fi) { - key = '-' + ukey; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::HD, key, ssb)); + } + // Interleaving Gain and Timing Components + for (const fraction &f : ilv_terms) + { + key = ukey + '+' + f.term; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::ILGT, key, ssb)); + if ("fs/2" != f.term) + { + key = ukey + '-' + f.term; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::ILGT, key, ssb)); } - // Harmonic Distortion Components - for (int i = 2; i <= m_hd; ++i) { - if (is_even(i)) { - // even order - key = std::to_string(i) + ukey; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::HD, key, ssb)); - if (cplx) { - key.insert(0, 1, '-'); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::HD, key, ssb)); - } - } else { - // odd order - // real data: j = +i - // cplx data: j = -i for 3, 7, 11... - // j = +i for 5, 9, 13... - int j = (cplx && is_odd(i / 2)) ? -i : i; - key = std::to_string(j) + ukey; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::HD, key, ssb)); - if (find_qe) { - key = std::to_string(-j) + ukey; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::HD, key, ssb)); - } + if (find_qe) + { + key = negate (ukey + '+' + f.term, true); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::ILGT, key, ssb)); + if ("fs/2" != f.term) + { + key = negate (ukey + '-' + f.term, true); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::ILGT, key, ssb)); } } - // Interleaving Gain and Timing Components - for (const fraction& f : ilv_terms) { - key = ukey + '+' + f.term; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::ILGT, key, ssb)); - if ("fs/2" != f.term) { - key = ukey + '-' + f.term; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::ILGT, key, ssb)); - } - if (find_qe) { - key = negate(ukey + '+' + f.term, true); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::ILGT, key, ssb)); - if ("fs/2" != f.term) { - key = negate(ukey + '-' + f.term, true); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::ILGT, key, ssb)); - } - } + } + // Intermodulation Distorion Components + for (const str_t &ka : fund_keys) + { + if (ka == ukey) + { + continue; } - // Intermodulation Distorion Components - for (const str_t& ka : fund_keys) { - if (ka == ukey) { - continue; - } - const str_t& kb = ukey; - for (int order = 2; order <= m_imd; ++order) { - int group = is_even(order) ? 0 : 1; - int pp = 0; - int qq = 0; - str_t p = ""; - str_t q = ""; - for (; group <= order; group += 2) { - if (group < order) { - // form: p * kx MINUS q * ky - pp = (order + group) / 2; - qq = order - pp; - p = (1 == pp) ? "" : std::to_string(pp); - q = (1 == qq) ? "" : std::to_string(qq); - if (0 == group) { - key = p + kb + '-' + q + ka; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - if (cplx) { - key = negate(key, true); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - } - } else if (is_even(order)) { - // even order - key = p + ka + '-' + q + kb; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - key = p + kb + '-' + q + ka; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - if (cplx) { - key = negate(p + ka + '-' + q + kb, true); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - key = negate(p + kb + '-' + q + ka, true); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - } - } else { - // odd order - bool neg = cplx && is_odd(group / 2); - key = negate(p + ka + '-' + q + kb, neg); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - key = negate(p + kb + '-' + q + ka, neg); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - if (cplx) { - key = negate(p + ka + '-' + q + kb, !neg); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - key = negate(p + kb + '-' + q + ka, !neg); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - } + const str_t &kb = ukey; + for (int order = 2; order <= m_imd; ++order) + { + int group = is_even (order) ? 0 : 1; + int pp = 0; + int qq = 0; + str_t p = ""; + str_t q = ""; + for (; group <= order; group += 2) + { + if (group < order) + { + // form: p * kx MINUS q * ky + pp = (order + group) / 2; + qq = order - pp; + p = (1 == pp) ? "" : std::to_string (pp); + q = (1 == qq) ? "" : std::to_string (qq); + if (0 == group) + { + key = p + kb + '-' + q + ka; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, key, + ssb)); + if (cplx) + { + key = negate (key, true); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); } - } else { // group == order - // form: p * kx PLUS q * ky - if (is_even(order)) { - // even order - for (qq = 1; qq < group; ++qq) { - pp = order - qq; - p = (1 == pp) ? "" : std::to_string(pp); - q = (1 == qq) ? "" : std::to_string(qq); - key = p + ka + '+' + q + kb; - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - } - if (cplx) { - for (pp = 1; pp < group; ++pp) { - qq = order - pp; - p = (1 == pp) ? "" : std::to_string(pp); - q = (1 == qq) ? "" : std::to_string(qq); - key = negate(p + ka + '+' + q + kb, true); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - } - } - } else { - // odd order - bool neg = cplx && is_odd(group / 2); - for (qq = 1; qq < group; ++qq) { - pp = order - qq; - p = (1 == pp) ? "" : std::to_string(pp); - q = (1 == qq) ? "" : std::to_string(qq); - key = negate(p + ka + '+' + q + kb, neg); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); + } + else if (is_even (order)) + { + // even order + key = p + ka + '-' + q + kb; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, key, + ssb)); + key = p + kb + '-' + q + ka; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, key, + ssb)); + if (cplx) + { + key = negate (p + ka + '-' + q + kb, true); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); + key = negate (p + kb + '-' + q + ka, true); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); + } + } + else + { + // odd order + bool neg = cplx && is_odd (group / 2); + key = negate (p + ka + '-' + q + kb, neg); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, key, + ssb)); + key = negate (p + kb + '-' + q + ka, neg); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, key, + ssb)); + if (cplx) + { + key = negate (p + ka + '-' + q + kb, !neg); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); + key = negate (p + kb + '-' + q + ka, !neg); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); + } + } + } + else + { // group == order + // form: p * kx PLUS q * ky + if (is_even (order)) + { + // even order + for (qq = 1; qq < group; ++qq) + { + pp = order - qq; + p = (1 == pp) ? "" : std::to_string (pp); + q = (1 == qq) ? "" : std::to_string (qq); + key = p + ka + '+' + q + kb; + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); + } + if (cplx) + { + for (pp = 1; pp < group; ++pp) + { + qq = order - pp; + p = (1 == pp) ? "" : std::to_string (pp); + q = (1 == qq) ? "" : std::to_string (qq); + key = negate (p + ka + '+' + q + kb, true); + add_comp (keys, comps, key, + fa_fixed_tone::create ( + FACompTag::IMD, key, ssb)); } - if (find_qe) { - for (pp = 1; pp < group; ++pp) { - qq = order - pp; - p = (1 == pp) ? "" : std::to_string(pp); - q = (1 == qq) ? "" : std::to_string(qq); - key = negate(p + ka + '+' + q + kb, !neg); - add_comp(keys, comps, key, fa_fixed_tone::create(FACompTag::IMD, key, ssb)); - } + } + } + else + { + // odd order + bool neg = cplx && is_odd (group / 2); + for (qq = 1; qq < group; ++qq) + { + pp = order - qq; + p = (1 == pp) ? "" : std::to_string (pp); + q = (1 == qq) ? "" : std::to_string (qq); + key = negate (p + ka + '+' + q + kb, neg); + add_comp (keys, comps, key, + fa_fixed_tone::create (FACompTag::IMD, + key, ssb)); + } + if (find_qe) + { + for (pp = 1; pp < group; ++pp) + { + qq = order - pp; + p = (1 == pp) ? "" : std::to_string (pp); + q = (1 == qq) ? "" : std::to_string (qq); + key = negate (p + ka + '+' + q + kb, !neg); + add_comp (keys, comps, key, + fa_fixed_tone::create ( + FACompTag::IMD, key, ssb)); } } } @@ -853,689 +1029,788 @@ namespace genalyzer_impl { // Non-Public } } } - // WO Components - ssb = (m_ssb_wo < 0) ? m_ssb_def : m_ssb_wo; - if (1 == m_wo) { - add_comp(keys, comps, "wo", fa_wo_tone::create(ssb)); - } else { - for (int i = 1; i <= m_wo; ++i) { - key = "wo" + std::to_string(i); - add_comp(keys, comps, key, fa_wo_tone::create(ssb)); - } - } - // Done! - return comp_data; } - - void fourier_analysis::if_key_not_available_throw(const str_t& key) const + // WO Components + ssb = (m_ssb_wo < 0) ? m_ssb_def : m_ssb_wo; + if (1 == m_wo) + { + add_comp (keys, comps, "wo", fa_wo_tone::create (ssb)); + } + else { - if (is_reserved(key)) { - throw runtime_error("key '" + key + "' is reserved"); - } else if (is_comp(key) || is_var(key)) { - throw runtime_error("key '" + key + "' already exists"); - } else if (!is_valid(key)) { - throw runtime_error("key '" + key + "' is invalid"); + for (int i = 1; i <= m_wo; ++i) + { + key = "wo" + std::to_string (i); + add_comp (keys, comps, key, fa_wo_tone::create (ssb)); } } + // Done! + return comp_data; +} + +void +fourier_analysis::if_key_not_available_throw (const str_t &key) const +{ + if (is_reserved (key)) + { + throw runtime_error ("key '" + key + "' is reserved"); + } + else if (is_comp (key) || is_var (key)) + { + throw runtime_error ("key '" + key + "' already exists"); + } + else if (!is_valid (key)) + { + throw runtime_error ("key '" + key + "' is invalid"); + } +} } // namespace genalyzer_impl - Non-Public -namespace genalyzer_impl { // Analysis and related subroutines - - namespace { - - using comp_index_mag_t = std::pair; - - enum class FAMask : int { - AB = 0x1000, // Analysis Band - Comp, // All components - WO, // Used to search for worst others - NAD, // Noise and distortion - THD, // Total harmonic distortion: HD + IMD - ILV, // Interleaving: ILOS + ILGT - Dist, // Total distortion: THD + UserDist [+ CLK] [+ ILV] - Noise // Total noise: NAD - Dist - }; - - real_t alias(real_t freq, real_t fs, bool fold) +namespace genalyzer_impl +{ // Analysis and related subroutines + +namespace +{ + +using comp_index_mag_t = std::pair; + +enum class FAMask : int +{ + AB = 0x1000, // Analysis Band + Comp, // All components + WO, // Used to search for worst others + NAD, // Noise and distortion + THD, // Total harmonic distortion: HD + IMD + ILV, // Interleaving: ILOS + ILGT + Dist, // Total distortion: THD + UserDist [+ CLK] [+ ILV] + Noise // Total noise: NAD - Dist +}; + +real_t +alias (real_t freq, real_t fs, bool fold) +{ + freq -= std::floor (freq / fs) * fs; // freq in [0, fs) + return (fold && fs < 2 * freq) ? (fs - freq) : freq; +} + +bool +check_args (const real_t *msq_data, const size_t msq_size, const size_t nfft, + const cplx_t *fft_data, const size_t fft_size) +{ + check_array ("", "mean-square magnitude array", msq_data, msq_size); + bool cplx = msq_size == nfft; + if (!cplx) + { + if (msq_size != nfft / 2 + 1) { - freq -= std::floor(freq / fs) * fs; // freq in [0, fs) - return (fold && fs < 2 * freq) ? (fs - freq) : freq; + throw runtime_error ("check_args : data size error"); } - - bool check_args( - const real_t* msq_data, - const size_t msq_size, - const size_t nfft, - const cplx_t* fft_data, - const size_t fft_size - ) - { - check_array("", "mean-square magnitude array", msq_data, msq_size); - bool cplx = msq_size == nfft; - if (!cplx) { - if (msq_size != nfft / 2 + 1) { - throw runtime_error("check_args : data size error"); - } - } - if (fft_data) { - if (msq_size != fft_size) { - throw runtime_error("check_args : data size error"); - } - } - return cplx; - } - - fa_tone_results null_tone_results(FACompTag tag) + } + if (fft_data) + { + if (msq_size != fft_size) { - fa_tone_results results; - results.set(FAToneResult::Tag , static_cast(tag)); - results.set(FAToneResult::Freq , 0.0); - results.set(FAToneResult::FFinal , 0.0); - results.set(FAToneResult::FWAvg , 0.0); - results.set(FAToneResult::InBand , 0.0); - results.set(FAToneResult::I1 , -1.0); - results.set(FAToneResult::I2 , -1.0); - results.set(FAToneResult::NBins , 0.0); - results.set_mag(0.0); - return results; + throw runtime_error ("check_args : data size error"); } - - real_t fa_db10(real_t msq_num, real_t msq_den = 1.0) + } + return cplx; +} + +fa_tone_results +null_tone_results (FACompTag tag) +{ + fa_tone_results results; + results.set (FAToneResult::Tag, static_cast (tag)); + results.set (FAToneResult::Freq, 0.0); + results.set (FAToneResult::FFinal, 0.0); + results.set (FAToneResult::FWAvg, 0.0); + results.set (FAToneResult::InBand, 0.0); + results.set (FAToneResult::I1, -1.0); + results.set (FAToneResult::I2, -1.0); + results.set (FAToneResult::NBins, 0.0); + results.set_mag (0.0); + return results; +} + +real_t +fa_db10 (real_t msq_num, real_t msq_den = 1.0) +{ + if (msq_num <= 0.0 && msq_den <= 0.0) + { + return 0.0; + } + else if (msq_num <= 0.0) + { + return k_abs_min_db; + } + else if (msq_den <= 0.0) + { + return k_abs_max_db; + } + else + { + return bounded_db10 (msq_num / msq_den); + } +} + +real_t +fa_phase (const fa_tone_results &r, const cplx_t *fft_data, bool cplx, + real_t fdata, real_t fshift) +{ + real_t phase = 0.0; + if (fft_data && 1 == r.get (FAToneResult::NBins)) + { + diff_t index = static_cast (r.get (FAToneResult::I1)); + phase = std::arg (fft_data[index]); + if (!cplx) { - if (msq_num <= 0.0 && msq_den <= 0.0) { - return 0.0; - } else if (msq_num <= 0.0) { - return k_abs_min_db; - } else if (msq_den <= 0.0) { - return k_abs_max_db; - } else { - return bounded_db10(msq_num / msq_den); + real_t f = r.get (FAToneResult::Freq) + fshift; + f -= std::floor (f / fdata) * fdata; // f in [0, fdata) + if (fdata <= 2 * f) + { + phase *= -1.0; // invert phase if falias is in 2nd NZ } } - - real_t fa_phase( - const fa_tone_results& r, - const cplx_t* fft_data, - bool cplx, - real_t fdata, - real_t fshift - ) + } + return phase; +} + +diff_p +get_lrbins (size_t nfft, bool cplx, real_t cycles, int ssb) +{ + // Find nearest half cycle: + real_t nearest_half_cycle = cycles; // initialize to exact cycles + bool on_half_cycle = false; // false: x.0, true: x.5 + if (0 < ssb) + { // generate_comps() guarantees 0 <= ssb + nearest_half_cycle = std::round (nearest_half_cycle * 2.0); + on_half_cycle = is_odd (static_cast (nearest_half_cycle)); + nearest_half_cycle *= 0.5; // nearest half cycle (x.0 or x.5) + } + else + { + nearest_half_cycle + = std::round (nearest_half_cycle); // nearest whole cycle (x.0) + } + // Re-alias for special cases + nearest_half_cycle + = alias (nearest_half_cycle, static_cast (nfft), !cplx); + // Resolve SSB: + int min_ssb = std::get<0> (fourier_analysis::mmd_ssb); + int max_ssb = std::get<1> (fourier_analysis::mmd_ssb); + max_ssb = static_cast (std::min (nfft / 2, max_ssb)); + if (is_even (nfft) && !on_half_cycle) + { // Example( NFFT=32, !on_half_cycle ): + max_ssb -= 1; // ssb=16 -> 1+2*16=33 bins - too many! + } // subtract 1: ssb=15 -> 1+2*15=31 bins - OK + ssb = std::clamp (ssb, min_ssb, max_ssb); + real_t half_width = static_cast (ssb); + if (on_half_cycle) + { + half_width -= 0.5; + } + // Left and right bins: + diff_t lbin = static_cast (nearest_half_cycle - half_width); + diff_t rbin = static_cast (nearest_half_cycle + half_width); + return diff_p (lbin, rbin); +} + +bool +has_tone_results (const fourier_analysis_component &c) +{ + return (FACompType::DC == c.type) || (FACompType::FixedTone == c.type) + || (FACompType::MaxTone == c.type) || (FACompType::WOTone == c.type); +} + +fa_tone_results +meas_dc (const fa_dc &comp, const real_t *msq_data, const size_t msq_size, + const size_t nfft, fourier_analysis::mask_map &masks) +{ + const bool cplx = msq_size == nfft; + const diff_p lrbins = get_lrbins (nfft, cplx, 0.0, comp.ssb); + fourier_analysis_comp_mask m (cplx, msq_size); + m.set_range (lrbins.first, lrbins.second); + masks.at (to_int (FACompTag::DC)) = m; + masks.at (to_int (FAMask::Comp)) |= m; + size_t i1, i2, nbins; + std::tie (i1, i2, nbins) = m.get_indexes (); + real_t fwavg = 0.0; // FIXME: Real: 0.0 by definition; Cplx: calc + bool inband = masks.at (to_int (FAMask::AB)).overlaps (i1, i2); + real_t mag2 = m.sum (msq_data, msq_size); + fa_tone_results results; + results.set (FAToneResult::Tag, static_cast (FACompTag::DC)); + results.set (FAToneResult::Freq, 0.0); + results.set (FAToneResult::FFinal, 0.0); + results.set (FAToneResult::FWAvg, fwavg); + results.set (FAToneResult::I1, static_cast (i1)); + results.set (FAToneResult::I2, static_cast (i2)); + results.set (FAToneResult::NBins, static_cast (nbins)); + results.set (FAToneResult::InBand, inband ? 1.0 : 0.0); + results.set_mag (mag2); + return results; +} + +fa_tone_results +meas_fixed_tone (const str_t &key, const fa_fixed_tone &comp, + const real_t *msq_data, const size_t msq_size, + const size_t nfft, fourier_analysis::mask_map &masks, + fourier_analysis::var_map &vars) +{ + const bool cplx = msq_size == nfft; + const real_t fbin = vars.at ("fbin"); + const real_t fdata = vars.at ("fdata"); + const real_t fshift = vars.at ("fshift"); + const real_t freq + = expression (comp.freq).evaluate (vars); // "actual" frequency + const real_t ffinal = alias (freq + fshift, fdata, + !cplx); // freq after translation and aliasing + const diff_p lrbins = get_lrbins (nfft, cplx, (ffinal / fbin), comp.ssb); + vars[key] = freq; + fourier_analysis_comp_mask m (cplx, msq_size); + m.set_range (lrbins.first, lrbins.second); + masks.at (to_int (comp.tag)) |= m; + masks.at (to_int (FAMask::Comp)) |= m; + size_t i1, i2, nbins; + std::tie (i1, i2, nbins) = m.get_indexes (); + real_t fwavg = 0.0; // FIXME + bool inband = masks.at (to_int (FAMask::AB)).overlaps (i1, i2); + real_t mag2 = m.sum (msq_data, msq_size); + fa_tone_results results; + results.set (FAToneResult::Tag, static_cast (comp.tag)); + results.set (FAToneResult::Freq, freq); + results.set (FAToneResult::FFinal, ffinal); + results.set (FAToneResult::FWAvg, fwavg); + results.set (FAToneResult::InBand, inband ? 1.0 : 0.0); + results.set (FAToneResult::I1, static_cast (i1)); + results.set (FAToneResult::I2, static_cast (i2)); + results.set (FAToneResult::NBins, static_cast (nbins)); + results.set_mag (mag2); + return results; +} + +// May implement search band in future. Note: search band != analysis band. +fa_tone_results +meas_max_tone (const str_t &key, const fa_max_tone &comp, + const real_t *msq_data, const size_t msq_size, + const size_t nfft, fourier_analysis::mask_map &masks, + fourier_analysis::var_map &vars) +{ + fourier_analysis_comp_mask search_mask = masks.at (to_int (FAMask::AB)); + fourier_analysis_comp_mask &comp_mask = masks.at (to_int (FAMask::Comp)); + search_mask.unset_ranges (comp_mask); + diff_t max_index, lower, upper; + std::tie (max_index, lower, upper) + = search_mask.find_max_index (msq_data, msq_size); + if (max_index < 0) + { + return null_tone_results (comp.tag); + } + const bool cplx = msq_size == nfft; + const real_t fbin = vars.at ("fbin"); + const real_t fshift = vars.at ("fshift"); + const real_t ffinal = max_index * fbin; + const real_t freq = ffinal - fshift; // this is a best guess + diff_p lrbins + = get_lrbins (nfft, cplx, static_cast (max_index), comp.ssb); + // Unlike FixedTone, MaxTone stops when it runs into another tone. Since DC + // is always found and is always at bin 0, we never have to worry about + // MaxTone wrapping. + lrbins.first = std::max (lower, lrbins.first); + lrbins.second = std::min (lrbins.second, upper); + fourier_analysis_comp_mask m (cplx, msq_size); + m.set_range (lrbins.first, lrbins.second); + comp_mask |= m; // add this range to component mask + masks.at (to_int (comp.tag)) |= m; // add this range to tag mask + size_t i1, i2, nbins; + std::tie (i1, i2, nbins) = m.get_indexes (); + real_t fwavg = 0.0; // FIXME + bool inband = masks.at (to_int (FAMask::AB)).overlaps (i1, i2); + real_t mag2 = m.sum (msq_data, msq_size); + vars[key] = freq; // should probably use fwavg (once implemented) + fa_tone_results results; + results.set (FAToneResult::Tag, static_cast (comp.tag)); + results.set (FAToneResult::Freq, freq); + results.set (FAToneResult::FFinal, ffinal); + results.set (FAToneResult::FWAvg, fwavg); + results.set (FAToneResult::InBand, inband ? 1.0 : 0.0); + results.set (FAToneResult::I1, static_cast (i1)); + results.set (FAToneResult::I2, static_cast (i2)); + results.set (FAToneResult::NBins, static_cast (nbins)); + results.set_mag (mag2); + return results; +} + +fa_tone_results +meas_wo_tone (const fa_wo_tone &comp, const real_t *msq_data, + const size_t msq_size, const size_t nfft, const real_t fbin, + const real_t fshift, fourier_analysis::mask_map &masks) +{ + fourier_analysis_comp_mask &wo_mask = masks.at (to_int (FAMask::WO)); + fourier_analysis_comp_mask &comp_mask = masks.at (to_int (FAMask::Comp)); + diff_t max_index, lower, upper; + std::tie (max_index, lower, upper) + = wo_mask.find_max_index (msq_data, msq_size); + if (max_index < 0) + { + return null_tone_results (comp.tag); + } + const bool cplx = msq_size == nfft; + const real_t ffinal = max_index * fbin; + const real_t freq = ffinal - fshift; // best guess + diff_p lrbins + = get_lrbins (nfft, cplx, static_cast (max_index), comp.ssb); + // Unlike FixedTone, MaxTone stops when it runs into another tone. Since DC + // is always found and is always at bin 0, we never have to worry about + // MaxTone wrapping. + lrbins.first = std::max (lower, lrbins.first); + lrbins.second = std::min (lrbins.second, upper); + fourier_analysis_comp_mask m (cplx, msq_size); + m.set_range (lrbins.first, lrbins.second); + comp_mask |= m; // add this range to component mask + wo_mask.unset_ranges (m); // remove this range from WO search mask + size_t i1, i2, nbins; + std::tie (i1, i2, nbins) = m.get_indexes (); + real_t fwavg = 0.0; // FIXME + real_t mag2 = m.sum (msq_data, msq_size); + fa_tone_results results; + results.set (FAToneResult::Tag, static_cast (comp.tag)); + results.set (FAToneResult::Freq, freq); + results.set (FAToneResult::FFinal, ffinal); + results.set (FAToneResult::FWAvg, fwavg); + results.set (FAToneResult::InBand, 1.0); // by definition + results.set (FAToneResult::I1, static_cast (i1)); + results.set (FAToneResult::I2, static_cast (i2)); + results.set (FAToneResult::NBins, static_cast (nbins)); + results.set_mag (mag2); + return results; +} + +void +update_maxspur (size_t key_index, const fa_tone_results &results, + bool dc_as_dist, const fourier_analysis::mask_map &masks, + comp_index_mag_t &maxspur_im) +{ + // A tone is a candidate for maxspur if: + // 1. it is in-band and non-Signal (these are assumed) + // 2. it is not DC, unless DC is treated as distortion (dc_as_dist is + // true) + // 3. it does not overlap any Signal tones (this needs explanation) + if (0.0 != results.get (FAToneResult::FFinal) || dc_as_dist) + { + const fourier_analysis_comp_mask &sig_mask + = masks.at (to_int (FACompTag::Signal)); + if (!sig_mask.overlaps (results.i1, results.i2)) { - real_t phase = 0.0; - if (fft_data && 1 == r.get(FAToneResult::NBins)) { - diff_t index = static_cast(r.get(FAToneResult::I1)); - phase = std::arg(fft_data[index]); - if (!cplx) { - real_t f = r.get(FAToneResult::Freq) + fshift; - f -= std::floor(f / fdata) * fdata; // f in [0, fdata) - if (fdata <= 2 * f) { - phase *= -1.0; // invert phase if falias is in 2nd NZ - } - } + real_t mag2 = results.get (FAToneResult::Mag); + mag2 *= mag2; + if (maxspur_im.first < 0 || maxspur_im.second < mag2) + { + maxspur_im.first = static_cast (key_index); + maxspur_im.second = mag2; } - return phase; } - - diff_p get_lrbins(size_t nfft, bool cplx, real_t cycles, int ssb) + } +} + +void +tone_updates (const str_t &key, size_t key_index, FACompTag tag, + const fa_tone_results &results, bool dc_as_dist, + fourier_analysis::mask_map &masks, + const std::set &ilos_clk_keys, + comp_index_mag_t &carrier_im, comp_index_mag_t &maxspur_im) +{ + if (ilos_clk_keys.find (key) != ilos_clk_keys.end ()) + { + masks.at (to_int (FACompTag::CLK)).set_range (results.i1, results.i2); + } + if (results.inband) + { + if (FACompTag::Signal == tag) { - // Find nearest half cycle: - real_t nearest_half_cycle = cycles; // initialize to exact cycles - bool on_half_cycle = false; // false: x.0, true: x.5 - if (0 < ssb) { // generate_comps() guarantees 0 <= ssb - nearest_half_cycle = std::round(nearest_half_cycle * 2.0); - on_half_cycle = is_odd(static_cast(nearest_half_cycle)); - nearest_half_cycle *= 0.5; // nearest half cycle (x.0 or x.5) - } else { - nearest_half_cycle = std::round(nearest_half_cycle); // nearest whole cycle (x.0) - } - // Re-alias for special cases - nearest_half_cycle = alias(nearest_half_cycle, static_cast(nfft), !cplx); - // Resolve SSB: - int min_ssb = std::get<0>(fourier_analysis::mmd_ssb); - int max_ssb = std::get<1>(fourier_analysis::mmd_ssb); - max_ssb = static_cast(std::min(nfft / 2, max_ssb)); - if (is_even(nfft) && !on_half_cycle) { // Example( NFFT=32, !on_half_cycle ): - max_ssb -= 1; // ssb=16 -> 1+2*16=33 bins - too many! - } // subtract 1: ssb=15 -> 1+2*15=31 bins - OK - ssb = std::clamp(ssb, min_ssb, max_ssb); - real_t half_width = static_cast(ssb); - if (on_half_cycle) { - half_width -= 0.5; + real_t mag2 = results.get (FAToneResult::Mag); + mag2 *= mag2; + if (carrier_im.first < 0 || mag2 < carrier_im.second) + { + carrier_im.first = static_cast (key_index); + carrier_im.second = mag2; } - // Left and right bins: - diff_t lbin = static_cast(nearest_half_cycle - half_width); - diff_t rbin = static_cast(nearest_half_cycle + half_width); - return diff_p(lbin, rbin); } - - bool has_tone_results(const fourier_analysis_component& c) + else { - return (FACompType::DC == c.type) - || (FACompType::FixedTone == c.type) - || (FACompType::MaxTone == c.type) - || (FACompType::WOTone == c.type); + update_maxspur (key_index, results, dc_as_dist, masks, maxspur_im); } - - fa_tone_results meas_dc( - const fa_dc& comp, - const real_t* msq_data, - const size_t msq_size, - const size_t nfft, - fourier_analysis::mask_map& masks - ) + } +} + +} // namespace anonymous + +fourier_analysis::mask_map +fourier_analysis::initialize_masks (bool cplx, size_t size) +{ + mask_map masks{ + { to_int (FAMask::AB), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::Comp), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::WO), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::NAD), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::THD), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::ILV), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::Dist), fourier_analysis_comp_mask (cplx, size) }, + { to_int (FAMask::Noise), fourier_analysis_comp_mask (cplx, size) } + }; + for (const std::pair &kv : fa_comp_tag_map) + { + masks.emplace (kv.first, fourier_analysis_comp_mask (cplx, size)); + } + return masks; +} + +fourier_analysis_results +fourier_analysis::analyze_impl (const real_t *msq_data, const size_t msq_size, + const size_t nfft, FreqAxisType axis_type, + const cplx_t *fft_data, + const size_t fft_size) const +{ + // + // Setup + // + const bool cplx = check_args (msq_data, msq_size, nfft, fft_data, fft_size); + mask_map masks = initialize_masks (cplx, msq_size); + var_map vars = initialize_vars (nfft); + const real_t fbin = vars.at ("fbin"); + const real_t fdata = vars.at ("fdata"); + const real_t fsample = vars.at ("fs"); + const real_t fshift = vars.at ("fshift"); + fourier_analysis_results results; + // + // Analysis Band + // + setup_analysis_band (cplx, masks.at (to_int (FAMask::AB)), vars); + // + // Component Generation + // CLK and ILOS components may overlap. Since the ILOS tag has higher + // priority, generate_comps() creates a dedicated list of CLK keys. + // + comp_data_t comp_data = generate_comps (cplx); + const str_vector &keys = std::get<0> (comp_data); + const comp_map &comps = std::get<1> (comp_data); + const std::set &ilos_clk_keys = std::get<2> (comp_data); + // + // Main Component Loop + // + comp_index_mag_t carrier_im{ -1, 0.0 }; + comp_index_mag_t maxspur_im{ -1, 0.0 }; + size_t key_index = 0; + for (; key_index < keys.size (); ++key_index) + { + const str_t &key = keys[key_index]; + const fourier_analysis_component &comp = *comps.at (key); + switch (comp.type) { - const bool cplx = msq_size == nfft; - const diff_p lrbins = get_lrbins(nfft, cplx, 0.0, comp.ssb); - fourier_analysis_comp_mask m (cplx, msq_size); - m.set_range(lrbins.first, lrbins.second); - masks.at(to_int(FACompTag::DC)) = m; - masks.at(to_int(FAMask::Comp)) |= m; - size_t i1, i2, nbins; - std::tie(i1, i2, nbins) = m.get_indexes(); - real_t fwavg = 0.0; // FIXME: Real: 0.0 by definition; Cplx: calc - bool inband = masks.at(to_int(FAMask::AB)).overlaps(i1, i2); - real_t mag2 = m.sum(msq_data, msq_size); - fa_tone_results results; - results.set(FAToneResult::Tag , static_cast(FACompTag::DC)); - results.set(FAToneResult::Freq , 0.0); - results.set(FAToneResult::FFinal , 0.0); - results.set(FAToneResult::FWAvg , fwavg); - results.set(FAToneResult::I1 , static_cast(i1)); - results.set(FAToneResult::I2 , static_cast(i2)); - results.set(FAToneResult::NBins , static_cast(nbins)); - results.set(FAToneResult::InBand , inband ? 1.0 : 0.0); - results.set_mag(mag2); - return results; + case FACompType::DC: + { + auto &c = static_cast (comp); + fa_tone_results r = meas_dc (c, msq_data, msq_size, nfft, masks); + if (r.inband && dc_as_dist) + { + update_maxspur (key_index, r, dc_as_dist, masks, maxspur_im); + } + results.add_tone (key, std::move (r)); + break; + } + case FACompType::FixedTone: + { + auto &c = static_cast (comp); + fa_tone_results r = meas_fixed_tone (key, c, msq_data, msq_size, + nfft, masks, vars); + tone_updates (key, key_index, comp.tag, r, dc_as_dist, masks, + ilos_clk_keys, carrier_im, maxspur_im); + results.add_tone (key, std::move (r)); + break; + } + case FACompType::MaxTone: + { + auto &c = static_cast (comp); + fa_tone_results r = meas_max_tone (key, c, msq_data, msq_size, + nfft, masks, vars); + tone_updates (key, key_index, comp.tag, r, dc_as_dist, masks, + ilos_clk_keys, carrier_im, maxspur_im); + results.add_tone (key, std::move (r)); + break; + } + default: + break; } - - fa_tone_results meas_fixed_tone( - const str_t& key, - const fa_fixed_tone& comp, - const real_t* msq_data, - const size_t msq_size, - const size_t nfft, - fourier_analysis::mask_map& masks, - fourier_analysis::var_map& vars - ) + if (FACompType::WOTone == comp.type) { - const bool cplx = msq_size == nfft; - const real_t fbin = vars.at("fbin"); - const real_t fdata = vars.at("fdata"); - const real_t fshift = vars.at("fshift"); - const real_t freq = expression(comp.freq).evaluate(vars); // "actual" frequency - const real_t ffinal = alias(freq + fshift, fdata, !cplx); // freq after translation and aliasing - const diff_p lrbins = get_lrbins(nfft, cplx, (ffinal / fbin), comp.ssb); - vars[key] = freq; - fourier_analysis_comp_mask m (cplx, msq_size); - m.set_range(lrbins.first, lrbins.second); - masks.at(to_int(comp.tag)) |= m; - masks.at(to_int(FAMask::Comp)) |= m; - size_t i1, i2, nbins; - std::tie(i1, i2, nbins) = m.get_indexes(); - real_t fwavg = 0.0; // FIXME - bool inband = masks.at(to_int(FAMask::AB)).overlaps(i1, i2); - real_t mag2 = m.sum(msq_data, msq_size); - fa_tone_results results; - results.set(FAToneResult::Tag , static_cast(comp.tag)); - results.set(FAToneResult::Freq , freq); - results.set(FAToneResult::FFinal , ffinal); - results.set(FAToneResult::FWAvg , fwavg); - results.set(FAToneResult::InBand , inband ? 1.0 : 0.0); - results.set(FAToneResult::I1 , static_cast(i1)); - results.set(FAToneResult::I2 , static_cast(i2)); - results.set(FAToneResult::NBins , static_cast(nbins)); - results.set_mag(mag2); - return results; + break; } - - // May implement search band in future. Note: search band != analysis band. - fa_tone_results meas_max_tone( - const str_t& key, - const fa_max_tone& comp, - const real_t* msq_data, - const size_t msq_size, - const size_t nfft, - fourier_analysis::mask_map& masks, - fourier_analysis::var_map& vars - ) + } + // + // Worst Others + // WOs are handled separately in order to guarantee max to min order + // + std::multimap wo_mag_map; // maps WO magnitude to WO key + std::map wo_res_map; // maps WO key to WO results + fourier_analysis_comp_mask &wo_mask = masks.at (to_int (FAMask::WO)); + wo_mask = masks.at (to_int (FAMask::AB)); // Initialize WO mask with AB mask + wo_mask.unset_ranges (masks.at ( + to_int (FAMask::Comp))); // Then remove all components already found + const size_t first_wo_index = key_index; + for (; key_index < keys.size (); ++key_index) + { + const str_t &key = keys[key_index]; + auto &c = static_cast (*comps.at (key)); + fa_tone_results r + = meas_wo_tone (c, msq_data, msq_size, nfft, fbin, fshift, masks); + wo_mag_map.insert ({ r.get (FAToneResult::Mag), key }); + wo_res_map[key] = std::move (r); + } + // WOs are found. Now add to results in order from max to min. Update + // MaxSpur. + int wo_num = 0; + for (auto iter = wo_mag_map.crbegin (); iter != wo_mag_map.crend (); ++iter) + { + const str_t &key = iter->second; + str_t new_key = "wo"; + if (1 < m_wo) { - fourier_analysis_comp_mask search_mask = masks.at(to_int(FAMask::AB)); - fourier_analysis_comp_mask& comp_mask = masks.at(to_int(FAMask::Comp)); - search_mask.unset_ranges(comp_mask); - diff_t max_index, lower, upper; - std::tie(max_index, lower, upper) = search_mask.find_max_index(msq_data, msq_size); - if (max_index < 0) { - return null_tone_results(comp.tag); - } - const bool cplx = msq_size == nfft; - const real_t fbin = vars.at("fbin"); - const real_t fshift = vars.at("fshift"); - const real_t ffinal = max_index * fbin; - const real_t freq = ffinal - fshift; // this is a best guess - diff_p lrbins = get_lrbins(nfft, cplx, static_cast(max_index), comp.ssb); - // Unlike FixedTone, MaxTone stops when it runs into another tone. Since DC is always - // found and is always at bin 0, we never have to worry about MaxTone wrapping. - lrbins.first = std::max(lower, lrbins.first); - lrbins.second = std::min(lrbins.second, upper); - fourier_analysis_comp_mask m (cplx, msq_size); - m.set_range(lrbins.first, lrbins.second); - comp_mask |= m; // add this range to component mask - masks.at(to_int(comp.tag)) |= m; // add this range to tag mask - size_t i1, i2, nbins; - std::tie(i1, i2, nbins) = m.get_indexes(); - real_t fwavg = 0.0; // FIXME - bool inband = masks.at(to_int(FAMask::AB)).overlaps(i1, i2); - real_t mag2 = m.sum(msq_data, msq_size); - vars[key] = freq; // should probably use fwavg (once implemented) - fa_tone_results results; - results.set(FAToneResult::Tag , static_cast(comp.tag)); - results.set(FAToneResult::Freq , freq); - results.set(FAToneResult::FFinal , ffinal); - results.set(FAToneResult::FWAvg , fwavg); - results.set(FAToneResult::InBand , inband ? 1.0 : 0.0); - results.set(FAToneResult::I1 , static_cast(i1)); - results.set(FAToneResult::I2 , static_cast(i2)); - results.set(FAToneResult::NBins , static_cast(nbins)); - results.set_mag(mag2); - return results; + new_key += std::to_string (++wo_num); } - - fa_tone_results meas_wo_tone( - const fa_wo_tone& comp, - const real_t* msq_data, - const size_t msq_size, - const size_t nfft, - const real_t fbin, - const real_t fshift, - fourier_analysis::mask_map& masks - ) + if (1 == m_wo || 1 == wo_num) { - fourier_analysis_comp_mask& wo_mask = masks.at(to_int(FAMask::WO)); - fourier_analysis_comp_mask& comp_mask = masks.at(to_int(FAMask::Comp)); - diff_t max_index, lower, upper; - std::tie(max_index, lower, upper) = wo_mask.find_max_index(msq_data, msq_size); - if (max_index < 0) { - return null_tone_results(comp.tag); - } - const bool cplx = msq_size == nfft; - const real_t ffinal = max_index * fbin; - const real_t freq = ffinal - fshift; // best guess - diff_p lrbins = get_lrbins(nfft, cplx, static_cast(max_index), comp.ssb); - // Unlike FixedTone, MaxTone stops when it runs into another tone. Since DC is always - // found and is always at bin 0, we never have to worry about MaxTone wrapping. - lrbins.first = std::max(lower, lrbins.first); - lrbins.second = std::min(lrbins.second, upper); - fourier_analysis_comp_mask m (cplx, msq_size); - m.set_range(lrbins.first, lrbins.second); - comp_mask |= m; // add this range to component mask - wo_mask.unset_ranges(m); // remove this range from WO search mask - size_t i1, i2, nbins; - std::tie(i1, i2, nbins) = m.get_indexes(); - real_t fwavg = 0.0; // FIXME - real_t mag2 = m.sum(msq_data, msq_size); - fa_tone_results results; - results.set(FAToneResult::Tag , static_cast(comp.tag)); - results.set(FAToneResult::Freq , freq); - results.set(FAToneResult::FFinal , ffinal); - results.set(FAToneResult::FWAvg , fwavg); - results.set(FAToneResult::InBand , 1.0); // by definition - results.set(FAToneResult::I1 , static_cast(i1)); - results.set(FAToneResult::I2 , static_cast(i2)); - results.set(FAToneResult::NBins , static_cast(nbins)); - results.set_mag(mag2); - return results; + update_maxspur (first_wo_index, wo_res_map.at (key), dc_as_dist, + masks, maxspur_im); } - - void update_maxspur( - size_t key_index, - const fa_tone_results& results, - bool dc_as_dist, - const fourier_analysis::mask_map& masks, - comp_index_mag_t& maxspur_im - ) + results.add_tone (new_key, std::move (wo_res_map.at (key))); + } + // + // Second pass for dBc, phase, and phase_c. + // If there are no in-band Signal components, there is no Carrier. + // + real_t carrier_phase = 0.0; + if (0 < carrier_im.first) + { + str_t carrier_key = keys[carrier_im.first]; + fa_tone_results &carrier_results = results.tone_results.at (carrier_key); + carrier_phase + = fa_phase (carrier_results, fft_data, cplx, fdata, fshift); + } + for (size_t i = 0; i < keys.size (); ++i) + { + const str_t &key = keys[i]; + if (has_tone_results (*comps.at (key))) { - // A tone is a candidate for maxspur if: - // 1. it is in-band and non-Signal (these are assumed) - // 2. it is not DC, unless DC is treated as distortion (dc_as_dist is true) - // 3. it does not overlap any Signal tones (this needs explanation) - if (0.0 != results.get(FAToneResult::FFinal) || dc_as_dist) { - const fourier_analysis_comp_mask& sig_mask = masks.at(to_int(FACompTag::Signal)); - if (!sig_mask.overlaps(results.i1, results.i2)) { - real_t mag2 = results.get(FAToneResult::Mag); - mag2 *= mag2; - if (maxspur_im.first < 0 || maxspur_im.second < mag2) { - maxspur_im.first = static_cast(key_index); - maxspur_im.second = mag2; - } - } - } + fa_tone_results &r = results.tone_results.at (key); + real_t mag = r.get (FAToneResult::Mag); + real_t phase = fa_phase (r, fft_data, cplx, fdata, fshift); + r.set (FAToneResult::OrderIndex, static_cast (i)); + r.set (FAToneResult::Mag_dBc, + fa_db10 (mag * mag, carrier_im.second)); + r.set (FAToneResult::Phase, phase); + r.set (FAToneResult::Phase_c, phase - carrier_phase); } - - void tone_updates( - const str_t& key, - size_t key_index, - FACompTag tag, - const fa_tone_results& results, - bool dc_as_dist, - fourier_analysis::mask_map& masks, - const std::set& ilos_clk_keys, - comp_index_mag_t& carrier_im, - comp_index_mag_t& maxspur_im - ) + } + // + // ffinal adjustment (only for complex analysis) + // + if (cplx && FreqAxisType::DcCenter == axis_type) + { + for (std::pair &kv : results.tone_results) { - if (ilos_clk_keys.find(key) != ilos_clk_keys.end()) { - masks.at(to_int(FACompTag::CLK)).set_range(results.i1, results.i2); - } - if (results.inband) { - if (FACompTag::Signal == tag) { - real_t mag2 = results.get(FAToneResult::Mag); - mag2 *= mag2; - if (carrier_im.first < 0 || mag2 < carrier_im.second) { - carrier_im.first = static_cast(key_index); - carrier_im.second = mag2; - } - } else { - update_maxspur(key_index, results, dc_as_dist, masks, maxspur_im); - } - } - } - - } // namespace anonymous - - fourier_analysis::mask_map fourier_analysis::initialize_masks(bool cplx, size_t size) - { - mask_map masks { - {to_int(FAMask::AB) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::Comp) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::WO) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::NAD) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::THD) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::ILV) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::Dist) , fourier_analysis_comp_mask(cplx, size)}, - {to_int(FAMask::Noise) , fourier_analysis_comp_mask(cplx, size)} - }; - for (const std::pair& kv : fa_comp_tag_map) { - masks.emplace(kv.first, fourier_analysis_comp_mask(cplx, size)); - } - return masks; - } - - fourier_analysis_results fourier_analysis::analyze_impl( - const real_t* msq_data, - const size_t msq_size, - const size_t nfft, - FreqAxisType axis_type, - const cplx_t* fft_data, - const size_t fft_size - ) const - { - // - // Setup - // - const bool cplx = check_args(msq_data, msq_size, nfft, fft_data, fft_size); - mask_map masks = initialize_masks(cplx, msq_size); - var_map vars = initialize_vars(nfft); - const real_t fbin = vars.at("fbin"); - const real_t fdata = vars.at("fdata"); - const real_t fsample = vars.at("fs"); - const real_t fshift = vars.at("fshift"); - fourier_analysis_results results; - // - // Analysis Band - // - setup_analysis_band(cplx, masks.at(to_int(FAMask::AB)), vars); - // - // Component Generation - // CLK and ILOS components may overlap. Since the ILOS tag has higher priority, - // generate_comps() creates a dedicated list of CLK keys. - // - comp_data_t comp_data = generate_comps(cplx); - const str_vector& keys = std::get<0>(comp_data); - const comp_map& comps = std::get<1>(comp_data); - const std::set& ilos_clk_keys = std::get<2>(comp_data); - // - // Main Component Loop - // - comp_index_mag_t carrier_im {-1, 0.0}; - comp_index_mag_t maxspur_im {-1, 0.0}; - size_t key_index = 0; - for (; key_index < keys.size(); ++key_index) { - const str_t& key = keys[key_index]; - const fourier_analysis_component& comp = *comps.at(key); - switch (comp.type) + double &ffinal = kv.second.results[FAToneResult::FFinal]; + if (fdata <= 2 * ffinal) { - case FACompType::DC : { - auto& c = static_cast(comp); - fa_tone_results r = meas_dc(c, msq_data, msq_size, nfft, masks); - if (r.inband && dc_as_dist) { - update_maxspur(key_index, r, dc_as_dist, masks, maxspur_im); - } - results.add_tone(key, std::move(r)); - break; - } case FACompType::FixedTone : { - auto& c = static_cast(comp); - fa_tone_results r = meas_fixed_tone(key, c, msq_data, msq_size, nfft, masks, vars); - tone_updates(key, key_index, comp.tag, r, dc_as_dist, masks, ilos_clk_keys, - carrier_im, maxspur_im); - results.add_tone(key, std::move(r)); - break; - } case FACompType::MaxTone : { - auto& c = static_cast(comp); - fa_tone_results r = meas_max_tone(key, c, msq_data, msq_size, nfft, masks, vars); - tone_updates(key, key_index, comp.tag, r, dc_as_dist, masks, ilos_clk_keys, - carrier_im, maxspur_im); - results.add_tone(key, std::move(r)); - break; - } default : - break; - } - if (FACompType::WOTone == comp.type) { - break; - } - } - // - // Worst Others - // WOs are handled separately in order to guarantee max to min order - // - std::multimap wo_mag_map; // maps WO magnitude to WO key - std::map wo_res_map; // maps WO key to WO results - fourier_analysis_comp_mask& wo_mask = masks.at(to_int(FAMask::WO)); - wo_mask = masks.at(to_int(FAMask::AB)); // Initialize WO mask with AB mask - wo_mask.unset_ranges(masks.at(to_int(FAMask::Comp))); // Then remove all components already found - const size_t first_wo_index = key_index; - for (; key_index < keys.size(); ++key_index) { - const str_t& key = keys[key_index]; - auto& c = static_cast(*comps.at(key)); - fa_tone_results r = meas_wo_tone(c, msq_data, msq_size, nfft, fbin, fshift, masks); - wo_mag_map.insert({r.get(FAToneResult::Mag), key}); - wo_res_map[key] = std::move(r); - } - // WOs are found. Now add to results in order from max to min. Update MaxSpur. - int wo_num = 0; - for (auto iter = wo_mag_map.crbegin(); iter != wo_mag_map.crend(); ++iter) { - const str_t& key = iter->second; - str_t new_key = "wo"; - if (1 < m_wo) { - new_key += std::to_string(++wo_num); - } - if (1 == m_wo || 1 == wo_num) { - update_maxspur(first_wo_index, wo_res_map.at(key), dc_as_dist, masks, maxspur_im); - } - results.add_tone(new_key, std::move(wo_res_map.at(key))); - } - // - // Second pass for dBc, phase, and phase_c. - // If there are no in-band Signal components, there is no Carrier. - // - real_t carrier_phase = 0.0; - if (0 < carrier_im.first) { - str_t carrier_key = keys[carrier_im.first]; - fa_tone_results& carrier_results = results.tone_results.at(carrier_key); - carrier_phase = fa_phase(carrier_results, fft_data, cplx, fdata, fshift); - } - for (size_t i = 0; i < keys.size(); ++i) { - const str_t& key = keys[i]; - if (has_tone_results(*comps.at(key))) { - fa_tone_results& r = results.tone_results.at(key); - real_t mag = r.get(FAToneResult::Mag); - real_t phase = fa_phase(r, fft_data, cplx, fdata, fshift); - r.set(FAToneResult::OrderIndex, static_cast(i)); - r.set(FAToneResult::Mag_dBc, fa_db10(mag * mag, carrier_im.second)); - r.set(FAToneResult::Phase, phase); - r.set(FAToneResult::Phase_c, phase - carrier_phase); - } - } - // - // ffinal adjustment (only for complex analysis) - // - if (cplx && FreqAxisType::DcCenter == axis_type) { - for (std::pair& kv : results.tone_results) { - double& ffinal = kv.second.results[FAToneResult::FFinal]; - if (fdata <= 2 * ffinal) { - ffinal -= fdata; - } - } - } - // - // Components finished, now the rest of the results - // - finalize_masks(masks); - std::tuple ab_info = masks.at(to_int(FAMask::AB)).get_indexes(); - real_t ab_nbins = static_cast(std::get<2>(ab_info)); - real_t ab_width = cplx ? ab_nbins * fbin : std::fmin(fdata / 2, ab_nbins * fbin); - real_t nad_ss = masks.at(to_int(FAMask::NAD)).sum(msq_data, msq_size); - real_t noise_ss = masks.at(to_int(FAMask::Noise)).sum(msq_data, msq_size); - real_t noise_nbins = masks.at(to_int(FAMask::Noise)).count_r(); - real_t signal_ss = masks.at(to_int(FACompTag::Signal)).sum(msq_data, msq_size); - results.set(FAResult::AnalysisType , static_cast(AnalysisType::Fourier)); - results.set(FAResult::SignalType , cplx ? 1.0 : 0.0); - results.set(FAResult::NFFT , static_cast(nfft)); - results.set(FAResult::DataSize , static_cast(msq_size)); - results.set(FAResult::FBin , fbin); - results.set(FAResult::FData , fdata); - results.set(FAResult::FSample , fsample); - results.set(FAResult::FShift , fshift); - results.set(FAResult::FSNR , fa_db10(1.0, noise_ss)); - results.set(FAResult::SNR , fa_db10(signal_ss, noise_ss)); - results.set(FAResult::SINAD , fa_db10(signal_ss, nad_ss)); - results.set(FAResult::SFDR , fa_db10(carrier_im.second, maxspur_im.second)); - results.set(FAResult::ABN , fa_db10(noise_ss / std::fmax(1.0, noise_nbins))); // avoid div by 0 - results.set(FAResult::NSD , fa_db10(noise_ss / ab_width)); - results.set(FAResult::CarrierIndex , static_cast(carrier_im.first)); - results.set(FAResult::MaxSpurIndex , static_cast(maxspur_im.first)); - results.set(FAResult::AB_Width , ab_width); - results.set(FAResult::AB_I1 , static_cast(std::get<0>(ab_info))); - results.set(FAResult::AB_I2 , static_cast(std::get<1>(ab_info))); - results.set(FAResult::AB_NBins , ab_nbins); - results.set(FAResult::AB_RSS , masks.at(to_int(FAMask::AB)).root_sum(msq_data, msq_size)); - results.set(FAResult::Signal_NBins , masks.at(to_int(FACompTag::Signal)).count_r()); - results.set(FAResult::Signal_RSS , std::sqrt(signal_ss)); - results.set(FAResult::CLK_NBins , masks.at(to_int(FACompTag::CLK)).count_r()); - results.set(FAResult::CLK_RSS , masks.at(to_int(FACompTag::CLK)).root_sum(msq_data, msq_size)); - results.set(FAResult::HD_NBins , masks.at(to_int(FACompTag::HD)).count_r()); - results.set(FAResult::HD_RSS , masks.at(to_int(FACompTag::HD)).root_sum(msq_data, msq_size)); - results.set(FAResult::ILOS_NBins , masks.at(to_int(FACompTag::ILOS)).count_r()); - results.set(FAResult::ILOS_RSS , masks.at(to_int(FACompTag::ILOS)).root_sum(msq_data, msq_size)); - results.set(FAResult::ILGT_NBins , masks.at(to_int(FACompTag::ILGT)).count_r()); - results.set(FAResult::ILGT_RSS , masks.at(to_int(FACompTag::ILGT)).root_sum(msq_data, msq_size)); - results.set(FAResult::IMD_NBins , masks.at(to_int(FACompTag::IMD)).count_r()); - results.set(FAResult::IMD_RSS , masks.at(to_int(FACompTag::IMD)).root_sum(msq_data, msq_size)); - results.set(FAResult::UserDist_NBins , masks.at(to_int(FACompTag::UserDist)).count_r()); - results.set(FAResult::UserDist_RSS , masks.at(to_int(FACompTag::UserDist)).root_sum(msq_data, msq_size)); - results.set(FAResult::THD_NBins , masks.at(to_int(FAMask::THD)).count_r()); - results.set(FAResult::THD_RSS , masks.at(to_int(FAMask::THD)).root_sum(msq_data, msq_size)); - results.set(FAResult::ILV_NBins , masks.at(to_int(FAMask::ILV)).count_r()); - results.set(FAResult::ILV_RSS , masks.at(to_int(FAMask::ILV)).root_sum(msq_data, msq_size)); - results.set(FAResult::Dist_NBins , masks.at(to_int(FAMask::Dist)).count_r()); - results.set(FAResult::Dist_RSS , masks.at(to_int(FAMask::Dist)).root_sum(msq_data, msq_size)); - results.set(FAResult::Noise_NBins , masks.at(to_int(FAMask::Noise)).count_r()); - results.set(FAResult::Noise_RSS , std::sqrt(noise_ss)); - results.set(FAResult::NAD_NBins , masks.at(to_int(FAMask::NAD)).count_r()); - results.set(FAResult::NAD_RSS , std::sqrt(nad_ss)); - return results; - } - - // This function needs a detailed explanation. Don't edit this function unless you know what - // you are doing! Even the author wasn't quite sure what he was doing :) - void fourier_analysis::finalize_masks(mask_map& masks) const - { - const fourier_analysis_comp_mask& ab_mask = masks.at(to_int(FAMask::AB)); - // Signal Mask: remove out-of-band Signals - fourier_analysis_comp_mask& sig_mask = masks.at(to_int(FACompTag::Signal)); - sig_mask &= ab_mask; - // Noise-And-Distortion Mask: start with AnalysisBand, remove DC and Signals - fourier_analysis_comp_mask& nad_mask = masks.at(to_int(FAMask::NAD)); - nad_mask = ab_mask; - if (!dc_as_dist) { // Do not unset DC ranges if DC is treated as distortion - nad_mask.unset_ranges(masks.at(to_int(FACompTag::DC))); - } - nad_mask.unset_ranges(sig_mask); - // Tag Masks: remove Signals and out-of-band components; by virtue of the NAD mask, also - // remove DC if it is not treated as distortion - for (const std::pair& kv : fa_comp_tag_map) { - if (to_int(FACompTag::Signal) != kv.first) { // Don't touch the Signal mask! - masks.at(kv.first) &= nad_mask; + ffinal -= fdata; } } - // THD - masks.at(to_int(FAMask::THD)) = masks.at(to_int(FACompTag::HD)); - masks.at(to_int(FAMask::THD)) |= masks.at(to_int(FACompTag::IMD)); - // Interleaving - masks.at(to_int(FAMask::ILV)) = masks.at(to_int(FACompTag::ILOS)); - masks.at(to_int(FAMask::ILV)) |= masks.at(to_int(FACompTag::ILGT)); - // Total Distortion - masks.at(to_int(FAMask::Dist)) = masks.at(to_int(FAMask::THD)); - masks.at(to_int(FAMask::Dist)) |= masks.at(to_int(FACompTag::UserDist)); - if (dc_as_dist) { - masks.at(to_int(FAMask::Dist)) |= masks.at(to_int(FACompTag::DC)); - } - if (!clk_as_noise) { - masks.at(to_int(FAMask::Dist)) |= masks.at(to_int(FACompTag::CLK)); - } - if (!ilv_as_noise) { - masks.at(to_int(FAMask::Dist)) |= masks.at(to_int(FAMask::ILV)); - } - // Noise - masks.at(to_int(FAMask::Noise)) = nad_mask; - masks.at(to_int(FAMask::Noise)).unset_ranges(masks.at(to_int(FAMask::Dist))); - } - - fourier_analysis::var_map fourier_analysis::initialize_vars(size_t nfft) const - { - var_map vars (m_user_vars); - real_t fsample = expression(m_fsample).evaluate(vars); - assert_gt0("", "fs", fsample); - vars["fs"] = fsample; - real_t fdata = expression(m_fdata).evaluate(vars); - assert_gt0("", "fdata", fdata); - real_t fbin = fdata / static_cast(nfft); - vars["fdata"] = fdata; - vars["fbin"] = fbin; - real_t fshift = expression(m_fshift).evaluate(vars); - vars["fshift"] = fshift; - return vars; - } - - void fourier_analysis::setup_analysis_band( - bool cplx, fourier_analysis_comp_mask& mask, var_map& vars) const - { - real_t center = expression(m_ab_center).evaluate(vars); - real_t width = expression(m_ab_width).evaluate(vars); - const real_t fbin = vars.at("fbin"); - const real_t fdata = vars.at("fdata"); - width = std::clamp(width, fbin, fdata); // [ fbin, fdata ] - width = std::round(width / fbin); // [ 1, nfft ] - if (mask.size() == static_cast(width)) { - mask.set_all(); - return; + } + // + // Components finished, now the rest of the results + // + finalize_masks (masks); + std::tuple ab_info + = masks.at (to_int (FAMask::AB)).get_indexes (); + real_t ab_nbins = static_cast (std::get<2> (ab_info)); + real_t ab_width + = cplx ? ab_nbins * fbin : std::fmin (fdata / 2, ab_nbins * fbin); + real_t nad_ss = masks.at (to_int (FAMask::NAD)).sum (msq_data, msq_size); + real_t noise_ss = masks.at (to_int (FAMask::Noise)).sum (msq_data, msq_size); + real_t noise_nbins = masks.at (to_int (FAMask::Noise)).count_r (); + real_t signal_ss + = masks.at (to_int (FACompTag::Signal)).sum (msq_data, msq_size); + results.set (FAResult::AnalysisType, + static_cast (AnalysisType::Fourier)); + results.set (FAResult::SignalType, cplx ? 1.0 : 0.0); + results.set (FAResult::NFFT, static_cast (nfft)); + results.set (FAResult::DataSize, static_cast (msq_size)); + results.set (FAResult::FBin, fbin); + results.set (FAResult::FData, fdata); + results.set (FAResult::FSample, fsample); + results.set (FAResult::FShift, fshift); + results.set (FAResult::FSNR, fa_db10 (1.0, noise_ss)); + results.set (FAResult::SNR, fa_db10 (signal_ss, noise_ss)); + results.set (FAResult::SINAD, fa_db10 (signal_ss, nad_ss)); + results.set (FAResult::SFDR, fa_db10 (carrier_im.second, maxspur_im.second)); + results.set ( + FAResult::ABN, + fa_db10 (noise_ss / std::fmax (1.0, noise_nbins))); // avoid div by 0 + results.set (FAResult::NSD, fa_db10 (noise_ss / ab_width)); + results.set (FAResult::CarrierIndex, static_cast (carrier_im.first)); + results.set (FAResult::MaxSpurIndex, static_cast (maxspur_im.first)); + results.set (FAResult::AB_Width, ab_width); + results.set (FAResult::AB_I1, static_cast (std::get<0> (ab_info))); + results.set (FAResult::AB_I2, static_cast (std::get<1> (ab_info))); + results.set (FAResult::AB_NBins, ab_nbins); + results.set (FAResult::AB_RSS, + masks.at (to_int (FAMask::AB)).root_sum (msq_data, msq_size)); + results.set (FAResult::Signal_NBins, + masks.at (to_int (FACompTag::Signal)).count_r ()); + results.set (FAResult::Signal_RSS, std::sqrt (signal_ss)); + results.set (FAResult::CLK_NBins, + masks.at (to_int (FACompTag::CLK)).count_r ()); + results.set ( + FAResult::CLK_RSS, + masks.at (to_int (FACompTag::CLK)).root_sum (msq_data, msq_size)); + results.set (FAResult::HD_NBins, + masks.at (to_int (FACompTag::HD)).count_r ()); + results.set ( + FAResult::HD_RSS, + masks.at (to_int (FACompTag::HD)).root_sum (msq_data, msq_size)); + results.set (FAResult::ILOS_NBins, + masks.at (to_int (FACompTag::ILOS)).count_r ()); + results.set ( + FAResult::ILOS_RSS, + masks.at (to_int (FACompTag::ILOS)).root_sum (msq_data, msq_size)); + results.set (FAResult::ILGT_NBins, + masks.at (to_int (FACompTag::ILGT)).count_r ()); + results.set ( + FAResult::ILGT_RSS, + masks.at (to_int (FACompTag::ILGT)).root_sum (msq_data, msq_size)); + results.set (FAResult::IMD_NBins, + masks.at (to_int (FACompTag::IMD)).count_r ()); + results.set ( + FAResult::IMD_RSS, + masks.at (to_int (FACompTag::IMD)).root_sum (msq_data, msq_size)); + results.set (FAResult::UserDist_NBins, + masks.at (to_int (FACompTag::UserDist)).count_r ()); + results.set ( + FAResult::UserDist_RSS, + masks.at (to_int (FACompTag::UserDist)).root_sum (msq_data, msq_size)); + results.set (FAResult::THD_NBins, + masks.at (to_int (FAMask::THD)).count_r ()); + results.set (FAResult::THD_RSS, + masks.at (to_int (FAMask::THD)).root_sum (msq_data, msq_size)); + results.set (FAResult::ILV_NBins, + masks.at (to_int (FAMask::ILV)).count_r ()); + results.set (FAResult::ILV_RSS, + masks.at (to_int (FAMask::ILV)).root_sum (msq_data, msq_size)); + results.set (FAResult::Dist_NBins, + masks.at (to_int (FAMask::Dist)).count_r ()); + results.set (FAResult::Dist_RSS, + masks.at (to_int (FAMask::Dist)).root_sum (msq_data, msq_size)); + results.set (FAResult::Noise_NBins, + masks.at (to_int (FAMask::Noise)).count_r ()); + results.set (FAResult::Noise_RSS, std::sqrt (noise_ss)); + results.set (FAResult::NAD_NBins, + masks.at (to_int (FAMask::NAD)).count_r ()); + results.set (FAResult::NAD_RSS, std::sqrt (nad_ss)); + return results; +} + +// This function needs a detailed explanation. Don't edit this function unless +// you know what you are doing! Even the author wasn't quite sure what he was +// doing :) +void +fourier_analysis::finalize_masks (mask_map &masks) const +{ + const fourier_analysis_comp_mask &ab_mask = masks.at (to_int (FAMask::AB)); + // Signal Mask: remove out-of-band Signals + fourier_analysis_comp_mask &sig_mask = masks.at (to_int (FACompTag::Signal)); + sig_mask &= ab_mask; + // Noise-And-Distortion Mask: start with AnalysisBand, remove DC and Signals + fourier_analysis_comp_mask &nad_mask = masks.at (to_int (FAMask::NAD)); + nad_mask = ab_mask; + if (!dc_as_dist) + { // Do not unset DC ranges if DC is treated as distortion + nad_mask.unset_ranges (masks.at (to_int (FACompTag::DC))); + } + nad_mask.unset_ranges (sig_mask); + // Tag Masks: remove Signals and out-of-band components; by virtue of the NAD + // mask, also remove DC if it is not treated as distortion + for (const std::pair &kv : fa_comp_tag_map) + { + if (to_int (FACompTag::Signal) != kv.first) + { // Don't touch the Signal mask! + masks.at (kv.first) &= nad_mask; } - center = alias(center, fdata, !cplx); - center = std::round(2.0 * center / fbin) / 2.0; // nearest half cycle - center = alias(center, fdata, !cplx); - diff_t lbin = static_cast(std::ceil( center - width / 2)); - diff_t rbin = static_cast(std::floor(center + width / 2)); - mask.set_range(lbin, rbin); } + // THD + masks.at (to_int (FAMask::THD)) = masks.at (to_int (FACompTag::HD)); + masks.at (to_int (FAMask::THD)) |= masks.at (to_int (FACompTag::IMD)); + // Interleaving + masks.at (to_int (FAMask::ILV)) = masks.at (to_int (FACompTag::ILOS)); + masks.at (to_int (FAMask::ILV)) |= masks.at (to_int (FACompTag::ILGT)); + // Total Distortion + masks.at (to_int (FAMask::Dist)) = masks.at (to_int (FAMask::THD)); + masks.at (to_int (FAMask::Dist)) |= masks.at (to_int (FACompTag::UserDist)); + if (dc_as_dist) + { + masks.at (to_int (FAMask::Dist)) |= masks.at (to_int (FACompTag::DC)); + } + if (!clk_as_noise) + { + masks.at (to_int (FAMask::Dist)) |= masks.at (to_int (FACompTag::CLK)); + } + if (!ilv_as_noise) + { + masks.at (to_int (FAMask::Dist)) |= masks.at (to_int (FAMask::ILV)); + } + // Noise + masks.at (to_int (FAMask::Noise)) = nad_mask; + masks.at (to_int (FAMask::Noise)) + .unset_ranges (masks.at (to_int (FAMask::Dist))); +} + +fourier_analysis::var_map +fourier_analysis::initialize_vars (size_t nfft) const +{ + var_map vars (m_user_vars); + real_t fsample = expression (m_fsample).evaluate (vars); + assert_gt0 ("", "fs", fsample); + vars["fs"] = fsample; + real_t fdata = expression (m_fdata).evaluate (vars); + assert_gt0 ("", "fdata", fdata); + real_t fbin = fdata / static_cast (nfft); + vars["fdata"] = fdata; + vars["fbin"] = fbin; + real_t fshift = expression (m_fshift).evaluate (vars); + vars["fshift"] = fshift; + return vars; +} + +void +fourier_analysis::setup_analysis_band (bool cplx, + fourier_analysis_comp_mask &mask, + var_map &vars) const +{ + real_t center = expression (m_ab_center).evaluate (vars); + real_t width = expression (m_ab_width).evaluate (vars); + const real_t fbin = vars.at ("fbin"); + const real_t fdata = vars.at ("fdata"); + width = std::clamp (width, fbin, fdata); // [ fbin, fdata ] + width = std::round (width / fbin); // [ 1, nfft ] + if (mask.size () == static_cast (width)) + { + mask.set_all (); + return; + } + center = alias (center, fdata, !cplx); + center = std::round (2.0 * center / fbin) / 2.0; // nearest half cycle + center = alias (center, fdata, !cplx); + diff_t lbin = static_cast (std::ceil (center - width / 2)); + diff_t rbin = static_cast (std::floor (center + width / 2)); + mask.set_range (lbin, rbin); +} } // namespace genalyzer_impl - Non-Public diff --git a/src/fourier_analysis_comp_mask.cpp b/src/fourier_analysis_comp_mask.cpp index 6850dde..a2e002a 100644 --- a/src/fourier_analysis_comp_mask.cpp +++ b/src/fourier_analysis_comp_mask.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "fourier_analysis_comp_mask.hpp" #include "exceptions.hpp" @@ -5,250 +8,321 @@ #include -namespace genalyzer_impl { - - fourier_analysis_comp_mask::fourier_analysis_comp_mask( - bool cplx, size_t array_size, const std::vector& init) - : m_mode {cplx ? Wrap : Stop}, - m_ufirst {0}, - m_ulast {array_size - 1}, - m_usize {array_size}, - m_first {0}, - m_last {static_cast(array_size - 1)}, - m_size {static_cast(array_size)}, - m_data (init) - { - if (!m_data.empty()) { - const char* msg = "fourier_analysis_comp_mask : invalid construction"; - if ( is_odd(m_data.size()) || (m_usize < m_data.back()) ) { - throw runtime_error(msg); - } - for (size_t i = 1; i < m_data.size(); ++i) { - if (m_data[i] <= m_data[i - 1]) { - throw runtime_error(msg); - } +namespace genalyzer_impl +{ + +fourier_analysis_comp_mask::fourier_analysis_comp_mask ( + bool cplx, size_t array_size, const std::vector &init) + : m_mode{ cplx ? Wrap : Stop }, m_ufirst{ 0 }, m_ulast{ array_size - 1 }, + m_usize{ array_size }, m_first{ 0 }, + m_last{ static_cast (array_size - 1) }, + m_size{ static_cast (array_size) }, m_data (init) +{ + if (!m_data.empty ()) + { + const char *msg = "fourier_analysis_comp_mask : invalid construction"; + if (is_odd (m_data.size ()) || (m_usize < m_data.back ())) + { + throw runtime_error (msg); + } + for (size_t i = 1; i < m_data.size (); ++i) + { + if (m_data[i] <= m_data[i - 1]) + { + throw runtime_error (msg); } } } +} - fourier_analysis_comp_mask& fourier_analysis_comp_mask::operator&=(fourier_analysis_comp_mask m) +fourier_analysis_comp_mask & +fourier_analysis_comp_mask::operator&= (fourier_analysis_comp_mask m) +{ + if_not_compat_then_throw (m); + this->invert (); // !A + m.invert (); // !B + *this |= m; // !A + !B + this->invert (); // !(!A + !B) + return *this; // De Morgan: A * B = !(!A + !B) +} + +fourier_analysis_comp_mask & +fourier_analysis_comp_mask::operator|= (const fourier_analysis_comp_mask &m) +{ + if_not_compat_then_throw (m); + for (size_t range = 0; range < m.num_ranges (); ++range) { - if_not_compat_then_throw(m); - this->invert(); // !A - m.invert(); // !B - *this |= m; // !A + !B - this->invert(); // !(!A + !B) - return *this; // De Morgan: A * B = !(!A + !B) + size_t i1 = m.m_data[range * 2]; + size_t i2 = m.m_data[range * 2 + 1]; + this->set_range_safe (i1, i2 - 1); // subtract 1 because i2 is 1-past! } + return *this; +} - fourier_analysis_comp_mask& fourier_analysis_comp_mask::operator|=( - const fourier_analysis_comp_mask& m) +size_t +fourier_analysis_comp_mask::count () const +{ + size_t count = 0; + for (size_t range = 0; range < num_ranges (); ++range) { - if_not_compat_then_throw(m); - for (size_t range = 0; range < m.num_ranges(); ++range) { - size_t i1 = m.m_data[range * 2]; - size_t i2 = m.m_data[range * 2 + 1]; - this->set_range_safe(i1, i2 - 1); // subtract 1 because i2 is 1-past! + const size_t i1 = m_data[range * 2]; + const size_t i2 = m_data[range * 2 + 1]; + for (size_t i = i1; i < i2; ++i) + { + ++count; } - return *this; } + return count; +} - size_t fourier_analysis_comp_mask::count() const +std::tuple +fourier_analysis_comp_mask::find_max_index (const real_t *data, + size_t size) const +{ + if (m_usize != size) { - size_t count = 0; - for (size_t range = 0; range < num_ranges(); ++range) { - const size_t i1 = m_data[range * 2]; - const size_t i2 = m_data[range * 2 + 1]; - for (size_t i = i1; i < i2; ++i) { - ++count; - } - } - return count; + throw runtime_error ( + "fourier_analysis_comp_mask::find_max_index : size error"); } - - std::tuple - fourier_analysis_comp_mask::find_max_index(const real_t* data, size_t size) const + real_t max_value = 0.0; + diff_t max_index = -1; + size_t max_range = 0; + for (size_t range = 0; range < num_ranges (); ++range) { - if (m_usize != size) { - throw runtime_error("fourier_analysis_comp_mask::find_max_index : size error"); - } - real_t max_value = 0.0; - diff_t max_index = -1; - size_t max_range = 0; - for (size_t range = 0; range < num_ranges(); ++range) { - const size_t i1 = m_data[range * 2]; - const size_t i2 = m_data[range * 2 + 1]; - for (size_t i = i1; i < i2; ++i) { - if (max_value < data[i]) { - max_value = data[i]; - max_index = i; - max_range = range; - } + const size_t i1 = m_data[range * 2]; + const size_t i2 = m_data[range * 2 + 1]; + for (size_t i = i1; i < i2; ++i) + { + if (max_value < data[i]) + { + max_value = data[i]; + max_index = i; + max_range = range; } } - if (max_index < 0) { - return std::make_tuple(-1, -1, -1); - } else { - diff_t lower = static_cast(m_data[max_range * 2]); - diff_t upper = static_cast(m_data[max_range * 2 + 1]) - 1; - return std::make_tuple(max_index, lower, upper); - } } - - std::tuple fourier_analysis_comp_mask::get_indexes() const + if (max_index < 0) { - if (1 == num_ranges()) { - return std::make_tuple(m_data[0], m_data[1] - 1, m_data[1] - m_data[0]); - } else if (2 == num_ranges() && m_ufirst == m_data[0] && m_usize == m_data[3]) { - return std::make_tuple(m_data[2], m_data[1] - 1, m_data[1] + m_data[3] - m_data[2]); - } else { - throw runtime_error("fourier_analysis_comp_mask::get_indexes : invalid use"); - } + return std::make_tuple (-1, -1, -1); + } + else + { + diff_t lower = static_cast (m_data[max_range * 2]); + diff_t upper = static_cast (m_data[max_range * 2 + 1]) - 1; + return std::make_tuple (max_index, lower, upper); } +} - void fourier_analysis_comp_mask::invert() +std::tuple +fourier_analysis_comp_mask::get_indexes () const +{ + if (1 == num_ranges ()) { - if (m_data.empty()) { - set_all(); - return; - } - if (m_ufirst == m_data.front()) { - m_data.erase(m_data.begin()); - } else { - m_data.insert(m_data.begin(), m_ufirst); - } - if (m_usize == m_data.back()) { - m_data.pop_back(); - } else { - m_data.push_back(m_usize); - } + return std::make_tuple (m_data[0], m_data[1] - 1, m_data[1] - m_data[0]); + } + else if (2 == num_ranges () && m_ufirst == m_data[0] && m_usize == m_data[3]) + { + return std::make_tuple (m_data[2], m_data[1] - 1, + m_data[1] + m_data[3] - m_data[2]); + } + else + { + throw runtime_error ( + "fourier_analysis_comp_mask::get_indexes : invalid use"); } +} - bool fourier_analysis_comp_mask::overlaps(size_t left, size_t right) const +void +fourier_analysis_comp_mask::invert () +{ + if (m_data.empty ()) { - size_t left_index = get_index(left); - size_t right_index = get_index(right); - if (is_odd(left_index) || is_odd(right_index)) { // if either are inside a range - return true; - } - return left_index != right_index; // true if left and right straddle one or more ranges + set_all (); + return; + } + if (m_ufirst == m_data.front ()) + { + m_data.erase (m_data.begin ()); + } + else + { + m_data.insert (m_data.begin (), m_ufirst); + } + if (m_usize == m_data.back ()) + { + m_data.pop_back (); } + else + { + m_data.push_back (m_usize); + } +} + +bool +fourier_analysis_comp_mask::overlaps (size_t left, size_t right) const +{ + size_t left_index = get_index (left); + size_t right_index = get_index (right); + if (is_odd (left_index) || is_odd (right_index)) + { // if either are inside a range + return true; + } + return left_index + != right_index; // true if left and right straddle one or more ranges +} - void fourier_analysis_comp_mask::set_range(diff_t left, diff_t right) +void +fourier_analysis_comp_mask::set_range (diff_t left, diff_t right) +{ + if (right < left) + { + throw runtime_error ( + "fourier_analysis_comp_mask::set_range : right < left"); + } + size_t uleft = 0; + size_t uright = 0; + if (Stop == m_mode) + { + uleft = static_cast (std::max (m_first, left)); + uright = static_cast (std::min (right, m_last)); + } + else { - if (right < left) { - throw runtime_error("fourier_analysis_comp_mask::set_range : right < left"); + if (m_last < right - left) + { + throw runtime_error ( + "fourier_analysis_comp_mask::set_range : size < range"); } - size_t uleft = 0; - size_t uright = 0; - if (Stop == m_mode) { - uleft = static_cast(std::max(m_first, left)); - uright = static_cast(std::min(right, m_last)); - } else { - if (m_last < right - left) { - throw runtime_error("fourier_analysis_comp_mask::set_range : size < range"); - } - if (left < m_first) { - left += m_size; - if (left < m_first) { - throw runtime_error("fourier_analysis_comp_mask::set_range : left out of range"); - } + if (left < m_first) + { + left += m_size; + if (left < m_first) + { + throw runtime_error ( + "fourier_analysis_comp_mask::set_range : left out of range"); } - if (m_last < right) { - right -= m_size; - if (m_last < right) { - throw runtime_error("fourier_analysis_comp_mask::set_range : right out of range"); - } - } - uleft = static_cast(left); - uright = static_cast(right); } - if (uright < uleft) { - set_range_safe(m_ufirst, uright); - set_range_safe(uleft, m_ulast); - } else { - set_range_safe(uleft, uright); + if (m_last < right) + { + right -= m_size; + if (m_last < right) + { + throw runtime_error ("fourier_analysis_comp_mask::set_range : " + "right out of range"); + } } + uleft = static_cast (left); + uright = static_cast (right); + } + if (uright < uleft) + { + set_range_safe (m_ufirst, uright); + set_range_safe (uleft, m_ulast); + } + else + { + set_range_safe (uleft, uright); } +} - real_t fourier_analysis_comp_mask::sum(const real_t* data, size_t size) const +real_t +fourier_analysis_comp_mask::sum (const real_t *data, size_t size) const +{ + if (m_usize != size) { - if (m_usize != size) { - throw runtime_error("fourier_analysis_comp_mask::sum : size error"); - } - real_t mag = 0.0; - for (size_t range = 0; range < num_ranges(); ++range) { - const size_t i1 = m_data[range * 2]; - const size_t i2 = m_data[range * 2 + 1]; - for (size_t i = i1; i < i2; ++i) { - mag += data[i]; - } + throw runtime_error ("fourier_analysis_comp_mask::sum : size error"); + } + real_t mag = 0.0; + for (size_t range = 0; range < num_ranges (); ++range) + { + const size_t i1 = m_data[range * 2]; + const size_t i2 = m_data[range * 2 + 1]; + for (size_t i = i1; i < i2; ++i) + { + mag += data[i]; } - return mag; } + return mag; +} - void fourier_analysis_comp_mask::unset_ranges(const fourier_analysis_comp_mask& m) +void +fourier_analysis_comp_mask::unset_ranges (const fourier_analysis_comp_mask &m) +{ + if (&m == this) { - if (&m == this) { - this->clear(); - return; - } - if_not_compat_then_throw(m); - this->invert(); - *this |= m; - this->invert(); + this->clear (); + return; } + if_not_compat_then_throw (m); + this->invert (); + *this |= m; + this->invert (); +} - size_t fourier_analysis_comp_mask::get_index(size_t value) const +size_t +fourier_analysis_comp_mask::get_index (size_t value) const +{ + size_t index = 0; + while (index < m_data.size ()) { - size_t index = 0; - while (index < m_data.size()) { - if (value < m_data[index]) { - break; - } - ++index; + if (value < m_data[index]) + { + break; } - return index; + ++index; } + return index; +} - void fourier_analysis_comp_mask::if_not_compat_then_throw(const fourier_analysis_comp_mask& m) +void +fourier_analysis_comp_mask::if_not_compat_then_throw ( + const fourier_analysis_comp_mask &m) +{ + if ((m.m_mode != this->m_mode) || (m.m_size != this->m_size)) { - if ((m.m_mode != this->m_mode) || (m.m_size != this->m_size)) { - throw runtime_error("fourier_analysis_comp_mask : mask is incompatible"); - } + throw runtime_error ( + "fourier_analysis_comp_mask : mask is incompatible"); } +} - void fourier_analysis_comp_mask::set_range_safe(size_t left, size_t right) +void +fourier_analysis_comp_mask::set_range_safe (size_t left, size_t right) +{ + right += 1; // right is now 1-past + if (m_data.empty () || m_data.back () < left) { - right += 1; // right is now 1-past - if (m_data.empty() || m_data.back() < left) { - m_data.push_back(left); - m_data.push_back(right); - return; - } - size_t left_index = get_index(left); - size_t right_index = get_index(right); - // left and left_index adjustments - if (is_even(left_index)) { // even: left is not in a range - // Explain this... - if (0 < left_index && left == m_data[left_index - 1]) { - left_index -= 2; - left = m_data[left_index]; - } - } else { // odd: left is in a range - // Explain this... - left_index -= 1; - left = m_data[left_index]; - } - // right and right_index adjustments - if (is_odd(right_index)) { // odd: right is in a range - // Explain this... - right = m_data[right_index]; - right_index += 1; + m_data.push_back (left); + m_data.push_back (right); + return; + } + size_t left_index = get_index (left); + size_t right_index = get_index (right); + // left and left_index adjustments + if (is_even (left_index)) + { // even: left is not in a range + // Explain this... + if (0 < left_index && left == m_data[left_index - 1]) + { + left_index -= 2; + left = m_data[left_index]; } - // Update m_data - m_data.erase(m_data.begin() + left_index, m_data.begin() + right_index); - m_data.insert(m_data.begin() + left_index, {left, right}); } + else + { // odd: left is in a range + // Explain this... + left_index -= 1; + left = m_data[left_index]; + } + // right and right_index adjustments + if (is_odd (right_index)) + { // odd: right is in a range + // Explain this... + right = m_data[right_index]; + right_index += 1; + } + // Update m_data + m_data.erase (m_data.begin () + left_index, m_data.begin () + right_index); + m_data.insert (m_data.begin () + left_index, { left, right }); +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/fourier_transforms.cpp b/src/fourier_transforms.cpp index 7f8fc6b..ccd9b24 100644 --- a/src/fourier_transforms.cpp +++ b/src/fourier_transforms.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "fourier_transforms.hpp" #include "constants.hpp" @@ -11,1004 +14,1106 @@ #include #include -namespace genalyzer_impl { - - namespace { // Window Function Constants - - const real_t blackman_harris_kx = 1.9688861870585801; - const real_t blackman_harris_k0 = 0.35875; - const real_t blackman_harris_k1 = -0.48829; - const real_t blackman_harris_k2 = 0.14128; - const real_t blackman_harris_k3 = -0.01168; - const real_t hann_kx = 1.6329922791756648; - const real_t hann_k0 = 0.5; - const real_t hann_k1 = -0.5; - - } // namespace anonymous - - namespace { // Window-Only Functions - - // For Complex FFT - void blackman_harris( - const real_t* i_data, - const real_t* q_data, - real_t* out_data, - size_t in_stride, - size_t navg, - size_t nfft - ) - { - const real_t scalar = blackman_harris_kx; - const real_t k1 = k_2pi / static_cast(nfft); - const real_t k2 = k1 * 2; - const real_t k3 = k1 * 3; - const size_t in_row_stride = nfft * in_stride; - const size_t out_row_stride = nfft * 2; - size_t i = 0; - real_t x = 0.0; - if (1 == navg) { - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[j] = w * scalar * i_data[i]; - out_data[j+1] = w * scalar * q_data[i]; - i += in_stride; - x += 1.0; - } - } else if (2 == navg) { - const real_t* i2_data = i_data + in_row_stride; - const real_t* q2_data = q_data + in_row_stride; - real_t* out2_data = out_data + out_row_stride; - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[j] = w * scalar * i_data[i]; - out_data[j+1] = w * scalar * q_data[i]; - out2_data[j] = w * scalar * i2_data[i]; - out2_data[j+1] = w * scalar * q2_data[i]; - i += in_stride; - x += 1.0; - } - } else { // 2 < navg - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - const real_t* pi = i_data; - const real_t* pq = q_data; - real_t* po = out_data; - for (size_t k = 0; k < navg; ++k) { - po[j] = w * scalar * pi[i]; - po[j+1] = w * scalar * pq[i]; - pi += in_row_stride; - pq += in_row_stride; - po += out_row_stride; - } - i += in_stride; - x += 1.0; - } - } - } +namespace genalyzer_impl +{ - // For Real FFT - void blackman_harris( - const real_t* in_data, - real_t* out_data, - size_t navg, - size_t nfft, - RfftScale scale - ) - { - const real_t scalar = blackman_harris_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); - const real_t k1 = k_2pi / static_cast(nfft); - const real_t k2 = k1 * 2; - const real_t k3 = k1 * 3; - const size_t out_stride = (nfft / 2 + 1) * 2; - real_t x = 0.0; - if (1 == navg) { - for (size_t i = 0; i < nfft; ++i) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[i] = w * scalar * in_data[i]; - x += 1.0; - } - } else if (2 == navg) { - const real_t* in2_data = in_data + nfft; - real_t* out2_data = out_data + out_stride; - for (size_t i = 0; i < nfft; ++i) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[i] = w * scalar * in_data[i]; - out2_data[i] = w * scalar * in2_data[i]; - x += 1.0; - } - } else { // 2 < navg - for (size_t i = 0; i < nfft; ++i) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - const real_t* pi = in_data; - real_t* po = out_data; - for (size_t j = 0; j < navg; ++j) { - po[i] = w * scalar * pi[i]; - pi += nfft; - po += out_stride; - } - x += 1.0; - } - } - } +namespace +{ // Window Function Constants - // For Complex FFT - void hann( - const real_t* i_data, - const real_t* q_data, - real_t* out_data, - size_t in_stride, - size_t navg, - size_t nfft - ) - { - const real_t scalar = hann_kx; - const real_t k1 = k_2pi / static_cast(nfft); - const size_t in_row_stride = nfft * in_stride; - const size_t out_row_stride = nfft * 2; - size_t i = 0; - real_t x = 0.0; - if (1 == navg) { - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[j] = w * scalar * i_data[i]; - out_data[j+1] = w * scalar * q_data[i]; - i += in_stride; - x += 1.0; - } - } else if (2 == navg) { - const real_t* i2_data = i_data + nfft * in_stride; - const real_t* q2_data = q_data + nfft * in_stride; - real_t* out2_data = out_data + out_row_stride; - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[j] = w * scalar * i_data[i]; - out_data[j+1] = w * scalar * q_data[i]; - out2_data[j] = w * scalar * i2_data[i]; - out2_data[j+1] = w * scalar * q2_data[i]; - i += in_stride; - x += 1.0; - } - } else { // 2 < navg - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - const real_t* pi = i_data; - const real_t* pq = q_data; - real_t* po = out_data; - for (size_t k = 0; k < navg; ++k) { - po[j] = w * scalar * pi[i]; - po[j+1] = w * scalar * pq[i]; - pi += in_row_stride; - pq += in_row_stride; - po += out_row_stride; - } - i += in_stride; - x += 1.0; - } - } - } +const real_t blackman_harris_kx = 1.9688861870585801; +const real_t blackman_harris_k0 = 0.35875; +const real_t blackman_harris_k1 = -0.48829; +const real_t blackman_harris_k2 = 0.14128; +const real_t blackman_harris_k3 = -0.01168; +const real_t hann_kx = 1.6329922791756648; +const real_t hann_k0 = 0.5; +const real_t hann_k1 = -0.5; + +} // namespace anonymous - // For Real FFT - void hann( - const real_t* in_data, - real_t* out_data, - size_t navg, - size_t nfft, - RfftScale scale - ) - { - const real_t scalar = hann_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); - const real_t k1 = k_2pi / static_cast(nfft); - const size_t out_stride = (nfft / 2 + 1) * 2; - real_t x = 0.0; - if (1 == navg) { - for (size_t i = 0; i < nfft; ++i) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[i] = w * scalar * in_data[i]; - x += 1.0; - } - } else if (2 == navg) { - const real_t* in2_data = in_data + nfft; - real_t* out2_data = out_data + out_stride; - for (size_t i = 0; i < nfft; ++i) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[i] = w * scalar * in_data[i]; - out2_data[i] = w * scalar * in2_data[i]; - x += 1.0; - } - } else { // 2 < navg - for (size_t i = 0; i < nfft; ++i) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - const real_t* pi = in_data; - real_t* po = out_data; - for (size_t j = 0; j < navg; ++j) { - po[i] = w * scalar * pi[i]; - pi += nfft; - po += out_stride; - } - x += 1.0; - } +namespace +{ // Window-Only Functions + +// For Complex FFT +void +blackman_harris (const real_t *i_data, const real_t *q_data, real_t *out_data, + size_t in_stride, size_t navg, size_t nfft) +{ + const real_t scalar = blackman_harris_kx; + const real_t k1 = k_2pi / static_cast (nfft); + const real_t k2 = k1 * 2; + const real_t k3 = k1 * 3; + const size_t in_row_stride = nfft * in_stride; + const size_t out_row_stride = nfft * 2; + size_t i = 0; + real_t x = 0.0; + if (1 == navg) + { + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[j] = w * scalar * i_data[i]; + out_data[j + 1] = w * scalar * q_data[i]; + i += in_stride; + x += 1.0; + } + } + else if (2 == navg) + { + const real_t *i2_data = i_data + in_row_stride; + const real_t *q2_data = q_data + in_row_stride; + real_t *out2_data = out_data + out_row_stride; + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[j] = w * scalar * i_data[i]; + out_data[j + 1] = w * scalar * q_data[i]; + out2_data[j] = w * scalar * i2_data[i]; + out2_data[j + 1] = w * scalar * q2_data[i]; + i += in_stride; + x += 1.0; + } + } + else + { // 2 < navg + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + const real_t *pi = i_data; + const real_t *pq = q_data; + real_t *po = out_data; + for (size_t k = 0; k < navg; ++k) + { + po[j] = w * scalar * pi[i]; + po[j + 1] = w * scalar * pq[i]; + pi += in_row_stride; + pq += in_row_stride; + po += out_row_stride; } + i += in_stride; + x += 1.0; } + } +} - // For Complex FFT - void no_window( - const real_t* i_data, - const real_t* q_data, - real_t* out_data, - size_t in_stride, - size_t navg, - size_t nfft - ) - { - const size_t out_size = navg * nfft * 2; - size_t i = 0; - for (size_t j = 0; j < out_size; j += 2) { - out_data[j] = i_data[i]; - out_data[j+1] = q_data[i]; - i += in_stride; +// For Real FFT +void +blackman_harris (const real_t *in_data, real_t *out_data, size_t navg, + size_t nfft, RfftScale scale) +{ + const real_t scalar + = blackman_harris_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); + const real_t k1 = k_2pi / static_cast (nfft); + const real_t k2 = k1 * 2; + const real_t k3 = k1 * 3; + const size_t out_stride = (nfft / 2 + 1) * 2; + real_t x = 0.0; + if (1 == navg) + { + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[i] = w * scalar * in_data[i]; + x += 1.0; + } + } + else if (2 == navg) + { + const real_t *in2_data = in_data + nfft; + real_t *out2_data = out_data + out_stride; + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[i] = w * scalar * in_data[i]; + out2_data[i] = w * scalar * in2_data[i]; + x += 1.0; + } + } + else + { // 2 < navg + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + const real_t *pi = in_data; + real_t *po = out_data; + for (size_t j = 0; j < navg; ++j) + { + po[i] = w * scalar * pi[i]; + pi += nfft; + po += out_stride; } + x += 1.0; } + } +} - // For Real FFT - void no_window( - const real_t* in_data, - real_t* out_data, - size_t navg, - size_t nfft, - RfftScale scale - ) - { - const real_t scalar = (RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0; - const size_t out_stride = (nfft / 2 + 1) * 2; - for (size_t j = 0; j < navg; ++j) { - for (size_t i = 0; i < nfft; ++i) { - out_data[i] = scalar * in_data[i]; - } - in_data += nfft; - out_data += out_stride; +// For Complex FFT +void +hann (const real_t *i_data, const real_t *q_data, real_t *out_data, + size_t in_stride, size_t navg, size_t nfft) +{ + const real_t scalar = hann_kx; + const real_t k1 = k_2pi / static_cast (nfft); + const size_t in_row_stride = nfft * in_stride; + const size_t out_row_stride = nfft * 2; + size_t i = 0; + real_t x = 0.0; + if (1 == navg) + { + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[j] = w * scalar * i_data[i]; + out_data[j + 1] = w * scalar * q_data[i]; + i += in_stride; + x += 1.0; + } + } + else if (2 == navg) + { + const real_t *i2_data = i_data + nfft * in_stride; + const real_t *q2_data = q_data + nfft * in_stride; + real_t *out2_data = out_data + out_row_stride; + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[j] = w * scalar * i_data[i]; + out_data[j + 1] = w * scalar * q_data[i]; + out2_data[j] = w * scalar * i2_data[i]; + out2_data[j + 1] = w * scalar * q2_data[i]; + i += in_stride; + x += 1.0; + } + } + else + { // 2 < navg + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + const real_t *pi = i_data; + const real_t *pq = q_data; + real_t *po = out_data; + for (size_t k = 0; k < navg; ++k) + { + po[j] = w * scalar * pi[i]; + po[j + 1] = w * scalar * pq[i]; + pi += in_row_stride; + pq += in_row_stride; + po += out_row_stride; } + i += in_stride; + x += 1.0; } + } +} - } // namespace anonymous - - namespace { // Normalize-Window Functions - - // For Complex FFT - template - void norm_blackman_harris( - const T* i_data, - const T* q_data, - real_t* out_data, - size_t in_stride, - int n, - size_t navg, - size_t nfft, - CodeFormat format - ) - { - const real_t scalar = blackman_harris_kx * 2.0 / (1 << n); - const real_t offset = (CodeFormat::OffsetBinary == format) ? -blackman_harris_kx : 0.0; - const real_t k1 = k_2pi / static_cast(nfft); - const real_t k2 = k1 * 2; - const real_t k3 = k1 * 3; - const size_t in_row_stride = nfft * in_stride; - const size_t out_row_stride = nfft * 2; - size_t i = 0; - real_t x = 0.0; - if (1 == navg) { - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[j] = w * std::fma(scalar, static_cast(i_data[i]), offset); - out_data[j+1] = w * std::fma(scalar, static_cast(q_data[i]), offset); - i += in_stride; - x += 1.0; - } - } else if (2 == navg) { - const T* i2_data = i_data + in_row_stride; - const T* q2_data = q_data + in_row_stride; - real_t* out2_data = out_data + out_row_stride; - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[j] = w * std::fma(scalar, static_cast(i_data[i]), offset); - out_data[j+1] = w * std::fma(scalar, static_cast(q_data[i]), offset); - out2_data[j] = w * std::fma(scalar, static_cast(i2_data[i]), offset); - out2_data[j+1] = w * std::fma(scalar, static_cast(q2_data[i]), offset); - i += in_stride; - x += 1.0; - } - } else { // 2 < navg - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - const T* pi = i_data; - const T* pq = q_data; - real_t* po = out_data; - for (size_t k = 0; k < navg; ++k) { - po[j] = w * std::fma(scalar, static_cast(pi[i]), offset); - po[j+1] = w * std::fma(scalar, static_cast(pq[i]), offset); - pi += in_row_stride; - pq += in_row_stride; - po += out_row_stride; - } - i += in_stride; - x += 1.0; - } +// For Real FFT +void +hann (const real_t *in_data, real_t *out_data, size_t navg, size_t nfft, + RfftScale scale) +{ + const real_t scalar + = hann_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); + const real_t k1 = k_2pi / static_cast (nfft); + const size_t out_stride = (nfft / 2 + 1) * 2; + real_t x = 0.0; + if (1 == navg) + { + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[i] = w * scalar * in_data[i]; + x += 1.0; + } + } + else if (2 == navg) + { + const real_t *in2_data = in_data + nfft; + real_t *out2_data = out_data + out_stride; + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[i] = w * scalar * in_data[i]; + out2_data[i] = w * scalar * in2_data[i]; + x += 1.0; + } + } + else + { // 2 < navg + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + const real_t *pi = in_data; + real_t *po = out_data; + for (size_t j = 0; j < navg; ++j) + { + po[i] = w * scalar * pi[i]; + pi += nfft; + po += out_stride; } + x += 1.0; } + } +} - // For Real FFT - template - void norm_blackman_harris( - const T* in_data, - real_t* out_data, - int n, - size_t navg, - size_t nfft, - CodeFormat format, - RfftScale scale - ) - { - real_t s = blackman_harris_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); - const real_t scalar = s * 2.0 / (1 << n); - const real_t offset = (CodeFormat::OffsetBinary == format) ? -s : 0.0; - const real_t k1 = k_2pi / static_cast(nfft); - const real_t k2 = k1 * 2; - const real_t k3 = k1 * 3; - const size_t out_stride = (nfft / 2 + 1) * 2; - real_t x = 0.0; - if (1 == navg) { - for (size_t i = 0; i < nfft; ++i) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[i] = w * std::fma(scalar, static_cast(in_data[i]), offset); - x += 1.0; - } - } else if (2 == navg) { - const T* in2_data = in_data + nfft; - real_t* out2_data = out_data + out_stride; - for (size_t i = 0; i < nfft; ++i) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - out_data[i] = w * std::fma(scalar, static_cast(in_data[i]), offset); - out2_data[i] = w * std::fma(scalar, static_cast(in2_data[i]), offset); - x += 1.0; - } - } else { // 2 < navg - for (size_t i = 0; i < nfft; ++i) { - const real_t w = blackman_harris_k0 - + blackman_harris_k1 * std::cos(k1 * x) - + blackman_harris_k2 * std::cos(k2 * x) - + blackman_harris_k3 * std::cos(k3 * x); - const T* pi = in_data; - real_t* po = out_data; - for (size_t j = 0; j < navg; ++j) { - po[i] = w * std::fma(scalar, static_cast(pi[i]), offset); - pi += nfft; - po += out_stride; - } - x += 1.0; - } - } +// For Complex FFT +void +no_window (const real_t *i_data, const real_t *q_data, real_t *out_data, + size_t in_stride, size_t navg, size_t nfft) +{ + const size_t out_size = navg * nfft * 2; + size_t i = 0; + for (size_t j = 0; j < out_size; j += 2) + { + out_data[j] = i_data[i]; + out_data[j + 1] = q_data[i]; + i += in_stride; + } +} + +// For Real FFT +void +no_window (const real_t *in_data, real_t *out_data, size_t navg, size_t nfft, + RfftScale scale) +{ + const real_t scalar = (RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0; + const size_t out_stride = (nfft / 2 + 1) * 2; + for (size_t j = 0; j < navg; ++j) + { + for (size_t i = 0; i < nfft; ++i) + { + out_data[i] = scalar * in_data[i]; } + in_data += nfft; + out_data += out_stride; + } +} + +} // namespace anonymous - // For Complex FFT - template - void norm_hann( - const T* i_data, - const T* q_data, - real_t* out_data, - size_t in_stride, - int n, - size_t navg, - size_t nfft, - CodeFormat format - ) - { - const real_t scalar = hann_kx * 2.0 / (1 << n); - const real_t offset = (CodeFormat::OffsetBinary == format) ? -hann_kx : 0.0; - const real_t k1 = k_2pi / static_cast(nfft); - const size_t in_row_stride = nfft * in_stride; - const size_t out_row_stride = nfft * 2; - size_t i = 0; - real_t x = 0.0; - if (1 == navg) { - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[j] = w * std::fma(scalar, static_cast(i_data[i]), offset); - out_data[j+1] = w * std::fma(scalar, static_cast(q_data[i]), offset); - i += in_stride; - x += 1.0; - } - } else if (2 == navg) { - const T* i2_data = i_data + nfft * in_stride; - const T* q2_data = q_data + nfft * in_stride; - real_t* out2_data = out_data + out_row_stride; - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[j] = w * std::fma(scalar, static_cast(i_data[i]), offset); - out_data[j+1] = w * std::fma(scalar, static_cast(q_data[i]), offset); - out2_data[j] = w * std::fma(scalar, static_cast(i2_data[i]), offset); - out2_data[j+1] = w * std::fma(scalar, static_cast(q2_data[i]), offset); - i += in_stride; - x += 1.0; - } - } else { // 2 < navg - for (size_t j = 0; j < out_row_stride; j += 2) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - const T* pi = i_data; - const T* pq = q_data; - real_t* po = out_data; - for (size_t k = 0; k < navg; ++k) { - po[j] = w * std::fma(scalar, static_cast(pi[i]), offset); - po[j+1] = w * std::fma(scalar, static_cast(pq[i]), offset); - pi += in_row_stride; - pq += in_row_stride; - po += out_row_stride; - } - i += in_stride; - x += 1.0; - } +namespace +{ // Normalize-Window Functions + +// For Complex FFT +template +void +norm_blackman_harris (const T *i_data, const T *q_data, real_t *out_data, + size_t in_stride, int n, size_t navg, size_t nfft, + CodeFormat format) +{ + const real_t scalar = blackman_harris_kx * 2.0 / (1 << n); + const real_t offset + = (CodeFormat::OffsetBinary == format) ? -blackman_harris_kx : 0.0; + const real_t k1 = k_2pi / static_cast (nfft); + const real_t k2 = k1 * 2; + const real_t k3 = k1 * 3; + const size_t in_row_stride = nfft * in_stride; + const size_t out_row_stride = nfft * 2; + size_t i = 0; + real_t x = 0.0; + if (1 == navg) + { + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[j] + = w * std::fma (scalar, static_cast (i_data[i]), offset); + out_data[j + 1] + = w * std::fma (scalar, static_cast (q_data[i]), offset); + i += in_stride; + x += 1.0; + } + } + else if (2 == navg) + { + const T *i2_data = i_data + in_row_stride; + const T *q2_data = q_data + in_row_stride; + real_t *out2_data = out_data + out_row_stride; + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[j] + = w * std::fma (scalar, static_cast (i_data[i]), offset); + out_data[j + 1] + = w * std::fma (scalar, static_cast (q_data[i]), offset); + out2_data[j] + = w + * std::fma (scalar, static_cast (i2_data[i]), offset); + out2_data[j + 1] + = w + * std::fma (scalar, static_cast (q2_data[i]), offset); + i += in_stride; + x += 1.0; + } + } + else + { // 2 < navg + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + const T *pi = i_data; + const T *pq = q_data; + real_t *po = out_data; + for (size_t k = 0; k < navg; ++k) + { + po[j] + = w * std::fma (scalar, static_cast (pi[i]), offset); + po[j + 1] + = w * std::fma (scalar, static_cast (pq[i]), offset); + pi += in_row_stride; + pq += in_row_stride; + po += out_row_stride; } + i += in_stride; + x += 1.0; } + } +} - // For Real FFT - template - void norm_hann( - const T* in_data, - real_t* out_data, - int n, - size_t navg, - size_t nfft, - CodeFormat format, - RfftScale scale - ) - { - real_t s = hann_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); - const real_t scalar = s * 2.0 / (1 << n); - const real_t offset = (CodeFormat::OffsetBinary == format) ? -s : 0.0; - const real_t k1 = k_2pi / static_cast(nfft); - const size_t out_stride = (nfft / 2 + 1) * 2; - real_t x = 0.0; - if (1 == navg) { - for (size_t i = 0; i < nfft; ++i) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[i] = w * std::fma(scalar, static_cast(in_data[i]), offset); - x += 1.0; - } - } else if (2 == navg) { - const T* in2_data = in_data + nfft; - real_t* out2_data = out_data + out_stride; - for (size_t i = 0; i < nfft; ++i) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - out_data[i] = w * std::fma(scalar, static_cast(in_data[i]), offset); - out2_data[i] = w * std::fma(scalar, static_cast(in2_data[i]), offset); - x += 1.0; - } - } else { // 2 < navg - for (size_t i = 0; i < nfft; ++i) { - const real_t w = hann_k0 + hann_k1 * std::cos(k1 * x); - const T* pi = in_data; - real_t* po = out_data; - for (size_t j = 0; j < navg; ++j) { - po[i] = w * std::fma(scalar, static_cast(pi[i]), offset); - pi += nfft; - po += out_stride; - } - x += 1.0; - } +// For Real FFT +template +void +norm_blackman_harris (const T *in_data, real_t *out_data, int n, size_t navg, + size_t nfft, CodeFormat format, RfftScale scale) +{ + real_t s + = blackman_harris_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); + const real_t scalar = s * 2.0 / (1 << n); + const real_t offset = (CodeFormat::OffsetBinary == format) ? -s : 0.0; + const real_t k1 = k_2pi / static_cast (nfft); + const real_t k2 = k1 * 2; + const real_t k3 = k1 * 3; + const size_t out_stride = (nfft / 2 + 1) * 2; + real_t x = 0.0; + if (1 == navg) + { + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[i] + = w + * std::fma (scalar, static_cast (in_data[i]), offset); + x += 1.0; + } + } + else if (2 == navg) + { + const T *in2_data = in_data + nfft; + real_t *out2_data = out_data + out_stride; + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + out_data[i] + = w + * std::fma (scalar, static_cast (in_data[i]), offset); + out2_data[i] + = w + * std::fma (scalar, static_cast (in2_data[i]), offset); + x += 1.0; + } + } + else + { // 2 < navg + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = blackman_harris_k0 + + blackman_harris_k1 * std::cos (k1 * x) + + blackman_harris_k2 * std::cos (k2 * x) + + blackman_harris_k3 * std::cos (k3 * x); + const T *pi = in_data; + real_t *po = out_data; + for (size_t j = 0; j < navg; ++j) + { + po[i] + = w * std::fma (scalar, static_cast (pi[i]), offset); + pi += nfft; + po += out_stride; } + x += 1.0; } + } +} - // For Complex FFT - template - void norm_no_window( - const T* i_data, - const T* q_data, - real_t* out_data, - size_t in_stride, - int n, - size_t navg, - size_t nfft, - CodeFormat format - ) - { - const real_t scalar = 2.0 / (1 << n); - const real_t offset = (CodeFormat::OffsetBinary == format) ? -1.0 : 0.0; - const size_t out_size = navg * nfft * 2; - size_t i = 0; - for (size_t j = 0; j < out_size; j += 2) { - out_data[j] = std::fma(scalar, static_cast(i_data[i]), offset); - out_data[j+1] = std::fma(scalar, static_cast(q_data[i]), offset); - i += in_stride; +// For Complex FFT +template +void +norm_hann (const T *i_data, const T *q_data, real_t *out_data, + size_t in_stride, int n, size_t navg, size_t nfft, + CodeFormat format) +{ + const real_t scalar = hann_kx * 2.0 / (1 << n); + const real_t offset = (CodeFormat::OffsetBinary == format) ? -hann_kx : 0.0; + const real_t k1 = k_2pi / static_cast (nfft); + const size_t in_row_stride = nfft * in_stride; + const size_t out_row_stride = nfft * 2; + size_t i = 0; + real_t x = 0.0; + if (1 == navg) + { + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[j] + = w * std::fma (scalar, static_cast (i_data[i]), offset); + out_data[j + 1] + = w * std::fma (scalar, static_cast (q_data[i]), offset); + i += in_stride; + x += 1.0; + } + } + else if (2 == navg) + { + const T *i2_data = i_data + nfft * in_stride; + const T *q2_data = q_data + nfft * in_stride; + real_t *out2_data = out_data + out_row_stride; + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[j] + = w * std::fma (scalar, static_cast (i_data[i]), offset); + out_data[j + 1] + = w * std::fma (scalar, static_cast (q_data[i]), offset); + out2_data[j] + = w + * std::fma (scalar, static_cast (i2_data[i]), offset); + out2_data[j + 1] + = w + * std::fma (scalar, static_cast (q2_data[i]), offset); + i += in_stride; + x += 1.0; + } + } + else + { // 2 < navg + for (size_t j = 0; j < out_row_stride; j += 2) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + const T *pi = i_data; + const T *pq = q_data; + real_t *po = out_data; + for (size_t k = 0; k < navg; ++k) + { + po[j] + = w * std::fma (scalar, static_cast (pi[i]), offset); + po[j + 1] + = w * std::fma (scalar, static_cast (pq[i]), offset); + pi += in_row_stride; + pq += in_row_stride; + po += out_row_stride; } + i += in_stride; + x += 1.0; } + } +} - // For Real FFT - template - void norm_no_window( - const T* in_data, - real_t* out_data, - int n, - size_t navg, - size_t nfft, - CodeFormat format, - RfftScale scale - ) - { - real_t s = (RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0; - const real_t scalar = s * 2.0 / (1 << n); - const real_t offset = (CodeFormat::OffsetBinary == format) ? -s : 0.0; - const size_t out_stride = (nfft / 2 + 1) * 2; - for (size_t j = 0; j < navg; ++j) { - for (size_t i = 0; i < nfft; ++i) { - out_data[i] = std::fma(scalar, static_cast(in_data[i]), offset); - } - in_data += nfft; - out_data += out_stride; +// For Real FFT +template +void +norm_hann (const T *in_data, real_t *out_data, int n, size_t navg, size_t nfft, + CodeFormat format, RfftScale scale) +{ + real_t s = hann_kx * ((RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0); + const real_t scalar = s * 2.0 / (1 << n); + const real_t offset = (CodeFormat::OffsetBinary == format) ? -s : 0.0; + const real_t k1 = k_2pi / static_cast (nfft); + const size_t out_stride = (nfft / 2 + 1) * 2; + real_t x = 0.0; + if (1 == navg) + { + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[i] + = w + * std::fma (scalar, static_cast (in_data[i]), offset); + x += 1.0; + } + } + else if (2 == navg) + { + const T *in2_data = in_data + nfft; + real_t *out2_data = out_data + out_stride; + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + out_data[i] + = w + * std::fma (scalar, static_cast (in_data[i]), offset); + out2_data[i] + = w + * std::fma (scalar, static_cast (in2_data[i]), offset); + x += 1.0; + } + } + else + { // 2 < navg + for (size_t i = 0; i < nfft; ++i) + { + const real_t w = hann_k0 + hann_k1 * std::cos (k1 * x); + const T *pi = in_data; + real_t *po = out_data; + for (size_t j = 0; j < navg; ++j) + { + po[i] + = w * std::fma (scalar, static_cast (pi[i]), offset); + pi += nfft; + po += out_stride; } + x += 1.0; } + } +} - } // namespace anonymous - - namespace { // FFTW Functions - - void exec_fftw(real_t* data, size_t navg, size_t nfft) - { - diff_t navg_ = static_cast(navg); - diff_t nfft_ = static_cast(nfft); - // FFT size: FFTW "rank" and "dims" - int rank = 1; - fftw_iodim64 dims {nfft_, 2, 2}; - // FFT averaging: FFTW "howmany_rank" and "howmany_dims" - int howmany_rank = 1; - fftw_iodim64 howmany_dims = {navg_, nfft_ * 2, nfft_ * 2}; - // FFTW plan setup and execution - fftw_plan plan = fftw_plan_guru64_split_dft( - rank, - &dims, - howmany_rank, - &howmany_dims, - data, // I input - data + 1, // Q input - data, // Re output - data + 1, // Im output - FFTW_ESTIMATE); - if (nullptr == plan) { - throw runtime_error("FFTW Plan is NULL"); - } - fftw_execute(plan); - fftw_destroy_plan(plan); - } - - void exec_rfftw(real_t* data, size_t navg, size_t nfft) - { - diff_t navg_ = static_cast(navg); - diff_t nfft_ = static_cast(nfft); - diff_t out_stride = nfft_ / 2 + 1; - // FFT size: FFTW "rank" and "dims" - int rank = 1; - fftw_iodim64 dims {nfft_, 1, 1}; - // FFT averaging: FFTW "howmany_rank" and "howmany_dims" - int howmany_rank = 1; - fftw_iodim64 howmany_dims {navg_, out_stride * 2, out_stride}; - // Plan setup and execution - fftw_complex* out_data = reinterpret_cast(data); - fftw_plan plan = fftw_plan_guru64_dft_r2c( - rank, - &dims, - howmany_rank, - &howmany_dims, - data, - out_data, - FFTW_ESTIMATE); - if (nullptr == plan) { - throw runtime_error("FFTW Plan is NULL"); - } - fftw_execute(plan); - fftw_destroy_plan(plan); +// For Complex FFT +template +void +norm_no_window (const T *i_data, const T *q_data, real_t *out_data, + size_t in_stride, int n, size_t navg, size_t nfft, + CodeFormat format) +{ + const real_t scalar = 2.0 / (1 << n); + const real_t offset = (CodeFormat::OffsetBinary == format) ? -1.0 : 0.0; + const size_t out_size = navg * nfft * 2; + size_t i = 0; + for (size_t j = 0; j < out_size; j += 2) + { + out_data[j] = std::fma (scalar, static_cast (i_data[i]), offset); + out_data[j + 1] + = std::fma (scalar, static_cast (q_data[i]), offset); + i += in_stride; + } +} + +// For Real FFT +template +void +norm_no_window (const T *in_data, real_t *out_data, int n, size_t navg, + size_t nfft, CodeFormat format, RfftScale scale) +{ + real_t s = (RfftScale::DbfsSin == scale) ? k_sqrt2 : 1.0; + const real_t scalar = s * 2.0 / (1 << n); + const real_t offset = (CodeFormat::OffsetBinary == format) ? -s : 0.0; + const size_t out_stride = (nfft / 2 + 1) * 2; + for (size_t j = 0; j < navg; ++j) + { + for (size_t i = 0; i < nfft; ++i) + { + out_data[i] + = std::fma (scalar, static_cast (in_data[i]), offset); } + in_data += nfft; + out_data += out_stride; + } +} - } // namespace anonymous +} // namespace anonymous - namespace { // Scaling and Averaging Functions +namespace +{ // FFTW Functions - void reduce_and_scale_fft(real_t* fftw_data, real_t* out_data, size_t navg, size_t nfft) +void +exec_fftw (real_t *data, size_t navg, size_t nfft) +{ + diff_t navg_ = static_cast (navg); + diff_t nfft_ = static_cast (nfft); + // FFT size: FFTW "rank" and "dims" + int rank = 1; + fftw_iodim64 dims{ nfft_, 2, 2 }; + // FFT averaging: FFTW "howmany_rank" and "howmany_dims" + int howmany_rank = 1; + fftw_iodim64 howmany_dims = { navg_, nfft_ * 2, nfft_ * 2 }; + // FFTW plan setup and execution + fftw_plan plan + = fftw_plan_guru64_split_dft (rank, &dims, howmany_rank, &howmany_dims, + data, // I input + data + 1, // Q input + data, // Re output + data + 1, // Im output + FFTW_ESTIMATE); + if (nullptr == plan) + { + throw runtime_error ("FFTW Plan is NULL"); + } + fftw_execute (plan); + fftw_destroy_plan (plan); +} + +void +exec_rfftw (real_t *data, size_t navg, size_t nfft) +{ + diff_t navg_ = static_cast (navg); + diff_t nfft_ = static_cast (nfft); + diff_t out_stride = nfft_ / 2 + 1; + // FFT size: FFTW "rank" and "dims" + int rank = 1; + fftw_iodim64 dims{ nfft_, 1, 1 }; + // FFT averaging: FFTW "howmany_rank" and "howmany_dims" + int howmany_rank = 1; + fftw_iodim64 howmany_dims{ navg_, out_stride * 2, out_stride }; + // Plan setup and execution + fftw_complex *out_data = reinterpret_cast (data); + fftw_plan plan = fftw_plan_guru64_dft_r2c ( + rank, &dims, howmany_rank, &howmany_dims, data, out_data, FFTW_ESTIMATE); + if (nullptr == plan) + { + throw runtime_error ("FFTW Plan is NULL"); + } + fftw_execute (plan); + fftw_destroy_plan (plan); +} + +} // namespace anonymous + +namespace +{ // Scaling and Averaging Functions + +void +reduce_and_scale_fft (real_t *fftw_data, real_t *out_data, size_t navg, + size_t nfft) +{ + cplx_t *cfftw_data = reinterpret_cast (fftw_data); + cplx_t *cout_data = reinterpret_cast (out_data); + for (size_t i = 0; i < nfft; ++i) + { + cout_data[i] = { std::norm (cfftw_data[i]), std::arg (cfftw_data[i]) }; + } + for (size_t j = 1; j < navg; ++j) + { + cfftw_data += nfft; + for (size_t i = 0; i < nfft; ++i) { - cplx_t* cfftw_data = reinterpret_cast(fftw_data); - cplx_t* cout_data = reinterpret_cast(out_data); - for (size_t i = 0; i < nfft; ++i) { - cout_data[i] = {std::norm(cfftw_data[i]), std::arg(cfftw_data[i])}; - } - for (size_t j = 1; j < navg; ++j) { - cfftw_data += nfft; - for (size_t i = 0; i < nfft; ++i) { - cout_data[i] += cplx_t(std::norm(cfftw_data[i]), std::arg(cfftw_data[i])); - } - } - const real_t avg_scalar = 1.0 / static_cast(navg); - const real_t fft_scalar = 1.0 / static_cast(nfft); - for (size_t i = 0; i < nfft; ++i) { - cplx_t& x = cout_data[i]; - x *= avg_scalar; - x = std::polar(std::sqrt(x.real()) * fft_scalar, x.imag()); - } + cout_data[i] + += cplx_t (std::norm (cfftw_data[i]), std::arg (cfftw_data[i])); } + } + const real_t avg_scalar = 1.0 / static_cast (navg); + const real_t fft_scalar = 1.0 / static_cast (nfft); + for (size_t i = 0; i < nfft; ++i) + { + cplx_t &x = cout_data[i]; + x *= avg_scalar; + x = std::polar (std::sqrt (x.real ()) * fft_scalar, x.imag ()); + } +} - void reduce_and_scale_rfft( - real_t* fftw_data, real_t* out_data, size_t navg, size_t nfft, RfftScale scale) +void +reduce_and_scale_rfft (real_t *fftw_data, real_t *out_data, size_t navg, + size_t nfft, RfftScale scale) +{ + cplx_t *cfftw_data = reinterpret_cast (fftw_data); + cplx_t *cout_data = reinterpret_cast (out_data); + const size_t cout_size = nfft / 2 + 1; + for (size_t i = 0; i < cout_size; ++i) + { + cout_data[i] = { std::norm (cfftw_data[i]), std::arg (cfftw_data[i]) }; + } + for (size_t j = 1; j < navg; ++j) + { + cfftw_data += cout_size; + for (size_t i = 0; i < cout_size; ++i) { - cplx_t* cfftw_data = reinterpret_cast(fftw_data); - cplx_t* cout_data = reinterpret_cast(out_data); - const size_t cout_size = nfft / 2 + 1; - for (size_t i = 0; i < cout_size; ++i) { - cout_data[i] = {std::norm(cfftw_data[i]), std::arg(cfftw_data[i])}; - } - for (size_t j = 1; j < navg; ++j) { - cfftw_data += cout_size; - for (size_t i = 0; i < cout_size; ++i) { - cout_data[i] += cplx_t(std::norm(cfftw_data[i]), std::arg(cfftw_data[i])); - } - } - const real_t avg_scalar = 1.0 / static_cast(navg); - real_t s = (RfftScale::Native == scale) ? 1.0 : k_sqrt2; - const real_t fft_scalar = s / static_cast(nfft); - for (size_t i = 0; i < cout_size; ++i) { - cplx_t& x = cout_data[i]; - x *= avg_scalar; - x = std::polar(std::sqrt(x.real()) * fft_scalar, x.imag()); - } - if (RfftScale::Native != scale) { - cout_data[0] /= k_sqrt2; - if (1 < nfft && is_even(nfft)) { - cout_data[cout_size - 1] /= k_sqrt2; - } - } + cout_data[i] + += cplx_t (std::norm (cfftw_data[i]), std::arg (cfftw_data[i])); } - - void scale_fft(real_t* data, size_t nfft) + } + const real_t avg_scalar = 1.0 / static_cast (navg); + real_t s = (RfftScale::Native == scale) ? 1.0 : k_sqrt2; + const real_t fft_scalar = s / static_cast (nfft); + for (size_t i = 0; i < cout_size; ++i) + { + cplx_t &x = cout_data[i]; + x *= avg_scalar; + x = std::polar (std::sqrt (x.real ()) * fft_scalar, x.imag ()); + } + if (RfftScale::Native != scale) + { + cout_data[0] /= k_sqrt2; + if (1 < nfft && is_even (nfft)) { - const size_t size = 2 * nfft; - const real_t scalar = 1.0 / static_cast(nfft); - for (size_t i = 0; i < size; ++i) { - data[i] *= scalar; - } + cout_data[cout_size - 1] /= k_sqrt2; } + } +} - void scale_rfft(real_t* data, size_t nfft, RfftScale scale) +void +scale_fft (real_t *data, size_t nfft) +{ + const size_t size = 2 * nfft; + const real_t scalar = 1.0 / static_cast (nfft); + for (size_t i = 0; i < size; ++i) + { + data[i] *= scalar; + } +} + +void +scale_rfft (real_t *data, size_t nfft, RfftScale scale) +{ + const size_t size = (nfft / 2 + 1) * 2; + real_t s = (RfftScale::Native == scale) ? 1.0 : k_sqrt2; + const real_t scalar = s / static_cast (nfft); + for (size_t i = 0; i < size; ++i) + { + data[i] *= scalar; + } + if (RfftScale::Native != scale) + { + data[0] /= k_sqrt2; + data[1] /= k_sqrt2; + if (1 < nfft && is_even (nfft)) { - const size_t size = (nfft / 2 + 1) * 2; - real_t s = (RfftScale::Native == scale) ? 1.0 : k_sqrt2; - const real_t scalar = s / static_cast(nfft); - for (size_t i = 0; i < size; ++i) { - data[i] *= scalar; - } - if (RfftScale::Native != scale) { - data[0] /= k_sqrt2; - data[1] /= k_sqrt2; - if (1 < nfft && is_even(nfft)) { - data[size - 1] /= k_sqrt2; - data[size - 2] /= k_sqrt2; - } - } + data[size - 1] /= k_sqrt2; + data[size - 2] /= k_sqrt2; } + } +} + +} // namespace anonymous + +void +fft (const real_t *i_data, size_t i_size, const real_t *q_data, size_t q_size, + real_t *out_data, size_t out_size, size_t navg, size_t nfft, + Window window) +{ + size_t in_stride = 1; + if (0 == q_size) + { + // Interleaved I/Q + check_array ("", "input array", i_data, i_size, true); + i_size /= 2; + q_size = i_size; + q_data = i_data + 1; + in_stride = 2; + } + else + { + // Split I/Q + check_array_pair ("", "I array", i_data, i_size, "Q array", q_data, + q_size); + } + check_array ("", "output array", out_data, out_size); + size_t out_size_expected + = fft_size (i_size, q_size, navg, nfft); // may modify navg and nfft + assert_eq ("", "output array size", out_size, "expected", out_size_expected); + // If not averaging (1 == navg), use out_data directly. Otherwise, allocate + // temporary array to store result of normalization/windowing and FFT. For + // example, + // navg = 4, nfft = 16 + // => i_size = 64 + // q_size = 64 + // out_size = 16 * 2 = 32 + // tmp.size = navg * out_size = 128 + std::vector tmp ((1 == navg) ? 0 : 2 * i_size); + real_t *fftw_data = (1 == navg) ? out_data : tmp.data (); + switch (window) + { + case Window::BlackmanHarris: + blackman_harris (i_data, q_data, fftw_data, in_stride, navg, nfft); + break; + case Window::Hann: + hann (i_data, q_data, fftw_data, in_stride, navg, nfft); + break; + case Window::NoWindow: + no_window (i_data, q_data, fftw_data, in_stride, navg, nfft); + break; + default: + throw runtime_error ("unsupported window"); + } + exec_fftw (fftw_data, navg, nfft); + if (1 == navg) + { + scale_fft (out_data, nfft); + } + else + { + reduce_and_scale_fft (fftw_data, out_data, navg, nfft); + } +} + +template +void +fft (const T *i_data, size_t i_size, const T *q_data, size_t q_size, + real_t *out_data, size_t out_size, int n, size_t navg, size_t nfft, + Window window, CodeFormat format) +{ + size_t in_stride = 1; + if (0 == q_size) + { + // Interleaved I/Q + check_array ("", "input array", i_data, i_size, true); + i_size /= 2; + q_size = i_size; + q_data = i_data + 1; + in_stride = 2; + } + else + { + // Split I/Q + check_array_pair ("", "I array", i_data, i_size, "Q array", q_data, + q_size); + } + check_array ("", "output array", out_data, out_size); + size_t out_size_expected + = fft_size (i_size, q_size, navg, nfft); // may modify navg and nfft + assert_eq ("", "output array size", out_size, "expected", out_size_expected); + check_code_width ("", n); + // If not averaging (1 == navg), use out_data directly. Otherwise, allocate + // temporary array to store result of normalization/windowing and FFT. For + // example, + // navg = 4, nfft = 16 + // => i_size = 64 + // q_size = 64 + // out_size = 16 * 2 = 32 + // tmp.size = navg * out_size = 128 + std::vector tmp ((1 == navg) ? 0 : 2 * i_size); + real_t *fftw_data = (1 == navg) ? out_data : tmp.data (); + switch (window) + { + case Window::BlackmanHarris: + norm_blackman_harris (i_data, q_data, fftw_data, in_stride, n, navg, + nfft, format); + break; + case Window::Hann: + norm_hann (i_data, q_data, fftw_data, in_stride, n, navg, nfft, format); + break; + case Window::NoWindow: + norm_no_window (i_data, q_data, fftw_data, in_stride, n, navg, nfft, + format); + break; + default: + throw runtime_error ("unsupported window"); + } + exec_fftw (fftw_data, navg, nfft); + if (1 == navg) + { + scale_fft (out_data, nfft); + } + else + { + reduce_and_scale_fft (fftw_data, out_data, navg, nfft); + } +} - } // namespace anonymous - - void fft( - const real_t* i_data, - size_t i_size, - const real_t* q_data, - size_t q_size, - real_t* out_data, - size_t out_size, - size_t navg, - size_t nfft, - Window window - ) - { - size_t in_stride = 1; - if (0 == q_size) { - // Interleaved I/Q - check_array("", "input array", i_data, i_size, true); - i_size /= 2; - q_size = i_size; - q_data = i_data + 1; - in_stride = 2; - } else { - // Split I/Q - check_array_pair("", "I array", i_data, i_size, "Q array", q_data, q_size); - } - check_array("", "output array", out_data, out_size); - size_t out_size_expected = fft_size(i_size, q_size, navg, nfft); // may modify navg and nfft - assert_eq("", "output array size", out_size, "expected", out_size_expected); - // If not averaging (1 == navg), use out_data directly. Otherwise, allocate temporary - // array to store result of normalization/windowing and FFT. For example, - // navg = 4, nfft = 16 - // => i_size = 64 - // q_size = 64 - // out_size = 16 * 2 = 32 - // tmp.size = navg * out_size = 128 - std::vector tmp ((1 == navg) ? 0 : 2 * i_size); - real_t* fftw_data = (1 == navg) ? out_data : tmp.data(); - switch (window) - { - case Window::BlackmanHarris: - blackman_harris(i_data, q_data, fftw_data, in_stride, navg, nfft); - break; - case Window::Hann: - hann(i_data, q_data, fftw_data, in_stride, navg, nfft); - break; - case Window::NoWindow: - no_window(i_data, q_data, fftw_data, in_stride, navg, nfft); - break; - default: - throw runtime_error("unsupported window"); - } - exec_fftw(fftw_data, navg, nfft); - if (1 == navg) { - scale_fft(out_data, nfft); - } else { - reduce_and_scale_fft(fftw_data, out_data, navg, nfft); - } - } - - template - void fft( - const T* i_data, - size_t i_size, - const T* q_data, - size_t q_size, - real_t* out_data, - size_t out_size, - int n, - size_t navg, - size_t nfft, - Window window, - CodeFormat format - ) - { - size_t in_stride = 1; - if (0 == q_size) { - // Interleaved I/Q - check_array("", "input array", i_data, i_size, true); - i_size /= 2; - q_size = i_size; - q_data = i_data + 1; - in_stride = 2; - } else { - // Split I/Q - check_array_pair("", "I array", i_data, i_size, "Q array", q_data, q_size); - } - check_array("", "output array", out_data, out_size); - size_t out_size_expected = fft_size(i_size, q_size, navg, nfft); // may modify navg and nfft - assert_eq("", "output array size", out_size, "expected", out_size_expected); - check_code_width("", n); - // If not averaging (1 == navg), use out_data directly. Otherwise, allocate temporary - // array to store result of normalization/windowing and FFT. For example, - // navg = 4, nfft = 16 - // => i_size = 64 - // q_size = 64 - // out_size = 16 * 2 = 32 - // tmp.size = navg * out_size = 128 - std::vector tmp ((1 == navg) ? 0 : 2 * i_size); - real_t* fftw_data = (1 == navg) ? out_data : tmp.data(); - switch (window) - { - case Window::BlackmanHarris: - norm_blackman_harris(i_data, q_data, fftw_data, in_stride, n, navg, nfft, format); - break; - case Window::Hann: - norm_hann(i_data, q_data, fftw_data, in_stride, n, navg, nfft, format); - break; - case Window::NoWindow: - norm_no_window(i_data, q_data, fftw_data, in_stride, n, navg, nfft, format); - break; - default: - throw runtime_error("unsupported window"); - } - exec_fftw(fftw_data, navg, nfft); - if (1 == navg) { - scale_fft(out_data, nfft); - } else { - reduce_and_scale_fft(fftw_data, out_data, navg, nfft); - } - } - - template void fft(const int16_t*, size_t, const int16_t*, size_t, real_t*, size_t, int, size_t, size_t, Window, CodeFormat); - template void fft(const int32_t*, size_t, const int32_t*, size_t, real_t*, size_t, int, size_t, size_t, Window, CodeFormat); - template void fft(const int64_t*, size_t, const int64_t*, size_t, real_t*, size_t, int, size_t, size_t, Window, CodeFormat); - - void rfft( - const real_t* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - size_t navg, - size_t nfft, - Window window, - RfftScale scale - ) - { - check_array("", "input array", in_data, in_size); - check_array("", "output array", out_data, out_size); - size_t out_size_expected = rfft_size(in_size, navg, nfft); - assert_eq("", "output array size", out_size, "expected", out_size_expected); - // If not averaging (1 == navg), use out_data directly. Otherwise, allocate temporary - // array to store result of windowing and FFT. For example, - // navg = 4, nfft = 16 - // => in_size = 64 - // out_size = (16/2 + 1) * 2 = 18 - // tmp.size = navg * out_size = 72 - std::vector tmp ((1 == navg) ? 0 : navg * out_size); - real_t* fftw_data = (1 == navg) ? out_data : tmp.data(); - switch (window) - { - case Window::BlackmanHarris: - blackman_harris(in_data, fftw_data, navg, nfft, scale); - break; - case Window::Hann: - hann(in_data, fftw_data, navg, nfft, scale); - break; - case Window::NoWindow: - no_window(in_data, fftw_data, navg, nfft, scale); - break; - default: - throw runtime_error("unsupported window"); - } - exec_rfftw(fftw_data, navg, nfft); - if (1 == navg) { - scale_rfft(out_data, nfft, scale); - } else { - reduce_and_scale_rfft(fftw_data, out_data, navg, nfft, scale); - } - } - - template - void rfft( - const T* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - int n, - size_t navg, - size_t nfft, - Window window, - CodeFormat format, - RfftScale scale - ) - { - check_array("", "input array", in_data, in_size); - check_array("", "output array", out_data, out_size); - size_t out_size_expected = rfft_size(in_size, navg, nfft); - assert_eq("", "output array size", out_size, "expected", out_size_expected); - check_code_width("", n); - // If not averaging (1 == navg), use out_data directly. Otherwise, allocate temporary - // array to store result of normalization/windowing and FFT. For example, - // navg = 4, nfft = 16 - // => in_size = 64 - // out_size = (16/2 + 1) * 2 = 18 - // tmp.size = navg * out_size = 72 - std::vector tmp ((1 == navg) ? 0 : navg * out_size); - real_t* fftw_data = (1 == navg) ? out_data : tmp.data(); - switch (window) - { - case Window::BlackmanHarris: - norm_blackman_harris(in_data, fftw_data, n, navg, nfft, format, scale); - break; - case Window::Hann: - norm_hann(in_data, fftw_data, n, navg, nfft, format, scale); - break; - case Window::NoWindow: - norm_no_window(in_data, fftw_data, n, navg, nfft, format, scale); - break; - default: - throw runtime_error("unsupported window"); - } - exec_rfftw(fftw_data, navg, nfft); - if (1 == navg) { - scale_rfft(out_data, nfft, scale); - } else { - reduce_and_scale_rfft(fftw_data, out_data, navg, nfft, scale); - } - } - - template void rfft(const int16_t*, size_t, real_t*, size_t, int, size_t, size_t, Window, CodeFormat, RfftScale); - template void rfft(const int32_t*, size_t, real_t*, size_t, int, size_t, size_t, Window, CodeFormat, RfftScale); - template void rfft(const int64_t*, size_t, real_t*, size_t, int, size_t, size_t, Window, CodeFormat, RfftScale); +template void fft (const int16_t *, size_t, const int16_t *, size_t, real_t *, + size_t, int, size_t, size_t, Window, CodeFormat); +template void fft (const int32_t *, size_t, const int32_t *, size_t, real_t *, + size_t, int, size_t, size_t, Window, CodeFormat); +template void fft (const int64_t *, size_t, const int64_t *, size_t, real_t *, + size_t, int, size_t, size_t, Window, CodeFormat); + +void +rfft (const real_t *in_data, size_t in_size, real_t *out_data, size_t out_size, + size_t navg, size_t nfft, Window window, RfftScale scale) +{ + check_array ("", "input array", in_data, in_size); + check_array ("", "output array", out_data, out_size); + size_t out_size_expected = rfft_size (in_size, navg, nfft); + assert_eq ("", "output array size", out_size, "expected", out_size_expected); + // If not averaging (1 == navg), use out_data directly. Otherwise, allocate + // temporary array to store result of windowing and FFT. For example, + // navg = 4, nfft = 16 + // => in_size = 64 + // out_size = (16/2 + 1) * 2 = 18 + // tmp.size = navg * out_size = 72 + std::vector tmp ((1 == navg) ? 0 : navg * out_size); + real_t *fftw_data = (1 == navg) ? out_data : tmp.data (); + switch (window) + { + case Window::BlackmanHarris: + blackman_harris (in_data, fftw_data, navg, nfft, scale); + break; + case Window::Hann: + hann (in_data, fftw_data, navg, nfft, scale); + break; + case Window::NoWindow: + no_window (in_data, fftw_data, navg, nfft, scale); + break; + default: + throw runtime_error ("unsupported window"); + } + exec_rfftw (fftw_data, navg, nfft); + if (1 == navg) + { + scale_rfft (out_data, nfft, scale); + } + else + { + reduce_and_scale_rfft (fftw_data, out_data, navg, nfft, scale); + } +} + +template +void +rfft (const T *in_data, size_t in_size, real_t *out_data, size_t out_size, + int n, size_t navg, size_t nfft, Window window, CodeFormat format, + RfftScale scale) +{ + check_array ("", "input array", in_data, in_size); + check_array ("", "output array", out_data, out_size); + size_t out_size_expected = rfft_size (in_size, navg, nfft); + assert_eq ("", "output array size", out_size, "expected", out_size_expected); + check_code_width ("", n); + // If not averaging (1 == navg), use out_data directly. Otherwise, allocate + // temporary array to store result of normalization/windowing and FFT. For + // example, + // navg = 4, nfft = 16 + // => in_size = 64 + // out_size = (16/2 + 1) * 2 = 18 + // tmp.size = navg * out_size = 72 + std::vector tmp ((1 == navg) ? 0 : navg * out_size); + real_t *fftw_data = (1 == navg) ? out_data : tmp.data (); + switch (window) + { + case Window::BlackmanHarris: + norm_blackman_harris (in_data, fftw_data, n, navg, nfft, format, scale); + break; + case Window::Hann: + norm_hann (in_data, fftw_data, n, navg, nfft, format, scale); + break; + case Window::NoWindow: + norm_no_window (in_data, fftw_data, n, navg, nfft, format, scale); + break; + default: + throw runtime_error ("unsupported window"); + } + exec_rfftw (fftw_data, navg, nfft); + if (1 == navg) + { + scale_rfft (out_data, nfft, scale); + } + else + { + reduce_and_scale_rfft (fftw_data, out_data, navg, nfft, scale); + } +} + +template void rfft (const int16_t *, size_t, real_t *, size_t, int, size_t, + size_t, Window, CodeFormat, RfftScale); +template void rfft (const int32_t *, size_t, real_t *, size_t, int, size_t, + size_t, Window, CodeFormat, RfftScale); +template void rfft (const int64_t *, size_t, real_t *, size_t, int, size_t, + size_t, Window, CodeFormat, RfftScale); } // namespace genalyzer_impl -namespace genalyzer_impl { +namespace genalyzer_impl +{ - namespace { +namespace +{ - // fft: in_size is the size of either the I or Q waveform (not the sum) - // rfft: in_size is the size of the waveform - void resolve_navg_and_nfft(const size_t in_size, size_t& navg, size_t& nfft) +// fft: in_size is the size of either the I or Q waveform (not the sum) +// rfft: in_size is the size of the waveform +void +resolve_navg_and_nfft (const size_t in_size, size_t &navg, size_t &nfft) +{ + assert_gt0 ("", "input size", in_size); + if (k_abs_max_fft_navg < navg) + { + throw runtime_error ("navg (" + std::to_string (navg) + + ") exceeds limit (" + + std::to_string (k_abs_max_fft_navg) + ")"); + } + if (0 == navg && 0 == nfft) + { + navg = 1; + nfft = in_size; + } + else if (0 == navg) + { + navg = in_size / nfft; + if (0 == navg) { - assert_gt0("", "input size", in_size); - if (k_abs_max_fft_navg < navg) { - throw runtime_error("navg (" + std::to_string(navg) - + ") exceeds limit (" + std::to_string(k_abs_max_fft_navg) + ")"); - } - if (0 == navg && 0 == nfft) { - navg = 1; - nfft = in_size; - } else if (0 == navg) { - navg = in_size / nfft; - if (0 == navg) { - throw runtime_error("derived navg == 0"); - } - if (k_abs_max_fft_navg < navg) { - throw runtime_error("derived navg (" + std::to_string(navg) - + ") exceeds limit (" + std::to_string(k_abs_max_fft_navg) + ")"); - } - } else if (0 == nfft) { - nfft = in_size / navg; - } - size_t in_size_expected = navg * nfft; - try { - assert_eq("", "input size", in_size, "expected", in_size_expected); - } catch (const std::exception& e) { - throw runtime_error(str_t(e.what()) + "\nExpected input size = navg * nfft = " - + std::to_string(navg) + " * " + std::to_string(nfft) + " = " - + std::to_string(in_size_expected) + "\nGot input size = " - + std::to_string(in_size)); - } + throw runtime_error ("derived navg == 0"); + } + if (k_abs_max_fft_navg < navg) + { + throw runtime_error ("derived navg (" + std::to_string (navg) + + ") exceeds limit (" + + std::to_string (k_abs_max_fft_navg) + ")"); } - - } // namespace anonymous + } + else if (0 == nfft) + { + nfft = in_size / navg; + } + size_t in_size_expected = navg * nfft; + try + { + assert_eq ("", "input size", in_size, "expected", in_size_expected); + } + catch (const std::exception &e) + { + throw runtime_error ( + str_t (e.what ()) + "\nExpected input size = navg * nfft = " + + std::to_string (navg) + " * " + std::to_string (nfft) + " = " + + std::to_string (in_size_expected) + + "\nGot input size = " + std::to_string (in_size)); + } +} + +} // namespace anonymous - size_t fft_size(size_t i_size, size_t q_size, size_t& navg, size_t& nfft) +size_t +fft_size (size_t i_size, size_t q_size, size_t &navg, size_t &nfft) +{ + if (0 == q_size) { - if (0 == q_size) { - if (is_odd(i_size)) { - throw runtime_error("size of interleaved array must be even"); - } - i_size /= 2; - } else { - assert_eq("", "I size", i_size, "Q size", q_size); + if (is_odd (i_size)) + { + throw runtime_error ("size of interleaved array must be even"); } - resolve_navg_and_nfft(i_size, navg, nfft); - size_t size = nfft * 2; - return size; + i_size /= 2; } - - size_t rfft_size(size_t in_size, size_t& navg, size_t& nfft) + else { - resolve_navg_and_nfft(in_size, navg, nfft); - size_t size = (nfft / 2 + 1) * 2; // integer division intentional - return size; + assert_eq ("", "I size", i_size, "Q size", q_size); } + resolve_navg_and_nfft (i_size, navg, nfft); + size_t size = nfft * 2; + return size; +} + +size_t +rfft_size (size_t in_size, size_t &navg, size_t &nfft) +{ + resolve_navg_and_nfft (in_size, navg, nfft); + size_t size = (nfft / 2 + 1) * 2; // integer division intentional + return size; +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/fourier_utilities.cpp b/src/fourier_utilities.cpp index a41b97c..760c808 100644 --- a/src/fourier_utilities.cpp +++ b/src/fourier_utilities.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "fourier_utilities.hpp" #include "constants.hpp" @@ -9,102 +12,133 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - real_t alias(real_t fs, real_t freq, FreqAxisType axis_type) +real_t +alias (real_t fs, real_t freq, FreqAxisType axis_type) +{ + assert_gt0 ("", "fs", fs); + freq -= std::floor (freq / fs) * fs; // freq in [0, fs) + if (FreqAxisType::DcCenter == axis_type) { - assert_gt0("", "fs", fs); - freq -= std::floor(freq / fs) * fs; // freq in [0, fs) - if (FreqAxisType::DcCenter == axis_type) { - return (fs <= 2 * freq) ? (freq - fs) : freq; - } else if (FreqAxisType::Real == axis_type) { - return (fs < 2 * freq) ? (fs - freq) : freq; - } else { - return freq; - } + return (fs <= 2 * freq) ? (freq - fs) : freq; } - - real_t coherent(size_t nfft, real_t fs, real_t freq) + else if (FreqAxisType::Real == axis_type) { - assert_gt0("", "nfft", nfft); - assert_gt0("", "fs", fs); - if (1 == nfft) { - return freq; - } - real_t fbin = fs / static_cast(nfft); - assert_gt0("", "fbin", fbin); - real_t cycles = std::fabs(freq) / fbin; - if (is_pow2(nfft)) { - cycles = std::floor(cycles); - if (0.0 == std::fmod(cycles, 2.0)) { - cycles += 1.0; - } - cycles = std::copysign(cycles, freq); - } else { - cycles = std::copysign(std::round(cycles), freq); - } - return cycles * fbin; + return (fs < 2 * freq) ? (fs - freq) : freq; } + else + { + return freq; + } +} - void fftshift(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) +real_t +coherent (size_t nfft, real_t fs, real_t freq) +{ + assert_gt0 ("", "nfft", nfft); + assert_gt0 ("", "fs", fs); + if (1 == nfft) { - check_array_pair("", "input array", in_data, in_size, "output_array", out_data, out_size); - size_t offset = in_size / 2; - if (is_odd(in_size)) { - offset += 1; - } - if (in_data == out_data) { - std::rotate(out_data, out_data + offset, out_data + out_size); - } else { - std::rotate_copy(in_data, in_data + offset, in_data + in_size, out_data); + return freq; + } + real_t fbin = fs / static_cast (nfft); + assert_gt0 ("", "fbin", fbin); + real_t cycles = std::fabs (freq) / fbin; + if (is_pow2 (nfft)) + { + cycles = std::floor (cycles); + if (0.0 == std::fmod (cycles, 2.0)) + { + cycles += 1.0; } + cycles = std::copysign (cycles, freq); + } + else + { + cycles = std::copysign (std::round (cycles), freq); } + return cycles * fbin; +} - void freq_axis( - real_t* data, - size_t size, - size_t nfft, - FreqAxisType axis_type, - real_t fs, - FreqAxisFormat axis_format - ) +void +fftshift (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size) +{ + check_array_pair ("", "input array", in_data, in_size, "output_array", + out_data, out_size); + size_t offset = in_size / 2; + if (is_odd (in_size)) { - check_array("", "output array", data, size); - assert_eq("", "array size", size, "expected", freq_axis_size(nfft, axis_type)); - real_t start = 0.0; - if (FreqAxisType::DcCenter == axis_type) { - start = -static_cast(nfft / 2); - } - std::iota(data, data + size, start); - real_t unit = 1.0; - if (FreqAxisFormat::Freq == axis_format) { - unit = fs / static_cast(nfft); - } else if (FreqAxisFormat::Norm == axis_format) { - unit /= static_cast(nfft); - } - if (1.0 != unit) { - for (size_t i = 0; i < size; ++i) { - data[i] *= unit; - } - } + offset += 1; } + if (in_data == out_data) + { + std::rotate (out_data, out_data + offset, out_data + out_size); + } + else + { + std::rotate_copy (in_data, in_data + offset, in_data + in_size, + out_data); + } +} - void ifftshift(const real_t* in_data, size_t in_size, real_t* out_data, size_t out_size) +void +freq_axis (real_t *data, size_t size, size_t nfft, FreqAxisType axis_type, + real_t fs, FreqAxisFormat axis_format) +{ + check_array ("", "output array", data, size); + assert_eq ("", "array size", size, "expected", + freq_axis_size (nfft, axis_type)); + real_t start = 0.0; + if (FreqAxisType::DcCenter == axis_type) { - check_array_pair("", "input array", in_data, in_size, "output_array", out_data, out_size); - size_t offset = in_size / 2; - if (in_data == out_data) { - std::rotate(out_data, out_data + offset, out_data + out_size); - } else { - std::rotate_copy(in_data, in_data + offset, in_data + in_size, out_data); + start = -static_cast (nfft / 2); + } + std::iota (data, data + size, start); + real_t unit = 1.0; + if (FreqAxisFormat::Freq == axis_format) + { + unit = fs / static_cast (nfft); + } + else if (FreqAxisFormat::Norm == axis_format) + { + unit /= static_cast (nfft); + } + if (1.0 != unit) + { + for (size_t i = 0; i < size; ++i) + { + data[i] *= unit; } } +} - size_t freq_axis_size(size_t nfft, FreqAxisType axis_type) +void +ifftshift (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size) +{ + check_array_pair ("", "input array", in_data, in_size, "output_array", + out_data, out_size); + size_t offset = in_size / 2; + if (in_data == out_data) { - assert_gt0("", "nfft", nfft); - size_t size = (FreqAxisType::Real == axis_type) ? nfft / 2 + 1 : nfft; - return size; + std::rotate (out_data, out_data + offset, out_data + out_size); } + else + { + std::rotate_copy (in_data, in_data + offset, in_data + in_size, + out_data); + } +} + +size_t +freq_axis_size (size_t nfft, FreqAxisType axis_type) +{ + assert_gt0 ("", "nfft", nfft); + size_t size = (FreqAxisType::Real == axis_type) ? nfft / 2 + 1 : nfft; + return size; +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/json.cpp b/src/json.cpp index f9ed285..f72a6c5 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "fourier_analysis.hpp" #include @@ -11,132 +14,152 @@ using json = nlohmann::json; -namespace genalyzer_impl { +namespace genalyzer_impl +{ - std::shared_ptr fourier_analysis::load(const str_t& filename) +std::shared_ptr +fourier_analysis::load (const str_t &filename) +{ + std::ifstream ifs (filename); + if (!ifs.is_open ()) { - std::ifstream ifs (filename); - if (!ifs.is_open()) { - throw runtime_error("unable to open file '" + filename + "'"); - } - try { - json j; - ifs >> j; // error handling? - std::shared_ptr p = std::make_shared(); - j["en_conv_offset"].get_to(p->en_conv_offset); - j["en_fund_images"].get_to(p->en_fund_images); - j["en_quad_errors"].get_to(p->en_quad_errors); - j["clk_as_noise"].get_to(p->clk_as_noise); - j["dc_as_dist"].get_to(p->dc_as_dist); - j["ilv_as_noise"].get_to(p->ilv_as_noise); - p->set_analysis_band(j["ab_center"].get(), j["ab_width"].get()); - p->set_fdata(j["fdata"].get()); - p->set_fsample(j["fsample"].get()); - p->set_fshift(j["fshift"].get()); - p->set_hd(j["hd"].get()); - p->set_imd(j["imd"].get()); - p->set_wo(j["wo"].get()); - p->set_ssb(FASsb::Default, j["ssb_def"].get()); - p->set_ssb(FASsb::DC , j["ssb_dc" ].get()); - p->set_ssb(FASsb::Signal , j["ssb_sig"].get()); - p->set_ssb(FASsb::WO , j["ssb_wo" ].get()); - p->set_clk(j["clk"].get>()); - p->set_ilv(j["ilv"].get>()); - // components - for (const json& jcomp : j["user_comps"]) { - str_t key = jcomp["key"].get(); - str_t type_str = jcomp["type"].get(); - str_t tag_str = jcomp["tag"].get(); - switch (static_cast(fa_comp_type_map.at(type_str))) - { - case FACompType::FixedTone : { - FACompTag tag = static_cast(fa_comp_tag_map.at(tag_str)); - str_t freq = jcomp["freq"].get(); - int ssb = jcomp["ssb"].get(); - p->add_fixed_tone(key, tag, freq, ssb); - break; - } - case FACompType::MaxTone : { - FACompTag tag = static_cast(fa_comp_tag_map.at(tag_str)); - int ssb = jcomp["ssb"].get(); - p->add_max_tone(key, tag, "0", "fdata", ssb); - break; - } - default: - throw std::exception(); - } - } - // variables - var_map vars; - j["user_vars"].get_to(vars); - for (const var_map::value_type& kv : vars) { - p->set_var(kv.first, kv.second); + throw runtime_error ("unable to open file '" + filename + "'"); + } + try + { + json j; + ifs >> j; // error handling? + std::shared_ptr p + = std::make_shared (); + j["en_conv_offset"].get_to (p->en_conv_offset); + j["en_fund_images"].get_to (p->en_fund_images); + j["en_quad_errors"].get_to (p->en_quad_errors); + j["clk_as_noise"].get_to (p->clk_as_noise); + j["dc_as_dist"].get_to (p->dc_as_dist); + j["ilv_as_noise"].get_to (p->ilv_as_noise); + p->set_analysis_band (j["ab_center"].get (), + j["ab_width"].get ()); + p->set_fdata (j["fdata"].get ()); + p->set_fsample (j["fsample"].get ()); + p->set_fshift (j["fshift"].get ()); + p->set_hd (j["hd"].get ()); + p->set_imd (j["imd"].get ()); + p->set_wo (j["wo"].get ()); + p->set_ssb (FASsb::Default, j["ssb_def"].get ()); + p->set_ssb (FASsb::DC, j["ssb_dc"].get ()); + p->set_ssb (FASsb::Signal, j["ssb_sig"].get ()); + p->set_ssb (FASsb::WO, j["ssb_wo"].get ()); + p->set_clk (j["clk"].get > ()); + p->set_ilv (j["ilv"].get > ()); + // components + for (const json &jcomp : j["user_comps"]) + { + str_t key = jcomp["key"].get (); + str_t type_str = jcomp["type"].get (); + str_t tag_str = jcomp["tag"].get (); + switch (static_cast (fa_comp_type_map.at (type_str))) + { + case FACompType::FixedTone: + { + FACompTag tag + = static_cast (fa_comp_tag_map.at (tag_str)); + str_t freq = jcomp["freq"].get (); + int ssb = jcomp["ssb"].get (); + p->add_fixed_tone (key, tag, freq, ssb); + break; + } + case FACompType::MaxTone: + { + FACompTag tag + = static_cast (fa_comp_tag_map.at (tag_str)); + int ssb = jcomp["ssb"].get (); + p->add_max_tone (key, tag, "0", "fdata", ssb); + break; + } + default: + throw std::exception (); } - return p; - } catch (const std::exception&) { - throw runtime_error("error loading fourier_analysis object from file '" + filename + "'"); } + // variables + var_map vars; + j["user_vars"].get_to (vars); + for (const var_map::value_type &kv : vars) + { + p->set_var (kv.first, kv.second); + } + return p; } + catch (const std::exception &) + { + throw runtime_error ("error loading fourier_analysis object from file '" + + filename + "'"); + } +} - void fourier_analysis::save_impl(const str_t& filename) const +void +fourier_analysis::save_impl (const str_t &filename) const +{ + std::ofstream ofs (filename); + if (!ofs.is_open ()) { - std::ofstream ofs (filename); - if (!ofs.is_open()) { - throw runtime_error("Unable to open file '" + filename + "'"); - } - json jcomps; - for (const str_t& key : m_user_keys) { - const fourier_analysis_component& comp = *m_user_comps.at(key); - switch (comp.type) - { - case FACompType::FixedTone : { - auto c = static_cast(comp); - jcomps.push_back(json { - {"freq" , c.freq}, - {"key" , key}, - {"ssb" , c.ssb}, - {"tag" , fa_comp_tag_map.at(to_int(c.tag))}, - {"type" , fa_comp_type_map.at(to_int(c.type))}}); - break; - } - case FACompType::MaxTone : { - auto c = static_cast(comp); - jcomps.push_back(json { - {"key" , key}, - {"ssb" , c.ssb}, - {"tag" , fa_comp_tag_map.at(to_int(c.tag))}, - {"type" , fa_comp_type_map.at(to_int(c.type))}}); - break; - } - default : - continue; - } + throw runtime_error ("Unable to open file '" + filename + "'"); + } + json jcomps; + for (const str_t &key : m_user_keys) + { + const fourier_analysis_component &comp = *m_user_comps.at (key); + switch (comp.type) + { + case FACompType::FixedTone: + { + auto c = static_cast (comp); + jcomps.push_back ( + json{ { "freq", c.freq }, + { "key", key }, + { "ssb", c.ssb }, + { "tag", fa_comp_tag_map.at (to_int (c.tag)) }, + { "type", fa_comp_type_map.at (to_int (c.type)) } }); + break; + } + case FACompType::MaxTone: + { + auto c = static_cast (comp); + jcomps.push_back ( + json{ { "key", key }, + { "ssb", c.ssb }, + { "tag", fa_comp_tag_map.at (to_int (c.tag)) }, + { "type", fa_comp_type_map.at (to_int (c.type)) } }); + break; + } + default: + continue; } - json j; - j["ab_center"] = m_ab_center; - j["ab_width"] = m_ab_width; - j["clk"] = m_clk; - j["clk_as_noise"] = clk_as_noise; - j["dc_as_dist"] = dc_as_dist; - j["en_conv_offset"] = en_conv_offset; - j["en_fund_images"] = en_fund_images; - j["en_quad_errors"] = en_quad_errors; - j["fdata"] = m_fdata; - j["fsample"] = m_fsample; - j["fshift"] = m_fshift; - j["hd"] = m_hd; - j["ilv"] = m_ilv; - j["ilv_as_noise"] = ilv_as_noise; - j["imd"] = m_imd; - j["ssb_dc"] = m_ssb_dc; - j["ssb_def"] = m_ssb_def; - j["ssb_sig"] = m_ssb_sig; - j["ssb_wo"] = m_ssb_wo; - j["user_comps"] = jcomps; - j["user_vars"] = m_user_vars; - j["version"] = version_string(); - j["wo"] = m_wo; - ofs << std::setw(4) << j << std::endl; } + json j; + j["ab_center"] = m_ab_center; + j["ab_width"] = m_ab_width; + j["clk"] = m_clk; + j["clk_as_noise"] = clk_as_noise; + j["dc_as_dist"] = dc_as_dist; + j["en_conv_offset"] = en_conv_offset; + j["en_fund_images"] = en_fund_images; + j["en_quad_errors"] = en_quad_errors; + j["fdata"] = m_fdata; + j["fsample"] = m_fsample; + j["fshift"] = m_fshift; + j["hd"] = m_hd; + j["ilv"] = m_ilv; + j["ilv_as_noise"] = ilv_as_noise; + j["imd"] = m_imd; + j["ssb_dc"] = m_ssb_dc; + j["ssb_def"] = m_ssb_def; + j["ssb_sig"] = m_ssb_sig; + j["ssb_wo"] = m_ssb_wo; + j["user_comps"] = jcomps; + j["user_vars"] = m_user_vars; + j["version"] = version_string (); + j["wo"] = m_wo; + ofs << std::setw (4) << j << std::endl; +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/manager.cpp b/src/manager.cpp index cdd1919..238e5f5 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "manager.hpp" #include "enum_maps.hpp" @@ -8,117 +11,144 @@ #include #include -namespace genalyzer_impl::manager { - - static std::map object_map; - - void clear() +namespace genalyzer_impl::manager +{ + +static std::map object_map; + +void +clear () +{ + object_map.clear (); +} + +bool +equal (const str_t &key1, const str_t &key2) +{ + contains (key1, true); + contains (key2, true); + const object &obj1 = *object_map.at (key1); + const object &obj2 = *object_map.at (key2); + return obj1.equals (obj2); +} + +bool +contains (const str_t &key, bool throw_if_not_found) +{ + bool not_found = object_map.end () == object_map.find (key); + if (not_found && throw_if_not_found) { - object_map.clear(); + throw runtime_error ("manager::contains : key '" + key + "' not found"); } - - bool equal(const str_t& key1, const str_t& key2) + return !not_found; +} + +void +remove (const str_t &key) +{ + object_map.erase (key); +} + +str_t +save (const str_t &key, const str_t &filename) +{ + contains (key, true); + str_t fn = get_filename_from_object_key (key, filename); + object_map.at (key)->save (fn); + return fn; +} + +size_t +size () +{ + return object_map.size (); +} + +str_t +to_string (const str_t &key) +{ + if (contains (key)) { - contains(key1, true); - contains(key2, true); - const object& obj1 = *object_map.at(key1); - const object& obj2 = *object_map.at(key2); - return obj1.equals(obj2); + return object_map.at (key)->to_string (); } - - bool contains(const str_t& key, bool throw_if_not_found) + else { - bool not_found = object_map.end() == object_map.find(key); - if (not_found && throw_if_not_found) { - throw runtime_error("manager::contains : key '" + key + "' not found"); + std::vector header{ { "Key", object_type_map.name () } }; + std::vector rows; + for (const auto &kv : object_map) + { + const str_t &obj_key = kv.first; + ObjectType obj_type = object_map.at (obj_key)->object_type (); + rows.push_back ({ obj_key, object_type_map.at (to_int (obj_type)) }); } - return !not_found; + return table (header, rows, 2, true, true); } +} - void remove(const str_t& key) - { - object_map.erase(key); - } +str_t +type_str (const str_t &key) +{ + return object_type_map.at (to_int (type (key))); +} - str_t save(const str_t& key, const str_t& filename) - { - contains(key, true); - str_t fn = get_filename_from_object_key(key, filename); - object_map.at(key)->save(fn); - return fn; - } +} // namespace genalyzer::manager - size_t size() - { - return object_map.size(); - } +namespace genalyzer_impl::manager +{ - str_t to_string(const str_t& key) +void +add_object (const str_t &key, object::pointer obj, bool replace) +{ + if (!std::regex_match (key, std::regex (key_pattern))) { - if (contains(key)) { - return object_map.at(key)->to_string(); - } else { - std::vector header { {"Key", object_type_map.name()} }; - std::vector rows; - for (const auto& kv : object_map) { - const str_t& obj_key = kv.first; - ObjectType obj_type = object_map.at(obj_key)->object_type(); - rows.push_back( {obj_key, object_type_map.at(to_int(obj_type))} ); - } - return table(header, rows, 2, true, true); - } + throw runtime_error ("manager::add_object : invalid key"); } - - str_t type_str(const str_t& key) + if (!obj) { - return object_type_map.at(to_int(type(key))); + throw runtime_error ("manager::add_object : object is null"); } - -} // namespace genalyzer::manager - -namespace genalyzer_impl::manager { - - void add_object(const str_t& key, object::pointer obj, bool replace) - { - if (!std::regex_match(key, std::regex(key_pattern))) { - throw runtime_error("manager::add_object : invalid key"); - } - if (!obj) { - throw runtime_error("manager::add_object : object is null"); - } - if (contains(key)) { - if (replace) { - object_map.erase(key); - } else { - throw runtime_error("manager::add_object : key already exists"); - } - } - object_map.insert({key, std::move(obj)}); - } - - str_t get_filename_from_object_key(const str_t& key, str_t filename) + if (contains (key)) { - static const std::regex json_ext_pat {".+[.]json$", std::regex::icase}; - if (filename.empty()) { - filename = key; + if (replace) + { + object_map.erase (key); } - if (!std::regex_match(filename, json_ext_pat)) { - filename += ".json"; + else + { + throw runtime_error ("manager::add_object : key already exists"); } - return filename; } - - object::pointer get_object(const str_t& key) + object_map.insert ({ key, std::move (obj) }); +} + +str_t +get_filename_from_object_key (const str_t &key, str_t filename) +{ + static const std::regex json_ext_pat{ ".+[.]json$", std::regex::icase }; + if (filename.empty ()) { - contains(key, true); - object::pointer obj = object_map.at(key); - return obj; + filename = key; } - - ObjectType type(const str_t& key) + if (!std::regex_match (filename, json_ext_pat)) { - contains(key, true); - return object_map.at(key)->object_type(); + filename += ".json"; } + return filename; +} + +object::pointer +get_object (const str_t &key) +{ + contains (key, true); + object::pointer obj = object_map.at (key); + return obj; +} + +ObjectType +type (const str_t &key) +{ + contains (key, true); + return object_map.at (key)->object_type (); +} } // namespace genalyzer::manager \ No newline at end of file diff --git a/src/platform.cpp b/src/platform.cpp index 43145be..ecc1cc1 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -1,16 +1,20 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "type_aliases.hpp" -namespace genalyzer_impl { +namespace genalyzer_impl +{ - static_assert(sizeof(int16_t) == 2, "sizeof(int16_t) != 2"); - static_assert(sizeof(int32_t) == 4, "sizeof(int32_t) != 4"); - static_assert(sizeof(int64_t) == 8, "sizeof(int64_t) != 8"); - static_assert(sizeof(uint16_t) == 2, "sizeof(uint16_t) != 2"); - static_assert(sizeof(uint32_t) == 4, "sizeof(uint32_t) != 4"); - static_assert(sizeof(uint64_t) == 8, "sizeof(uint64_t) != 8"); - static_assert(sizeof(real_t) == 8, "sizeof(real_t) != 8"); - static_assert(sizeof(cplx_t) == 16, "sizeof(cplx_t) != 16"); +static_assert (sizeof (int16_t) == 2, "sizeof(int16_t) != 2"); +static_assert (sizeof (int32_t) == 4, "sizeof(int32_t) != 4"); +static_assert (sizeof (int64_t) == 8, "sizeof(int64_t) != 8"); +static_assert (sizeof (uint16_t) == 2, "sizeof(uint16_t) != 2"); +static_assert (sizeof (uint32_t) == 4, "sizeof(uint32_t) != 4"); +static_assert (sizeof (uint64_t) == 8, "sizeof(uint64_t) != 8"); +static_assert (sizeof (real_t) == 8, "sizeof(real_t) != 8"); +static_assert (sizeof (cplx_t) == 16, "sizeof(cplx_t) != 16"); - static_assert(sizeof(int) >= 4, "sizeof(int) < 4"); +static_assert (sizeof (int) >= 4, "sizeof(int) < 4"); } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/processes.cpp b/src/processes.cpp index 89d847a..a23d0e8 100644 --- a/src/processes.cpp +++ b/src/processes.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "processes.hpp" #include "constants.hpp" @@ -10,288 +13,320 @@ #include #include -namespace genalyzer_impl { - - template - void downsample( - const T* in_data, - size_t in_size, - T* out_data, - size_t out_size, - int ratio, - bool interleaved - ) +namespace genalyzer_impl +{ + +template +void +downsample (const T *in_data, size_t in_size, T *out_data, size_t out_size, + int ratio, bool interleaved) +{ + check_array ("", "input array", in_data, in_size); + check_array ("", "output array", out_data, out_size); + size_t out_size_expected = downsample_size (in_size, ratio, interleaved); + assert_eq ("", "output array size", out_size, "expected", out_size_expected); + size_t i = 0; + if (interleaved) { - check_array("", "input array", in_data, in_size); - check_array("", "output array", out_data, out_size); - size_t out_size_expected = downsample_size(in_size, ratio, interleaved); - assert_eq("", "output array size", out_size, "expected", out_size_expected); - size_t i = 0; - if (interleaved) { - // check for even in_size ?? - const size_t jump = ratio * 2; - for (size_t j = 0; j < out_size; ++j) { - out_data[j] = in_data[i]; - ++j; - out_data[j] = in_data[i + 1]; - i += jump; - } - } else { - for (size_t j = 0; j < out_size; ++j) { - out_data[j] = in_data[i]; - i += ratio; - } + // check for even in_size ?? + const size_t jump = ratio * 2; + for (size_t j = 0; j < out_size; ++j) + { + out_data[j] = in_data[i]; + ++j; + out_data[j] = in_data[i + 1]; + i += jump; } } - - template void downsample(const real_t* , size_t, real_t* , size_t, int, bool); - template void downsample(const int16_t*, size_t, int16_t*, size_t, int, bool); - template void downsample(const int32_t*, size_t, int32_t*, size_t, int, bool); - template void downsample(const int64_t*, size_t, int64_t*, size_t, int, bool); - - size_t downsample_size(size_t in_size, int ratio, bool interleaved) + else { - assert_gt0("", "downsample ratio", ratio); - size_t out_size = 0; - if (interleaved) { - if (is_odd(in_size)) { - throw runtime_error("size of interleaved array must be even"); - } - in_size /= 2; - out_size = in_size / ratio; - if (0 < in_size % ratio) { - out_size += 1; - } - out_size *= 2; - } else { - out_size = in_size / ratio; - if (0 < in_size % ratio) { - out_size += 1; - } + for (size_t j = 0; j < out_size; ++j) + { + out_data[j] = in_data[i]; + i += ratio; } - return out_size; } +} + +template void downsample (const real_t *, size_t, real_t *, size_t, int, bool); +template void downsample (const int16_t *, size_t, int16_t *, size_t, int, + bool); +template void downsample (const int32_t *, size_t, int32_t *, size_t, int, + bool); +template void downsample (const int64_t *, size_t, int64_t *, size_t, int, + bool); - void fshift( - const real_t* i_data, - size_t i_size, - const real_t* q_data, - size_t q_size, - real_t* out_data, - size_t out_size, - real_t fs, - real_t _fshift - ) +size_t +downsample_size (size_t in_size, int ratio, bool interleaved) +{ + assert_gt0 ("", "downsample ratio", ratio); + size_t out_size = 0; + if (interleaved) { - assert_gt0("", "fs", fs); - _fshift -= std::floor(_fshift / fs) * fs; // [0, fs) - const real_t twopix = k_2pi * _fshift / fs; - if (0 == q_size) { - // Interleaved I/Q - check_array_pair("", "input array", i_data, i_size, "output array", out_data, out_size, true); - const size_t size = i_size / 2; - const cplx_t* pin = reinterpret_cast(i_data); - cplx_t* pout = reinterpret_cast(out_data); - const cplx_t jtwopix = {0.0, twopix}; - cplx_t jtwopix_n = 0.0; - for (size_t i = 0; i < size; ++i) { - pout[i] = pin[i] * std::exp(jtwopix_n); - jtwopix_n += jtwopix; - } - } else { - // Split I/Q - check_array_pair("", "I array", i_data, i_size, "Q array", q_data, q_size); - check_array("", "output array", out_data, out_size); - assert_eq("", "output array size", out_size, "expected", i_size * 2); - real_t twopix_n = 0.0; - for (size_t i = 0, j = 0; i < i_size; ++i, j += 2) { - real_t x = std::cos(twopix_n); - real_t y = std::sin(twopix_n); - out_data[j] = i_data[i] * x - q_data[i] * y; - out_data[j+1] = i_data[i] * y + q_data[i] * x; - twopix_n += twopix; - } + if (is_odd (in_size)) + { + throw runtime_error ("size of interleaved array must be even"); + } + in_size /= 2; + out_size = in_size / ratio; + if (0 < in_size % ratio) + { + out_size += 1; + } + out_size *= 2; + } + else + { + out_size = in_size / ratio; + if (0 < in_size % ratio) + { + out_size += 1; } } + return out_size; +} - template - void fshift( - const T* i_data, - size_t i_size, - const T* q_data, - size_t q_size, - T* out_data, - size_t out_size, - int n, - real_t fs, - real_t _fshift, - CodeFormat format - ) +void +fshift (const real_t *i_data, size_t i_size, const real_t *q_data, + size_t q_size, real_t *out_data, size_t out_size, real_t fs, + real_t _fshift) +{ + assert_gt0 ("", "fs", fs); + _fshift -= std::floor (_fshift / fs) * fs; // [0, fs) + const real_t twopix = k_2pi * _fshift / fs; + if (0 == q_size) { - resolution_to_minmax(n, format); - assert_gt0("", "fs", fs); - _fshift -= std::floor(_fshift / fs) * fs; // [0, fs) - const real_t twopix = k_2pi * _fshift / fs; - size_t in_stride = 0; - if (0 == q_size) { - // Interleaved I/Q - check_array("", "input array", i_data, i_size, true); - i_size /= 2; - q_size = i_size; - q_data = i_data + 1; - in_stride = 2; - } else { - // Split I/Q - check_array_pair("", "I array", i_data, i_size, "Q array", q_data, q_size); - in_stride = 1; + // Interleaved I/Q + check_array_pair ("", "input array", i_data, i_size, "output array", + out_data, out_size, true); + const size_t size = i_size / 2; + const cplx_t *pin = reinterpret_cast (i_data); + cplx_t *pout = reinterpret_cast (out_data); + const cplx_t jtwopix = { 0.0, twopix }; + cplx_t jtwopix_n = 0.0; + for (size_t i = 0; i < size; ++i) + { + pout[i] = pin[i] * std::exp (jtwopix_n); + jtwopix_n += jtwopix; } - check_array("", "output array", out_data, out_size); - assert_eq("", "output array size", out_size, "expected", i_size + q_size); - real_t twopix_n = 0.0; - const real_t min_code = -std::pow(2.0, n - 1); - const real_t max_code = -1.0 - min_code; - const real_t os = (CodeFormat::OffsetBinary == format) ? -min_code : 0.0; - for (size_t i = 0, j = 0; j < out_size; i += in_stride, j += 2) { - real_t x = std::cos(twopix_n); - real_t y = std::sin(twopix_n); - real_t itmp1 = static_cast(i_data[i]) - os; - real_t qtmp1 = static_cast(q_data[i]) - os; - real_t itmp2 = std::clamp(std::round(itmp1 * x - qtmp1 * y), min_code, max_code); - real_t qtmp2 = std::clamp(std::round(itmp1 * y + qtmp1 * x), min_code, max_code); - out_data[j] = static_cast(itmp2 + os); - out_data[j+1] = static_cast(qtmp2 + os); - twopix_n += twopix; + } + else + { + // Split I/Q + check_array_pair ("", "I array", i_data, i_size, "Q array", q_data, + q_size); + check_array ("", "output array", out_data, out_size); + assert_eq ("", "output array size", out_size, "expected", i_size * 2); + real_t twopix_n = 0.0; + for (size_t i = 0, j = 0; i < i_size; ++i, j += 2) + { + real_t x = std::cos (twopix_n); + real_t y = std::sin (twopix_n); + out_data[j] = i_data[i] * x - q_data[i] * y; + out_data[j + 1] = i_data[i] * y + q_data[i] * x; + twopix_n += twopix; } } - - template void fshift(const int16_t*, size_t, const int16_t*, size_t, int16_t*, size_t, int, real_t, real_t, CodeFormat); - template void fshift(const int32_t*, size_t, const int32_t*, size_t, int32_t*, size_t, int, real_t, real_t, CodeFormat); - template void fshift(const int64_t*, size_t, const int64_t*, size_t, int64_t*, size_t, int, real_t, real_t, CodeFormat); - - size_t fshift_size(size_t i_size, size_t q_size) +} + +template +void +fshift (const T *i_data, size_t i_size, const T *q_data, size_t q_size, + T *out_data, size_t out_size, int n, real_t fs, real_t _fshift, + CodeFormat format) +{ + resolution_to_minmax (n, format); + assert_gt0 ("", "fs", fs); + _fshift -= std::floor (_fshift / fs) * fs; // [0, fs) + const real_t twopix = k_2pi * _fshift / fs; + size_t in_stride = 0; + if (0 == q_size) { - if (0 == q_size) { - // Input I contains Interleaved I/Q; Input Q is unused - if (is_odd(i_size)) { - throw runtime_error("size of interleaved array must be even"); - } - return i_size; - } else { - // Split I/Q - assert_eq("", "I size", i_size, "Q size", q_size); - return i_size + q_size; + // Interleaved I/Q + check_array ("", "input array", i_data, i_size, true); + i_size /= 2; + q_size = i_size; + q_data = i_data + 1; + in_stride = 2; + } + else + { + // Split I/Q + check_array_pair ("", "I array", i_data, i_size, "Q array", q_data, + q_size); + in_stride = 1; + } + check_array ("", "output array", out_data, out_size); + assert_eq ("", "output array size", out_size, "expected", i_size + q_size); + real_t twopix_n = 0.0; + const real_t min_code = -std::pow (2.0, n - 1); + const real_t max_code = -1.0 - min_code; + const real_t os = (CodeFormat::OffsetBinary == format) ? -min_code : 0.0; + for (size_t i = 0, j = 0; j < out_size; i += in_stride, j += 2) + { + real_t x = std::cos (twopix_n); + real_t y = std::sin (twopix_n); + real_t itmp1 = static_cast (i_data[i]) - os; + real_t qtmp1 = static_cast (q_data[i]) - os; + real_t itmp2 = std::clamp (std::round (itmp1 * x - qtmp1 * y), min_code, + max_code); + real_t qtmp2 = std::clamp (std::round (itmp1 * y + qtmp1 * x), min_code, + max_code); + out_data[j] = static_cast (itmp2 + os); + out_data[j + 1] = static_cast (qtmp2 + os); + twopix_n += twopix; + } +} + +template void fshift (const int16_t *, size_t, const int16_t *, size_t, + int16_t *, size_t, int, real_t, real_t, CodeFormat); +template void fshift (const int32_t *, size_t, const int32_t *, size_t, + int32_t *, size_t, int, real_t, real_t, CodeFormat); +template void fshift (const int64_t *, size_t, const int64_t *, size_t, + int64_t *, size_t, int, real_t, real_t, CodeFormat); + +size_t +fshift_size (size_t i_size, size_t q_size) +{ + if (0 == q_size) + { + // Input I contains Interleaved I/Q; Input Q is unused + if (is_odd (i_size)) + { + throw runtime_error ("size of interleaved array must be even"); } + return i_size; } - - template - void normalize( - const T* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - int n, - CodeFormat format - ) + else { - check_array_pair("normalize : ", "input array", in_data, in_size, "output array", out_data, out_size); - check_code_width("normalize : ", n); - const real_t scalar = 2.0 / (1 << n); - if (CodeFormat::OffsetBinary == format) { - for (size_t i = 0; i < out_size; ++i) { - out_data[i] = std::fma(scalar, static_cast(in_data[i]), -1.0); - } - } else { - for (size_t i = 0; i < out_size; ++i) { - out_data[i] = scalar * static_cast(in_data[i]); - } + // Split I/Q + assert_eq ("", "I size", i_size, "Q size", q_size); + return i_size + q_size; + } +} + +template +void +normalize (const T *in_data, size_t in_size, real_t *out_data, size_t out_size, + int n, CodeFormat format) +{ + check_array_pair ("normalize : ", "input array", in_data, in_size, + "output array", out_data, out_size); + check_code_width ("normalize : ", n); + const real_t scalar = 2.0 / (1 << n); + if (CodeFormat::OffsetBinary == format) + { + for (size_t i = 0; i < out_size; ++i) + { + out_data[i] + = std::fma (scalar, static_cast (in_data[i]), -1.0); + } + } + else + { + for (size_t i = 0; i < out_size; ++i) + { + out_data[i] = scalar * static_cast (in_data[i]); } } +} + +template void normalize (const int16_t *, size_t, real_t *, size_t, int, + CodeFormat); +template void normalize (const int32_t *, size_t, real_t *, size_t, int, + CodeFormat); +template void normalize (const int64_t *, size_t, real_t *, size_t, int, + CodeFormat); - template void normalize(const int16_t*, size_t, real_t*, size_t, int, CodeFormat); - template void normalize(const int32_t*, size_t, real_t*, size_t, int, CodeFormat); - template void normalize(const int64_t*, size_t, real_t*, size_t, int, CodeFormat); - - void polyval( - const real_t* in_data, - size_t in_size, - real_t* out_data, - size_t out_size, - const real_t* c_data, - size_t c_size - ) +void +polyval (const real_t *in_data, size_t in_size, real_t *out_data, + size_t out_size, const real_t *c_data, size_t c_size) +{ + check_array_pair ("polyval : ", "input array", in_data, in_size, + "output array", out_data, out_size); + check_array ("polyval : ", "coefficient array", c_data, c_size); + std::vector c (c_data, c_data + c_size); + while (1 < c.size () && 0.0 == c.back ()) { - check_array_pair("polyval : ", "input array", in_data, in_size, "output array", out_data, out_size); - check_array("polyval : ", "coefficient array", c_data, c_size); - std::vector c (c_data, c_data + c_size); - while (1 < c.size() && 0.0 == c.back()) { - c.pop_back(); + c.pop_back (); + } + const real_t last_c = c.back (); + c.pop_back (); + if (c.empty ()) + { + // y = c0 + std::fill (out_data, out_data + out_size, last_c); + } + else if (1 == c.size ()) + { + // y = c1 * x + c0 + const real_t c0 = c[0]; + for (size_t i = 0; i < out_size; ++i) + { + out_data[i] = std::fma (last_c, in_data[i], c0); } - const real_t last_c = c.back(); - c.pop_back(); - if (c.empty()) { - // y = c0 - std::fill(out_data, out_data + out_size, last_c); - } else if (1 == c.size()) { - // y = c1 * x + c0 - const real_t c0 = c[0]; - for (size_t i = 0; i < out_size; ++i) { - out_data[i] = std::fma(last_c, in_data[i], c0); - } - } else { - std::reverse(c.begin(), c.end()); - // Horner's method - // 3rd degree example: - // y = x * (x * (x * c3 + c2) + c1) + c0 - for (size_t i = 0; i < out_size; ++i) { - real_t tmp = last_c; - for (real_t cn : c) { - tmp = std::fma(in_data[i], tmp, cn); - } - out_data[i] = tmp; + } + else + { + std::reverse (c.begin (), c.end ()); + // Horner's method + // 3rd degree example: + // y = x * (x * (x * c3 + c2) + c1) + c0 + for (size_t i = 0; i < out_size; ++i) + { + real_t tmp = last_c; + for (real_t cn : c) + { + tmp = std::fma (in_data[i], tmp, cn); } + out_data[i] = tmp; } } +} - template - void quantize( - const real_t* in_data, - size_t in_size, - T* out_data, - size_t out_size, - real_t fsr, - int n, - real_t noise, - CodeFormat format - ) +template +void +quantize (const real_t *in_data, size_t in_size, T *out_data, size_t out_size, + real_t fsr, int n, real_t noise, CodeFormat format) +{ + const char *trace = "quantize : "; + check_array_pair (trace, "input array", in_data, in_size, "output array", + out_data, out_size); + assert_gt0 (trace, "fsr", fsr); + resolution_to_minmax (n, format); + const real_t lsb = fsr / (1 << n); + const real_t min_code = -std::pow (2.0, n - 1); + const real_t max_code = -1.0 - min_code; + const real_t os = (CodeFormat::OffsetBinary == format) ? -min_code : 0.0; + if (0.0 == noise) { - const char* trace = "quantize : "; - check_array_pair(trace, "input array", in_data, in_size, "output array", out_data, out_size); - assert_gt0(trace, "fsr", fsr); - resolution_to_minmax(n, format); - const real_t lsb = fsr / (1 << n); - const real_t min_code = -std::pow(2.0, n - 1); - const real_t max_code = -1.0 - min_code; - const real_t os = (CodeFormat::OffsetBinary == format) ? -min_code : 0.0; - if (0.0 == noise) { - for (size_t i = 0; i < out_size; ++i) { - real_t c = std::floor(in_data[i] / lsb); - c = std::clamp(c, min_code, max_code); - out_data[i] = static_cast(c + os); - } - } else { - std::random_device rdev; - std::mt19937 rgen (rdev()); - auto ngen = std::bind(std::normal_distribution(0.0, std::fabs(noise)), rgen); - for (size_t i = 0; i < out_size; ++i) { - real_t c = std::floor((in_data[i] + ngen()) / lsb); - c = std::clamp(c, min_code, max_code); - out_data[i] = static_cast(c + os); - } + for (size_t i = 0; i < out_size; ++i) + { + real_t c = std::floor (in_data[i] / lsb); + c = std::clamp (c, min_code, max_code); + out_data[i] = static_cast (c + os); + } + } + else + { + std::random_device rdev; + std::mt19937 rgen (rdev ()); + auto ngen = std::bind ( + std::normal_distribution (0.0, std::fabs (noise)), rgen); + for (size_t i = 0; i < out_size; ++i) + { + real_t c = std::floor ((in_data[i] + ngen ()) / lsb); + c = std::clamp (c, min_code, max_code); + out_data[i] = static_cast (c + os); } } +} - template void quantize(const real_t*, size_t, int16_t*, size_t, real_t, int, real_t, CodeFormat); - template void quantize(const real_t*, size_t, int32_t*, size_t, real_t, int, real_t, CodeFormat); - template void quantize(const real_t*, size_t, int64_t*, size_t, real_t, int, real_t, CodeFormat); +template void quantize (const real_t *, size_t, int16_t *, size_t, real_t, int, + real_t, CodeFormat); +template void quantize (const real_t *, size_t, int32_t *, size_t, real_t, int, + real_t, CodeFormat); +template void quantize (const real_t *, size_t, int64_t *, size_t, real_t, int, + real_t, CodeFormat); } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp index 2ecf4e2..954e81c 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "utils.hpp" #include @@ -5,53 +8,63 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - str_t to_string(real_t n, FPFormat fmt, int max_prec) +str_t +to_string (real_t n, FPFormat fmt, int max_prec) +{ + if (!std::isfinite (n)) { - if (!std::isfinite(n)) { - throw runtime_error("to_string : non-finite number"); - } - int max_digits10 = std::numeric_limits::max_digits10; - if (max_prec < 0 || max_digits10 < max_prec) { - max_prec = max_digits10; - } - std::ostringstream ss; - ss.precision(max_prec); - switch (fmt) - { - case FPFormat::Auto : - ss << std::defaultfloat << n; - break; - case FPFormat::Eng : { - bool neg = std::signbit(n); - n = std::fabs(n); - real_t exp3 = 0; - if (0.0 < n) { - exp3 = std::floor(std::log10(n) / 3) * 3; // snap exponent to nearest multiple of 3 - } - if (exp3 < -3 || 0 < exp3) { - n *= std::pow(10.0, -exp3); - } - if (neg) { - ss << '-'; - } - ss << std::defaultfloat << n; - if (exp3 < -3 || 0 < exp3) { - ss << 'e' << exp3; - } - break; - } - case FPFormat::Fix : - ss << std::fixed << n; - break; - case FPFormat::Sci : - ss << std::scientific << n; - break; - default: - throw runtime_error("to_string : unknown floating point format"); - } - return ss.str(); + throw runtime_error ("to_string : non-finite number"); } + int max_digits10 = std::numeric_limits::max_digits10; + if (max_prec < 0 || max_digits10 < max_prec) + { + max_prec = max_digits10; + } + std::ostringstream ss; + ss.precision (max_prec); + switch (fmt) + { + case FPFormat::Auto: + ss << std::defaultfloat << n; + break; + case FPFormat::Eng: + { + bool neg = std::signbit (n); + n = std::fabs (n); + real_t exp3 = 0; + if (0.0 < n) + { + exp3 = std::floor (std::log10 (n) / 3) + * 3; // snap exponent to nearest multiple of 3 + } + if (exp3 < -3 || 0 < exp3) + { + n *= std::pow (10.0, -exp3); + } + if (neg) + { + ss << '-'; + } + ss << std::defaultfloat << n; + if (exp3 < -3 || 0 < exp3) + { + ss << 'e' << exp3; + } + break; + } + case FPFormat::Fix: + ss << std::fixed << n; + break; + case FPFormat::Sci: + ss << std::scientific << n; + break; + default: + throw runtime_error ("to_string : unknown floating point format"); + } + return ss.str (); +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/version.cpp b/src/version.cpp index 4979ef1..093597c 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -1,19 +1,23 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "version.hpp" #include #define TO_STRING(s) #s -#define MACRO_TO_STRING(s) TO_STRING(s) +#define MACRO_TO_STRING(s) TO_STRING (s) -namespace genalyzer_impl { +namespace genalyzer_impl +{ - std::string_view version_string() - { - static const char* s = - MACRO_TO_STRING(GENALYZER_VERSION_MAJOR) "." - MACRO_TO_STRING(GENALYZER_VERSION_MINOR) "." - MACRO_TO_STRING(GENALYZER_VERSION_PATCH); - return s; - } +std::string_view +version_string () +{ + static const char *s + = MACRO_TO_STRING (GENALYZER_VERSION_MAJOR) "." MACRO_TO_STRING ( + GENALYZER_VERSION_MINOR) "." MACRO_TO_STRING (GENALYZER_VERSION_PATCH); + return s; +} } // namespace genalyzer_impl \ No newline at end of file diff --git a/src/waveforms.cpp b/src/waveforms.cpp index ece3f2a..cc9029e 100644 --- a/src/waveforms.cpp +++ b/src/waveforms.cpp @@ -1,3 +1,6 @@ +// Copyright (C) 2024 Analog Devices, Inc. +// +// SPDX short identifier: ADIBSD OR GPL-2.0-or-later #include "waveforms.hpp" #include "constants.hpp" @@ -8,156 +11,152 @@ #include #include -namespace genalyzer_impl { +namespace genalyzer_impl +{ - namespace { +namespace +{ - void sinusoid( - double(*func)(double), - real_t* data, - size_t size, - real_t fs, - real_t ampl, - real_t freq, - real_t phase, - real_t td, - real_t tj - ) +void +sinusoid (double (*func) (double), real_t *data, size_t size, real_t fs, + real_t ampl, real_t freq, real_t phase, real_t td, real_t tj) +{ + check_array ("", "output array", data, size); + assert_gt0 ("", "fs", fs); + const real_t twopif = k_2pi * freq; + const real_t twopifts = twopif / fs; + const real_t twopiftd_plus_phase = std::fma (twopif, td, phase); + real_t theta = twopiftd_plus_phase; + if (0.0 == tj) + { + for (size_t i = 0; i < size; ++i) { - check_array("", "output array", data, size); - assert_gt0("", "fs", fs); - const real_t twopif = k_2pi * freq; - const real_t twopifts = twopif / fs; - const real_t twopiftd_plus_phase = std::fma(twopif, td, phase); - real_t theta = twopiftd_plus_phase; - if (0.0 == tj) { - for (size_t i = 0; i < size; ++i) { - data[i] = ampl * func(theta); - theta += twopifts; - } - } else { - std::random_device rdev; - std::mt19937 rgen (rdev()); - auto ngen = std::bind(std::normal_distribution(0.0, twopif * tj), rgen); - for (size_t i = 0; i < size; ++i) { - data[i] = theta + ngen(); - theta += twopifts; - } // breaking into two loops gives modest speed improvement - for (size_t i = 0; i < size; ++i) { - data[i] = ampl * func(data[i]); - } - } + data[i] = ampl * func (theta); + theta += twopifts; } - - } // namespace anonymous - - void cos( - real_t* data, - size_t size, - real_t fs, - real_t ampl, - real_t freq, - real_t phase, - real_t td, - real_t tj - ) + } + else { - sinusoid(std::cos, data, size, fs, ampl, freq, phase, td, tj); + std::random_device rdev; + std::mt19937 rgen (rdev ()); + auto ngen = std::bind ( + std::normal_distribution (0.0, twopif * tj), rgen); + for (size_t i = 0; i < size; ++i) + { + data[i] = theta + ngen (); + theta += twopifts; + } // breaking into two loops gives modest speed improvement + for (size_t i = 0; i < size; ++i) + { + data[i] = ampl * func (data[i]); + } } - - void gaussian(real_t* data, size_t size, real_t mean, real_t sd) +} + +} // namespace anonymous + +void +cos (real_t *data, size_t size, real_t fs, real_t ampl, real_t freq, + real_t phase, real_t td, real_t tj) +{ + sinusoid (std::cos, data, size, fs, ampl, freq, phase, td, tj); +} + +void +gaussian (real_t *data, size_t size, real_t mean, real_t sd) +{ + check_array ("", "output array", data, size); + if (0.0 == sd) { - check_array("", "output array", data, size); - if (0.0 == sd) { - for (size_t i = 0; i < size; ++i) { - data[i] = mean; - } - } else { - std::random_device rdev; - std::mt19937 rgen (rdev()); - auto ngen = std::bind(std::normal_distribution(mean, std::fabs(sd)), rgen); - for (size_t i = 0; i < size; ++i) { - data[i] = ngen(); - } + for (size_t i = 0; i < size; ++i) + { + data[i] = mean; } } - - void ramp(real_t* data, size_t size, real_t start, real_t stop, real_t noise) + else { - check_array("", "output array", data, size); - const real_t step = (stop - start) / static_cast(size); - real_t x = start + step / 2; - if (0.0 == noise) { - for (size_t i = 0; i < size; ++i) { - data[i] = x; - x += step; - } - } else { - std::random_device rdev; - std::mt19937 rgen (rdev()); - auto ngen = std::bind(std::normal_distribution(0.0, std::fabs(noise)), rgen); - for (size_t i = 0; i < size; ++i) { - data[i] = x + ngen(); - x += step; - } + std::random_device rdev; + std::mt19937 rgen (rdev ()); + auto ngen = std::bind ( + std::normal_distribution (mean, std::fabs (sd)), rgen); + for (size_t i = 0; i < size; ++i) + { + data[i] = ngen (); } } - - void sin( - real_t* data, - size_t size, - real_t fs, - real_t ampl, - real_t freq, - real_t phase, - real_t td, - real_t tj - ) +} + +void +ramp (real_t *data, size_t size, real_t start, real_t stop, real_t noise) +{ + check_array ("", "output array", data, size); + const real_t step = (stop - start) / static_cast (size); + real_t x = start + step / 2; + if (0.0 == noise) { - sinusoid(std::sin, data, size, fs, ampl, freq, phase, td, tj); + for (size_t i = 0; i < size; ++i) + { + data[i] = x; + x += step; + } } - - template - std::map wf_analysis(const T* wf_data, size_t wf_size) + else { - check_array("", "waveform array", wf_data, wf_size); - std_reduce_t r = std_reduce(wf_data, wf_size, 0, wf_size); - real_t n = static_cast(wf_size); - real_t avg = r.sum / n; - real_t rms = std::sqrt(r.sumsq / n); - real_t rmsac = std::sqrt(rms * rms - avg * avg); - std::vector keys = wf_analysis_ordered_keys(); - return std::map { - { keys[0] , r.min }, - { keys[1] , r.max }, - { keys[2] , (r.max + r.min) / 2 }, - { keys[3] , r.max - r.min }, - { keys[4] , avg }, - { keys[5] , rms }, - { keys[6] , rmsac }, - { keys[7] , static_cast(r.min_index) }, - { keys[8] , static_cast(r.max_index) }}; + std::random_device rdev; + std::mt19937 rgen (rdev ()); + auto ngen = std::bind ( + std::normal_distribution (0.0, std::fabs (noise)), rgen); + for (size_t i = 0; i < size; ++i) + { + data[i] = x + ngen (); + x += step; + } } +} - template std::map wf_analysis(const int16_t*, size_t); - template std::map wf_analysis(const int32_t*, size_t); - template std::map wf_analysis(const int64_t*, size_t); - template std::map wf_analysis(const real_t*, size_t); +void +sin (real_t *data, size_t size, real_t fs, real_t ampl, real_t freq, + real_t phase, real_t td, real_t tj) +{ + sinusoid (std::sin, data, size, fs, ampl, freq, phase, td, tj); +} - const std::vector& wf_analysis_ordered_keys() - { - static const std::vector keys { - "min", - "max", - "mid", - "range", - "avg", - "rms", - "rmsac", - "min_index", - "max_index" - }; - return keys; - } +template +std::map +wf_analysis (const T *wf_data, size_t wf_size) +{ + check_array ("", "waveform array", wf_data, wf_size); + std_reduce_t r = std_reduce (wf_data, wf_size, 0, wf_size); + real_t n = static_cast (wf_size); + real_t avg = r.sum / n; + real_t rms = std::sqrt (r.sumsq / n); + real_t rmsac = std::sqrt (rms * rms - avg * avg); + std::vector keys = wf_analysis_ordered_keys (); + return std::map{ + { keys[0], r.min }, + { keys[1], r.max }, + { keys[2], (r.max + r.min) / 2 }, + { keys[3], r.max - r.min }, + { keys[4], avg }, + { keys[5], rms }, + { keys[6], rmsac }, + { keys[7], static_cast (r.min_index) }, + { keys[8], static_cast (r.max_index) } + }; +} + +template std::map wf_analysis (const int16_t *, size_t); +template std::map wf_analysis (const int32_t *, size_t); +template std::map wf_analysis (const int64_t *, size_t); +template std::map wf_analysis (const real_t *, size_t); + +const std::vector & +wf_analysis_ordered_keys () +{ + static const std::vector keys{ "min", "max", "mid", + "range", "avg", "rms", + "rmsac", "min_index", "max_index" }; + return keys; +} } // namespace genalyzer_impl diff --git a/tests/cJSON.c b/tests/cJSON.c index 524ba46..d38c66c 100644 --- a/tests/cJSON.c +++ b/tests/cJSON.c @@ -32,25 +32,25 @@ #pragma GCC visibility push(default) #endif #if defined(_MSC_VER) -#pragma warning (push) +#pragma warning(push) /* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) +#pragma warning(disable : 4001) #endif -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #ifdef ENABLE_LOCALES #include #endif #if defined(_MSC_VER) -#pragma warning (pop) +#pragma warning(pop) #endif #ifdef __GNUC__ #pragma GCC visibility pop @@ -69,9 +69,10 @@ #endif #define false ((cJSON_bool)0) -/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has + * been defined in math.h */ #ifndef isinf -#define isinf(d) (isnan((d - d)) && !isnan(d)) +#define isinf(d) (isnan ((d - d)) && !isnan (d)) #endif #ifndef isnan #define isnan(d) (d != d) @@ -79,100 +80,111 @@ #ifndef NAN #ifdef _WIN32 -#define NAN sqrt(-1.0) +#define NAN sqrt (-1.0) #else -#define NAN 0.0/0.0 +#define NAN 0.0 / 0.0 #endif #endif -typedef struct { - const unsigned char *json; - size_t position; +typedef struct +{ + const unsigned char *json; + size_t position; } error; static error global_error = { NULL, 0 }; -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +CJSON_PUBLIC (const char *) cJSON_GetErrorPtr (void) { - return (const char*) (global_error.json + global_error.position); + return (const char *)(global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +CJSON_PUBLIC (char *) cJSON_GetStringValue (const cJSON *const item) { - if (!cJSON_IsString(item)) + if (!cJSON_IsString (item)) { - return NULL; + return NULL; } - return item->valuestring; + return item->valuestring; } -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +CJSON_PUBLIC (double) cJSON_GetNumberValue (const cJSON *const item) { - if (!cJSON_IsNumber(item)) + if (!cJSON_IsNumber (item)) { - return (double) NAN; + return (double)NAN; } - return item->valuedouble; + return item->valuedouble; } -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +/* This is a safeguard to prevent copy-pasters from using incompatible C and + * header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) \ + || (CJSON_VERSION_PATCH != 15) +#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif -CJSON_PUBLIC(const char*) cJSON_Version(void) +CJSON_PUBLIC (const char *) cJSON_Version (void) { - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + static char version[15]; + sprintf (version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, + CJSON_VERSION_PATCH); - return version; + return version; } -/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ -static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +/* Case insensitive string comparison, doesn't consider two NULL pointers equal + * though */ +static int +case_insensitive_strcmp (const unsigned char *string1, + const unsigned char *string2) { - if ((string1 == NULL) || (string2 == NULL)) + if ((string1 == NULL) || (string2 == NULL)) { - return 1; + return 1; } - if (string1 == string2) + if (string1 == string2) { - return 0; + return 0; } - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + for (; tolower (*string1) == tolower (*string2); (void)string1++, string2++) { - if (*string1 == '\0') + if (*string1 == '\0') { - return 0; + return 0; } } - return tolower(*string1) - tolower(*string2); + return tolower (*string1) - tolower (*string2); } typedef struct internal_hooks { - void *(CJSON_CDECL *allocate)(size_t size); - void (CJSON_CDECL *deallocate)(void *pointer); - void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); + void *(CJSON_CDECL *allocate) (size_t size); + void (CJSON_CDECL *deallocate) (void *pointer); + void *(CJSON_CDECL *reallocate) (void *pointer, size_t size); } internal_hooks; #if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ -static void * CJSON_CDECL internal_malloc(size_t size) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static + */ +static void *CJSON_CDECL +internal_malloc (size_t size) { - return malloc(size); + return malloc (size); } -static void CJSON_CDECL internal_free(void *pointer) +static void CJSON_CDECL +internal_free (void *pointer) { - free(pointer); + free (pointer); } -static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +static void *CJSON_CDECL +internal_realloc (void *pointer, size_t size) { - return realloc(pointer, size); + return realloc (pointer, size); } #else #define internal_malloc malloc @@ -181,2939 +193,3141 @@ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) #endif /* strlen of character literals resolved at compile time */ -#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) +#define static_strlen(string_literal) (sizeof (string_literal) - sizeof ("")) -static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; +static internal_hooks global_hooks + = { internal_malloc, internal_free, internal_realloc }; -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +static unsigned char * +cJSON_strdup (const unsigned char *string, const internal_hooks *const hooks) { - size_t length = 0; - unsigned char *copy = NULL; + size_t length = 0; + unsigned char *copy = NULL; - if (string == NULL) + if (string == NULL) { - return NULL; + return NULL; } - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) + length = strlen ((const char *)string) + sizeof (""); + copy = (unsigned char *)hooks->allocate (length); + if (copy == NULL) { - return NULL; + return NULL; } - memcpy(copy, string, length); + memcpy (copy, string, length); - return copy; + return copy; } -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +CJSON_PUBLIC (void) cJSON_InitHooks (cJSON_Hooks *hooks) { - if (hooks == NULL) + if (hooks == NULL) { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; } - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) { - global_hooks.allocate = hooks->malloc_fn; + global_hooks.allocate = hooks->malloc_fn; } - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) { - global_hooks.deallocate = hooks->free_fn; + global_hooks.deallocate = hooks->free_fn; } - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { - global_hooks.reallocate = realloc; + global_hooks.reallocate = realloc; } } /* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +static cJSON * +cJSON_New_Item (const internal_hooks *const hooks) { - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) + cJSON *node = (cJSON *)hooks->allocate (sizeof (cJSON)); + if (node) { - memset(node, '\0', sizeof(cJSON)); + memset (node, '\0', sizeof (cJSON)); } - return node; + return node; } /* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +CJSON_PUBLIC (void) cJSON_Delete (cJSON *item) { - cJSON *next = NULL; - while (item != NULL) + cJSON *next = NULL; + while (item != NULL) { - next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { - cJSON_Delete(item->child); + cJSON_Delete (item->child); } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { - global_hooks.deallocate(item->valuestring); + global_hooks.deallocate (item->valuestring); } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { - global_hooks.deallocate(item->string); + global_hooks.deallocate (item->string); } - global_hooks.deallocate(item); - item = next; + global_hooks.deallocate (item); + item = next; } } /* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) +static unsigned char +get_decimal_point (void) { #ifdef ENABLE_LOCALES - struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; + struct lconv *lconv = localeconv (); + return (unsigned char)lconv->decimal_point[0]; #else - return '.'; + return '.'; #endif } typedef struct { - const unsigned char *content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ - internal_hooks hooks; + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the + current offset. */ + internal_hooks hooks; } parse_buffer; -/* check if the given size is left to read in a given parse buffer (starting with 1) */ -#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the given size is left to read in a given parse buffer (starting + * with 1) */ +#define can_read(buffer, size) \ + ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) /* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +#define can_access_at_index(buffer, index) \ + ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) \ + (!can_access_at_index (buffer, index)) /* get a pointer to the buffer at the position */ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) -/* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) -{ - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; +/* Parse the input text to generate a number, and populate the result into + * item. */ +static cJSON_bool +parse_number (cJSON *const item, parse_buffer *const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point (); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal + * point of the current locale (for strtod) This also takes care of '\0' not + * necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof (number_c_string) - 1)) + && can_access_at_index (input_buffer, i); + i++) + { + switch (buffer_at_offset (input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset (input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; - default: - goto loop_end; + default: + goto loop_end; } } loop_end: - number_c_string[i] = '\0'; + number_c_string[i] = '\0'; - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) + number = strtod ((const char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) { - return false; /* parse_error */ + return false; /* parse_error */ } - item->valuedouble = number; + item->valuedouble = number; - /* use saturation in case of overflow */ - if (number >= INT_MAX) + /* use saturation in case of overflow */ + if (number >= INT_MAX) { - item->valueint = INT_MAX; + item->valueint = INT_MAX; } - else if (number <= (double)INT_MIN) + else if (number <= (double)INT_MIN) { - item->valueint = INT_MIN; + item->valueint = INT_MIN; } - else + else { - item->valueint = (int)number; + item->valueint = (int)number; } - item->type = cJSON_Number; + item->type = cJSON_Number; - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; } -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or + * double */ +CJSON_PUBLIC (double) cJSON_SetNumberHelper (cJSON *object, double number) { - if (number >= INT_MAX) + if (number >= INT_MAX) { - object->valueint = INT_MAX; + object->valueint = INT_MAX; } - else if (number <= (double)INT_MIN) + else if (number <= (double)INT_MIN) { - object->valueint = INT_MIN; + object->valueint = INT_MIN; } - else + else { - object->valueint = (int)number; + object->valueint = (int)number; } - return object->valuedouble = number; + return object->valuedouble = number; } -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +CJSON_PUBLIC (char *) +cJSON_SetValuestring (cJSON *object, const char *valuestring) { - char *copy = NULL; - /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ - if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should + * not set valuestring */ + if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { - return NULL; + return NULL; } - if (strlen(valuestring) <= strlen(object->valuestring)) + if (strlen (valuestring) <= strlen (object->valuestring)) { - strcpy(object->valuestring, valuestring); - return object->valuestring; + strcpy (object->valuestring, valuestring); + return object->valuestring; } - copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); - if (copy == NULL) + copy = (char *)cJSON_strdup ((const unsigned char *)valuestring, + &global_hooks); + if (copy == NULL) { - return NULL; + return NULL; } - if (object->valuestring != NULL) + if (object->valuestring != NULL) { - cJSON_free(object->valuestring); + cJSON_free (object->valuestring); } - object->valuestring = copy; + object->valuestring = copy; - return copy; + return copy; } typedef struct { - unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) +static unsigned char * +ensure (printbuffer *const p, size_t needed) { - unsigned char *newbuffer = NULL; - size_t newsize = 0; + unsigned char *newbuffer = NULL; + size_t newsize = 0; - if ((p == NULL) || (p->buffer == NULL)) + if ((p == NULL) || (p->buffer == NULL)) { - return NULL; + return NULL; } - if ((p->length > 0) && (p->offset >= p->length)) + if ((p->length > 0) && (p->offset >= p->length)) { - /* make sure that offset is valid */ - return NULL; + /* make sure that offset is valid */ + return NULL; } - if (needed > INT_MAX) + if (needed > INT_MAX) { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; } - needed += p->offset + 1; - if (needed <= p->length) + needed += p->offset + 1; + if (needed <= p->length) { - return p->buffer + p->offset; + return p->buffer + p->offset; } - if (p->noalloc) { - return NULL; + if (p->noalloc) + { + return NULL; } - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) { - newsize = INT_MAX; + newsize = INT_MAX; } - else + else { - return NULL; + return NULL; } } - else + else { - newsize = needed * 2; + newsize = needed * 2; } - if (p->hooks.reallocate != NULL) + if (p->hooks.reallocate != NULL) { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) + /* reallocate with realloc if available */ + newbuffer = (unsigned char *)p->hooks.reallocate (p->buffer, newsize); + if (newbuffer == NULL) { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; + p->hooks.deallocate (p->buffer); + p->length = 0; + p->buffer = NULL; - return NULL; + return NULL; } } - else + else { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) + /* otherwise reallocate manually */ + newbuffer = (unsigned char *)p->hooks.allocate (newsize); + if (!newbuffer) { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; + p->hooks.deallocate (p->buffer); + p->length = 0; + p->buffer = NULL; - return NULL; + return NULL; } - memcpy(newbuffer, p->buffer, p->offset + 1); - p->hooks.deallocate(p->buffer); + memcpy (newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate (p->buffer); } - p->length = newsize; - p->buffer = newbuffer; + p->length = newsize; + p->buffer = newbuffer; - return newbuffer + p->offset; + return newbuffer + p->offset; } -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) +/* calculate the new length of the string in a printbuffer and update the + * offset */ +static void +update_offset (printbuffer *const buffer) { - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) { - return; + return; } - buffer_pointer = buffer->buffer + buffer->offset; + buffer_pointer = buffer->buffer + buffer->offset; - buffer->offset += strlen((const char*)buffer_pointer); + buffer->offset += strlen ((const char *)buffer_pointer); } /* securely comparison of floating-point variables */ -static cJSON_bool compare_double(double a, double b) +static cJSON_bool +compare_double (double a, double b) { - double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); - return (fabs(a - b) <= maxVal * DBL_EPSILON); + double maxVal = fabs (a) > fabs (b) ? fabs (a) : fabs (b); + return (fabs (a - b) <= maxVal * DBL_EPSILON); } /* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool +print_number (const cJSON *const item, printbuffer *const output_buffer) { - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - double test = 0.0; + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] + = { 0 }; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point (); + double test = 0.0; - if (output_buffer == NULL) + if (output_buffer == NULL) { - return false; + return false; } - /* This checks for NaN and Infinity */ - if (isnan(d) || isinf(d)) + /* This checks for NaN and Infinity */ + if (isnan (d) || isinf (d)) { - length = sprintf((char*)number_buffer, "null"); + length = sprintf ((char *)number_buffer, "null"); } - else if(d == (double)item->valueint) - { - length = sprintf((char*)number_buffer, "%d", item->valueint); - } - else + else if (d == (double)item->valueint) { - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); + length = sprintf ((char *)number_buffer, "%d", item->valueint); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero + * digits */ + length = sprintf ((char *)number_buffer, "%1.15g", d); - /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) + /* Check whether the original double can be recovered */ + if ((sscanf ((char *)number_buffer, "%lg", &test) != 1) + || !compare_double ((double)test, d)) { - /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); + /* If not, print with 17 decimal places of precision */ + length = sprintf ((char *)number_buffer, "%1.17g", d); } } - /* sprintf failed or buffer overrun occurred */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof (number_buffer) - 1))) { - return false; + return false; } - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) + /* reserve appropriate space in the output */ + output_pointer = ensure (output_buffer, (size_t)length + sizeof ("")); + if (output_pointer == NULL) { - return false; + return false; } - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) { - if (number_buffer[i] == decimal_point) + if (number_buffer[i] == decimal_point) { - output_pointer[i] = '.'; - continue; + output_pointer[i] = '.'; + continue; } - output_pointer[i] = number_buffer[i]; + output_pointer[i] = number_buffer[i]; } - output_pointer[i] = '\0'; + output_pointer[i] = '\0'; - output_buffer->offset += (size_t)length; + output_buffer->offset += (size_t)length; - return true; + return true; } /* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) +static unsigned +parse_hex4 (const unsigned char *const input) { - unsigned int h = 0; - size_t i = 0; + unsigned int h = 0; + size_t i = 0; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) { - h += (unsigned int) input[i] - '0'; + h += (unsigned int)input[i] - '0'; } - else if ((input[i] >= 'A') && (input[i] <= 'F')) + else if ((input[i] >= 'A') && (input[i] <= 'F')) { - h += (unsigned int) 10 + input[i] - 'A'; + h += (unsigned int)10 + input[i] - 'A'; } - else if ((input[i] >= 'a') && (input[i] <= 'f')) + else if ((input[i] >= 'a') && (input[i] <= 'f')) { - h += (unsigned int) 10 + input[i] - 'a'; + h += (unsigned int)10 + input[i] - 'a'; } - else /* invalid */ + else /* invalid */ { - return 0; + return 0; } - if (i < 3) + if (i < 3) { - /* shift left to make place for the next nibble */ - h = h << 4; + /* shift left to make place for the next nibble */ + h = h << 4; } } - return h; + return h; } /* converts a UTF-16 literal to UTF-8 * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +static unsigned char +utf16_literal_to_utf8 (const unsigned char *const input_pointer, + const unsigned char *const input_end, + unsigned char **output_pointer) { - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; - if ((input_end - first_sequence) < 6) + if ((input_end - first_sequence) < 6) { - /* input ends unexpectedly */ - goto fail; + /* input ends unexpectedly */ + goto fail; } - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); + /* get the first utf16 sequence */ + first_code = parse_hex4 (first_sequence + 2); - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { - goto fail; + goto fail; } - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ - if ((input_end - second_sequence) < 6) + if ((input_end - second_sequence) < 6) { - /* input ends unexpectedly */ - goto fail; + /* input ends unexpectedly */ + goto fail; } - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { - /* missing second half of the surrogate pair */ - goto fail; + /* missing second half of the surrogate pair */ + goto fail; } - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + /* get the second utf16 sequence */ + second_code = parse_hex4 (second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { - /* invalid second half of the surrogate pair */ - goto fail; + /* invalid second half of the surrogate pair */ + goto fail; } - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + /* calculate the unicode codepoint from the surrogate pair */ + codepoint + = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); } - else + else { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; } - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; } - else if (codepoint < 0x800) + else if (codepoint < 0x800) { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ } - else if (codepoint < 0x10000) + else if (codepoint < 0x10000) { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ } - else if (codepoint <= 0x10FFFF) + else if (codepoint <= 0x10FFFF) { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ } - else + else { - /* invalid unicode codepoint */ - goto fail; + /* invalid unicode codepoint */ + goto fail; } - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; + utf8_position--) { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; + /* 10xxxxxx */ + (*output_pointer)[utf8_position] + = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; } - /* encode first byte */ - if (utf8_length > 1) + /* encode first byte */ + if (utf8_length > 1) { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + (*output_pointer)[0] + = (unsigned char)((codepoint | first_byte_mark) & 0xFF); } - else + else { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); } - *output_pointer += utf8_length; + *output_pointer += utf8_length; - return sequence_length; + return sequence_length; fail: - return 0; + return 0; } /* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) -{ - const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { - /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } +static cJSON_bool +parse_string (cJSON *const item, parse_buffer *const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset (input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset (input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset (input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) + && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) + >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a + * backslash */ + goto fail; + } + skipped_bytes++; input_end++; - } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { - goto fail; /* allocation failure */ - } - } + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) + || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t)(input_end - buffer_at_offset (input_buffer)) + - skipped_bytes; + output = (unsigned char *)input_buffer->hooks.allocate (allocation_length + + sizeof ("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) { - if (*input_pointer != '\\') + if (*input_pointer != '\\') { - *output_pointer++ = *input_pointer++; + *output_pointer++ = *input_pointer++; } - /* escape sequence */ - else + /* escape sequence */ + else { - unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) { - goto fail; + goto fail; } - switch (input_pointer[1]) + switch (input_pointer[1]) { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8 ( + input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; } - input_pointer += sequence_length; + input_pointer += sequence_length; } } - /* zero terminate the output */ - *output_pointer = '\0'; + /* zero terminate the output */ + *output_pointer = '\0'; - item->type = cJSON_String; - item->valuestring = (char*)output; + item->type = cJSON_String; + item->valuestring = (char *)output; - input_buffer->offset = (size_t) (input_end - input_buffer->content); - input_buffer->offset++; + input_buffer->offset = (size_t)(input_end - input_buffer->content); + input_buffer->offset++; - return true; + return true; fail: - if (output != NULL) + if (output != NULL) { - input_buffer->hooks.deallocate(output); + input_buffer->hooks.deallocate (output); } - if (input_pointer != NULL) + if (input_pointer != NULL) { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); } - return false; + return false; } /* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +static cJSON_bool +print_string_ptr (const unsigned char *const input, + printbuffer *const output_buffer) { - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; - if (output_buffer == NULL) + if (output_buffer == NULL) { - return false; + return false; } - /* empty string */ - if (input == NULL) + /* empty string */ + if (input == NULL) { - output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) + output = ensure (output_buffer, sizeof ("\"\"")); + if (output == NULL) { - return false; + return false; } - strcpy((char*)output, "\"\""); + strcpy ((char *)output, "\"\""); - return true; + return true; } - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) { - switch (*input_pointer) + switch (*input_pointer) { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if (*input_pointer < 32) - { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; } } - output_length = (size_t)(input_pointer - input) + escape_characters; + output_length = (size_t)(input_pointer - input) + escape_characters; - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) + output = ensure (output_buffer, output_length + sizeof ("\"\"")); + if (output == NULL) { - return false; + return false; } - /* no characters have to be escaped */ - if (escape_characters == 0) + /* no characters have to be escaped */ + if (escape_characters == 0) { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; + output[0] = '\"'; + memcpy (output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; - return true; + return true; } - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; + (void)input_pointer++, output_pointer++) { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + if ((*input_pointer > 31) && (*input_pointer != '\"') + && (*input_pointer != '\\')) { - /* normal character, copy */ - *output_pointer = *input_pointer; + /* normal character, copy */ + *output_pointer = *input_pointer; } - else + else { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf ((char *)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; } } } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; - return true; + return true; } /* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +static cJSON_bool +print_string (const cJSON *const item, printbuffer *const p) { - return print_string_ptr((unsigned char*)item->valuestring, p); + return print_string_ptr ((unsigned char *)item->valuestring, p); } /* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_value (cJSON *const item, + parse_buffer *const input_buffer); +static cJSON_bool print_value (const cJSON *const item, + printbuffer *const output_buffer); +static cJSON_bool parse_array (cJSON *const item, + parse_buffer *const input_buffer); +static cJSON_bool print_array (const cJSON *const item, + printbuffer *const output_buffer); +static cJSON_bool parse_object (cJSON *const item, + parse_buffer *const input_buffer); +static cJSON_bool print_object (const cJSON *const item, + printbuffer *const output_buffer); /* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +static parse_buffer * +buffer_skip_whitespace (parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL)) + if ((buffer == NULL) || (buffer->content == NULL)) { - return NULL; + return NULL; } - if (cannot_access_at_index(buffer, 0)) + if (cannot_access_at_index (buffer, 0)) { - return buffer; + return buffer; } - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + while (can_access_at_index (buffer, 0) + && (buffer_at_offset (buffer)[0] <= 32)) { - buffer->offset++; + buffer->offset++; } - if (buffer->offset == buffer->length) + if (buffer->offset == buffer->length) { - buffer->offset--; + buffer->offset--; } - return buffer; + return buffer; } -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer + */ +static parse_buffer * +skip_utf8_bom (parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { - return NULL; + return NULL; } - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + if (can_access_at_index (buffer, 4) + && (strncmp ((const char *)buffer_at_offset (buffer), "\xEF\xBB\xBF", 3) + == 0)) { - buffer->offset += 3; + buffer->offset += 3; } - return buffer; + return buffer; } -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +CJSON_PUBLIC (cJSON *) +cJSON_ParseWithOpts (const char *value, const char **return_parse_end, + cJSON_bool require_null_terminated) { - size_t buffer_length; + size_t buffer_length; - if (NULL == value) + if (NULL == value) { - return NULL; + return NULL; } - /* Adding null character size due to require_null_terminated. */ - buffer_length = strlen(value) + sizeof(""); + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen (value) + sizeof (""); - return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); + return cJSON_ParseWithLengthOpts (value, buffer_length, return_parse_end, + require_null_terminated); } /* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +CJSON_PUBLIC (cJSON *) +cJSON_ParseWithLengthOpts (const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated) { - parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; - cJSON *item = NULL; + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; - if (value == NULL || 0 == buffer_length) + if (value == NULL || 0 == buffer_length) { - goto fail; + goto fail; } - buffer.content = (const unsigned char*)value; - buffer.length = buffer_length; - buffer.offset = 0; - buffer.hooks = global_hooks; + buffer.content = (const unsigned char *)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; - item = cJSON_New_Item(&global_hooks); - if (item == NULL) /* memory fail */ + item = cJSON_New_Item (&global_hooks); + if (item == NULL) /* memory fail */ { - goto fail; + goto fail; } - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + if (!parse_value (item, buffer_skip_whitespace (skip_utf8_bom (&buffer)))) { - /* parse failure. ep is set. */ - goto fail; + /* parse failure. ep is set. */ + goto fail; } - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) + /* if we require null-terminated JSON without appended garbage, skip and then + * check for a null terminator */ + if (require_null_terminated) { - buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + buffer_skip_whitespace (&buffer); + if ((buffer.offset >= buffer.length) + || buffer_at_offset (&buffer)[0] != '\0') { - goto fail; + goto fail; } } - if (return_parse_end) + if (return_parse_end) { - *return_parse_end = (const char*)buffer_at_offset(&buffer); + *return_parse_end = (const char *)buffer_at_offset (&buffer); } - return item; + return item; fail: - if (item != NULL) + if (item != NULL) { - cJSON_Delete(item); + cJSON_Delete (item); } - if (value != NULL) + if (value != NULL) { - error local_error; - local_error.json = (const unsigned char*)value; - local_error.position = 0; + error local_error; + local_error.json = (const unsigned char *)value; + local_error.position = 0; - if (buffer.offset < buffer.length) + if (buffer.offset < buffer.length) { - local_error.position = buffer.offset; + local_error.position = buffer.offset; } - else if (buffer.length > 0) + else if (buffer.length > 0) { - local_error.position = buffer.length - 1; + local_error.position = buffer.length - 1; } - if (return_parse_end != NULL) + if (return_parse_end != NULL) { - *return_parse_end = (const char*)local_error.json + local_error.position; + *return_parse_end + = (const char *)local_error.json + local_error.position; } - global_error = local_error; + global_error = local_error; } - return NULL; + return NULL; } /* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +CJSON_PUBLIC (cJSON *) cJSON_Parse (const char *value) { - return cJSON_ParseWithOpts(value, 0, 0); + return cJSON_ParseWithOpts (value, 0, 0); } -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +CJSON_PUBLIC (cJSON *) +cJSON_ParseWithLength (const char *value, size_t buffer_length) { - return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); + return cJSON_ParseWithLengthOpts (value, buffer_length, 0, 0); } #define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +static unsigned char * +print (const cJSON *const item, cJSON_bool format, + const internal_hooks *const hooks) { - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char *printed = NULL; + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; - memset(buffer, 0, sizeof(buffer)); + memset (buffer, 0, sizeof (buffer)); - /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if (buffer->buffer == NULL) + /* create buffer */ + buffer->buffer = (unsigned char *)hooks->allocate (default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) { - goto fail; + goto fail; } - /* print the value */ - if (!print_value(item, buffer)) + /* print the value */ + if (!print_value (item, buffer)) { - goto fail; + goto fail; } - update_offset(buffer); + update_offset (buffer); - /* check if reallocate is available */ - if (hooks->reallocate != NULL) + /* check if reallocate is available */ + if (hooks->reallocate != NULL) { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); - if (printed == NULL) { - goto fail; + printed = (unsigned char *)hooks->reallocate (buffer->buffer, + buffer->offset + 1); + if (printed == NULL) + { + goto fail; } - buffer->buffer = NULL; + buffer->buffer = NULL; } - else /* otherwise copy the JSON over to a new buffer */ + else /* otherwise copy the JSON over to a new buffer */ { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) + printed = (unsigned char *)hooks->allocate (buffer->offset + 1); + if (printed == NULL) { - goto fail; + goto fail; } - memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ + memcpy (printed, buffer->buffer, + cjson_min (buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ - /* free the buffer */ - hooks->deallocate(buffer->buffer); + /* free the buffer */ + hooks->deallocate (buffer->buffer); } - return printed; + return printed; fail: - if (buffer->buffer != NULL) + if (buffer->buffer != NULL) { - hooks->deallocate(buffer->buffer); + hooks->deallocate (buffer->buffer); } - if (printed != NULL) + if (printed != NULL) { - hooks->deallocate(printed); + hooks->deallocate (printed); } - return NULL; + return NULL; } /* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +CJSON_PUBLIC (char *) cJSON_Print (const cJSON *item) { - return (char*)print(item, true, &global_hooks); + return (char *)print (item, true, &global_hooks); } -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +CJSON_PUBLIC (char *) cJSON_PrintUnformatted (const cJSON *item) { - return (char*)print(item, false, &global_hooks); + return (char *)print (item, false, &global_hooks); } -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +CJSON_PUBLIC (char *) +cJSON_PrintBuffered (const cJSON *item, int prebuffer, cJSON_bool fmt) { - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if (prebuffer < 0) + if (prebuffer < 0) { - return NULL; + return NULL; } - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) + p.buffer = (unsigned char *)global_hooks.allocate ((size_t)prebuffer); + if (!p.buffer) { - return NULL; + return NULL; } - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; - if (!print_value(item, &p)) + if (!print_value (item, &p)) { - global_hooks.deallocate(p.buffer); - return NULL; + global_hooks.deallocate (p.buffer); + return NULL; } - return (char*)p.buffer; + return (char *)p.buffer; } -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +CJSON_PUBLIC (cJSON_bool) +cJSON_PrintPreallocated (cJSON *item, char *buffer, const int length, + const cJSON_bool format) { - printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if ((length < 0) || (buffer == NULL)) + if ((length < 0) || (buffer == NULL)) { - return false; + return false; } - p.buffer = (unsigned char*)buffer; - p.length = (size_t)length; - p.offset = 0; - p.noalloc = true; - p.format = format; - p.hooks = global_hooks; + p.buffer = (unsigned char *)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; - return print_value(item, &p); + return print_value (item, &p); } /* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool +parse_value (cJSON *const item, parse_buffer *const input_buffer) { - if ((input_buffer == NULL) || (input_buffer->content == NULL)) + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { - return false; /* no input */ + return false; /* no input */ } - /* parse the different types of values */ - /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + /* parse the different types of values */ + /* null */ + if (can_read (input_buffer, 4) + && (strncmp ((const char *)buffer_at_offset (input_buffer), "null", 4) + == 0)) { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; } - /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + /* false */ + if (can_read (input_buffer, 5) + && (strncmp ((const char *)buffer_at_offset (input_buffer), "false", 5) + == 0)) { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; + item->type = cJSON_False; + input_buffer->offset += 5; + return true; } - /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + /* true */ + if (can_read (input_buffer, 4) + && (strncmp ((const char *)buffer_at_offset (input_buffer), "true", 4) + == 0)) { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; } - /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + /* string */ + if (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == '\"')) { - return parse_string(item, input_buffer); + return parse_string (item, input_buffer); } - /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + /* number */ + if (can_access_at_index (input_buffer, 0) + && ((buffer_at_offset (input_buffer)[0] == '-') + || ((buffer_at_offset (input_buffer)[0] >= '0') + && (buffer_at_offset (input_buffer)[0] <= '9')))) { - return parse_number(item, input_buffer); + return parse_number (item, input_buffer); } - /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + /* array */ + if (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == '[')) { - return parse_array(item, input_buffer); + return parse_array (item, input_buffer); } - /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + /* object */ + if (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == '{')) { - return parse_object(item, input_buffer); + return parse_object (item, input_buffer); } - return false; + return false; } /* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool +print_value (const cJSON *const item, printbuffer *const output_buffer) { - unsigned char *output = NULL; + unsigned char *output = NULL; - if ((item == NULL) || (output_buffer == NULL)) + if ((item == NULL) || (output_buffer == NULL)) { - return false; + return false; } - switch ((item->type) & 0xFF) + switch ((item->type) & 0xFF) { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "null"); - return true; + case cJSON_NULL: + output = ensure (output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy ((char *)output, "null"); + return true; - case cJSON_False: - output = ensure(output_buffer, 6); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "false"); - return true; + case cJSON_False: + output = ensure (output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy ((char *)output, "false"); + return true; - case cJSON_True: - output = ensure(output_buffer, 5); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "true"); - return true; + case cJSON_True: + output = ensure (output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy ((char *)output, "true"); + return true; - case cJSON_Number: - return print_number(item, output_buffer); + case cJSON_Number: + return print_number (item, output_buffer); - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - return false; - } + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if (output == NULL) - { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } + raw_length = strlen (item->valuestring) + sizeof (""); + output = ensure (output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy (output, item->valuestring, raw_length); + return true; + } - case cJSON_String: - return print_string(item, output_buffer); + case cJSON_String: + return print_string (item, output_buffer); - case cJSON_Array: - return print_array(item, output_buffer); + case cJSON_Array: + return print_array (item, output_buffer); - case cJSON_Object: - return print_object(item, output_buffer); + case cJSON_Object: + return print_object (item, output_buffer); - default: - return false; + default: + return false; } } /* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool +parse_array (cJSON *const item, parse_buffer *const input_buffer) { - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; - if (input_buffer->depth >= CJSON_NESTING_LIMIT) + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { - return false; /* to deeply nested */ + return false; /* to deeply nested */ } - input_buffer->depth++; + input_buffer->depth++; - if (buffer_at_offset(input_buffer)[0] != '[') + if (buffer_at_offset (input_buffer)[0] != '[') { - /* not an array */ - goto fail; + /* not an array */ + goto fail; } - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + input_buffer->offset++; + buffer_skip_whitespace (input_buffer); + if (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == ']')) { - /* empty array */ - goto success; + /* empty array */ + goto success; } - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index (input_buffer, 0)) { - input_buffer->offset--; - goto fail; + input_buffer->offset--; + goto fail; } - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) + /* allocate next item */ + cJSON *new_item = cJSON_New_Item (&(input_buffer->hooks)); + if (new_item == NULL) { - goto fail; /* allocation failure */ + goto fail; /* allocation failure */ } - /* attach next item to list */ - if (head == NULL) + /* attach next item to list */ + if (head == NULL) { - /* start the linked list */ - current_item = head = new_item; + /* start the linked list */ + current_item = head = new_item; } - else + else { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; } - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace (input_buffer); + if (!parse_value (current_item, input_buffer)) { - goto fail; /* failed to parse value */ + goto fail; /* failed to parse value */ } - buffer_skip_whitespace(input_buffer); + buffer_skip_whitespace (input_buffer); } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + while (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == ',')); - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + if (cannot_access_at_index (input_buffer, 0) + || buffer_at_offset (input_buffer)[0] != ']') { - goto fail; /* expected end of array */ + goto fail; /* expected end of array */ } success: - input_buffer->depth--; + input_buffer->depth--; - if (head != NULL) { - head->prev = current_item; + if (head != NULL) + { + head->prev = current_item; } - item->type = cJSON_Array; - item->child = head; + item->type = cJSON_Array; + item->child = head; - input_buffer->offset++; + input_buffer->offset++; - return true; + return true; fail: - if (head != NULL) + if (head != NULL) { - cJSON_Delete(head); + cJSON_Delete (head); } - return false; + return false; } /* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool +print_array (const cJSON *const item, printbuffer *const output_buffer) { - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; - if (output_buffer == NULL) + if (output_buffer == NULL) { - return false; + return false; } - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure (output_buffer, 1); + if (output_pointer == NULL) { - return false; + return false; } - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; - while (current_element != NULL) + while (current_element != NULL) { - if (!print_value(current_element, output_buffer)) + if (!print_value (current_element, output_buffer)) { - return false; + return false; } - update_offset(output_buffer); - if (current_element->next) + update_offset (output_buffer); + if (current_element->next) { - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = ensure (output_buffer, length + 1); + if (output_pointer == NULL) { - return false; + return false; } - *output_pointer++ = ','; - if(output_buffer->format) + *output_pointer++ = ','; + if (output_buffer->format) { - *output_pointer++ = ' '; + *output_pointer++ = ' '; } - *output_pointer = '\0'; - output_buffer->offset += length; + *output_pointer = '\0'; + output_buffer->offset += length; } - current_element = current_element->next; + current_element = current_element->next; } - output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) + output_pointer = ensure (output_buffer, 2); + if (output_pointer == NULL) { - return false; + return false; } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; - return true; + return true; } /* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool +parse_object (cJSON *const item, parse_buffer *const input_buffer) { - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; - if (input_buffer->depth >= CJSON_NESTING_LIMIT) + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { - return false; /* to deeply nested */ + return false; /* to deeply nested */ } - input_buffer->depth++; + input_buffer->depth++; - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + if (cannot_access_at_index (input_buffer, 0) + || (buffer_at_offset (input_buffer)[0] != '{')) { - goto fail; /* not an object */ + goto fail; /* not an object */ } - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + input_buffer->offset++; + buffer_skip_whitespace (input_buffer); + if (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == '}')) { - goto success; /* empty object */ + goto success; /* empty object */ } - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index (input_buffer, 0)) { - input_buffer->offset--; - goto fail; + input_buffer->offset--; + goto fail; } - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) + /* allocate next item */ + cJSON *new_item = cJSON_New_Item (&(input_buffer->hooks)); + if (new_item == NULL) { - goto fail; /* allocation failure */ + goto fail; /* allocation failure */ } - /* attach next item to list */ - if (head == NULL) + /* attach next item to list */ + if (head == NULL) { - /* start the linked list */ - current_item = head = new_item; + /* start the linked list */ + current_item = head = new_item; } - else + else { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; } - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace (input_buffer); + if (!parse_string (current_item, input_buffer)) { - goto fail; /* failed to parse name */ + goto fail; /* failed to parse name */ } - buffer_skip_whitespace(input_buffer); + buffer_skip_whitespace (input_buffer); - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + if (cannot_access_at_index (input_buffer, 0) + || (buffer_at_offset (input_buffer)[0] != ':')) { - goto fail; /* invalid object */ + goto fail; /* invalid object */ } - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace (input_buffer); + if (!parse_value (current_item, input_buffer)) { - goto fail; /* failed to parse value */ + goto fail; /* failed to parse value */ } - buffer_skip_whitespace(input_buffer); + buffer_skip_whitespace (input_buffer); } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + while (can_access_at_index (input_buffer, 0) + && (buffer_at_offset (input_buffer)[0] == ',')); - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + if (cannot_access_at_index (input_buffer, 0) + || (buffer_at_offset (input_buffer)[0] != '}')) { - goto fail; /* expected end of object */ + goto fail; /* expected end of object */ } success: - input_buffer->depth--; + input_buffer->depth--; - if (head != NULL) { - head->prev = current_item; + if (head != NULL) + { + head->prev = current_item; } - item->type = cJSON_Object; - item->child = head; + item->type = cJSON_Object; + item->child = head; - input_buffer->offset++; - return true; + input_buffer->offset++; + return true; fail: - if (head != NULL) + if (head != NULL) { - cJSON_Delete(head); + cJSON_Delete (head); } - return false; + return false; } /* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool +print_object (const cJSON *const item, printbuffer *const output_buffer) { - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; - if (output_buffer == NULL) + if (output_buffer == NULL) { - return false; + return false; } - /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) + /* Compose the output: */ + length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure (output_buffer, length + 1); + if (output_pointer == NULL) { - return false; + return false; } - *output_pointer++ = '{'; - output_buffer->depth++; - if (output_buffer->format) + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) { - *output_pointer++ = '\n'; + *output_pointer++ = '\n'; } - output_buffer->offset += length; + output_buffer->offset += length; - while (current_item) + while (current_item) { - if (output_buffer->format) + if (output_buffer->format) { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) + size_t i; + output_pointer = ensure (output_buffer, output_buffer->depth); + if (output_pointer == NULL) { - return false; + return false; } - for (i = 0; i < output_buffer->depth; i++) + for (i = 0; i < output_buffer->depth; i++) { - *output_pointer++ = '\t'; + *output_pointer++ = '\t'; } - output_buffer->offset += output_buffer->depth; + output_buffer->offset += output_buffer->depth; } - /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + /* print key */ + if (!print_string_ptr ((unsigned char *)current_item->string, + output_buffer)) { - return false; + return false; } - update_offset(output_buffer); + update_offset (output_buffer); - length = (size_t) (output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = ensure (output_buffer, length); + if (output_pointer == NULL) { - return false; + return false; } - *output_pointer++ = ':'; - if (output_buffer->format) + *output_pointer++ = ':'; + if (output_buffer->format) { - *output_pointer++ = '\t'; + *output_pointer++ = '\t'; } - output_buffer->offset += length; + output_buffer->offset += length; - /* print value */ - if (!print_value(current_item, output_buffer)) + /* print value */ + if (!print_value (current_item, output_buffer)) { - return false; + return false; } - update_offset(output_buffer); + update_offset (output_buffer); - /* print comma if not last */ - length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure (output_buffer, length + 1); + if (output_pointer == NULL) { - return false; + return false; } - if (current_item->next) + if (current_item->next) { - *output_pointer++ = ','; + *output_pointer++ = ','; } - if (output_buffer->format) + if (output_buffer->format) { - *output_pointer++ = '\n'; + *output_pointer++ = '\n'; } - *output_pointer = '\0'; - output_buffer->offset += length; + *output_pointer = '\0'; + output_buffer->offset += length; - current_item = current_item->next; + current_item = current_item->next; } - output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) + output_pointer = ensure ( + output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) { - return false; + return false; } - if (output_buffer->format) + if (output_buffer->format) { - size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) { - *output_pointer++ = '\t'; + *output_pointer++ = '\t'; } } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; - return true; + return true; } /* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +CJSON_PUBLIC (int) cJSON_GetArraySize (const cJSON *array) { - cJSON *child = NULL; - size_t size = 0; + cJSON *child = NULL; + size_t size = 0; - if (array == NULL) + if (array == NULL) { - return 0; + return 0; } - child = array->child; + child = array->child; - while(child != NULL) + while (child != NULL) { - size++; - child = child->next; + size++; + child = child->next; } - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - return (int)size; + return (int)size; } -static cJSON* get_array_item(const cJSON *array, size_t index) +static cJSON * +get_array_item (const cJSON *array, size_t index) { - cJSON *current_child = NULL; + cJSON *current_child = NULL; - if (array == NULL) + if (array == NULL) { - return NULL; + return NULL; } - current_child = array->child; - while ((current_child != NULL) && (index > 0)) + current_child = array->child; + while ((current_child != NULL) && (index > 0)) { - index--; - current_child = current_child->next; + index--; + current_child = current_child->next; } - return current_child; + return current_child; } -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +CJSON_PUBLIC (cJSON *) cJSON_GetArrayItem (const cJSON *array, int index) { - if (index < 0) + if (index < 0) { - return NULL; + return NULL; } - return get_array_item(array, (size_t)index); + return get_array_item (array, (size_t)index); } -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +static cJSON * +get_object_item (const cJSON *const object, const char *const name, + const cJSON_bool case_sensitive) { - cJSON *current_element = NULL; + cJSON *current_element = NULL; - if ((object == NULL) || (name == NULL)) + if ((object == NULL) || (name == NULL)) { - return NULL; + return NULL; } - current_element = object->child; - if (case_sensitive) + current_element = object->child; + if (case_sensitive) { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + while ((current_element != NULL) && (current_element->string != NULL) + && (strcmp (name, current_element->string) != 0)) { - current_element = current_element->next; + current_element = current_element->next; } } - else + else { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + while ((current_element != NULL) + && (case_insensitive_strcmp ( + (const unsigned char *)name, + (const unsigned char *)(current_element->string)) + != 0)) { - current_element = current_element->next; + current_element = current_element->next; } } - if ((current_element == NULL) || (current_element->string == NULL)) { - return NULL; + if ((current_element == NULL) || (current_element->string == NULL)) + { + return NULL; } - return current_element; + return current_element; } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +CJSON_PUBLIC (cJSON *) +cJSON_GetObjectItem (const cJSON *const object, const char *const string) { - return get_object_item(object, string, false); + return get_object_item (object, string, false); } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +CJSON_PUBLIC (cJSON *) +cJSON_GetObjectItemCaseSensitive (const cJSON *const object, + const char *const string) { - return get_object_item(object, string, true); + return get_object_item (object, string, true); } -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +CJSON_PUBLIC (cJSON_bool) +cJSON_HasObjectItem (const cJSON *object, const char *string) { - return cJSON_GetObjectItem(object, string) ? 1 : 0; + return cJSON_GetObjectItem (object, string) ? 1 : 0; } /* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) +static void +suffix_object (cJSON *prev, cJSON *item) { - prev->next = item; - item->prev = prev; + prev->next = item; + item->prev = prev; } /* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +static cJSON * +create_reference (const cJSON *item, const internal_hooks *const hooks) { - cJSON *reference = NULL; - if (item == NULL) + cJSON *reference = NULL; + if (item == NULL) { - return NULL; + return NULL; } - reference = cJSON_New_Item(hooks); - if (reference == NULL) + reference = cJSON_New_Item (hooks); + if (reference == NULL) { - return NULL; + return NULL; } - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; + memcpy (reference, item, sizeof (cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; } -static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +static cJSON_bool +add_item_to_array (cJSON *array, cJSON *item) { - cJSON *child = NULL; + cJSON *child = NULL; - if ((item == NULL) || (array == NULL) || (array == item)) + if ((item == NULL) || (array == NULL) || (array == item)) { - return false; + return false; } - child = array->child; - /* - * To find the last item in array quickly, we use prev in array - */ - if (child == NULL) + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) { - /* list is empty, start new one */ - array->child = item; - item->prev = item; - item->next = NULL; + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; } - else + else { - /* append to the end */ - if (child->prev) + /* append to the end */ + if (child->prev) { - suffix_object(child->prev, item); - array->child->prev = item; + suffix_object (child->prev, item); + array->child->prev = item; } } - return true; + return true; } /* Add item to array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +CJSON_PUBLIC (cJSON_bool) cJSON_AddItemToArray (cJSON *array, cJSON *item) { - return add_item_to_array(array, item); + return add_item_to_array (array, item); } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push +#if defined(__clang__) \ + || (defined(__GNUC__) \ + && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic push #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wcast-qual" #endif /* helper function to cast away const */ -static void* cast_away_const(const void* string) +static void * +cast_away_const (const void *string) { - return (void*)string; + return (void *)string; } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop +#if defined(__clang__) \ + || (defined(__GNUC__) \ + && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic pop #endif - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +static cJSON_bool +add_item_to_object (cJSON *const object, const char *const string, + cJSON *const item, const internal_hooks *const hooks, + const cJSON_bool constant_key) { - char *new_key = NULL; - int new_type = cJSON_Invalid; + char *new_key = NULL; + int new_type = cJSON_Invalid; - if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) + if ((object == NULL) || (string == NULL) || (item == NULL) + || (object == item)) { - return false; + return false; } - if (constant_key) + if (constant_key) { - new_key = (char*)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; + new_key = (char *)cast_away_const (string); + new_type = item->type | cJSON_StringIsConst; } - else + else { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) + new_key = (char *)cJSON_strdup ((const unsigned char *)string, hooks); + if (new_key == NULL) { - return false; + return false; } - new_type = item->type & ~cJSON_StringIsConst; + new_type = item->type & ~cJSON_StringIsConst; } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { - hooks->deallocate(item->string); + hooks->deallocate (item->string); } - item->string = new_key; - item->type = new_type; + item->string = new_key; + item->type = new_type; - return add_item_to_array(object, item); + return add_item_to_array (object, item); } -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +CJSON_PUBLIC (cJSON_bool) +cJSON_AddItemToObject (cJSON *object, const char *string, cJSON *item) { - return add_item_to_object(object, string, item, &global_hooks, false); + return add_item_to_object (object, string, item, &global_hooks, false); } /* Add an item to an object with constant string as key */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +CJSON_PUBLIC (cJSON_bool) +cJSON_AddItemToObjectCS (cJSON *object, const char *string, cJSON *item) { - return add_item_to_object(object, string, item, &global_hooks, true); + return add_item_to_object (object, string, item, &global_hooks, true); } -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +CJSON_PUBLIC (cJSON_bool) +cJSON_AddItemReferenceToArray (cJSON *array, cJSON *item) { - if (array == NULL) + if (array == NULL) { - return false; + return false; } - return add_item_to_array(array, create_reference(item, &global_hooks)); + return add_item_to_array (array, create_reference (item, &global_hooks)); } -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +CJSON_PUBLIC (cJSON_bool) +cJSON_AddItemReferenceToObject (cJSON *object, const char *string, cJSON *item) { - if ((object == NULL) || (string == NULL)) + if ((object == NULL) || (string == NULL)) { - return false; + return false; } - return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); + return add_item_to_object (object, string, + create_reference (item, &global_hooks), + &global_hooks, false); } -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC (cJSON *) +cJSON_AddNullToObject (cJSON *const object, const char *const name) { - cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) + cJSON *null = cJSON_CreateNull (); + if (add_item_to_object (object, name, null, &global_hooks, false)) { - return null; + return null; } - cJSON_Delete(null); - return NULL; + cJSON_Delete (null); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC (cJSON *) +cJSON_AddTrueToObject (cJSON *const object, const char *const name) { - cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) + cJSON *true_item = cJSON_CreateTrue (); + if (add_item_to_object (object, name, true_item, &global_hooks, false)) { - return true_item; + return true_item; } - cJSON_Delete(true_item); - return NULL; + cJSON_Delete (true_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC (cJSON *) +cJSON_AddFalseToObject (cJSON *const object, const char *const name) { - cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) + cJSON *false_item = cJSON_CreateFalse (); + if (add_item_to_object (object, name, false_item, &global_hooks, false)) { - return false_item; + return false_item; } - cJSON_Delete(false_item); - return NULL; + cJSON_Delete (false_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +CJSON_PUBLIC (cJSON *) +cJSON_AddBoolToObject (cJSON *const object, const char *const name, + const cJSON_bool boolean) { - cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + cJSON *bool_item = cJSON_CreateBool (boolean); + if (add_item_to_object (object, name, bool_item, &global_hooks, false)) { - return bool_item; + return bool_item; } - cJSON_Delete(bool_item); - return NULL; + cJSON_Delete (bool_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +CJSON_PUBLIC (cJSON *) +cJSON_AddNumberToObject (cJSON *const object, const char *const name, + const double number) { - cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) + cJSON *number_item = cJSON_CreateNumber (number); + if (add_item_to_object (object, name, number_item, &global_hooks, false)) { - return number_item; + return number_item; } - cJSON_Delete(number_item); - return NULL; + cJSON_Delete (number_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +CJSON_PUBLIC (cJSON *) +cJSON_AddStringToObject (cJSON *const object, const char *const name, + const char *const string) { - cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) + cJSON *string_item = cJSON_CreateString (string); + if (add_item_to_object (object, name, string_item, &global_hooks, false)) { - return string_item; + return string_item; } - cJSON_Delete(string_item); - return NULL; + cJSON_Delete (string_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +CJSON_PUBLIC (cJSON *) +cJSON_AddRawToObject (cJSON *const object, const char *const name, + const char *const raw) { - cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + cJSON *raw_item = cJSON_CreateRaw (raw); + if (add_item_to_object (object, name, raw_item, &global_hooks, false)) { - return raw_item; + return raw_item; } - cJSON_Delete(raw_item); - return NULL; + cJSON_Delete (raw_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC (cJSON *) +cJSON_AddObjectToObject (cJSON *const object, const char *const name) { - cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) + cJSON *object_item = cJSON_CreateObject (); + if (add_item_to_object (object, name, object_item, &global_hooks, false)) { - return object_item; + return object_item; } - cJSON_Delete(object_item); - return NULL; + cJSON_Delete (object_item); + return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC (cJSON *) +cJSON_AddArrayToObject (cJSON *const object, const char *const name) { - cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) + cJSON *array = cJSON_CreateArray (); + if (add_item_to_object (object, name, array, &global_hooks, false)) { - return array; + return array; } - cJSON_Delete(array); - return NULL; + cJSON_Delete (array); + return NULL; } -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +CJSON_PUBLIC (cJSON *) +cJSON_DetachItemViaPointer (cJSON *parent, cJSON *const item) { - if ((parent == NULL) || (item == NULL)) + if ((parent == NULL) || (item == NULL)) { - return NULL; + return NULL; } - if (item != parent->child) + if (item != parent->child) { - /* not the first element */ - item->prev->next = item->next; + /* not the first element */ + item->prev->next = item->next; } - if (item->next != NULL) + if (item->next != NULL) { - /* not the last element */ - item->next->prev = item->prev; + /* not the last element */ + item->next->prev = item->prev; } - if (item == parent->child) + if (item == parent->child) { - /* first element */ - parent->child = item->next; + /* first element */ + parent->child = item->next; } - else if (item->next == NULL) + else if (item->next == NULL) { - /* last element */ - parent->child->prev = item->prev; + /* last element */ + parent->child->prev = item->prev; } - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +CJSON_PUBLIC (cJSON *) cJSON_DetachItemFromArray (cJSON *array, int which) { - if (which < 0) + if (which < 0) { - return NULL; + return NULL; } - return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); + return cJSON_DetachItemViaPointer (array, + get_array_item (array, (size_t)which)); } -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +CJSON_PUBLIC (void) cJSON_DeleteItemFromArray (cJSON *array, int which) { - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); + cJSON_Delete (cJSON_DetachItemFromArray (array, which)); } -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +CJSON_PUBLIC (cJSON *) +cJSON_DetachItemFromObject (cJSON *object, const char *string) { - cJSON *to_detach = cJSON_GetObjectItem(object, string); + cJSON *to_detach = cJSON_GetObjectItem (object, string); - return cJSON_DetachItemViaPointer(object, to_detach); + return cJSON_DetachItemViaPointer (object, to_detach); } -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +CJSON_PUBLIC (cJSON *) +cJSON_DetachItemFromObjectCaseSensitive (cJSON *object, const char *string) { - cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive (object, string); - return cJSON_DetachItemViaPointer(object, to_detach); + return cJSON_DetachItemViaPointer (object, to_detach); } -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +CJSON_PUBLIC (void) +cJSON_DeleteItemFromObject (cJSON *object, const char *string) { - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); + cJSON_Delete (cJSON_DetachItemFromObject (object, string)); } -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +CJSON_PUBLIC (void) +cJSON_DeleteItemFromObjectCaseSensitive (cJSON *object, const char *string) { - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); + cJSON_Delete (cJSON_DetachItemFromObjectCaseSensitive (object, string)); } /* Replace array/object items with new ones. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +CJSON_PUBLIC (cJSON_bool) +cJSON_InsertItemInArray (cJSON *array, int which, cJSON *newitem) { - cJSON *after_inserted = NULL; + cJSON *after_inserted = NULL; - if (which < 0) + if (which < 0) { - return false; + return false; } - after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) + after_inserted = get_array_item (array, (size_t)which); + if (after_inserted == NULL) { - return add_item_to_array(array, newitem); + return add_item_to_array (array, newitem); } - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if (after_inserted == array->child) + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) { - array->child = newitem; + array->child = newitem; } - else + else { - newitem->prev->next = newitem; + newitem->prev->next = newitem; } - return true; + return true; } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +CJSON_PUBLIC (cJSON_bool) +cJSON_ReplaceItemViaPointer (cJSON *const parent, cJSON *const item, + cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { - return false; + return false; } - if (replacement == item) + if (replacement == item) { - return true; + return true; } - replacement->next = item->next; - replacement->prev = item->prev; + replacement->next = item->next; + replacement->prev = item->prev; - if (replacement->next != NULL) + if (replacement->next != NULL) { - replacement->next->prev = replacement; + replacement->next->prev = replacement; } - if (parent->child == item) + if (parent->child == item) { - if (parent->child->prev == parent->child) + if (parent->child->prev == parent->child) { - replacement->prev = replacement; + replacement->prev = replacement; } - parent->child = replacement; + parent->child = replacement; } - else - { /* - * To find the last item in array quickly, we use prev in array. - * We can't modify the last item's next pointer where this item was the parent's child - */ - if (replacement->prev != NULL) + else + { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the + * parent's child + */ + if (replacement->prev != NULL) { - replacement->prev->next = replacement; + replacement->prev->next = replacement; } - if (replacement->next == NULL) + if (replacement->next == NULL) { - parent->child->prev = replacement; + parent->child->prev = replacement; } } - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); + item->next = NULL; + item->prev = NULL; + cJSON_Delete (item); - return true; + return true; } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +CJSON_PUBLIC (cJSON_bool) +cJSON_ReplaceItemInArray (cJSON *array, int which, cJSON *newitem) { - if (which < 0) + if (which < 0) { - return false; + return false; } - return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); + return cJSON_ReplaceItemViaPointer ( + array, get_array_item (array, (size_t)which), newitem); } -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +static cJSON_bool +replace_item_in_object (cJSON *object, const char *string, cJSON *replacement, + cJSON_bool case_sensitive) { - if ((replacement == NULL) || (string == NULL)) + if ((replacement == NULL) || (string == NULL)) { - return false; + return false; } - /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) + && (replacement->string != NULL)) { - cJSON_free(replacement->string); + cJSON_free (replacement->string); } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if (replacement->string == NULL) + replacement->string + = (char *)cJSON_strdup ((const unsigned char *)string, &global_hooks); + if (replacement->string == NULL) { - return false; + return false; } - replacement->type &= ~cJSON_StringIsConst; + replacement->type &= ~cJSON_StringIsConst; - return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + return cJSON_ReplaceItemViaPointer ( + object, get_object_item (object, string, case_sensitive), replacement); } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +CJSON_PUBLIC (cJSON_bool) +cJSON_ReplaceItemInObject (cJSON *object, const char *string, cJSON *newitem) { - return replace_item_in_object(object, string, newitem, false); + return replace_item_in_object (object, string, newitem, false); } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +CJSON_PUBLIC (cJSON_bool) +cJSON_ReplaceItemInObjectCaseSensitive (cJSON *object, const char *string, + cJSON *newitem) { - return replace_item_in_object(object, string, newitem, true); + return replace_item_in_object (object, string, newitem, true); } /* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +CJSON_PUBLIC (cJSON *) cJSON_CreateNull (void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_NULL; + item->type = cJSON_NULL; } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +CJSON_PUBLIC (cJSON *) cJSON_CreateTrue (void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_True; + item->type = cJSON_True; } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +CJSON_PUBLIC (cJSON *) cJSON_CreateFalse (void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_False; + item->type = cJSON_False; } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) +CJSON_PUBLIC (cJSON *) cJSON_CreateBool (cJSON_bool boolean) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = boolean ? cJSON_True : cJSON_False; + item->type = boolean ? cJSON_True : cJSON_False; } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +CJSON_PUBLIC (cJSON *) cJSON_CreateNumber (double num) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_Number; - item->valuedouble = num; + item->type = cJSON_Number; + item->valuedouble = num; - /* use saturation in case of overflow */ - if (num >= INT_MAX) + /* use saturation in case of overflow */ + if (num >= INT_MAX) { - item->valueint = INT_MAX; + item->valueint = INT_MAX; } - else if (num <= (double)INT_MIN) + else if (num <= (double)INT_MIN) { - item->valueint = INT_MIN; + item->valueint = INT_MIN; } - else + else { - item->valueint = (int)num; + item->valueint = (int)num; } } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +CJSON_PUBLIC (cJSON *) cJSON_CreateString (const char *string) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) + item->type = cJSON_String; + item->valuestring = (char *)cJSON_strdup ((const unsigned char *)string, + &global_hooks); + if (!item->valuestring) { - cJSON_Delete(item); - return NULL; + cJSON_Delete (item); + return NULL; } } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +CJSON_PUBLIC (cJSON *) cJSON_CreateStringReference (const char *string) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item != NULL) { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char *)cast_away_const (string); } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +CJSON_PUBLIC (cJSON *) cJSON_CreateObjectReference (const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); + cJSON *item = cJSON_New_Item (&global_hooks); + if (item != NULL) + { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON *)cast_away_const (child); } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); +CJSON_PUBLIC (cJSON *) cJSON_CreateArrayReference (const cJSON *child) +{ + cJSON *item = cJSON_New_Item (&global_hooks); + if (item != NULL) + { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON *)cast_away_const (child); } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +CJSON_PUBLIC (cJSON *) cJSON_CreateRaw (const char *raw) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) + item->type = cJSON_Raw; + item->valuestring + = (char *)cJSON_strdup ((const unsigned char *)raw, &global_hooks); + if (!item->valuestring) { - cJSON_Delete(item); - return NULL; + cJSON_Delete (item); + return NULL; } } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +CJSON_PUBLIC (cJSON *) cJSON_CreateArray (void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type=cJSON_Array; + item->type = cJSON_Array; } - return item; + return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +CJSON_PUBLIC (cJSON *) cJSON_CreateObject (void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) + cJSON *item = cJSON_New_Item (&global_hooks); + if (item) { - item->type = cJSON_Object; + item->type = cJSON_Object; } - return item; + return item; } /* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +CJSON_PUBLIC (cJSON *) cJSON_CreateIntArray (const int *numbers, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) + if ((count < 0) || (numbers == NULL)) { - return NULL; + return NULL; } - a = cJSON_CreateArray(); + a = cJSON_CreateArray (); - for(i = 0; a && (i < (size_t)count); i++) + for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber(numbers[i]); - if (!n) + n = cJSON_CreateNumber (numbers[i]); + if (!n) { - cJSON_Delete(a); - return NULL; + cJSON_Delete (a); + return NULL; } - if(!i) + if (!i) { - a->child = n; + a->child = n; } - else + else { - suffix_object(p, n); + suffix_object (p, n); } - p = n; + p = n; } - if (a && a->child) { - a->child->prev = n; + if (a && a->child) + { + a->child->prev = n; } - return a; + return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +CJSON_PUBLIC (cJSON *) cJSON_CreateFloatArray (const float *numbers, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) + if ((count < 0) || (numbers == NULL)) { - return NULL; + return NULL; } - a = cJSON_CreateArray(); + a = cJSON_CreateArray (); - for(i = 0; a && (i < (size_t)count); i++) + for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) + n = cJSON_CreateNumber ((double)numbers[i]); + if (!n) { - cJSON_Delete(a); - return NULL; + cJSON_Delete (a); + return NULL; } - if(!i) + if (!i) { - a->child = n; + a->child = n; } - else + else { - suffix_object(p, n); + suffix_object (p, n); } - p = n; + p = n; } - if (a && a->child) { - a->child->prev = n; + if (a && a->child) + { + a->child->prev = n; } - return a; + return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +CJSON_PUBLIC (cJSON *) +cJSON_CreateDoubleArray (const double *numbers, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) + if ((count < 0) || (numbers == NULL)) { - return NULL; + return NULL; } - a = cJSON_CreateArray(); + a = cJSON_CreateArray (); - for(i = 0; a && (i < (size_t)count); i++) + for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber(numbers[i]); - if(!n) + n = cJSON_CreateNumber (numbers[i]); + if (!n) { - cJSON_Delete(a); - return NULL; + cJSON_Delete (a); + return NULL; } - if(!i) + if (!i) { - a->child = n; + a->child = n; } - else + else { - suffix_object(p, n); + suffix_object (p, n); } - p = n; + p = n; } - if (a && a->child) { - a->child->prev = n; + if (a && a->child) + { + a->child->prev = n; } - return a; + return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +CJSON_PUBLIC (cJSON *) +cJSON_CreateStringArray (const char *const *strings, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (strings == NULL)) + if ((count < 0) || (strings == NULL)) { - return NULL; + return NULL; } - a = cJSON_CreateArray(); + a = cJSON_CreateArray (); - for (i = 0; a && (i < (size_t)count); i++) + for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateString(strings[i]); - if(!n) + n = cJSON_CreateString (strings[i]); + if (!n) { - cJSON_Delete(a); - return NULL; + cJSON_Delete (a); + return NULL; } - if(!i) + if (!i) { - a->child = n; + a->child = n; } - else + else { - suffix_object(p,n); + suffix_object (p, n); } - p = n; + p = n; } - if (a && a->child) { - a->child->prev = n; + if (a && a->child) + { + a->child->prev = n; } - return a; + return a; } /* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +CJSON_PUBLIC (cJSON *) cJSON_Duplicate (const cJSON *item, cJSON_bool recurse) { - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; - /* Bail on bad ptr */ - if (!item) + /* Bail on bad ptr */ + if (!item) { - goto fail; + goto fail; } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) + /* Create new item */ + newitem = cJSON_New_Item (&global_hooks); + if (!newitem) { - goto fail; + goto fail; } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) + newitem->valuestring = (char *)cJSON_strdup ( + (unsigned char *)item->valuestring, &global_hooks); + if (!newitem->valuestring) { - goto fail; + goto fail; } } - if (item->string) + if (item->string) { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) + newitem->string + = (item->type & cJSON_StringIsConst) + ? item->string + : (char *)cJSON_strdup ((unsigned char *)item->string, + &global_hooks); + if (!newitem->string) { - goto fail; + goto fail; } } - /* If non-recursive, then we're done! */ - if (!recurse) + /* If non-recursive, then we're done! */ + if (!recurse) { - return newitem; + return newitem; } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) { - newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) + newchild = cJSON_Duplicate ( + child, + true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) { - goto fail; + goto fail; } - if (next != NULL) + if (next != NULL) { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; + /* If newitem->child already set, then crosswire ->prev and ->next + * and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; } - else + else { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; } - child = child->next; + child = child->next; } - if (newitem && newitem->child) + if (newitem && newitem->child) { - newitem->child->prev = newchild; + newitem->child->prev = newchild; } - return newitem; + return newitem; fail: - if (newitem != NULL) + if (newitem != NULL) { - cJSON_Delete(newitem); + cJSON_Delete (newitem); } - return NULL; + return NULL; } -static void skip_oneline_comment(char **input) +static void +skip_oneline_comment (char **input) { - *input += static_strlen("//"); + *input += static_strlen ("//"); - for (; (*input)[0] != '\0'; ++(*input)) + for (; (*input)[0] != '\0'; ++(*input)) { - if ((*input)[0] == '\n') { - *input += static_strlen("\n"); - return; + if ((*input)[0] == '\n') + { + *input += static_strlen ("\n"); + return; } } } -static void skip_multiline_comment(char **input) +static void +skip_multiline_comment (char **input) { - *input += static_strlen("/*"); + *input += static_strlen ("/*"); - for (; (*input)[0] != '\0'; ++(*input)) + for (; (*input)[0] != '\0'; ++(*input)) { - if (((*input)[0] == '*') && ((*input)[1] == '/')) + if (((*input)[0] == '*') && ((*input)[1] == '/')) { - *input += static_strlen("*/"); - return; + *input += static_strlen ("*/"); + return; } } } -static void minify_string(char **input, char **output) { - (*output)[0] = (*input)[0]; - *input += static_strlen("\""); - *output += static_strlen("\""); - +static void +minify_string (char **input, char **output) +{ + (*output)[0] = (*input)[0]; + *input += static_strlen ("\""); + *output += static_strlen ("\""); - for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { - (*output)[0] = (*input)[0]; + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) + { + (*output)[0] = (*input)[0]; - if ((*input)[0] == '\"') { - (*output)[0] = '\"'; - *input += static_strlen("\""); - *output += static_strlen("\""); - return; - } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { - (*output)[1] = (*input)[1]; - *input += static_strlen("\""); - *output += static_strlen("\""); + if ((*input)[0] == '\"') + { + (*output)[0] = '\"'; + *input += static_strlen ("\""); + *output += static_strlen ("\""); + return; + } + else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) + { + (*output)[1] = (*input)[1]; + *input += static_strlen ("\""); + *output += static_strlen ("\""); } } } -CJSON_PUBLIC(void) cJSON_Minify(char *json) +CJSON_PUBLIC (void) cJSON_Minify (char *json) { - char *into = json; + char *into = json; - if (json == NULL) + if (json == NULL) { - return; + return; } - while (json[0] != '\0') + while (json[0] != '\0') { - switch (json[0]) + switch (json[0]) { - case ' ': - case '\t': - case '\r': - case '\n': - json++; - break; + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; - case '/': - if (json[1] == '/') - { - skip_oneline_comment(&json); - } - else if (json[1] == '*') - { - skip_multiline_comment(&json); - } else { - json++; - } - break; + case '/': + if (json[1] == '/') + { + skip_oneline_comment (&json); + } + else if (json[1] == '*') + { + skip_multiline_comment (&json); + } + else + { + json++; + } + break; - case '\"': - minify_string(&json, (char**)&into); - break; + case '\"': + minify_string (&json, (char **)&into); + break; - default: - into[0] = json[0]; - json++; - into++; + default: + into[0] = json[0]; + json++; + into++; } } - /* and null-terminate. */ - *into = '\0'; + /* and null-terminate. */ + *into = '\0'; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsInvalid (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_Invalid; + return (item->type & 0xFF) == cJSON_Invalid; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsFalse (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_False; + return (item->type & 0xFF) == cJSON_False; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsTrue (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xff) == cJSON_True; + return (item->type & 0xff) == cJSON_True; } - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsBool (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & (cJSON_True | cJSON_False)) != 0; + return (item->type & (cJSON_True | cJSON_False)) != 0; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsNull (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_NULL; + return (item->type & 0xFF) == cJSON_NULL; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsNumber (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_Number; + return (item->type & 0xFF) == cJSON_Number; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsString (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_String; + return (item->type & 0xFF) == cJSON_String; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsArray (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_Array; + return (item->type & 0xFF) == cJSON_Array; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsObject (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_Object; + return (item->type & 0xFF) == cJSON_Object; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +CJSON_PUBLIC (cJSON_bool) cJSON_IsRaw (const cJSON *const item) { - if (item == NULL) + if (item == NULL) { - return false; + return false; } - return (item->type & 0xFF) == cJSON_Raw; + return (item->type & 0xFF) == cJSON_Raw; } -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +CJSON_PUBLIC (cJSON_bool) +cJSON_Compare (const cJSON *const a, const cJSON *const b, + const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { - return false; + return false; } - /* check if type is valid */ - switch (a->type & 0xFF) + /* check if type is valid */ + switch (a->type & 0xFF) { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; - default: - return false; + default: + return false; } - /* identical objects are equal */ - if (a == b) + /* identical objects are equal */ + if (a == b) { - return true; + return true; } - switch (a->type & 0xFF) + switch (a->type & 0xFF) { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; - case cJSON_Number: - if (compare_double(a->valuedouble, b->valuedouble)) - { - return true; - } - return false; + case cJSON_Number: + if (compare_double (a->valuedouble, b->valuedouble)) + { + return true; + } + return false; - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp (a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare (a_element, b_element, case_sensitive)) + { return false; - } - if (strcmp(a->valuestring, b->valuestring) == 0) - { - return true; - } + } + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) + { return false; + } - case cJSON_Array: - { - cJSON *a_element = a->child; - cJSON *b_element = b->child; + return true; + } - for (; (a_element != NULL) && (b_element != NULL);) + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach (a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item (b, a_element->string, case_sensitive); + if (b_element == NULL) { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; + return false; } - /* one of the arrays is longer than the other */ - if (a_element != b_element) { - return false; + if (!cJSON_Compare (a_element, b_element, case_sensitive)) + { + return false; } - - return true; } - case cJSON_Object: + /* doing this twice, once on a and b to prevent true comparison if a + * subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach (b_element, b) { - cJSON *a_element = NULL; - cJSON *b_element = NULL; - cJSON_ArrayForEach(a_element, a) + a_element = get_object_item (a, b_element->string, case_sensitive); + if (a_element == NULL) { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { - return false; - } - - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { - return false; - } + return false; } - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) + if (!cJSON_Compare (b_element, a_element, case_sensitive)) { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { - return false; - } + return false; } - - return true; } - default: - return false; + return true; + } + + default: + return false; } } -CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +CJSON_PUBLIC (void *) cJSON_malloc (size_t size) { - return global_hooks.allocate(size); + return global_hooks.allocate (size); } -CJSON_PUBLIC(void) cJSON_free(void *object) +CJSON_PUBLIC (void) cJSON_free (void *object) { - global_hooks.deallocate(object); + global_hooks.deallocate (object); } diff --git a/tests/cJSON.h b/tests/cJSON.h index 95a9cf6..ca0e52e 100644 --- a/tests/cJSON.h +++ b/tests/cJSON.h @@ -28,51 +28,61 @@ extern "C" { #endif -#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#if !defined(__WINDOWS__) \ + && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) \ + || defined(_WIN32)) #define __WINDOWS__ #endif #ifdef __WINDOWS__ -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + /* When compiling for windows, we specify a specific calling convention to + avoid issues where we are being called from a project with a different + default calling convention. For windows you have 3 define options: -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever + dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when + you want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if + you want to dllimport symbol -For *nix builds that support visibility attribute, you can define similar behavior by + For *nix builds that support visibility attribute, you can define similar + behavior by -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS + setting default visibility to hidden by adding + -fvisibility=hidden (for gcc) + or + -xldscope=hidden (for sun cc) + to CFLAGS -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way + CJSON_EXPORT_SYMBOLS does -*/ + */ #define CJSON_CDECL __cdecl #define CJSON_STDCALL __stdcall -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +/* export symbols by default, this is necessary for copy pasting the C and + * header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \ + && !defined(CJSON_EXPORT_SYMBOLS) #define CJSON_EXPORT_SYMBOLS #endif #if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL +#define CJSON_PUBLIC(type) type CJSON_STDCALL #elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#define CJSON_PUBLIC(type) __declspec (dllexport) type CJSON_STDCALL #elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#define CJSON_PUBLIC(type) __declspec (dllimport) type CJSON_STDCALL #endif #else /* !__WINDOWS__ */ #define CJSON_CDECL #define CJSON_STDCALL -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) \ + && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__ ((visibility ("default"))) type #else #define CJSON_PUBLIC(type) type #endif @@ -87,25 +97,27 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ /* cJSON Types: */ #define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) #define cJSON_Number (1 << 3) #define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) +#define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ +#define cJSON_Raw (1 << 7) /* raw json */ #define cJSON_IsReference 256 #define cJSON_StringIsConst 512 -/* The cJSON structure: */ -typedef struct cJSON -{ - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + /* The cJSON structure: */ + typedef struct cJSON + { + /* next/prev allow you to walk array/object chains. Alternatively, use + * GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + /* An array or object item will have a child pointer pointing to a chain of + * the items in the array/object. */ struct cJSON *child; /* The type of the item, as above. */ @@ -118,180 +130,268 @@ typedef struct cJSON /* The item's number, if type==cJSON_Number */ double valuedouble; - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + /* The item's name string, if this item is the child of, or is in the list + * of subitems of an object. */ char *string; -} cJSON; + } cJSON; -typedef struct cJSON_Hooks -{ - /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ - void *(CJSON_CDECL *malloc_fn)(size_t sz); - void (CJSON_CDECL *free_fn)(void *ptr); -} cJSON_Hooks; + typedef struct cJSON_Hooks + { + /* malloc/free are CDECL on Windows regardless of the default calling + * convention of the compiler, so ensure the hooks allow passing those + * functions directly. */ + void *(CJSON_CDECL *malloc_fn) (size_t sz); + void (CJSON_CDECL *free_fn) (void *ptr); + } cJSON_Hooks; -typedef int cJSON_bool; + typedef int cJSON_bool; -/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse + * them. This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - -/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); - -/* Render a cJSON entity to text for transfer/storage. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. */ -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); - -/* Check item type and return its value */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); -/* raw json */ -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); - -/* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/array that only references it's elements so - * they will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); - -/* These utilities create an Array of count items. - * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detach items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); - -/* Update array items. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will - * need to be released. With recurse!=0, it will duplicate any children connected to the item. - * The item->next and ->prev pointers are always zero on return from Duplicate. */ -/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); - -/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. - * The input pointer json cannot point to a read-only address area, such as a string constant, - * but should point to a readable and writable address area. */ -CJSON_PUBLIC(void) cJSON_Minify(char *json); - -/* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) -/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); - -/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ -#define cJSON_SetBoolValue(object, boolValue) ( \ - (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \ - (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \ - cJSON_Invalid\ -) + /* returns the version of cJSON as a string */ + CJSON_PUBLIC (const char *) cJSON_Version (void); + + /* Supply malloc, realloc and free functions to cJSON */ + CJSON_PUBLIC (void) cJSON_InitHooks (cJSON_Hooks *hooks); + + /* Memory Management: the caller is always responsible to free the results + * from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with + * stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The + * exception is cJSON_PrintPreallocated, where the caller has full + * responsibility of the buffer. */ + /* Supply a block of JSON, and this returns a cJSON object you can + * interrogate. */ + CJSON_PUBLIC (cJSON *) cJSON_Parse (const char *value); + CJSON_PUBLIC (cJSON *) + cJSON_ParseWithLength (const char *value, size_t buffer_length); + /* ParseWithOpts allows you to require (and check) that the JSON is null + * terminated, and to retrieve the pointer to the final byte parsed. */ + /* If you supply a ptr in return_parse_end and parsing fails, then + * return_parse_end will contain a pointer to the error so will match + * cJSON_GetErrorPtr(). */ + CJSON_PUBLIC (cJSON *) + cJSON_ParseWithOpts (const char *value, const char **return_parse_end, + cJSON_bool require_null_terminated); + CJSON_PUBLIC (cJSON *) + cJSON_ParseWithLengthOpts (const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated); + + /* Render a cJSON entity to text for transfer/storage. */ + CJSON_PUBLIC (char *) cJSON_Print (const cJSON *item); + /* Render a cJSON entity to text for transfer/storage without any formatting. + */ + CJSON_PUBLIC (char *) cJSON_PrintUnformatted (const cJSON *item); + /* Render a cJSON entity to text using a buffered strategy. prebuffer is a + * guess at the final size. guessing well reduces reallocation. fmt=0 gives + * unformatted, =1 gives formatted */ + CJSON_PUBLIC (char *) + cJSON_PrintBuffered (const cJSON *item, int prebuffer, cJSON_bool fmt); + /* Render a cJSON entity to text using a buffer already allocated in memory + * with given length. Returns 1 on success and 0 on failure. */ + /* NOTE: cJSON is not always 100% accurate in estimating how much memory it + * will use, so to be safe allocate 5 bytes more than you actually need */ + CJSON_PUBLIC (cJSON_bool) + cJSON_PrintPreallocated (cJSON *item, char *buffer, const int length, + const cJSON_bool format); + /* Delete a cJSON entity and all subentities. */ + CJSON_PUBLIC (void) cJSON_Delete (cJSON *item); + + /* Returns the number of items in an array (or object). */ + CJSON_PUBLIC (int) cJSON_GetArraySize (const cJSON *array); + /* Retrieve item number "index" from array "array". Returns NULL if + * unsuccessful. */ + CJSON_PUBLIC (cJSON *) cJSON_GetArrayItem (const cJSON *array, int index); + /* Get item "string" from object. Case insensitive. */ + CJSON_PUBLIC (cJSON *) + cJSON_GetObjectItem (const cJSON *const object, const char *const string); + CJSON_PUBLIC (cJSON *) + cJSON_GetObjectItemCaseSensitive (const cJSON *const object, + const char *const string); + CJSON_PUBLIC (cJSON_bool) + cJSON_HasObjectItem (const cJSON *object, const char *string); + /* For analysing failed parses. This returns a pointer to the parse error. + * You'll probably need to look a few chars back to make sense of it. Defined + * when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ + CJSON_PUBLIC (const char *) cJSON_GetErrorPtr (void); + + /* Check item type and return its value */ + CJSON_PUBLIC (char *) cJSON_GetStringValue (const cJSON *const item); + CJSON_PUBLIC (double) cJSON_GetNumberValue (const cJSON *const item); + + /* These functions check the type of an item */ + CJSON_PUBLIC (cJSON_bool) cJSON_IsInvalid (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsFalse (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsTrue (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsBool (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsNull (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsNumber (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsString (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsArray (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsObject (const cJSON *const item); + CJSON_PUBLIC (cJSON_bool) cJSON_IsRaw (const cJSON *const item); + + /* These calls create a cJSON item of the appropriate type. */ + CJSON_PUBLIC (cJSON *) cJSON_CreateNull (void); + CJSON_PUBLIC (cJSON *) cJSON_CreateTrue (void); + CJSON_PUBLIC (cJSON *) cJSON_CreateFalse (void); + CJSON_PUBLIC (cJSON *) cJSON_CreateBool (cJSON_bool boolean); + CJSON_PUBLIC (cJSON *) cJSON_CreateNumber (double num); + CJSON_PUBLIC (cJSON *) cJSON_CreateString (const char *string); + /* raw json */ + CJSON_PUBLIC (cJSON *) cJSON_CreateRaw (const char *raw); + CJSON_PUBLIC (cJSON *) cJSON_CreateArray (void); + CJSON_PUBLIC (cJSON *) cJSON_CreateObject (void); + + /* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ + CJSON_PUBLIC (cJSON *) cJSON_CreateStringReference (const char *string); + /* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ + CJSON_PUBLIC (cJSON *) cJSON_CreateObjectReference (const cJSON *child); + CJSON_PUBLIC (cJSON *) cJSON_CreateArrayReference (const cJSON *child); + + /* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the + * number array, otherwise array access will be out of bounds.*/ + CJSON_PUBLIC (cJSON *) cJSON_CreateIntArray (const int *numbers, int count); + CJSON_PUBLIC (cJSON *) + cJSON_CreateFloatArray (const float *numbers, int count); + CJSON_PUBLIC (cJSON *) + cJSON_CreateDoubleArray (const double *numbers, int count); + CJSON_PUBLIC (cJSON *) + cJSON_CreateStringArray (const char *const *strings, int count); + + /* Append item to the specified array/object. */ + CJSON_PUBLIC (cJSON_bool) cJSON_AddItemToArray (cJSON *array, cJSON *item); + CJSON_PUBLIC (cJSON_bool) + cJSON_AddItemToObject (cJSON *object, const char *string, cJSON *item); + /* Use this when string is definitely const (i.e. a literal, or as good as), + * and will definitely survive the cJSON object. WARNING: When this function + * was used, make sure to always check that (item->type & + * cJSON_StringIsConst) is zero before writing to `item->string` */ + CJSON_PUBLIC (cJSON_bool) + cJSON_AddItemToObjectCS (cJSON *object, const char *string, cJSON *item); + /* Append reference to item to the specified array/object. Use this when you + * want to add an existing cJSON to a new cJSON, but don't want to corrupt + * your existing cJSON. */ + CJSON_PUBLIC (cJSON_bool) + cJSON_AddItemReferenceToArray (cJSON *array, cJSON *item); + CJSON_PUBLIC (cJSON_bool) + cJSON_AddItemReferenceToObject (cJSON *object, const char *string, + cJSON *item); + + /* Remove/Detach items from Arrays/Objects. */ + CJSON_PUBLIC (cJSON *) + cJSON_DetachItemViaPointer (cJSON *parent, cJSON *const item); + CJSON_PUBLIC (cJSON *) cJSON_DetachItemFromArray (cJSON *array, int which); + CJSON_PUBLIC (void) cJSON_DeleteItemFromArray (cJSON *array, int which); + CJSON_PUBLIC (cJSON *) + cJSON_DetachItemFromObject (cJSON *object, const char *string); + CJSON_PUBLIC (cJSON *) + cJSON_DetachItemFromObjectCaseSensitive (cJSON *object, const char *string); + CJSON_PUBLIC (void) + cJSON_DeleteItemFromObject (cJSON *object, const char *string); + CJSON_PUBLIC (void) + cJSON_DeleteItemFromObjectCaseSensitive (cJSON *object, const char *string); + + /* Update array items. */ + CJSON_PUBLIC (cJSON_bool) + cJSON_InsertItemInArray ( + cJSON *array, int which, + cJSON *newitem); /* Shifts pre-existing items to the right. */ + CJSON_PUBLIC (cJSON_bool) + cJSON_ReplaceItemViaPointer (cJSON *const parent, cJSON *const item, + cJSON *replacement); + CJSON_PUBLIC (cJSON_bool) + cJSON_ReplaceItemInArray (cJSON *array, int which, cJSON *newitem); + CJSON_PUBLIC (cJSON_bool) + cJSON_ReplaceItemInObject (cJSON *object, const char *string, + cJSON *newitem); + CJSON_PUBLIC (cJSON_bool) + cJSON_ReplaceItemInObjectCaseSensitive (cJSON *object, const char *string, + cJSON *newitem); + + /* Duplicate a cJSON item */ + CJSON_PUBLIC (cJSON *) + cJSON_Duplicate (const cJSON *item, cJSON_bool recurse); + /* Duplicate will create a new, identical cJSON item to the one you pass, in + * new memory that will need to be released. With recurse!=0, it will + * duplicate any children connected to the item. The item->next and ->prev + * pointers are always zero on return from Duplicate. */ + /* Recursively compare two cJSON items for equality. If either a or b is NULL + * or invalid, they will be considered unequal. case_sensitive determines if + * object keys are treated case sensitive (1) or case insensitive (0) */ + CJSON_PUBLIC (cJSON_bool) + cJSON_Compare (const cJSON *const a, const cJSON *const b, + const cJSON_bool case_sensitive); + + /* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') + * from strings. The input pointer json cannot point to a read-only address + * area, such as a string constant, but should point to a readable and + * writable address area. */ + CJSON_PUBLIC (void) cJSON_Minify (char *json); + + /* Helper functions for creating and adding items to an object at the same + * time. They return the added item or NULL on failure. */ + CJSON_PUBLIC (cJSON *) + cJSON_AddNullToObject (cJSON *const object, const char *const name); + CJSON_PUBLIC (cJSON *) + cJSON_AddTrueToObject (cJSON *const object, const char *const name); + CJSON_PUBLIC (cJSON *) + cJSON_AddFalseToObject (cJSON *const object, const char *const name); + CJSON_PUBLIC (cJSON *) + cJSON_AddBoolToObject (cJSON *const object, const char *const name, + const cJSON_bool boolean); + CJSON_PUBLIC (cJSON *) + cJSON_AddNumberToObject (cJSON *const object, const char *const name, + const double number); + CJSON_PUBLIC (cJSON *) + cJSON_AddStringToObject (cJSON *const object, const char *const name, + const char *const string); + CJSON_PUBLIC (cJSON *) + cJSON_AddRawToObject (cJSON *const object, const char *const name, + const char *const raw); + CJSON_PUBLIC (cJSON *) + cJSON_AddObjectToObject (cJSON *const object, const char *const name); + CJSON_PUBLIC (cJSON *) + cJSON_AddArrayToObject (cJSON *const object, const char *const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble + * too. */ +#define cJSON_SetIntValue(object, number) \ + ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) + /* helper for the cJSON_SetNumberValue macro */ + CJSON_PUBLIC (double) cJSON_SetNumberHelper (cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) \ + ((object != NULL) ? cJSON_SetNumberHelper (object, (double)number) \ + : (number)) + /* Change the valuestring of a cJSON_String object, only takes effect when + * type of object is cJSON_String */ + CJSON_PUBLIC (char *) + cJSON_SetValuestring (cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns + * cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) \ + ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \ + ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) \ + | ((boolValue) ? cJSON_True : cJSON_False) \ + : cJSON_Invalid) /* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - -/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ -CJSON_PUBLIC(void *) cJSON_malloc(size_t size); -CJSON_PUBLIC(void) cJSON_free(void *object); +#define cJSON_ArrayForEach(element, array) \ + for (element = (array != NULL) ? (array)->child : NULL; element != NULL; \ + element = element->next) + + /* malloc/free objects using the malloc/free functions that have been set + * with cJSON_InitHooks */ + CJSON_PUBLIC (void *) cJSON_malloc (size_t size); + CJSON_PUBLIC (void) cJSON_free (void *object); #ifdef __cplusplus } diff --git a/tests/test_fa_get_all_results.c b/tests/test_fa_get_all_results.c index deaf2dd..1fe0c32 100644 --- a/tests/test_fa_get_all_results.c +++ b/tests/test_fa_get_all_results.c @@ -4,108 +4,120 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - int32_t *ref_qwfi, *ref_qwfq; - double *fft_out; - size_t results_size; - char **rkeys; - double *rvalues; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - tone_type ttype; - int qres; - unsigned long long npts, navg, nfft, tmp_win, num_tones; - double *freq, fs; - GnWindow win; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&ttype), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "navg", (void*)(&navg), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "nfft", (void*)(&nfft), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "fs", (void*)(&fs), DOUBLE); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "num_tones", (void*)(&num_tones), UINT64); - if (err_code != 0) - return err_code; + int err_code; + int32_t *ref_qwfi, *ref_qwfq; + double *fft_out; + size_t results_size; + char **rkeys; + double *rvalues; - freq = (double*)calloc(num_tones, sizeof(double)); - if (num_tones > 1) - err_code = read_array_from_json_file(test_filename, "freq", freq, DOUBLE, num_tones); - else - err_code = read_scalar_from_json_file(test_filename, "freq", (void*)(freq), DOUBLE); - if (err_code != 0) - return err_code; + // read parameters + tone_type ttype; + int qres; + unsigned long long npts, navg, nfft, tmp_win, num_tones; + double *freq, fs; + GnWindow win; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&ttype), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "navg", + (void *)(&navg), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "nfft", + (void *)(&nfft), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fs", (void *)(&fs), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "num_tones", + (void *)(&num_tones), UINT64); + if (err_code != 0) + return err_code; + freq = (double *)calloc (num_tones, sizeof (double)); + if (num_tones > 1) + err_code = read_array_from_json_file (test_filename, "freq", freq, DOUBLE, + num_tones); + else + err_code = read_scalar_from_json_file (test_filename, "freq", + (void *)(freq), DOUBLE); + if (err_code != 0) + return err_code; - err_code = read_scalar_from_json_file(test_filename, "win", (void*)(&tmp_win), UINT64); - if (err_code != 0) - return err_code; + err_code = read_scalar_from_json_file (test_filename, "win", + (void *)(&tmp_win), UINT64); + if (err_code != 0) + return err_code; - if (tmp_win==1) - win = GnWindowBlackmanHarris; - else if (tmp_win==2) - win = GnWindowHann; - else if (tmp_win==3) - win = GnWindowNoWindow; + if (tmp_win == 1) + win = GnWindowBlackmanHarris; + else if (tmp_win == 2) + win = GnWindowHann; + else if (tmp_win == 3) + win = GnWindowNoWindow; - // read reference waveforms - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_qwfi, INT32, npts); - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_qwfq, INT32, npts); + // read reference waveforms + ref_qwfi = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_qwfi, + INT32, npts); + ref_qwfq = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_qwfq, + INT32, npts); - // configuration - gn_config c = NULL; - err_code = gn_config_fftz(npts, qres, navg, nfft, win, &c); - if (err_code != 0) - return err_code; + // configuration + gn_config c = NULL; + err_code = gn_config_fftz (npts, qres, navg, nfft, win, &c); + if (err_code != 0) + return err_code; - // FFT of waveform - err_code = gn_fftz(&fft_out, ref_qwfi, ref_qwfq, &c); - if (err_code != 0) - return err_code; + // FFT of waveform + err_code = gn_fftz (&fft_out, ref_qwfi, ref_qwfq, &c); + if (err_code != 0) + return err_code; - // Configure Fourier analysis - err_code = gn_config_set_sample_rate(fs, &c); - if (err_code != 0) - return err_code; - err_code = gn_config_fa(freq[0], &c); - if (err_code != 0) - return err_code; + // Configure Fourier analysis + err_code = gn_config_set_sample_rate (fs, &c); + if (err_code != 0) + return err_code; + err_code = gn_config_fa (freq[0], &c); + if (err_code != 0) + return err_code; - err_code = gn_get_fa_results(&rkeys, &rvalues, &results_size, fft_out, &c); - if (err_code != 0) - return err_code; - - printf("\nAll Fourier Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - // free memory - free(ref_qwfi); - free(ref_qwfq); - free(fft_out); - free(rvalues); - for (size_t i = 0; i < results_size; ++i) - free(rkeys[i]); - free(rkeys); - gn_config_free(&c); - - return 0; + err_code = gn_get_fa_results (&rkeys, &rvalues, &results_size, fft_out, &c); + if (err_code != 0) + return err_code; + + printf ("\nAll Fourier Analysis Results:\n"); + for (size_t i = 0; i < results_size; i++) + printf ("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + + // free memory + free (ref_qwfi); + free (ref_qwfq); + free (fft_out); + free (rvalues); + for (size_t i = 0; i < results_size; ++i) + free (rkeys[i]); + free (rkeys); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_fa_get_single_result.c b/tests/test_fa_get_single_result.c index 58f48a8..c5203ab 100644 --- a/tests/test_fa_get_single_result.c +++ b/tests/test_fa_get_single_result.c @@ -4,101 +4,114 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - int32_t *ref_qwfi, *ref_qwfq; - double *fft_out; - double sfdr; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - tone_type ttype; - int qres; - unsigned long long npts, fft_navg, nfft, tmp_win, num_tones; - double *freq, fs; - GnWindow win; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&ttype), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "navg", (void*)(&fft_navg), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "nfft", (void*)(&nfft), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "fs", (void*)(&fs), DOUBLE); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "num_tones", (void*)(&num_tones), UINT64); - if (err_code != 0) - return err_code; - freq = (double*)calloc(num_tones, sizeof(double)); - if (num_tones > 1) - err_code = read_array_from_json_file(test_filename, "freq", freq, DOUBLE, num_tones); - else - err_code = read_scalar_from_json_file(test_filename, "freq", (void*)(freq), DOUBLE); - if (err_code != 0) - return err_code; + int err_code; + int32_t *ref_qwfi, *ref_qwfq; + double *fft_out; + double sfdr; - err_code = read_scalar_from_json_file(test_filename, "win", (void*)(&tmp_win), UINT64); - if (err_code != 0) - return err_code; + // read parameters + tone_type ttype; + int qres; + unsigned long long npts, fft_navg, nfft, tmp_win, num_tones; + double *freq, fs; + GnWindow win; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&ttype), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "navg", + (void *)(&fft_navg), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "nfft", + (void *)(&nfft), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fs", (void *)(&fs), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "num_tones", + (void *)(&num_tones), UINT64); + if (err_code != 0) + return err_code; + freq = (double *)calloc (num_tones, sizeof (double)); + if (num_tones > 1) + err_code = read_array_from_json_file (test_filename, "freq", freq, DOUBLE, + num_tones); + else + err_code = read_scalar_from_json_file (test_filename, "freq", + (void *)(freq), DOUBLE); + if (err_code != 0) + return err_code; - if (tmp_win==1) - win = GnWindowBlackmanHarris; - else if (tmp_win==2) - win = GnWindowHann; - else if (tmp_win==3) - win = GnWindowNoWindow; + err_code = read_scalar_from_json_file (test_filename, "win", + (void *)(&tmp_win), UINT64); + if (err_code != 0) + return err_code; - // read reference waveforms - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_qwfi, INT32, npts); - if (err_code != 0) - return err_code; - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_qwfq, INT32, npts); - if (err_code != 0) - return err_code; + if (tmp_win == 1) + win = GnWindowBlackmanHarris; + else if (tmp_win == 2) + win = GnWindowHann; + else if (tmp_win == 3) + win = GnWindowNoWindow; - // configuration - gn_config c = NULL; - err_code = gn_config_fftz(npts, qres, fft_navg, nfft, win, &c); - if (err_code != 0) - return err_code; + // read reference waveforms + ref_qwfi = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_qwfi, + INT32, npts); + if (err_code != 0) + return err_code; + ref_qwfq = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_qwfq, + INT32, npts); + if (err_code != 0) + return err_code; - // FFT of waveform - err_code = gn_fftz(&fft_out, ref_qwfi, ref_qwfq, &c); - if (err_code != 0) - return err_code; + // configuration + gn_config c = NULL; + err_code = gn_config_fftz (npts, qres, fft_navg, nfft, win, &c); + if (err_code != 0) + return err_code; - // Configure Fourier analysis - err_code = gn_config_set_sample_rate(fs, &c); - if (err_code != 0) - return err_code; - err_code = gn_config_fa(freq[0], &c); - if (err_code != 0) - return err_code; - err_code = gn_get_fa_single_result(&sfdr, "sfdr", fft_out, &c); - if (err_code != 0) - return err_code; - - printf("SFDR - %20.6f\n", sfdr); - - // free memory - free(ref_qwfi); - free(ref_qwfq); - free(fft_out); - gn_config_free(&c); - - return 0; + // FFT of waveform + err_code = gn_fftz (&fft_out, ref_qwfi, ref_qwfq, &c); + if (err_code != 0) + return err_code; + + // Configure Fourier analysis + err_code = gn_config_set_sample_rate (fs, &c); + if (err_code != 0) + return err_code; + err_code = gn_config_fa (freq[0], &c); + if (err_code != 0) + return err_code; + err_code = gn_get_fa_single_result (&sfdr, "sfdr", fft_out, &c); + if (err_code != 0) + return err_code; + + printf ("SFDR - %20.6f\n", sfdr); + + // free memory + free (ref_qwfi); + free (ref_qwfq); + free (fft_out); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_fft.c b/tests/test_fft.c index dff8913..e29f203 100644 --- a/tests/test_fft.c +++ b/tests/test_fft.c @@ -4,81 +4,91 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - int32_t *ref_qwfi, *ref_qwfq; - double *fft_out, *ref_fft_out; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - tone_type ttype; - int qres; - unsigned long long npts, fft_navg, nfft, tmp_win; - GnWindow win; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&ttype), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "navg", (void*)(&fft_navg), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "nfft", (void*)(&nfft), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "win", (void*)(&tmp_win), UINT64); - if (err_code != 0) - return err_code; - if (tmp_win==1) - win = GnWindowBlackmanHarris; - else if (tmp_win==2) - win = GnWindowHann; - else if (tmp_win==3) - win = GnWindowNoWindow; + int err_code; + int32_t *ref_qwfi, *ref_qwfq; + double *fft_out, *ref_fft_out; - // configuration - gn_config c = NULL; - err_code = gn_config_fftz(npts, qres, fft_navg, nfft, win, &c); - if (err_code != 0) - return err_code; + // read parameters + tone_type ttype; + int qres; + unsigned long long npts, fft_navg, nfft, tmp_win; + GnWindow win; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&ttype), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "navg", + (void *)(&fft_navg), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "nfft", + (void *)(&nfft), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "win", + (void *)(&tmp_win), UINT64); + if (err_code != 0) + return err_code; + if (tmp_win == 1) + win = GnWindowBlackmanHarris; + else if (tmp_win == 2) + win = GnWindowHann; + else if (tmp_win == 3) + win = GnWindowNoWindow; - // read reference waveforms - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq_i", ref_qwfi, INT32, npts); - if (err_code != 0) - return err_code; - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq_q", ref_qwfq, INT32, npts); - if (err_code != 0) - return err_code; + // configuration + gn_config c = NULL; + err_code = gn_config_fftz (npts, qres, fft_navg, nfft, win, &c); + if (err_code != 0) + return err_code; - // FFT of waveform - err_code = gn_fftz(&fft_out, ref_qwfi, ref_qwfq, &c); - if (err_code != 0) - return err_code; + // read reference waveforms + ref_qwfi = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq_i", ref_qwfi, + INT32, npts); + if (err_code != 0) + return err_code; + ref_qwfq = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq_q", ref_qwfq, + INT32, npts); + if (err_code != 0) + return err_code; - // read reference FFT - ref_fft_out = (double*)malloc(2*nfft*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "fft_test_vec", ref_fft_out, DOUBLE, 2*nfft); - if (err_code != 0) - return err_code; + // FFT of waveform + err_code = gn_fftz (&fft_out, ref_qwfi, ref_qwfq, &c); + if (err_code != 0) + return err_code; - // compare - assert(float_arrays_almost_equal(ref_fft_out, fft_out, 2*nfft, 6)); - - // free memory - free(ref_qwfi); - free(ref_qwfq); - free(fft_out); - free(ref_fft_out); - gn_config_free(&c); - - return 0; + // read reference FFT + ref_fft_out = (double *)malloc (2 * nfft * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "fft_test_vec", + ref_fft_out, DOUBLE, 2 * nfft); + if (err_code != 0) + return err_code; + + // compare + assert (float_arrays_almost_equal (ref_fft_out, fft_out, 2 * nfft, 6)); + + // free memory + free (ref_qwfi); + free (ref_qwfq); + free (fft_out); + free (ref_fft_out); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_gen_complex_tone.c b/tests/test_gen_complex_tone.c index 8fb3b3c..8bfd781 100644 --- a/tests/test_gen_complex_tone.c +++ b/tests/test_gen_complex_tone.c @@ -4,81 +4,106 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - double *awfi, *awfq, *ref_awfi, *ref_awfq; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - tone_type wf_type; - unsigned long long npts, num_tones; - double fs; - double *freq, *scale, *phase; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&wf_type), UINT64); - if (err_code != 0) - return err_code; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0) + int err_code; + double *awfi, *awfq, *ref_awfi, *ref_awfq; + + // read parameters + tone_type wf_type; + unsigned long long npts, num_tones; + double fs; + double *freq, *scale, *phase; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&wf_type), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fs", (void *)(&fs), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "num_tones", + (void *)(&num_tones), UINT64); + if (err_code != 0) + return err_code; + + freq = (double *)calloc (num_tones, sizeof (double)); + scale = (double *)calloc (num_tones, sizeof (double)); + phase = (double *)calloc (num_tones, sizeof (double)); + if (num_tones > 1) + { + err_code = read_array_from_json_file (test_filename, "freq", freq, + DOUBLE, num_tones); + if (err_code != 0) return err_code; - err_code = read_scalar_from_json_file(test_filename, "fs", (void*)(&fs), DOUBLE); - if (err_code != 0) + err_code = read_array_from_json_file (test_filename, "scale", scale, + DOUBLE, num_tones); + if (err_code != 0) return err_code; - err_code = read_scalar_from_json_file(test_filename, "num_tones", (void*)(&num_tones), UINT64); - if (err_code != 0) + err_code = read_array_from_json_file (test_filename, "phase", phase, + DOUBLE, num_tones); + if (err_code != 0) return err_code; - - freq = (double*)calloc(num_tones, sizeof(double)); - scale = (double*)calloc(num_tones, sizeof(double)); - phase = (double*)calloc(num_tones, sizeof(double)); - if (num_tones > 1) { - err_code = read_array_from_json_file(test_filename, "freq", freq, DOUBLE, num_tones); - if (err_code != 0)return err_code; - err_code = read_array_from_json_file(test_filename, "scale", scale, DOUBLE, num_tones); - if (err_code != 0)return err_code; - err_code = read_array_from_json_file(test_filename, "phase", phase, DOUBLE, num_tones); - if (err_code != 0)return err_code; } - else { - err_code = read_scalar_from_json_file(test_filename, "freq", (void*)(freq), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "scale", (void*)(scale), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "phase", (void*)(phase), DOUBLE); - if (err_code != 0)return err_code; + else + { + err_code = read_scalar_from_json_file (test_filename, "freq", + (void *)(freq), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "scale", + (void *)(scale), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "phase", + (void *)(phase), DOUBLE); + if (err_code != 0) + return err_code; } - // configuration - gn_config c = NULL; - err_code = gn_config_gen_tone(wf_type, npts, fs, num_tones, freq, scale, phase, &c); - if (err_code != 0)return err_code; + // configuration + gn_config c = NULL; + err_code = gn_config_gen_tone (wf_type, npts, fs, num_tones, freq, scale, + phase, &c); + if (err_code != 0) + return err_code; - // waveform generation - gn_gen_complex_tone(&awfi, &awfq, &c); + // waveform generation + gn_gen_complex_tone (&awfi, &awfq, &c); - // read reference waveform - ref_awfi = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_awfi, DOUBLE, npts); - if (err_code != 0)return err_code; - ref_awfq = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_awfq, DOUBLE, npts); - if (err_code != 0)return err_code; + // read reference waveform + ref_awfi = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_awfi, + DOUBLE, npts); + if (err_code != 0) + return err_code; + ref_awfq = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_awfq, + DOUBLE, npts); + if (err_code != 0) + return err_code; - // compare - assert(float_arrays_almost_equal(ref_awfi, awfi, npts, 6)); - assert(float_arrays_almost_equal(ref_awfq, awfq, npts, 6)); + // compare + assert (float_arrays_almost_equal (ref_awfi, awfi, npts, 6)); + assert (float_arrays_almost_equal (ref_awfq, awfq, npts, 6)); - // free memory - free(awfi); - free(awfq); - free(freq); - free(scale); - free(phase); - free(ref_awfi); - free(ref_awfq); - gn_config_free(&c); + // free memory + free (awfi); + free (awfq); + free (freq); + free (scale); + free (phase); + free (ref_awfi); + free (ref_awfq); + gn_config_free (&c); - return 0; + return 0; } diff --git a/tests/test_gen_real_tone.c b/tests/test_gen_real_tone.c index 3ce711f..da01483 100644 --- a/tests/test_gen_real_tone.c +++ b/tests/test_gen_real_tone.c @@ -4,72 +4,100 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - double *awf, *ref_awf; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - tone_type wf_type; - unsigned long long npts, num_tones; - double fs; - double *freq, *scale, *phase; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&wf_type), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "fs", (void*)(&fs), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "num_tones", (void*)(&num_tones), UINT64); - if (err_code != 0)return err_code; - - freq = (double*)calloc(num_tones, sizeof(double)); - scale = (double*)calloc(num_tones, sizeof(double)); - phase = (double*)calloc(num_tones, sizeof(double)); - if (num_tones > 1) { - err_code = read_array_from_json_file(test_filename, "freq", freq, DOUBLE, num_tones); - if (err_code != 0)return err_code; - err_code = read_array_from_json_file(test_filename, "scale", scale, DOUBLE, num_tones); - if (err_code != 0)return err_code; - err_code = read_array_from_json_file(test_filename, "phase", phase, DOUBLE, num_tones); - if (err_code != 0)return err_code; + int err_code; + double *awf, *ref_awf; + + // read parameters + tone_type wf_type; + unsigned long long npts, num_tones; + double fs; + double *freq, *scale, *phase; + err_code = read_scalar_from_json_file (test_filename, "wf_type", + (void *)(&wf_type), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fs", (void *)(&fs), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "num_tones", + (void *)(&num_tones), UINT64); + if (err_code != 0) + return err_code; + + freq = (double *)calloc (num_tones, sizeof (double)); + scale = (double *)calloc (num_tones, sizeof (double)); + phase = (double *)calloc (num_tones, sizeof (double)); + if (num_tones > 1) + { + err_code = read_array_from_json_file (test_filename, "freq", freq, + DOUBLE, num_tones); + if (err_code != 0) + return err_code; + err_code = read_array_from_json_file (test_filename, "scale", scale, + DOUBLE, num_tones); + if (err_code != 0) + return err_code; + err_code = read_array_from_json_file (test_filename, "phase", phase, + DOUBLE, num_tones); + if (err_code != 0) + return err_code; } - else { - err_code = read_scalar_from_json_file(test_filename, "freq", (void*)(freq), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "scale", (void*)(scale), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "phase", (void*)(phase), DOUBLE); - if (err_code != 0)return err_code; + else + { + err_code = read_scalar_from_json_file (test_filename, "freq", + (void *)(freq), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "scale", + (void *)(scale), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "phase", + (void *)(phase), DOUBLE); + if (err_code != 0) + return err_code; } - // configuration - gn_config c = NULL; - err_code = gn_config_gen_tone(wf_type, npts, fs, num_tones, freq, scale, phase, &c); - if (err_code != 0)return err_code; + // configuration + gn_config c = NULL; + err_code = gn_config_gen_tone (wf_type, npts, fs, num_tones, freq, scale, + phase, &c); + if (err_code != 0) + return err_code; - // waveform generation - err_code = gn_gen_real_tone(&awf, &c); - if (err_code != 0)return err_code; + // waveform generation + err_code = gn_gen_real_tone (&awf, &c); + if (err_code != 0) + return err_code; - // read reference waveform - ref_awf = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec", ref_awf, DOUBLE, npts); - if (err_code != 0)return err_code; + // read reference waveform + ref_awf = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec", ref_awf, + DOUBLE, npts); + if (err_code != 0) + return err_code; - // compare - assert(float_arrays_almost_equal(ref_awf, awf, npts, 6)); + // compare + assert (float_arrays_almost_equal (ref_awf, awf, npts, 6)); - // free memory - free(awf); - free(freq); - free(scale); - free(phase); - free(ref_awf); - gn_config_free(&c); + // free memory + free (awf); + free (freq); + free (scale); + free (phase); + free (ref_awf); + gn_config_free (&c); - return 0; + return 0; } diff --git a/tests/test_genalyzer.h b/tests/test_genalyzer.h index d2afee9..7d066f0 100644 --- a/tests/test_genalyzer.h +++ b/tests/test_genalyzer.h @@ -1,331 +1,384 @@ -/* - * test_genalyzer - Header file for running genalyzer tests - * - * Copyright (C) 2022 Analog Devices, Inc. - * Author: Srikanth Pagadarai - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * */ - - +#include "cJSON.h" #include #include #include +#include #include #include -#include #include -#include "cJSON.h" -typedef enum datatype {INT16, - INT32, - INT64, - UINT32, - UINT64, - DOUBLE} datatype; +typedef enum datatype +{ + INT16, + INT32, + INT64, + UINT32, + UINT64, + DOUBLE +} datatype; -static inline bool floats_almost_equal(double a, double b, size_t num_digits) +static inline bool +floats_almost_equal (double a, double b, size_t num_digits) { - return ((((int)floor(fabs(a - b) * pow(10.0, 1.0*num_digits))) == 0) ? true : false); + return ((((int)floor (fabs (a - b) * pow (10.0, 1.0 * num_digits))) == 0) + ? true + : false); } -bool float_arrays_almost_equal(double* a, double* b, size_t len, size_t num_digits) +bool +float_arrays_almost_equal (double *a, double *b, size_t len, size_t num_digits) { - bool result = true; - for (int n = 0; n < len; n++) - result &= floats_almost_equal(a[n], b[n], num_digits); + bool result = true; + for (int n = 0; n < len; n++) + result &= floats_almost_equal (a[n], b[n], num_digits); - return result; + return result; } -static inline bool int32_arrays_equal(const int* a, const int* b, size_t arr_size, size_t tol) +static inline bool +int32_arrays_equal (const int *a, const int *b, size_t arr_size, size_t tol) { - bool result = true; - for (int n = 0; n < arr_size; n++) - result &= (abs(a[n] - b[n]) <= tol) ? true : false; + bool result = true; + for (int n = 0; n < arr_size; n++) + result &= (abs (a[n] - b[n]) <= tol) ? true : false; - return result; + return result; } -static inline bool int64_arrays_equal(const long int* a, const long int* b, size_t arr_size, size_t tol) +static inline bool +int64_arrays_equal (const long int *a, const long int *b, size_t arr_size, + size_t tol) { - bool result = true; - for (int n = 0; n < arr_size; n++) - result &= (abs(a[n] - b[n]) <= tol) ? true : false; + bool result = true; + for (int n = 0; n < arr_size; n++) + result &= (abs (a[n] - b[n]) <= tol) ? true : false; - return result; + return result; } -bool int_arrays_almost_equal(void* a, void* b, size_t arr_size, size_t tol, datatype arr_type) +bool +int_arrays_almost_equal (void *a, void *b, size_t arr_size, size_t tol, + datatype arr_type) { - if (arr_type == INT32) - return (int32_arrays_equal(a, b, arr_size, tol)); - else if (arr_type == INT64) - return (int64_arrays_equal(a, b, arr_size, tol)); - else - return (false); + if (arr_type == INT32) + return (int32_arrays_equal (a, b, arr_size, tol)); + else if (arr_type == INT64) + return (int64_arrays_equal (a, b, arr_size, tol)); + else + return (false); } -int file_to_buffer(long *size, char **buffer, const char* file_name) +int +file_to_buffer (long *size, char **buffer, const char *file_name) { - FILE *fp; - long f_size; - char *buff; - - fp = fopen(file_name, "rb"); - if(!fp) { - perror(file_name); - exit(1); + FILE *fp; + long f_size; + char *buff; + + fp = fopen (file_name, "rb"); + if (!fp) + { + perror (file_name); + exit (1); } - fseek(fp, 0L, SEEK_END); - f_size = ftell(fp); - rewind(fp); + fseek (fp, 0L, SEEK_END); + f_size = ftell (fp); + rewind (fp); - // allocate memory - buff = calloc(1, f_size+1); - if(!buff) { - fclose(fp); - fputs("failed to allocate memory\n",stderr); - exit(1); + // allocate memory + buff = calloc (1, f_size + 1); + if (!buff) + { + fclose (fp); + fputs ("failed to allocate memory\n", stderr); + exit (1); } - // copy file into the buffer - if(fread(buff, f_size, 1 , fp)!=1) { - fclose(fp); - free(buff); - fputs("failed to read file\n",stderr); - exit(1); + // copy file into the buffer + if (fread (buff, f_size, 1, fp) != 1) + { + fclose (fp); + free (buff); + fputs ("failed to read file\n", stderr); + exit (1); } - *size = f_size; - *buffer = buff; + *size = f_size; + *buffer = buff; - return 0; + return 0; } -int extract_scalar(void *val, const char* file_name, const char* token_name, datatype result_type) +int +extract_scalar (void *val, const char *file_name, const char *token_name, + datatype result_type) { - const cJSON *token = NULL; - int status = 0; - long f_size; - char *buffer; - - file_to_buffer(&f_size, &buffer, file_name); - - cJSON *file_name_json = cJSON_Parse(buffer); - if (file_name_json == NULL) + const cJSON *token = NULL; + int status = 0; + long f_size; + char *buffer; + + file_to_buffer (&f_size, &buffer, file_name); + + cJSON *file_name_json = cJSON_Parse (buffer); + if (file_name_json == NULL) { - const char *error_ptr = cJSON_GetErrorPtr(); - if (error_ptr != NULL) - fprintf(stderr, "Error before: %s\n", error_ptr); - status = 0; - goto end; + const char *error_ptr = cJSON_GetErrorPtr (); + if (error_ptr != NULL) + fprintf (stderr, "Error before: %s\n", error_ptr); + status = 0; + goto end; } - token = cJSON_GetObjectItemCaseSensitive(file_name_json, token_name); - if (result_type == INT16) - *(int16_t*)val = token->valueint; - else if (result_type == INT32) - *(int32_t*)val = token->valueint; - else if (result_type == INT64) - *(int64_t*)val = token->valueint; - else if (result_type == UINT32) - *(uint32_t*)val = token->valueint; - else if (result_type == UINT64) - *(uint64_t*)val = token->valueint; - else if (result_type == DOUBLE) { - *(double*)val = token->valuedouble; + token = cJSON_GetObjectItemCaseSensitive (file_name_json, token_name); + if (result_type == INT16) + *(int16_t *)val = token->valueint; + else if (result_type == INT32) + *(int32_t *)val = token->valueint; + else if (result_type == INT64) + *(int64_t *)val = token->valueint; + else if (result_type == UINT32) + *(uint32_t *)val = token->valueint; + else if (result_type == UINT64) + *(uint64_t *)val = token->valueint; + else if (result_type == DOUBLE) + { + *(double *)val = token->valuedouble; } end: - cJSON_Delete(file_name_json); - return status; + cJSON_Delete (file_name_json); + return status; } -int extract_array(void *val, const char* file_name, const char* token_name, datatype result_type, size_t len) +int +extract_array (void *val, const char *file_name, const char *token_name, + datatype result_type, size_t len) { - const cJSON *token = NULL; - int status = 0; - long f_size; - char *buffer; - - file_to_buffer(&f_size, &buffer, file_name); - - cJSON *file_name_json = cJSON_Parse(buffer); - if (file_name_json == NULL) + const cJSON *token = NULL; + int status = 0; + long f_size; + char *buffer; + + file_to_buffer (&f_size, &buffer, file_name); + + cJSON *file_name_json = cJSON_Parse (buffer); + if (file_name_json == NULL) { - const char *error_ptr = cJSON_GetErrorPtr(); - if (error_ptr != NULL) - fprintf(stderr, "Error before: %s\n", error_ptr); - status = 0; - goto end; + const char *error_ptr = cJSON_GetErrorPtr (); + if (error_ptr != NULL) + fprintf (stderr, "Error before: %s\n", error_ptr); + status = 0; + goto end; } - token = cJSON_GetObjectItemCaseSensitive(file_name_json, token_name); - const cJSON *count = NULL; - size_t i = 0; - if (result_type == INT16) { - int16_t *tmp = (int16_t*)malloc(len*sizeof(int16_t)); - cJSON_ArrayForEach(count, token) { - tmp[i] = count->valueint; - i++; - } - memcpy(val, tmp, len*sizeof(int16_t)); - free(tmp); + token = cJSON_GetObjectItemCaseSensitive (file_name_json, token_name); + const cJSON *count = NULL; + size_t i = 0; + if (result_type == INT16) + { + int16_t *tmp = (int16_t *)malloc (len * sizeof (int16_t)); + cJSON_ArrayForEach (count, token) + { + tmp[i] = count->valueint; + i++; + } + memcpy (val, tmp, len * sizeof (int16_t)); + free (tmp); } - else if (result_type == INT32) { - int32_t *tmp = (int32_t*)malloc(len*sizeof(int32_t)); - cJSON_ArrayForEach(count, token) { - tmp[i] = count->valueint; - i++; - } - memcpy(val, tmp, len*sizeof(int32_t)); - free(tmp); + else if (result_type == INT32) + { + int32_t *tmp = (int32_t *)malloc (len * sizeof (int32_t)); + cJSON_ArrayForEach (count, token) + { + tmp[i] = count->valueint; + i++; + } + memcpy (val, tmp, len * sizeof (int32_t)); + free (tmp); } - else if (result_type == INT64) { - int64_t *tmp = (int64_t*)malloc(len*sizeof(int64_t)); - cJSON_ArrayForEach(count, token) { - tmp[i] = count->valueint; - i++; - } - memcpy(val, tmp, len*sizeof(int64_t)); - free(tmp); + else if (result_type == INT64) + { + int64_t *tmp = (int64_t *)malloc (len * sizeof (int64_t)); + cJSON_ArrayForEach (count, token) + { + tmp[i] = count->valueint; + i++; + } + memcpy (val, tmp, len * sizeof (int64_t)); + free (tmp); } - else if (result_type == UINT32) { - uint32_t *tmp = (uint32_t*)malloc(len*sizeof(uint32_t)); - cJSON_ArrayForEach(count, token) { - tmp[i] = count->valueint; - i++; - } - memcpy(val, tmp, len*sizeof(uint32_t)); - free(tmp); + else if (result_type == UINT32) + { + uint32_t *tmp = (uint32_t *)malloc (len * sizeof (uint32_t)); + cJSON_ArrayForEach (count, token) + { + tmp[i] = count->valueint; + i++; + } + memcpy (val, tmp, len * sizeof (uint32_t)); + free (tmp); } - else if (result_type == UINT64) { - uint64_t *tmp = (uint64_t*)malloc(len*sizeof(uint64_t)); - cJSON_ArrayForEach(count, token) { - tmp[i] = count->valueint; - i++; - } - memcpy(val, tmp, len*sizeof(uint64_t)); - free(tmp); + else if (result_type == UINT64) + { + uint64_t *tmp = (uint64_t *)malloc (len * sizeof (uint64_t)); + cJSON_ArrayForEach (count, token) + { + tmp[i] = count->valueint; + i++; + } + memcpy (val, tmp, len * sizeof (uint64_t)); + free (tmp); + } + else if (result_type == DOUBLE) + { + double *tmp = (double *)malloc (len * sizeof (double)); + cJSON_ArrayForEach (count, token) + { + tmp[i] = count->valuedouble; + i++; + } + memcpy (val, tmp, len * sizeof (double)); + free (tmp); } - else if (result_type == DOUBLE) { - double *tmp = (double*)malloc(len*sizeof(double)); - cJSON_ArrayForEach(count, token) { - tmp[i] = count->valuedouble; - i++; - } - memcpy(val, tmp, len*sizeof(double)); - free(tmp); - } end: - cJSON_Delete(file_name_json); - return status; + cJSON_Delete (file_name_json); + return status; } -void deinterleave(void* input, size_t in_size, void* result_re, void* result_im, datatype result_type) +void +deinterleave (void *input, size_t in_size, void *result_re, void *result_im, + datatype result_type) { - if (result_type == INT32) { - int* i32_input = input; - int* i32_result_re = result_re; - int* i32_result_im = result_im; - - for (int n = 0; n < in_size; n += 2) - i32_result_re[n / 2] = i32_input[n]; - for (int n = 1; n < in_size; n += 2) - i32_result_im[(n - 1) / 2] = i32_input[n]; - } else if (result_type == DOUBLE) { - double* d_input = input; - double* d_result_re = result_re; - double* d_result_im = result_im; - - for (int n = 0; n < in_size; n += 2) - d_result_re[n / 2] = d_input[n]; - for (int n = 1; n < in_size; n += 2) - d_result_im[(n - 1) / 2] = d_input[n]; + if (result_type == INT32) + { + int *i32_input = input; + int *i32_result_re = result_re; + int *i32_result_im = result_im; + + for (int n = 0; n < in_size; n += 2) + i32_result_re[n / 2] = i32_input[n]; + for (int n = 1; n < in_size; n += 2) + i32_result_im[(n - 1) / 2] = i32_input[n]; + } + else if (result_type == DOUBLE) + { + double *d_input = input; + double *d_result_re = result_re; + double *d_result_im = result_im; + + for (int n = 0; n < in_size; n += 2) + d_result_re[n / 2] = d_input[n]; + for (int n = 1; n < in_size; n += 2) + d_result_im[(n - 1) / 2] = d_input[n]; } } -int read_scalar_from_json_file(const char* file_name, const char* param_name, void* result, datatype result_type) +int +read_scalar_from_json_file (const char *file_name, const char *param_name, + void *result, datatype result_type) { - int err_code; - - if (result_type == INT16) { - int16_t i16_result; - err_code = extract_scalar((void*)(&i16_result), file_name, param_name, result_type); - *(int16_t*)result = i16_result; - } else if (result_type == INT32) { - int32_t i32_result; - err_code = extract_scalar((void*)(&i32_result), file_name, param_name, result_type); - *(int32_t*)result = i32_result; - } else if (result_type == INT64) { - int64_t i64_result; - err_code = extract_scalar((void*)(&i64_result), file_name, param_name, result_type); - *(int64_t*)result = i64_result; - } else if (result_type == UINT32) { - uint32_t ui32_result; - err_code = extract_scalar((void*)(&ui32_result), file_name, param_name, result_type); - *(uint32_t*)result = ui32_result; - } else if (result_type == UINT64) { - uint64_t ui64_result; - err_code = extract_scalar((void*)(&ui64_result), file_name, param_name, result_type); - *(uint64_t*)result = ui64_result; - } else if (result_type == DOUBLE) { - double d_result; - err_code = extract_scalar((void*)(&d_result), file_name, param_name, result_type); - *(double*)result = d_result; + int err_code; + + if (result_type == INT16) + { + int16_t i16_result; + err_code = extract_scalar ((void *)(&i16_result), file_name, param_name, + result_type); + *(int16_t *)result = i16_result; } - return err_code; + else if (result_type == INT32) + { + int32_t i32_result; + err_code = extract_scalar ((void *)(&i32_result), file_name, param_name, + result_type); + *(int32_t *)result = i32_result; + } + else if (result_type == INT64) + { + int64_t i64_result; + err_code = extract_scalar ((void *)(&i64_result), file_name, param_name, + result_type); + *(int64_t *)result = i64_result; + } + else if (result_type == UINT32) + { + uint32_t ui32_result; + err_code = extract_scalar ((void *)(&ui32_result), file_name, param_name, + result_type); + *(uint32_t *)result = ui32_result; + } + else if (result_type == UINT64) + { + uint64_t ui64_result; + err_code = extract_scalar ((void *)(&ui64_result), file_name, param_name, + result_type); + *(uint64_t *)result = ui64_result; + } + else if (result_type == DOUBLE) + { + double d_result; + err_code = extract_scalar ((void *)(&d_result), file_name, param_name, + result_type); + *(double *)result = d_result; + } + return err_code; } -int read_array_from_json_file(const char* file_name, const char* param_name, void* result, datatype result_type, size_t len) +int +read_array_from_json_file (const char *file_name, const char *param_name, + void *result, datatype result_type, size_t len) { - int err_code; - - if (result_type == INT16) { - int16_t *i16_result = (int16_t*)malloc(len*sizeof(int16_t)); - err_code = extract_array(i16_result, file_name, param_name, result_type, len); - memcpy (result, i16_result, len*sizeof(int16_t)); - free(i16_result); + int err_code; + + if (result_type == INT16) + { + int16_t *i16_result = (int16_t *)malloc (len * sizeof (int16_t)); + err_code = extract_array (i16_result, file_name, param_name, result_type, + len); + memcpy (result, i16_result, len * sizeof (int16_t)); + free (i16_result); + } + else if (result_type == INT32) + { + int32_t *i32_result = (int32_t *)malloc (len * sizeof (int32_t)); + err_code = extract_array (i32_result, file_name, param_name, result_type, + len); + memcpy (result, i32_result, len * sizeof (int32_t)); + free (i32_result); + } + else if (result_type == INT64) + { + int64_t *i64_result = (int64_t *)malloc (len * sizeof (int64_t)); + err_code = extract_array (i64_result, file_name, param_name, result_type, + len); + memcpy (result, i64_result, len * sizeof (int64_t)); + free (i64_result); + } + else if (result_type == UINT32) + { + uint32_t *ui32_result = (uint32_t *)malloc (len * sizeof (uint32_t)); + err_code = extract_array (ui32_result, file_name, param_name, + result_type, len); + memcpy (result, ui32_result, len * sizeof (uint32_t)); + free (ui32_result); } - else if (result_type == INT32) { - int32_t *i32_result = (int32_t*)malloc(len*sizeof(int32_t)); - err_code = extract_array(i32_result, file_name, param_name, result_type, len); - memcpy (result, i32_result, len*sizeof(int32_t)); - free(i32_result); - } else if (result_type == INT64) { - int64_t *i64_result = (int64_t*)malloc(len*sizeof(int64_t)); - err_code = extract_array(i64_result, file_name, param_name, result_type, len); - memcpy (result, i64_result, len*sizeof(int64_t)); - free(i64_result); - } else if (result_type == UINT32) { - uint32_t *ui32_result = (uint32_t*)malloc(len*sizeof(uint32_t)); - err_code = extract_array(ui32_result, file_name, param_name, result_type, len); - memcpy (result, ui32_result, len*sizeof(uint32_t)); - free(ui32_result); - } else if (result_type == UINT64) { - uint64_t *ui64_result = (uint64_t*)malloc(len*sizeof(uint64_t)); - err_code = extract_array(ui64_result, file_name, param_name, result_type, len); - memcpy (result, ui64_result, len*sizeof(uint64_t)); - free(ui64_result); - } else if (result_type == DOUBLE) { - double *d_result = (double*)malloc(len*sizeof(double)); - err_code = extract_array(d_result, file_name, param_name, result_type, len); - memcpy (result, d_result, len*sizeof(double)); - free(d_result); + else if (result_type == UINT64) + { + uint64_t *ui64_result = (uint64_t *)malloc (len * sizeof (uint64_t)); + err_code = extract_array (ui64_result, file_name, param_name, + result_type, len); + memcpy (result, ui64_result, len * sizeof (uint64_t)); + free (ui64_result); + } + else if (result_type == DOUBLE) + { + double *d_result = (double *)malloc (len * sizeof (double)); + err_code + = extract_array (d_result, file_name, param_name, result_type, len); + memcpy (result, d_result, len * sizeof (double)); + free (d_result); } - return err_code; + return err_code; } \ No newline at end of file diff --git a/tests/test_ha_get_all_results.c b/tests/test_ha_get_all_results.c index 3ea687b..fb3f25d 100644 --- a/tests/test_ha_get_all_results.c +++ b/tests/test_ha_get_all_results.c @@ -4,63 +4,77 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - int32_t *ref_qwf; - uint64_t *hist; - size_t hist_len; - size_t results_size; - char **rkeys; - double *rvalues; - - // read parameters - double fsr, qnoise; - int qres; - unsigned long long npts; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "fsr", (void*)(&fsr), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qnoise", (void*)(&qnoise), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0)return err_code; - - // configuration - gn_config c = NULL; - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - if (err_code != 0)return err_code; - - // read reference output waveform - ref_qwf = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq", ref_qwf, INT32, npts); - if (err_code != 0)return err_code; - - // histogram analysis - err_code = gn_histz(&hist, &hist_len, ref_qwf, &c); - if (err_code != 0)return err_code; - err_code = gn_get_ha_results(&rkeys, &rvalues, &results_size, hist, &c); - if (err_code != 0)return err_code; - - printf("Histogram length: %lu\n", hist_len); - size_t tmp_sum = 0; - for (size_t i = 0; i < hist_len; i++) - tmp_sum += hist[i]; - printf("tmp_sum: %lu\n", tmp_sum); - for (size_t i = 0; i < 20; i++) - printf("%4zu\t%4zu\n", i, hist[i]); - printf("\nAll Histogram Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + // read test waveform filename + const char *test_filename = argv[1]; - // free memory - free(ref_qwf); - free(hist); - gn_config_free(&c); - - return 0; + int err_code; + int32_t *ref_qwf; + uint64_t *hist; + size_t hist_len; + size_t results_size; + char **rkeys; + double *rvalues; + + // read parameters + double fsr, qnoise; + int qres; + unsigned long long npts; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fsr", (void *)(&fsr), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qnoise", + (void *)(&qnoise), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; + + // configuration + gn_config c = NULL; + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + if (err_code != 0) + return err_code; + + // read reference output waveform + ref_qwf = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq", ref_qwf, + INT32, npts); + if (err_code != 0) + return err_code; + + // histogram analysis + err_code = gn_histz (&hist, &hist_len, ref_qwf, &c); + if (err_code != 0) + return err_code; + err_code = gn_get_ha_results (&rkeys, &rvalues, &results_size, hist, &c); + if (err_code != 0) + return err_code; + + printf ("Histogram length: %lu\n", hist_len); + size_t tmp_sum = 0; + for (size_t i = 0; i < hist_len; i++) + tmp_sum += hist[i]; + printf ("tmp_sum: %lu\n", tmp_sum); + for (size_t i = 0; i < 20; i++) + printf ("%4zu\t%4zu\n", i, hist[i]); + printf ("\nAll Histogram Analysis Results:\n"); + for (size_t i = 0; i < results_size; i++) + printf ("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + + // free memory + free (ref_qwf); + free (hist); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_histz.c b/tests/test_histz.c index 3e2c36c..c6a1cf4 100644 --- a/tests/test_histz.c +++ b/tests/test_histz.c @@ -4,55 +4,68 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - int32_t *ref_qwf; - uint64_t *hist; - size_t hist_len; - - // read parameters - double fsr, qnoise; - int qres; - unsigned long long npts; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "fsr", (void*)(&fsr), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qnoise", (void*)(&qnoise), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0)return err_code; - - // configuration - gn_config c = NULL; - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - if (err_code != 0)return err_code; - - // read reference output waveform - ref_qwf = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq", ref_qwf, INT32, npts); - if (err_code != 0)return err_code; - - // Do waveform analysis - err_code = gn_histz(&hist, &hist_len, ref_qwf, &c); - if (err_code != 0)return err_code; - - printf("Histogram length: %lu\n", hist_len); - size_t tmp_sum = 0; - for (size_t i = 0; i < hist_len; i++) - tmp_sum += hist[i]; - printf("tmp_sum: %lu\n", tmp_sum); - for (size_t i = 0; i < 20; i++) - printf("%4zu\t%4zu\n", i, hist[i]); - - // free memory - free(ref_qwf); - free(hist); - gn_config_free(&c); - - return 0; + // read test waveform filename + const char *test_filename = argv[1]; + + int err_code; + int32_t *ref_qwf; + uint64_t *hist; + size_t hist_len; + + // read parameters + double fsr, qnoise; + int qres; + unsigned long long npts; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fsr", (void *)(&fsr), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qnoise", + (void *)(&qnoise), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; + + // configuration + gn_config c = NULL; + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + if (err_code != 0) + return err_code; + + // read reference output waveform + ref_qwf = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq", ref_qwf, + INT32, npts); + if (err_code != 0) + return err_code; + + // Do waveform analysis + err_code = gn_histz (&hist, &hist_len, ref_qwf, &c); + if (err_code != 0) + return err_code; + + printf ("Histogram length: %lu\n", hist_len); + size_t tmp_sum = 0; + for (size_t i = 0; i < hist_len; i++) + tmp_sum += hist[i]; + printf ("tmp_sum: %lu\n", tmp_sum); + for (size_t i = 0; i < 20; i++) + printf ("%4zu\t%4zu\n", i, hist[i]); + + // free memory + free (ref_qwf); + free (hist); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_quantize_complex_tone.c b/tests/test_quantize_complex_tone.c index 15bf22c..4f5e329 100644 --- a/tests/test_quantize_complex_tone.c +++ b/tests/test_quantize_complex_tone.c @@ -4,73 +4,97 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - double *ref_awfi, *ref_awfq; - int32_t *qwfi, *qwfq, *ref_qwfi, *ref_qwfq; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - double fsr, qnoise; - int qres; - unsigned long long npts; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "fsr", (void*)(&fsr), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qnoise", (void*)(&qnoise), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0)return err_code; - - // configuration - gn_config c = NULL; - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - if (err_code != 0)return err_code; + int err_code; + double *ref_awfi, *ref_awfq; + int32_t *qwfi, *qwfq, *ref_qwfi, *ref_qwfq; - // read reference waveforms - ref_awfi = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_awfi, DOUBLE, npts); - if (err_code != 0)return err_code; - ref_awfq = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_awfq, DOUBLE, npts); - if (err_code != 0)return err_code; - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq_i", ref_qwfi, INT32, npts); - if (err_code != 0)return err_code; - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq_q", ref_qwfq, INT32, npts); - if (err_code != 0)return err_code; - - // quantize waveform - err_code = gn_quantize(&qwfi, ref_awfi, &c); - if (err_code != 0)return err_code; - err_code = gn_quantize(&qwfq, ref_awfq, &c); - if (err_code != 0)return err_code; + // read parameters + double fsr, qnoise; + int qres; + unsigned long long npts; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fsr", (void *)(&fsr), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qnoise", + (void *)(&qnoise), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; - // read reference waveform - ref_awfi = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_awfi, DOUBLE, npts); - if (err_code != 0)return err_code; - ref_awfq = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_awfq, DOUBLE, npts); - if (err_code != 0)return err_code; + // configuration + gn_config c = NULL; + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + if (err_code != 0) + return err_code; - // compare - assert(int_arrays_almost_equal(ref_qwfi, qwfi, 0, npts, INT32)); - assert(int_arrays_almost_equal(ref_qwfq, qwfq, 0, npts, INT32)); + // read reference waveforms + ref_awfi = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_awfi, + DOUBLE, npts); + if (err_code != 0) + return err_code; + ref_awfq = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_awfq, + DOUBLE, npts); + if (err_code != 0) + return err_code; + ref_qwfi = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq_i", ref_qwfi, + INT32, npts); + if (err_code != 0) + return err_code; + ref_qwfq = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq_q", ref_qwfq, + INT32, npts); + if (err_code != 0) + return err_code; - // free memory - free(qwfi); - free(qwfq); - free(ref_qwfi); - free(ref_qwfq); - free(ref_awfi); - free(ref_awfq); - gn_config_free(&c); + // quantize waveform + err_code = gn_quantize (&qwfi, ref_awfi, &c); + if (err_code != 0) + return err_code; + err_code = gn_quantize (&qwfq, ref_awfq, &c); + if (err_code != 0) + return err_code; - return 0; + // read reference waveform + ref_awfi = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec_i", ref_awfi, + DOUBLE, npts); + if (err_code != 0) + return err_code; + ref_awfq = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec_q", ref_awfq, + DOUBLE, npts); + if (err_code != 0) + return err_code; + + // compare + assert (int_arrays_almost_equal (ref_qwfi, qwfi, 0, npts, INT32)); + assert (int_arrays_almost_equal (ref_qwfq, qwfq, 0, npts, INT32)); + + // free memory + free (qwfi); + free (qwfq); + free (ref_qwfi); + free (ref_qwfq); + free (ref_awfi); + free (ref_awfq); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_quantize_real_tone.c b/tests/test_quantize_real_tone.c index 06bb2d8..19e0c7e 100644 --- a/tests/test_quantize_real_tone.c +++ b/tests/test_quantize_real_tone.c @@ -4,55 +4,70 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - double *ref_awf; - int32_t *qwf, *ref_qwf; - - // read parameters - double fsr, qnoise; - int qres; - unsigned long long npts; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "fsr", (void*)(&fsr), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qnoise", (void*)(&qnoise), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0)return err_code; - - // configuration - gn_config c = NULL; - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - if (err_code != 0)return err_code; - - // read reference input waveform - ref_awf = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec", ref_awf, DOUBLE, npts); - if (err_code != 0)return err_code; - - // quantize waveform - err_code = gn_quantize(&qwf, ref_awf, &c); - if (err_code != 0)return err_code; - - // read reference output waveform - ref_qwf = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq", ref_qwf, INT32, npts); - if (err_code != 0)return err_code; - - // compare - assert(int_arrays_almost_equal(ref_qwf, qwf, 0, npts, INT32)); - - // free memory - free(qwf); - free(ref_qwf); - free(ref_awf); - gn_config_free(&c); - - return 0; + // read test waveform filename + const char *test_filename = argv[1]; + + int err_code; + double *ref_awf; + int32_t *qwf, *ref_qwf; + + // read parameters + double fsr, qnoise; + int qres; + unsigned long long npts; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fsr", (void *)(&fsr), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qnoise", + (void *)(&qnoise), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; + + // configuration + gn_config c = NULL; + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + if (err_code != 0) + return err_code; + + // read reference input waveform + ref_awf = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec", ref_awf, + DOUBLE, npts); + if (err_code != 0) + return err_code; + + // quantize waveform + err_code = gn_quantize (&qwf, ref_awf, &c); + if (err_code != 0) + return err_code; + + // read reference output waveform + ref_qwf = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq", ref_qwf, + INT32, npts); + if (err_code != 0) + return err_code; + + // compare + assert (int_arrays_almost_equal (ref_qwf, qwf, 0, npts, INT32)); + + // free memory + free (qwf); + free (ref_qwf); + free (ref_awf); + gn_config_free (&c); + + return 0; } diff --git a/tests/test_wfa_get_all_results.c b/tests/test_wfa_get_all_results.c index ddc37a3..5ba8eee 100644 --- a/tests/test_wfa_get_all_results.c +++ b/tests/test_wfa_get_all_results.c @@ -4,63 +4,79 @@ #include #include -int main(int argc, const char* argv[]) +int +main (int argc, const char *argv[]) { - // read test waveform filename - const char* test_filename = argv[1]; - - int err_code; - double *ref_awf; - int32_t *qwf, *ref_qwf; - size_t results_size; - char **rkeys; - double *rvalues; + // read test waveform filename + const char *test_filename = argv[1]; - // read parameters - double fsr, qnoise; - int qres; - unsigned long long npts; - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "fsr", (void*)(&fsr), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qnoise", (void*)(&qnoise), DOUBLE); - if (err_code != 0)return err_code; - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - if (err_code != 0)return err_code; - - // configuration - gn_config c = NULL; - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - if (err_code != 0)return err_code; + int err_code; + double *ref_awf; + int32_t *qwf, *ref_qwf; + size_t results_size; + char **rkeys; + double *rvalues; - // read reference input waveform - ref_awf = (double*)malloc(npts*sizeof(double)); - err_code = read_array_from_json_file(test_filename, "test_vec", ref_awf, DOUBLE, npts); - if (err_code != 0)return err_code; - - // quantize waveform - err_code = gn_quantize(&qwf, ref_awf, &c); - if (err_code != 0)return err_code; - - // read reference output waveform - ref_qwf = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vecq", ref_qwf, INT32, npts); - if (err_code != 0)return err_code; - - // Do waveform analysis - err_code = gn_get_wfa_results(&rkeys, &rvalues, &results_size, ref_qwf, &c); - if (err_code != 0)return err_code; - - printf("\nAll Waveform Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + // read parameters + double fsr, qnoise; + int qres; + unsigned long long npts; + err_code = read_scalar_from_json_file (test_filename, "npts", + (void *)(&npts), UINT64); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "fsr", (void *)(&fsr), + DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qnoise", + (void *)(&qnoise), DOUBLE); + if (err_code != 0) + return err_code; + err_code = read_scalar_from_json_file (test_filename, "qres", + (void *)(&qres), INT32); + if (err_code != 0) + return err_code; - // free memory - free(qwf); - free(ref_qwf); - free(ref_awf); - gn_config_free(&c); - - return 0; + // configuration + gn_config c = NULL; + err_code = gn_config_quantize (npts, fsr, qres, qnoise, &c); + if (err_code != 0) + return err_code; + + // read reference input waveform + ref_awf = (double *)malloc (npts * sizeof (double)); + err_code = read_array_from_json_file (test_filename, "test_vec", ref_awf, + DOUBLE, npts); + if (err_code != 0) + return err_code; + + // quantize waveform + err_code = gn_quantize (&qwf, ref_awf, &c); + if (err_code != 0) + return err_code; + + // read reference output waveform + ref_qwf = (int32_t *)malloc (npts * sizeof (int32_t)); + err_code = read_array_from_json_file (test_filename, "test_vecq", ref_qwf, + INT32, npts); + if (err_code != 0) + return err_code; + + // Do waveform analysis + err_code = gn_get_wfa_results (&rkeys, &rvalues, &results_size, ref_qwf, &c); + if (err_code != 0) + return err_code; + + printf ("\nAll Waveform Analysis Results:\n"); + for (size_t i = 0; i < results_size; i++) + printf ("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); + + // free memory + free (qwf); + free (ref_qwf); + free (ref_awf); + gn_config_free (&c); + + return 0; }