/*************************************************************************** * GGti.cpp - Good time interval class * * ----------------------------------------------------------------------- * * copyright (C) 2008-2015 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 GGti.cpp * @brief Good time interval class implementation. * @author Juergen Knoedlseder */ /* __ Includes ___________________________________________________________ */ #ifdef HAVE_CONFIG_H #include #endif #include "GException.hpp" #include "GTools.hpp" #include "GGti.hpp" #include "GFits.hpp" #include "GFitsTable.hpp" #include "GFitsBinTable.hpp" #include "GFitsTableDoubleCol.hpp" #include "GXmlElement.hpp" /* __ Method name definitions ____________________________________________ */ #define G_REDUCE "GGti::reduce(GTime&, GTime&)" #define G_REMOVE "GGti::remove(int&)" #define G_READ_XML "GGti::read(GXmlElement&)" #define G_WRITE_XML "GGti::write(GXmlElement&)" #define G_TSTART "GGti::tstart(int&)" #define G_TSTOP "GGti::tstop(int&)" #define G_INSERT_GTI "GGti::insert_gti(int&, GTime&, GTime&)" /* __ Macros _____________________________________________________________ */ /* __ Coding definitions _________________________________________________ */ /* __ Debug definitions __________________________________________________ */ /*========================================================================== = = = Constructors/destructors = = = ==========================================================================*/ /***********************************************************************//** * @brief Void constructor ***************************************************************************/ GGti::GGti(void) { // Initialise class members init_members(); // Return return; } /***********************************************************************//** * @brief Copy constructor * * @param[in] gti Good Time Intervals. ***************************************************************************/ GGti::GGti(const GGti& gti) { // Initialise class members init_members(); // Copy members copy_members(gti); // Return return; } /***********************************************************************//** * @brief XML element constructor * * @param[in] xml XML element. * * Constructs Good Time Intervals from an XML element. ***************************************************************************/ GGti::GGti(const GXmlElement& xml) { // Initialise members init_members(); // Read Good Time Intervals from XML element read(xml); // Return return; } /***********************************************************************//** * @brief Single time interval constructor * * @param[in] tstart Start time of interval. * @param[in] tstop Stop time of interval. * * Constructs Good Time Intervals from a single time interval, given by * [p@ tstart, @p tstop]. ***************************************************************************/ GGti::GGti(const GTime& tstart, const GTime& tstop) { // Initialise members init_members(); // Append time interval append(tstart, tstop); // Return return; } /***********************************************************************//** * @brief Time reference constructor * * @param[in] ref Time reference. * * Constructs Good Time Intervals using a specific time reference. The time * reference will be used when writing the Good Time Intervals into a FITS * file. ***************************************************************************/ GGti::GGti(const GTimeReference& ref) { // Initialise class members init_members(); // Set time reference this->reference(ref); // Return return; } /***********************************************************************//** * @brief Destructor ***************************************************************************/ GGti::~GGti(void) { // Free members free_members(); // Return return; } /*========================================================================== = = = Operators = = = ==========================================================================*/ /***********************************************************************//** * @brief Assignment operator * * @param[in] gti Good Time Intervals. * @return Good Time Intervals. ***************************************************************************/ GGti& GGti::operator=(const GGti& gti) { // Execute only if object is not identical if (this != >i) { // Free members free_members(); // Initialise private members init_members(); // Copy members copy_members(gti); } // endif: object was not identical // Return this object return *this; } /*========================================================================== = = = Public methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Clear Good Time Intervals ***************************************************************************/ void GGti::clear(void) { // Free members free_members(); // Initialise private members init_members(); // Return return; } /***********************************************************************//** * @brief Clone Good Time Intervals * * @return Pointer to deep copy of Good Time Intervals. ***************************************************************************/ GGti* GGti::clone(void) const { return new GGti(*this); } /***********************************************************************//** * @brief Append Good Time Interval * * @param[in] tstart Start time of interval. * @param[in] tstop Stop time of interval. * * Appends a Good Time Interval at the end of the container. ***************************************************************************/ void GGti::append(const GTime& tstart, const GTime& tstop) { // Insert GTI at end of list insert_gti(m_num, tstart, tstop); // Return return; } /***********************************************************************//** * @brief Insert Good Time Interval * * @param[in] tstart Start time of interval. * @param[in] tstop Stop time of interval. * * Inserts a Good Time Interval into the container after the first interval * that has a start time smaller than @p tstart. The method implicitely * assumes that the Good Time Intervals are ordered by increasing start time. ***************************************************************************/ void GGti::insert(const GTime& tstart, const GTime& tstop) { // Determine index at which GTI should be inserted int inx = 0; for (int i = 0; i < m_num; ++i) { if (tstart < m_start[i]) { break; } } // Insert interval insert_gti(inx, tstart, tstop); // Return return; } /***********************************************************************//** * @brief Merge all overlapping Good Time Intervals * * Merges all overlapping or connecting successive Good Time Intervals. The * method implicitely assumes that the intervals are ordered by increasing * start time. * * Note that the method does not actually reduce the memory size but just * updates the information on the number of elements in the array. ***************************************************************************/ void GGti::merge(void) { // Find overlaps int i = 0; int num = m_num; while (i < num-1) { // If GTI overlaps with following one then merge both GTIs, move // all remaining GTIs one position up, and reduce number of elements if (m_start[i+1] <= m_stop[i]) { m_start[i] = (m_start[i] < m_start[i+1]) ? m_start[i] : m_start[i+1]; m_stop[i] = (m_stop[i] > m_stop[i+1]) ? m_stop[i] : m_stop[i+1]; for (int k = i+2; k < num; ++k) { m_start[k-1] = m_start[k]; m_stop[k-1] = m_stop[k]; } num--; } // Otherwise increment GTI index else { i++; } } // endwhile: there were still GTIs to check // Update number of elements in GTI m_num = num; // Return return; } /***********************************************************************//** * @brief Merge Good Time Interval into container * * @param[in] tstart Start time of interval. * @param[in] tstop Stop time of interval. * * Inserts a Good Time Interval into the container after the first interval * that has a start time smaller than @p tstart and then merges any * overlapping or connecting Good Time Intervals. The method implicitely * assumes that the intervals are ordered by increasing start time. ***************************************************************************/ void GGti::merge(const GTime& tstart, const GTime& tstop) { // Determine index at which GTI should be inserted int inx = 0; for (int i = 0; i < m_num; ++i) { if (tstart < m_start[i]) { break; } } // Insert GTI insert_gti(inx, tstart, tstop); // Merge any overlapping GTIs merge(); // Return return; } /***********************************************************************//** * @brief Reduce Good Time Intervals to specified interval * * @param[in] tstart Start time of interval. * @param[in] tstop Stop time of interval. * * @exception GException::invalid_argument * Start time is later than stop time * * Reduces the Good Time Intervals to the specified interval. Reducing means * that all Good Time Intervals are dropped that fall outside the specified * interval [@p tstart, @p tstop], and Good Time Intervals will be limited * to >@p tstart and <=@p tstop in case that their boundaries are outside * [@p tstart, @p tstop]. ***************************************************************************/ void GGti::reduce(const GTime& tstart, const GTime& tstop) { // Throw an exception if time interval is invalid if (tstart > tstop) { std::string msg = "Invalid time interval specified. Start time "+ tstart.print(NORMAL)+" can not be later than " "stop time "+tstop.print(NORMAL)+"."; throw GException::invalid_argument(G_REDUCE, msg); } // Adjust existing GTIs. This will limit all GTIs to [tstart,tstop]. // All GTIs outside [tstart,tstop] will have start > stop. The number // of valid GTIs will also be determined. int num = 0; for (int i = 0; i < m_num; ++i) { if (m_start[i] < tstart) { m_start[i] = tstart; } if (m_stop[i] > tstop) { m_stop[i] = tstop; } if (m_start[i] <= m_stop[i]) { num++; } } // If we still have valid GTIs then allocate memory for them, copy // over the start and stop times, and update the attributes if (num > 0) { // Allocate new intervals GTime* start = new GTime[num]; GTime* stop = new GTime[num]; // Copy valid intervals for (int i = 0; i < m_num; ++i) { if (m_start[i] <= m_stop[i]) { start[i] = m_start[i]; stop[i] = m_stop[i]; } } // Free old memory if (m_start != NULL) delete [] m_start; if (m_stop != NULL) delete [] m_stop; // Set new memory m_start = start; m_stop = stop; // Set attributes m_num = num; set_attributes(); } // endif: there were still valid GTIs // ... otherwise we remove all GTIs else { clear(); } // Return return; } /***********************************************************************//** * @brief Remove Good Time Interval * * @param[in] index Good Time Interval index (0,...,size()-1). * * Removes Good Time Interval at @p index from the container. All intervals * after the specified @p index are moved forward by one position. * * Note that the method does not actually reduce the memory size but just * updates the information on the number of elements in the array. ***************************************************************************/ void GGti::remove(const int& index) { #if defined(G_RANGE_CHECK) // If index is outside boundary then throw an error if (index < 0 || index >= m_num) { throw GException::out_of_range(G_REMOVE, index, 0, m_num-1); } #endif // Move all elements located after index forward for (int i = index+1; i < m_num; ++i) { m_start[i-1] = m_start[i]; m_stop[i-1] = m_stop[i]; } // Reduce number of elements by one m_num--; // Update attributes set_attributes(); // Return return; } /***********************************************************************//** * @brief Reserve space for Good Time Intervals * * @param[in] num Number of elements. * * This method does nothing (it is needed to satisfy the GContainer * interface). ***************************************************************************/ void GGti::reserve(const int& num) { // Return return; } /***********************************************************************//** * @brief Append Good Time Intervals * * @param[in] gti Good Time Intervals. * * Append Good Time Intervals to the container. The method performs automatic * time reference conversion in case that the specified Good Time Intervals * @p gti have a time reference that differs from that of the current * instance. ***************************************************************************/ void GGti::extend(const GGti& gti) { // Do nothing if Good Time Intervals are empty if (!gti.is_empty()) { // Allocate new intervals int num = m_num+gti.size(); GTime* start = new GTime[num]; GTime* stop = new GTime[num]; // Initialise index int inx = 0; // Copy existing intervals for (; inx < m_num; ++inx) { start[inx] = m_start[inx]; stop[inx] = m_stop[inx]; } // Append intervals. Convert to GTI reference on the fly. for (int i = 0; i < gti.size(); ++i, ++inx) { double tstart = gti.m_start[i].convert(gti.reference()); double tstop = gti.m_stop[i].convert(gti.reference()); start[inx].set(tstart, this->reference()); stop[inx].set(tstop, this->reference()); } // Free memory if (m_start != NULL) delete [] m_start; if (m_stop != NULL) delete [] m_stop; // Set new memory m_start = start; m_stop = stop; // Set number of elements m_num = num; // Set attributes set_attributes(); } // endif: Good Time Intervals were not empty // Return return; } /***********************************************************************//** * @brief Load Good Time Intervals from FITS file * * @param[in] filename FITS filename. * @param[in] extname GTI extension name (defaults to "GTI") * * Loads the Good Time Intervals from FITS file. ***************************************************************************/ void GGti::load(const std::string& filename, const std::string& extname) { // Allocate FITS file GFits file; // Open FITS file file.open(filename); // Get GTI table const GFitsTable& table = *file.table(extname); // Read GTI from table read(table); // Close FITS file file.close(); // Return return; } /***********************************************************************//** * @brief Save Good Time Intervals intervals to FITS file * * @param[in] filename FITS filename. * @param[in] clobber Overwrite any existing GTI extension? * @param[in] extname GTI extension name (defaults to "GTI") * * Saves Good Time Intervals into extension @p extname of a FITS file. If the * file does not exist it is created. If the file exists the GTI is appended * as extension. If another GTI exists already it is overwritten if * @p clobber=true. ***************************************************************************/ void GGti::save(const std::string& filename, const bool& clobber, const std::string& extname) const { // Allocate FITS file GFits file; // Write GTI to FITS file write(file, extname); // Save to file file.saveto(filename, clobber); // Return return; } /***********************************************************************//** * @brief Read Good Time Intervals and time reference from FITS table * * @param[in] table FITS table. * * Reads the Good Time Intervals and time reference from a FITS table. ***************************************************************************/ void GGti::read(const GFitsTable& table) { // Free members free_members(); // Initialise attributes init_members(); // Read time reference m_reference.read(table); // Extract GTI information from FITS table m_num = table.integer("NAXIS2"); if (m_num > 0) { // Set GTIs m_start = new GTime[m_num]; m_stop = new GTime[m_num]; for (int i = 0; i < m_num; ++i) { m_start[i].set(table["START"]->real(i), m_reference); m_stop[i].set(table["STOP"]->real(i), m_reference); } // Set attributes set_attributes(); } // Return return; } /***********************************************************************//** * @brief Write Good Time Intervals and time reference into FITS object * * @param[in] file FITS file. * @param[in] extname GTI extension name (defaults to "GTI") * * Saves Good Time Intervals and time reference into a FITS object. If the * file does not exist it is created. If the file exists the GTI is appended * as extension. If another GTI exists already it is overwritten if * @p clobber=true. * * @todo Implement clobber method for overwriting of existing GTIs. ***************************************************************************/ void GGti::write(GFits& file, const std::string& extname) const { // Create GTI columns GFitsTableDoubleCol cstart = GFitsTableDoubleCol("START", m_num); GFitsTableDoubleCol cstop = GFitsTableDoubleCol("STOP", m_num); // Fill GTI columns in specified time reference for (int i = 0; i < m_num; ++i) { cstart(i) = m_start[i].convert(m_reference); cstop(i) = m_stop[i].convert(m_reference); } // Create GTI table GFitsBinTable* table = new GFitsBinTable(m_num); table->append(cstart); table->append(cstop); table->extname(extname); // Write time reference m_reference.write(*table); // Write to FITS file file.append(*table); // Free table delete table; // Return return; } /***********************************************************************//** * @brief Read Good Time Intervals from XML element * * @param[in] xml XML element. * * @exception GException::invalid_value * Invalid XML format encountered. * * Read Good Time Intervals from an XML element. The format of the Good Time * Intervals is * * * * The units of the @a tmin and @a tmax parameters are seconds. * * Note that the method also expects that the time reference is provided * as parameter in the @p xml element. ***************************************************************************/ void GGti::read(const GXmlElement& xml) { // Clear energy boundaries clear(); // Read time reference m_reference.read(xml); // Get energy boundaries parameter const GXmlElement* par = gammalib::xml_get_par(G_READ_XML, xml, "GoodTimeIntervals"); // Extract tmin and tmax attributes if (par->has_attribute("tmin") && par->has_attribute("tmax")) { double tmin = gammalib::todouble(par->attribute("tmin")); double tmax = gammalib::todouble(par->attribute("tmax")); append(GTime(tmin, m_reference), GTime(tmax, m_reference)); } else { std::string msg = "Attributes \"tmin\" and/or \"tmax\" not found" " in XML parameter \"GoodTimeIntervals\"." " Please verify the XML format."; throw GException::invalid_value(G_READ_XML, msg); } // Return return; } /***********************************************************************//** * @brief Write Good Time Intervals into XML element * * @param[in] xml XML element. * * Writes Good Time Intervals into an XML element. The format of the Good * Time Intervals is * * * * The units of the @a tmin and @a tmax parameters are seconds. * * The method also writes the time reference as parameter in the @p xml * element. * * This method does nothing if the Good Time Intervals are empty. ***************************************************************************/ void GGti::write(GXmlElement& xml) const { // Continue only if there are GTIs if (!is_empty()) { // Get parameter GXmlElement* par = gammalib::xml_need_par(G_WRITE_XML, xml, "GoodTimeIntervals"); // Write time interval par->attribute("tmin", gammalib::str(tstart().convert(m_reference))); par->attribute("tmax", gammalib::str(tstop().convert(m_reference))); // Write time reference m_reference.write(xml); } // endif: GTIs were not empty // Return return; } /***********************************************************************//** * @brief Returns earliest start time in Good Time Intervals * * @return Earliest start time in Good Time Intervals. ***************************************************************************/ const GTime& GGti::tstart(void) const { // Return return m_tstart; } /***********************************************************************//** * @brief Returns latest stop time in Good Time Intervals * * @return Latest stop time in Good Time Intervals. ***************************************************************************/ const GTime& GGti::tstop(void) const { // Return return m_tstop; } /***********************************************************************//** * @brief Returns start time for a given Good Time Interval * * @param[in] index Good Time Interval index (0,...,size()-1). * * @exception GException::out_of_range * Specified index is out of range. ***************************************************************************/ const GTime& GGti::tstart(const int& index) const { #if defined(G_RANGE_CHECK) // If index is outside boundary then throw an error if (index < 0 || index >= m_num) { throw GException::out_of_range(G_TSTART, index, 0, m_num-1); } #endif // Return return (m_start[index]); } /***********************************************************************//** * @brief Returns stop time for a given Good Time Interval * * @param[in] index Good Time Interval index (0,...,size()-1). * * @exception GException::out_of_range * Specified index is out of range. ***************************************************************************/ const GTime& GGti::tstop(const int& index) const { #if defined(G_RANGE_CHECK) // If index is outside boundary then throw an error if (index < 0 || index >= m_num) { throw GException::out_of_range(G_TSTOP, index, 0, m_num-1); } #endif // Return return (m_stop[index]); } /***********************************************************************//** * @brief Returns elapsed time * * @return Elapsed time [seconds]. * * Returns the elapsed time in seconds. The elapsed time is defined as the * time difference between the latest stop time and the earliest start time * in the Good Time Intervals. ***************************************************************************/ const double& GGti::telapse(void) const { // Return return m_telapse; } /***********************************************************************//** * @brief Returns ontime * * @return Ontime [seconds]. * * Returns the ontime in seconds. The ontime is defined as the sum of all * Good Time Intervals. ***************************************************************************/ const double& GGti::ontime(void) const { // Return return m_ontime; } /***********************************************************************//** * @brief Set time reference for Good Time Intervals * * @param[in] ref Time reference. * * Sets the time reference of the Good Time Intervals. This defines the * reference time which will be writted into the FITS file upon saving of * the Good Time Intervals. ***************************************************************************/ void GGti::reference(const GTimeReference& ref) { // Set time reference m_reference = ref; // Return return; } /***********************************************************************//** * @brief Return time reference for Good Time Intervals * * @return Time reference. * * Returns the time reference of the Good Time Intervals. ***************************************************************************/ const GTimeReference& GGti::reference(void) const { // Return time reference return m_reference; } /***********************************************************************//** * @brief Checks whether Good Time Intervals contain time * * @param[in] time Time to be checked. * * Checks if a given @p time falls in at least one of the Good Time * Intervals. The method exits when the first matching interval has been * found. ***************************************************************************/ bool GGti::contains(const GTime& time) const { // Initialise test bool found = false; // Test all GTIs for (int i = 0; i < m_num; ++i) { if (time >= m_start[i] && time <= m_stop[i]) { found = true; break; } } // Return result return found; } /***********************************************************************//** * @brief Print Good Time Intervals * * @param[in] chatter Chattiness (defaults to NORMAL). * @return String containing Good Time Interval information. ***************************************************************************/ std::string GGti::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("=== GGti ==="); // Append GTI information result.append("\n"+gammalib::parformat("Number of intervals")); result.append(gammalib::str(size())); result.append("\n"+gammalib::parformat("Ontime")); result.append(gammalib::str(ontime())+" sec"); result.append("\n"+gammalib::parformat("Elapsed time")); result.append(gammalib::str(telapse())+" sec"); result.append("\n"+gammalib::parformat("Time range")); result.append(gammalib::str(tstart().convert(m_reference))); result.append(" - "); result.append(gammalib::str(tstop().convert(m_reference))); result.append(" "+reference().timeunit()); result.append(" ("+reference().timesys()+")"); result.append("\n"+gammalib::parformat("Reference MDJ")); result.append(gammalib::str(reference().mjdref())); // EXPLICIT: Append time reference information if (chatter >= EXPLICIT) { result.append("\n"+reference().print(chatter)); } } // endif: chatter was not silent // Return result return result; } /*========================================================================== = = = Private methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Initialise class members ***************************************************************************/ void GGti::init_members(void) { // Initialise members m_num = 0; m_tstart.clear(); m_tstop.clear(); m_ontime = 0.0; m_telapse = 0.0; m_start = NULL; m_stop = NULL; // Initialise time reference with native reference GTime time; m_reference = time.reference(); // Return return; } /***********************************************************************//** * @brief Copy class members * * @param[in] gti Good Time Intervals. ***************************************************************************/ void GGti::copy_members(const GGti& gti) { // Copy attributes m_num = gti.m_num; m_tstart = gti.m_tstart; m_tstop = gti.m_tstop; m_ontime = gti.m_ontime; m_telapse = gti.m_telapse; m_reference = gti.m_reference; // Copy start/stop times if (m_num > 0) { m_start = new GTime[m_num]; m_stop = new GTime[m_num]; for (int i = 0; i < m_num; ++i) { m_start[i] = gti.m_start[i]; m_stop[i] = gti.m_stop[i]; } } // Return return; } /***********************************************************************//** * @brief Delete class members ***************************************************************************/ void GGti::free_members(void) { // Free memory if (m_start != NULL) delete [] m_start; if (m_stop != NULL) delete [] m_stop; // Signal free pointers m_start = NULL; m_stop = NULL; // Return return; } /***********************************************************************//** * @brief Set class attributes * * Compute the following class attributes: * * m_tstart - Earliest start time of GTIs * m_stop - Latest stop time of GTIs * m_telapse - Latest stop time minus earliest start time of GTIs [sec] * m_ontime - Sum of all intervals [sec] ***************************************************************************/ void GGti::set_attributes(void) { // If there are intervals then determine the start and stop time // from these intervals ... if (m_num > 0) { m_tstart = m_start[0]; m_tstop = m_stop[0]; for (int i = 1; i < m_num; ++i) { if (m_start[i] < m_tstart) m_tstart = m_start[i]; if (m_stop[i] > m_tstop) m_tstop = m_stop[i]; } } // ... otherwise clear the start and stop time else { m_tstart.clear(); m_tstop.clear(); } // Set attributes m_telapse = m_tstop.secs() - m_tstart.secs(); m_ontime = 0.0; for (int i = 0; i < m_num; ++i) { m_ontime += (m_stop[i].secs() - m_start[i].secs()); } // Return return; } /***********************************************************************//** * @brief Insert Good Time Interval * * @param[in] index Index after which interval is inserted. * @param[in] tstart Start time of interval. * @param[in] tstop Stop time of interval. * * @exception GException::invalid_argument * Start time later than stop time * * Inserts a Good Time Interval after the specified @p index in the Good * Time Intervals. The method does not reorder the intervals by time, * instead the client needs to determine the approriate @p index. * * Invalid parameters do not produce any exception, but are handled * transparently. If the interval is invalid (i.e. @p tstart > @p tstop) * an exception is thrown. If the @p index is out of the valid range, the * index will be adjusted to either the first or the last element. ***************************************************************************/ void GGti::insert_gti(const int& index, const GTime& tstart, const GTime& tstop) { // Throw an exception if time interval is invalid if (tstart > tstop) { std::string msg = "Invalid time interval specified. Start time "+ tstart.print(NORMAL)+" can not be later than " "stop time "+tstop.print(NORMAL)+"."; throw GException::invalid_argument(G_INSERT_GTI, msg); } // Set index int inx = index; // If inx is out of range then adjust it if (inx < 0) inx = 0; if (inx > m_num) inx = m_num; // Allocate new intervals int num = m_num+1; GTime* start = new GTime[num]; GTime* stop = new GTime[num]; // Copy intervals before GTI to be inserted for (int i = 0; i < inx; ++i) { start[i] = m_start[i]; stop[i] = m_stop[i]; } // Insert GTI start[inx] = tstart; stop[inx] = tstop; // Copy intervals after GTI to be inserted for (int i = inx+1; i < num; ++i) { start[i] = m_start[i-1]; stop[i] = m_stop[i-1]; } // Free memory if (m_start != NULL) delete [] m_start; if (m_stop != NULL) delete [] m_stop; // Set new memory m_start = start; m_stop = stop; // Set number of elements m_num = num; // Set attributes set_attributes(); // Return return; }