From e3578d801c43d58370cf51a87f723f1e4ffc32d6 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 28 Mar 2014 17:52:51 +0000 Subject: [PATCH] Some tests git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@497 64b25241-fba3-4117-9849-534c7e92360d --- src/tests/CMakeLists.txt | 6 +- src/tests/arithmetic/complex_carrier_test.cc | 98 +++++++++++ src/tests/arithmetic/conjugate_test.cc | 109 ++++++++++++ .../arithmetic/magnitude_squared_test.cc | 114 +++++++++++++ ...ex_arithmetic_libc.cc => multiply_test.cc} | 161 +++++++++++++----- src/tests/test_main.cc | 5 +- 6 files changed, 443 insertions(+), 50 deletions(-) create mode 100644 src/tests/arithmetic/complex_carrier_test.cc create mode 100644 src/tests/arithmetic/conjugate_test.cc create mode 100644 src/tests/arithmetic/magnitude_squared_test.cc rename src/tests/arithmetic/{complex_arithmetic_libc.cc => multiply_test.cc} (57%) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index cfd45ecb7..9da876e0e 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -105,20 +105,21 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/output_filter/adapters - ${CMAKE_SOURCE_DIR}/src/algorithms/pvt/libs + ${CMAKE_SOURCE_DIR}/src/algorithms/PVT/libs ${GLOG_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS} ${GNURADIO_RUNTIME_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS} + ${VOLK_INCLUDE_DIRS} ) if(OS_IS_MACOSX) if(MACOSX_MAVERICKS) - # Tell the linker where the libraries installed by MacPorts are set(MAC_LIBRARIES "-stdlib=libc++ -std=c++11") else(MACOSX_MAVERICKS) + # Tell the linker where the libraries installed by MacPorts are link_directories( /opt/local/lib ) # not very elegant, to be fixed. Needed? endif(MACOSX_MAVERICKS) endif(OS_IS_MACOSX) @@ -142,6 +143,7 @@ target_link_libraries(run_tests ${MAC_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${GNURADIO_ANALOG_LIBRARIES} ${ARMADILLO_LIBRARIES} + ${VOLK_LIBRARIES} gnss_sp_libs gnss_rx signal_generator_blocks diff --git a/src/tests/arithmetic/complex_carrier_test.cc b/src/tests/arithmetic/complex_carrier_test.cc new file mode 100644 index 000000000..37419aada --- /dev/null +++ b/src/tests/arithmetic/complex_carrier_test.cc @@ -0,0 +1,98 @@ +/*! + * \file complex_carrier_test.cc + * \brief This file implements tests for the generation of complex exponentials. + * \author Carles Fernandez-Prades, 2014. cfernandez(at)cttc.es + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR 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 GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + +#include +#include +#include +#include +#include "gnss_signal_processing.h" + +DEFINE_int32(size_carrier_test, 100000, "Size of the arrays used for complex carrier testing"); + + +TEST(ComplexCarrier_Test, StandardComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_carrier_test]; + std::complex* output = new std::complex[FLAGS_size_carrier_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_carrier_test); + double _f = 2000; + double _fs = 2000000; + double phase_step = (double)((GPS_TWO_PI * _f) / _fs); + double phase = 0; + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + for(int i = 0; i < FLAGS_size_carrier_test; i++) + { + output[i] = std::complex(cos(phase), sin(phase)); + phase += phase_step; + } + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "A " << FLAGS_size_carrier_test + << "-length complex carrier generated in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + + delete input; + delete output; +} + + + + +TEST(ComplexCarrier_Test, OwnComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_carrier_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_carrier_test); + std::complex* output = new std::complex[FLAGS_size_carrier_test]; + double _f = 2000; + double _fs = 2000000; + double phase_step = (double)((GPS_TWO_PI * _f) / _fs); + double phase = 0; + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + complex_exp_gen(output, _f, _fs, (unsigned int)FLAGS_size_carrier_test); + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "A " << FLAGS_size_carrier_test + << "-length complex carrier using fixed point generated in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + delete input; + delete output; +} diff --git a/src/tests/arithmetic/conjugate_test.cc b/src/tests/arithmetic/conjugate_test.cc new file mode 100644 index 000000000..b6646a7e0 --- /dev/null +++ b/src/tests/arithmetic/conjugate_test.cc @@ -0,0 +1,109 @@ +/*! + * \file conjugate_test.cc + * \brief This file implements tests for conjugation of long arrays. + * \author Carles Fernandez-Prades, 2012. cfernandez(at)cttc.es + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR 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 GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + +#include +#include +#include +#include + +DEFINE_int32(size_conjugate_test, 100000, "Size of the arrays used for conjugate testing"); + + + +TEST(Conjugate_Test, StandardCComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_conjugate_test]; + std::complex* output = new std::complex[FLAGS_size_conjugate_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_conjugate_test); + + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + for(int i = 0; i < FLAGS_size_conjugate_test; i++) + { + output[i] = std::conj(input[i]); + } + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "Conjugate of a " << FLAGS_size_conjugate_test + << "-length complex float vector finished in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + delete input; + delete output; +} + + + +TEST(Conjugate_Test, ArmadilloComplexImplementation) +{ + arma::cx_fvec input(FLAGS_size_conjugate_test, arma::fill::zeros); + arma::cx_fvec output(FLAGS_size_conjugate_test); + + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + output = arma::conj(input); + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "Conjugate of a " << FLAGS_size_conjugate_test + << "-length complex float Armadillo vector finished in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); +} + + +TEST(Conjugate_Test, VolkComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_conjugate_test]; + std::complex* output = new std::complex[FLAGS_size_conjugate_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_conjugate_test); + + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + volk_32fc_conjugate_32fc(output, input, FLAGS_size_conjugate_test); + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "Conjugate of a "<< FLAGS_size_conjugate_test + << "-length complex float vector using VOLK finished in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + delete input; + delete output; +} diff --git a/src/tests/arithmetic/magnitude_squared_test.cc b/src/tests/arithmetic/magnitude_squared_test.cc new file mode 100644 index 000000000..3168b0915 --- /dev/null +++ b/src/tests/arithmetic/magnitude_squared_test.cc @@ -0,0 +1,114 @@ +/*! + * \file magnitude_squared_test.cc + * \brief This file implements tests for the computation of magnitude squared + * in long arrays. + * \author Carles Fernandez-Prades, 2014. cfernandez(at)cttc.es + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR 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 GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + +#include +#include +#include +#include + +DEFINE_int32(size_magnitude_test, 100000, "Size of the arrays used for magnitude testing"); + + +TEST(MagnitudeSquared_Test, StandardCComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_magnitude_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_magnitude_test); + const float* inputPtr = (float*)input; + float* output = new float[FLAGS_size_magnitude_test]; + unsigned int number = 0; + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + for(number = 0; number < (unsigned int)FLAGS_size_magnitude_test; number++) + { + const float real = *inputPtr++; + const float imag = *inputPtr++; + *output++ = (real*real) + (imag*imag); + } + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "The squared magnitude of a " << FLAGS_size_magnitude_test + << "-length vector computed in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + delete input; + delete output; +} + + + +TEST(MagnitudeSquared_Test, ArmadilloComplexImplementation) +{ + arma::cx_fvec input(FLAGS_size_magnitude_test, arma::fill::zeros); + arma::fvec output(FLAGS_size_magnitude_test); + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + output = arma::abs(arma::square(input)); + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "The squared magnitude of a " << FLAGS_size_magnitude_test + << "-length vector using Armadillo computed in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); +} + + + +TEST(MagnitudeSquared_Test, VolkComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_magnitude_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_magnitude_test); + float* output = new float[FLAGS_size_magnitude_test]; + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + volk_32fc_magnitude_squared_32f(output, input, (unsigned int)FLAGS_size_magnitude_test); + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "The squared magnitude of a " << FLAGS_size_magnitude_test + << "-length vector using VOLK computed in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + delete input; + delete output; +} + +// volk_32f_accumulator_s32f_a(&d_input_power, d_magnitude, d_fft_size); + diff --git a/src/tests/arithmetic/complex_arithmetic_libc.cc b/src/tests/arithmetic/multiply_test.cc similarity index 57% rename from src/tests/arithmetic/complex_arithmetic_libc.cc rename to src/tests/arithmetic/multiply_test.cc index 6a321ef7a..fc8df93e4 100644 --- a/src/tests/arithmetic/complex_arithmetic_libc.cc +++ b/src/tests/arithmetic/multiply_test.cc @@ -1,6 +1,6 @@ /*! - * \file complex_arithmetic_libc.cc - * \brief This file implements a unit test for multiplication of long arrays. + * \file multiply_test.cc + * \brief This file implements tests for the multiplication of long arrays. * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com * Carles Fernandez-Prades, 2012. cfernandez(at)cttc.es * @@ -31,72 +31,45 @@ */ -#include #include #include #include -#include +#include -DEFINE_int32(size_multiply_test, 100000, "Size of the arrays used for calculations"); +DEFINE_int32(size_multiply_test, 100000, "Size of the arrays used for multiply testing"); -TEST(Multiply_Test, StandardCComplexImplementation) -{ - std::complex* input = new std::complex[FLAGS_size_multiply_test]; - std::complex* output = new std::complex[FLAGS_size_multiply_test]; - memset(input, 0, sizeof(std::complex) * FLAGS_size_multiply_test); - struct timeval tv; - gettimeofday(&tv, NULL); - long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; - for(int i = 0; i < FLAGS_size_multiply_test; i++) - { - output[i] = input[i] * input[i]; - } - gettimeofday(&tv, NULL); - long long int end = tv.tv_sec * 1000000 + tv.tv_usec; - std::cout << "Multiplication of "<< FLAGS_size_multiply_test - << " complex finished in " << (end - begin) - << " microseconds" << std::endl; - ASSERT_LE(0, end - begin); -} TEST(Multiply_Test, StandardCDoubleImplementation) { - double input[FLAGS_size_multiply_test]; - double output[FLAGS_size_multiply_test]; + double* input = new double[FLAGS_size_multiply_test]; + double* output = new double[FLAGS_size_multiply_test]; memset(input, 0, sizeof(double) * FLAGS_size_multiply_test); struct timeval tv; gettimeofday(&tv, NULL); long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + for(int i = 0; i < FLAGS_size_multiply_test; i++) { output[i] = input[i] * input[i]; } + gettimeofday(&tv, NULL); long long int end = tv.tv_sec * 1000000 + tv.tv_usec; - std::cout << "Multiplication of "<< FLAGS_size_multiply_test + std::cout << "Element-wise multiplication of " << FLAGS_size_multiply_test << " doubles finished in " << (end - begin) << " microseconds" << std::endl; ASSERT_LE(0, end - begin); + double acc = 0; + double expected = 0; + for(int i = 0; i < FLAGS_size_multiply_test; i++) + { + acc += output[i]; + } + ASSERT_EQ(expected, acc); + delete input; + delete output; } -TEST(Multiply_Test, ArmadilloComplexImplementation) -{ - arma::cx_fvec input(FLAGS_size_multiply_test, arma::fill::zeros); - arma::cx_fvec output(FLAGS_size_multiply_test); - - struct timeval tv; - gettimeofday(&tv, NULL); - long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; - - output = input % input; - - gettimeofday(&tv, NULL); - long long int end = tv.tv_sec * 1000000 + tv.tv_usec; - std::cout << "Element-wise multiplication of "<< FLAGS_size_multiply_test - << "-length complex armadillo vectors finished in " << (end - begin) - << " microseconds" << std::endl; - ASSERT_LE(0, end - begin); -} TEST(Multiply_Test, ArmadilloImplementation) { @@ -111,8 +84,102 @@ TEST(Multiply_Test, ArmadilloImplementation) gettimeofday(&tv, NULL); long long int end = tv.tv_sec * 1000000 + tv.tv_usec; - std::cout << "Element-wise multiplication of "<< FLAGS_size_multiply_test - << "-length armadillo vectors finished in " << (end - begin) + std::cout << "Element-wise multiplication of " << FLAGS_size_multiply_test + << "-length double armadillo vectors finished in " << (end - begin) << " microseconds" << std::endl; ASSERT_LE(0, end - begin); + ASSERT_EQ(0, arma::norm(output)); } + + + +TEST(Multiply_Test, StandardCComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_multiply_test]; + std::complex* output = new std::complex[FLAGS_size_multiply_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_multiply_test); + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + for(int i = 0; i < FLAGS_size_multiply_test; i++) + { + output[i] = input[i] * input[i]; + } + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "Element-wise multiplication of " << FLAGS_size_multiply_test + << " complex finished in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + std::complex expected(0,0); + std::complex result(0,0); + for(int i = 0; i < FLAGS_size_multiply_test; i++) + { + result += output[i]; + } + + ASSERT_EQ(expected, result); + delete input; + delete output; +} + + + +TEST(Multiply_Test, ArmadilloComplexImplementation) +{ + arma::cx_fvec input(FLAGS_size_multiply_test, arma::fill::zeros); + arma::cx_fvec output(FLAGS_size_multiply_test); + + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + output = input % input; + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "Element-wise multiplication of " << FLAGS_size_multiply_test + << "-length complex float Armadillo vectors finished in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + ASSERT_EQ(0, arma::norm(output)); +} + + + + +TEST(Multiply_Test, VolkComplexImplementation) +{ + std::complex* input = new std::complex[FLAGS_size_multiply_test]; + std::complex* output = new std::complex[FLAGS_size_multiply_test]; + memset(input, 0, sizeof(std::complex) * FLAGS_size_multiply_test); + + struct timeval tv; + gettimeofday(&tv, NULL); + long long int begin = tv.tv_sec * 1000000 + tv.tv_usec; + + volk_32fc_x2_multiply_32fc(output, input, input, FLAGS_size_multiply_test); + + gettimeofday(&tv, NULL); + long long int end = tv.tv_sec * 1000000 + tv.tv_usec; + std::cout << "Element-wise multiplication of " << FLAGS_size_multiply_test + << "-length complex float vector using VOLK finished in " << (end - begin) + << " microseconds" << std::endl; + ASSERT_LE(0, end - begin); + + float* mag = new float [FLAGS_size_multiply_test]; + volk_32fc_magnitude_32f(mag, output, FLAGS_size_multiply_test); + float* result; + volk_32f_accumulator_s32f(result, mag, FLAGS_size_multiply_test); + // Comparing floating-point numbers is tricky. + // Due to round-off errors, it is very unlikely that two floating-points will match exactly. + // See http://code.google.com/p/googletest/wiki/AdvancedGuide#Floating-Point_Comparison + float expected = 0; + ASSERT_FLOAT_EQ(expected, result[0]); + delete input; + delete output; + delete mag; +} + diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index 4209dab67..62b740ee7 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -68,7 +68,10 @@ using google::LogMessage; DECLARE_string(log_dir); -#include "arithmetic/complex_arithmetic_libc.cc" +#include "arithmetic/complex_carrier_test.cc" +#include "arithmetic/conjugate_test.cc" +#include "arithmetic/magnitude_squared_test.cc" +#include "arithmetic/multiply_test.cc" #include "configuration/file_configuration_test.cc" #include "configuration/in_memory_configuration_test.cc" #include "control_thread/control_message_factory_test.cc"