/*************************************************************************** * GResponseVectorCache.cpp - Response vector cache class * * ----------------------------------------------------------------------- * * copyright (C) 2020 by Juergen Knoedlseder * * ----------------------------------------------------------------------- * * * * 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 3 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, see . * * * ***************************************************************************/ /** * @file GResponseVectorCache.cpp * @brief Response vector cache class implementation * @author Juergen Knoedlseder */ /* __ Includes ___________________________________________________________ */ #ifdef HAVE_CONFIG_H #include #endif #include "GTools.hpp" #include "GVector.hpp" #include "GResponseVectorCache.hpp" /* __ Method name definitions ____________________________________________ */ /* __ Macros _____________________________________________________________ */ /* __ Coding definitions _________________________________________________ */ /* __ Debug definitions __________________________________________________ */ //#define G_DEBUG_VECTOR_CACHE //!< Debug vector cache /*========================================================================== = = = Constructors/destructors = = = ==========================================================================*/ /***********************************************************************//** * @brief Void constructor ***************************************************************************/ GResponseVectorCache::GResponseVectorCache(void) { // Initialise class members init_members(); // Return return; } /***********************************************************************//** * @brief Copy constructor * * @param[in] cache Response vector cache. ***************************************************************************/ GResponseVectorCache::GResponseVectorCache(const GResponseVectorCache& cache) { // Initialise class members init_members(); // Copy members copy_members(cache); // Return return; } /***********************************************************************//** * @brief Destructor ***************************************************************************/ GResponseVectorCache::~GResponseVectorCache(void) { // Free members free_members(); // Return return; } /*========================================================================== = = = Operators = = = ==========================================================================*/ /***********************************************************************//** * @brief Assignment operator * * @param[in] cache Response vector cache. * @return Response vector cache. ***************************************************************************/ GResponseVectorCache& GResponseVectorCache::operator=(const GResponseVectorCache& cache) { // Execute only if object is not identical if (this != &cache) { // Free members free_members(); // Initialise private members init_members(); // Copy members copy_members(cache); } // endif: object was not identical // Return this object return *this; } /*========================================================================== = = = Public methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Clear response vector cache ***************************************************************************/ void GResponseVectorCache::clear(void) { // Free members free_members(); // Initialise private members init_members(); // Return return; } /***********************************************************************//** * @brief Clone response cache * * @return Pointer to deep copy of response cache. ***************************************************************************/ GResponseVectorCache* GResponseVectorCache::clone(void) const { return new GResponseVectorCache(*this); } /***********************************************************************//** * @brief Set cache value * * @param[in] cache_id Cache identifier. * @param[in] vector Cache vector. * * Set cache vector for a given @p cache_id. ***************************************************************************/ void GResponseVectorCache::set(const std::string& cache_id, const GVector& vector) { // Debug vector cache #if defined(G_DEBUG_VECTOR_CACHE) std::cout << "GResponseVectorCache::set("; std::cout << cache_id << "," << vector.size() << "):"; #endif // Initialise pointers to values and indices double* values = NULL; int* indices = NULL; // Find cache index int index = find_cache(cache_id); // Determine size of vector cache int entries = vector.non_zeros(); // Debug vector cache #if defined(G_DEBUG_VECTOR_CACHE) if (index != -1) { std::cout << " entry found at index " << index; std::cout << " with " << m_cache_entries[index] << " elements."; std::cout << " Require " << entries << " elements."; std::cout << std::endl; } else { std::cout << " no entry found."; std::cout << " Require " << entries << " elements."; std::cout << std::endl; } #endif // If cache identifier does not yet exist then create new cache entry // and allocate memory to hold cache values and indices if (index == -1) { if (entries > 0) { values = new double[entries]; indices = new int[entries]; } m_cache_ids.push_back(cache_id); m_cache_entries.push_back(entries); m_cache_values.push_back(values); m_cache_indices.push_back(indices); } // ... otherwise update cache existing entry by allocating new memory // to hold cache values and indices in case that the number of entries // have changed else { if (m_cache_entries[index] != entries) { if (entries > 0) { values = new double[entries]; indices = new int[entries]; } if (m_cache_values[index] != NULL) delete [] m_cache_values[index]; if (m_cache_indices[index] != NULL) delete [] m_cache_indices[index]; m_cache_entries[index] = entries; m_cache_values[index] = values; m_cache_indices[index] = indices; } else { values = m_cache_values[index]; indices = m_cache_indices[index]; } } // Set cache vector for (int i = 0; i < vector.size(); ++i) { if (vector[i] != 0.0) { *values++ = vector[i]; *indices++ = i; } } // Return return; } /***********************************************************************//** * @brief Remove cache * * @param[in] cache_id Cache identifier. * * Remove cache for a given @p cache_id. ***************************************************************************/ void GResponseVectorCache::remove(const std::string& cache_id) { // Find cache index int index = find_cache(cache_id); // If cache index is valid then remove corresponding cache if (index != -1) { // Free memory if (m_cache_values[index] != NULL) delete [] m_cache_values[index]; if (m_cache_indices[index] != NULL) delete [] m_cache_indices[index]; // Erase entry m_cache_ids.erase(m_cache_ids.begin() + index); m_cache_entries.erase(m_cache_entries.begin() + index); m_cache_values.erase(m_cache_values.begin() + index); m_cache_indices.erase(m_cache_indices.begin() + index); } // endif: cache index was valid // Return return; } /***********************************************************************//** * @brief Check if cache contains a value for specific parameters * * @param[in] cache_id Cache identifier. * @param[in,out] vector Pointer to cached vector (only if found). * @return True if cached value was found, otherwise false. * * Check if the cache contains a value for a given @p name, reconstructed * energy @p ereco, and true energy @p etrue. * * If the @p value pointer argument is not NULL, the method will return the * cached value through this argument in case that the value exists. ***************************************************************************/ bool GResponseVectorCache::contains(const std::string& cache_id, GVector* vector) const { // Debug vector cache #if defined(G_DEBUG_VECTOR_CACHE) std::cout << "GResponseVectorCache::contains(" << cache_id; if (vector == NULL) { std::cout << ", NULL):"; } else { std::cout << "," << vector->size() << "):"; } #endif // Find cache index int index = find_cache(cache_id); // Set contains flag bool contains = (index != -1); // Debug vector cache #if defined(G_DEBUG_VECTOR_CACHE) if (contains) { std::cout << " entry found at index " << index; std::cout << " with " << m_cache_entries[index] << " elements."; std::cout << std::endl; } else { std::cout << " no entry found." << std::endl; } #endif // If cache contains the identifier and a pointer to a vector was // provided then fill the vector if (contains && vector != NULL) { // Get pointer to values and indices double* values = m_cache_values[index]; int* indices = m_cache_indices[index]; // Fill vector for (int i = 0; i < m_cache_entries[index]; ++i, ++values, ++indices) { (*vector)[*indices] = *values; } } // endif: filled vector // Return containment flag return contains; } /***********************************************************************//** * @brief Print response cache * * @param[in] chatter Chattiness. * @return String containing response cache information. ***************************************************************************/ std::string GResponseVectorCache::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append header result.append("=== GResponseVectorCache ==="); // Append total cache size result.append("\n"+gammalib::parformat("Number of cached vectors")); result.append(gammalib::str(size())); // Append cache information for (int i = 0; i < size(); ++i) { result.append("\n"+gammalib::parformat("Identifier")); result.append(m_cache_ids[i]); result.append(" ("+gammalib::str(m_cache_entries[i])+" values"); } } // endif: chatter was not silent // Return result return result; } /*========================================================================== = = = Private methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Initialise class members ***************************************************************************/ void GResponseVectorCache::init_members(void) { // Initialise members m_cache_ids.clear(); m_cache_entries.clear(); m_cache_values.clear(); m_cache_indices.clear(); // Return return; } /***********************************************************************//** * @brief Copy class members * * @param[in] cache Response cache. ***************************************************************************/ void GResponseVectorCache::copy_members(const GResponseVectorCache& cache) { // Copy members m_cache_ids = cache.m_cache_ids; m_cache_entries = cache.m_cache_entries; // Copy values and indices for (int i = 0; i < size(); ++i) { double* values = NULL; int* indices = NULL; if (m_cache_entries[i] > 0) { values = new double[m_cache_entries[i]]; indices = new int[m_cache_entries[i]]; for (int k = 0; k < m_cache_entries[i]; ++k) { values[k] = cache.m_cache_values[i][k]; indices[k] = cache.m_cache_indices[i][k]; } } m_cache_values.push_back(values); m_cache_indices.push_back(indices); } // Return return; } /***********************************************************************//** * @brief Delete class members ***************************************************************************/ void GResponseVectorCache::free_members(void) { // Loop over entries for (int i = 0; i < size(); ++i) { if (m_cache_values[i] != NULL) delete [] m_cache_values[i]; if (m_cache_indices[i] != NULL) delete [] m_cache_indices[i]; m_cache_values[i] = NULL; m_cache_indices[i] = NULL; } // Return return; } /***********************************************************************//** * @brief Find cache * * @param[in] cache_id Cache identifier. * @return Cache index (-1 if no cache was found) * * Find cache for a given @p cache_id. If no cache was found the method * returns -1. ***************************************************************************/ int GResponseVectorCache::find_cache(const std::string& cache_id) const { // Initialise cache index int index = -1; // Loop over cache for (int i = 0; i < m_cache_ids.size(); ++i) { if (m_cache_ids[i] == cache_id) { index = i; break; } } // Return index return index; }