#ifndef _utl_Trace_h_ #define _utl_Trace_h_ /** \file Template class for a FADC data or calibrated data container. \author Lukas Nellen \author Darko Veberic \author Tim Huege \version $Id$ \date 31 Jan 2003 \date 10 Jun 2005 DV update */ #include #include #include #include #include #include #include #include #include #include //#define TRACE_CHECKED_ACCESS namespace utl { // threevector of doubles, e.g., for time-series e-field data typedef utl::SVector<3, double> Vector3D; // threevector of complex, e.g., for frequency-spectrum e-field data typedef utl::SVector<3, std::complex > Vector3C; /** \class Trace Trace.h "utl/Trace.h" \brief Template class for a FADC data or calibrated data container. Use the typedefs (TraceD, TraceI, etc.) defined in Trace-fwd.h \author Lukas Nellen \author Darko Veberic \author Tim Huege \version $Id$ \date 31 Jan 2003 \date 10 Jun 2005 DV update \date 15 Jun 2009 TH remove explicit instantiations \ingroup stl time */ template class Trace { public: typedef T ValueType; typedef typename std::vector::size_type SizeType; typedef typename std::vector::iterator Iterator; typedef typename std::vector::const_iterator ConstIterator; Trace() : fBinning(0), fStart(0), fStop(0) { } Trace(const SizeType size, const double binning, const T& init = T()) : fArray(size, init), fBinning(binning), fStart(0), fStop(size) { } /// Construct from a c-array of T of size length Trace(const SizeType size, const T* const cArray, const double binning) : fArray(cArray, cArray + size), fBinning(binning), fStart(0), fStop(size) { } Trace(const Trace& trace) { operator=(trace); } Iterator Begin() { return fArray.begin(); } Iterator End() { return fArray.end(); } ConstIterator Begin() const { return fArray.begin(); } ConstIterator End() const { return fArray.end(); } /*! Stick the contents of the c-array \par array into the trace Example \code TraceI trace; int array[] = {1, 2, 3}; trace.Adopt(array, 3); cout << trace[0] << endl; \endcode */ template void Adopt(const T2* const cArray, const SizeType size) { fArray.resize(size); copy(cArray, cArray + size, fArray.begin()); fStart = 0; fStop = size; } //! Deprecated method to insert a single value at the end, please use PushBack() instead. void InsertValue(const T& value) { Deprecator::GetInstance().Deprecated("Trace::InsertValue(const T&)", "v2r7", "use Trace::PushBack(const T&)"); PushBack(value); } //! Insert a single value at the end void PushBack(const T& value) { // increase fStop if it points to the end of the trace if (fStop == (GetSize() - 1)) ++fStop; fArray.push_back(value); } //! Remove one value at the end of the trace void PopBack() { // decrease fStop if it points to the end of the trace if (fStop == (GetSize() - 1)) --fStop; fArray.pop_back(); } //! size of one slot double GetBinning() const { return fBinning; } void SetBinning(const double binning) { fBinning = binning; } //! Get valid data start bin SizeType GetStart() const { return fStart; } //! Set valid data start bin void SetStart(const SizeType start) { fStart = start; } //! Get valid data stop bin SizeType GetStop() const { return fStop; } //! Set valid data stop bin void SetStop(const SizeType stop) { fStop = stop; } SizeType GetSize() const { return fArray.size(); } void ClearTrace() { fArray.clear(); } void ResetAll(const T& value = T()) { std::fill(fArray.begin(), fArray.end(), value); } Trace& operator=(const Trace& trace) { fArray = trace.fArray; fBinning = trace.fBinning; fStart = trace.fStart; fStop = trace.fStop; return *this; } Trace operator-() const { Trace result(GetSize(), fBinning); transform(fArray.begin(), fArray.end(), result.Begin(), std::negate()); result.fStart = fStart; result.fStop = fStop; return result; } Trace operator+(const Trace& trace) const; Trace operator-(const Trace& trace) const; Trace operator*(const Trace& trace) const; Trace& operator+=(const Trace& trace); Trace& operator-=(const Trace& trace); Trace& operator*=(const Trace& trace); Trace& operator+=(const T value); Trace& operator-=(const T value); Trace& operator*=(const T value); Trace& operator/=(const T value); bool operator==(const Trace& trace) const { return fArray == trace.fArray && fBinning == trace.fBinning && fStart == trace.fStart && fStop == trace.fStop; } bool operator!=(const Trace& trace) const { return !operator==(trace); } #ifdef TRACE_CHECKED_ACCESS T& operator[](const SizeType i) { return fArray.at(i); } const T& operator[](const SizeType i) const { return fArray.at(i); } #else T& operator[](const SizeType i) { return fArray[i]; } const T& operator[](const SizeType i) const { return fArray[i]; } #endif //! trace entry with checked address T& At(const SizeType i) { return fArray.at(i); } //! trace entry with checked address const T& At(const SizeType i) const { return fArray.at(i); } void Swap(Trace& trace) { std::swap(fArray, trace.fArray); std::swap(fBinning, trace.fBinning); std::swap(fStart, trace.fStart); std::swap(fStop, trace.fStop); } protected: std::vector fArray; double fBinning; SizeType fStart; SizeType fStop; friend class ShadowPtr >; }; // To keep the forward declarations consistent // modify Trace-fwd when changing/adding below typedef Trace TraceUSI; typedef Trace TraceSI; typedef Trace TraceUI; typedef Trace TraceI; typedef Trace TraceF; typedef Trace TraceD; typedef Trace TraceB; typedef Trace > TraceC; typedef Trace TraceV3D; typedef Trace TraceV3C; // Trace + - * Trace #define INNER_ARITHMETIC_BINARY_OPERATOR(_op_, _stl_functor_) \ template \ Trace \ Trace::operator _op_(const Trace& trace) \ const \ { \ const SizeType size = GetSize(); \ if (size == trace.GetSize()) { \ Trace result(size, fBinning); \ transform(fArray.begin(), fArray.end(), trace.Begin(), result.Begin(), \ _stl_functor_()); \ result.fStart = fStart; \ result.fStop = fStop; \ return result; \ } else { \ std::ostringstream warn; \ warn << "Attempting to operate on two traces with different lengths (" \ << size << " and " << trace.GetSize() << ")."; \ WARNING(warn); \ Trace foo; \ return foo; \ } \ } INNER_ARITHMETIC_BINARY_OPERATOR(+, std::plus) INNER_ARITHMETIC_BINARY_OPERATOR(-, std::minus) INNER_ARITHMETIC_BINARY_OPERATOR(*, std::multiplies) #undef INNER_ARITHMETIC_BINARY_OPERATOR // Trace += -= *= Trace #define INNER_AUGMENTED_ARITHMETIC_OPERATOR(_op_, _stl_functor_) \ template \ Trace& \ Trace::operator _op_(const Trace& trace) \ { \ if (GetSize() == trace.GetSize()) { \ transform(fArray.begin(), fArray.end(), trace.Begin(), fArray.begin(), \ _stl_functor_()); \ } else { \ std::ostringstream warn; \ warn << "Attempting to operate on two traces with different lengths (" \ << GetSize() << " and " << trace.GetSize() << ")."; \ WARNING(warn); \ } \ return *this; \ } INNER_AUGMENTED_ARITHMETIC_OPERATOR(+=, std::plus) INNER_AUGMENTED_ARITHMETIC_OPERATOR(-=, std::minus) INNER_AUGMENTED_ARITHMETIC_OPERATOR(*=, std::multiplies) #undef INNER_AUGMENTED_ARITHMETIC_OPERATOR // Trace += -= *= /= T #define OUTER_AUGMENTED_ARITHMETIC_OPERATOR(_op_, _stl_functor_) \ template \ Trace& \ Trace::operator _op_(const T value) \ { \ transform(fArray.begin(), fArray.end(), fArray.begin(), \ bind2nd(_stl_functor_(), value)); \ return *this; \ } OUTER_AUGMENTED_ARITHMETIC_OPERATOR(+=, std::plus) OUTER_AUGMENTED_ARITHMETIC_OPERATOR(-=, std::minus) OUTER_AUGMENTED_ARITHMETIC_OPERATOR(*=, std::multiplies) OUTER_AUGMENTED_ARITHMETIC_OPERATOR(/=, std::divides) #undef OUTER_AUGMENTED_ARITHMETIC_OPERATOR // left: Trace + - * T2 // right: T2 + - * Trace #define LEFT_OUTER_ARITHMETIC_OPERATOR(_op_, _stl_functor_) \ template \ utl::Trace<_T2_> \ operator _op_(const utl::Trace<_T1_>& trace, const _T2_ value) \ { \ utl::Trace<_T2_> result(trace.GetSize(), trace.GetBinning()); \ transform(trace.Begin(), trace.End(), result.Begin(), \ bind2nd(_stl_functor_<_T2_>(), value)); \ result.SetStart(trace.GetStart()); \ result.SetStop(trace.GetStop()); \ return result; \ } #define RIGHT_OUTER_ARITHMETIC_OPERATOR(_op_, _stl_functor_) \ template \ utl::Trace<_T2_> \ operator _op_(const _T2_ value, const utl::Trace<_T1_>& trace) \ { \ utl::Trace<_T2_> result(trace.GetSize(), trace.GetBinning()); \ transform(trace.Begin(), trace.End(), result.Begin(), \ bind1st(_stl_functor_<_T2_>(), value)); \ result.SetStart(trace.GetStart()); \ result.SetStop(trace.GetStop()); \ return result; \ } LEFT_OUTER_ARITHMETIC_OPERATOR(+, std::plus) RIGHT_OUTER_ARITHMETIC_OPERATOR(+, std::plus) LEFT_OUTER_ARITHMETIC_OPERATOR(-, std::minus) RIGHT_OUTER_ARITHMETIC_OPERATOR(-, std::minus) LEFT_OUTER_ARITHMETIC_OPERATOR(*, std::multiplies) RIGHT_OUTER_ARITHMETIC_OPERATOR(*, std::multiplies) LEFT_OUTER_ARITHMETIC_OPERATOR(/, std::divides) #undef LEFT_OUTER_ARITHMETIC_OPERATOR #undef RIGHT_OUTER_ARITHMETIC_OPERATOR } // utl namespace std { template inline void swap(utl::Trace& t1, utl::Trace& t2) { t1.Swap(t2); } } #undef TRACE_CHECKED_ACCESS #endif // Configure (x)emacs for this file ... // Local Variables: // mode: c++ // compile-command: "make -C .. Traces/Trace.o -k" // End: