#ifndef INTERVAL_H #define INTERVAL_H namespace NSet { #define mIsEqual(x,y,eps) ( (x-y) < (eps) && (x-y) > (-eps) ) #define mIsZero(x, eps) ( (x) < (eps) && (x) > (-eps) ) //!\brief interval of values. //Note that start does not need to be lower than stop. That's why there is a sort() method. template class TInterval { public: inline TInterval(); inline TInterval(const T& start,const T& stop); inline TInterval(const TInterval& ti){ start=ti.start; stop=ti.stop; } inline TInterval& operator=(const TInterval&); inline bool operator==(const TInterval&) const; inline bool operator!=(const TInterval&) const; inline TInterval operator+(const TInterval&) const; inline TInterval& operator+=(const TInterval&); inline virtual TInterval* clone() const; inline void set(const T& start,const T& stop); inline bool isEqual(const TInterval& i,const T& eps) const; inline T width(bool allowrev=true) const; inline virtual T center() const; inline void shift(const T& len); inline void widen(const T& len,bool allowrev=true); inline virtual void scale(const T&); inline T atIndex(int,const T& step) const; inline bool isIncludes(const T&, bool allowrev=true ) const; inline void include(const T&, bool allowrev=true); inline void include(const TInterval&,bool allowrev=true); virtual void sort( bool asc=true ); inline bool isRev() const { return start > stop; } virtual bool hasStep() const { return false; } inline void Swap( T& a, T& b ) { T tmp = a; a = b; b = tmp; } public: T start; T stop; }; typedef TInterval SampleGate; typedef TInterval ZGate; template inline void WINAPI Swap( T& a, T& b ) { T tmp = a; a = b; b = tmp; } /*!\brief TInterval with step. */ template class TIntervalStep : public TInterval { public: inline TIntervalStep(); inline TIntervalStep(const T& start,const T& stop, const T& step); inline TIntervalStep(const TInterval&); inline TIntervalStep( const TIntervalStep& si ): TInterval(si), step(si.step) {} inline TIntervalStep& operator=(const TInterval&); inline bool operator==(const TIntervalStep&) const; inline bool operator!=(const TIntervalStep&) const; inline void getString(char* str) const; inline void setString(char*); inline virtual TInterval* clone() const; inline void set(const T& start,const T& stop,const T& step); inline bool isEqual(const TIntervalStep& i,const T& eps) const; inline T atIndex(int) const; inline void Normalise(); //!< Makes sure start&, float eps=mDefEps) const; /*!< epsilon refers to the steps, i.e eps=0.1 allows b to be 0.1 steps apart.*/ inline T snapStep(const T& inpstep) const; /*! inline TInterval& TInterval::operator=( const TInterval& intv ) { start = intv.start; stop = intv.stop; return *this; } template inline TInterval::TInterval() { start = 0; stop = 0; } template inline TInterval::TInterval( const T& t1, const T& t2 ) { start = t1; stop = t2; } template inline TInterval* TInterval::clone() const { return new TInterval( *this ); } template inline void TInterval::set( const T& t1, const T& t2 ) { start = t1; stop = t2; } template inline bool TInterval::isEqual( const TInterval& i, const T& eps ) const { return mIsEqual(start,i.start,eps) && mIsEqual(stop,i.stop,eps); } template inline bool TInterval::operator==( const TInterval& i ) const { return start == i.start && stop == i.stop; } template inline bool TInterval::operator!=( const TInterval& i ) const { return ! (i == *this); } template inline TInterval TInterval::operator+( const TInterval& i ) const { return TInterval(start+i.start, stop+i.stop); } template inline TInterval& TInterval::operator+=( const TInterval& i ) { start += i.start; stop += i.stop; return *this; } template inline T TInterval::width( bool allowrev ) const { return allowrev && isRev() ? start - stop : stop - start; } template inline T TInterval::center() const { return (start+stop)/2; } template inline void TInterval::shift( const T& len ) { start += len; stop += len; } template inline void TInterval::widen( const T& len, bool allowrev ) { if ( allowrev && isRev() ) { start += len; stop -= len; } else { start -= len; stop += len; } } template inline void TInterval::scale( const T& factor ) { start *= factor; stop *= factor; } template inline bool TInterval::isIncludes( const T& t, bool allowrev ) const { return allowrev && isRev() ? t>=stop && start>=t : t>=start && stop>=t; } template inline void TInterval::include( const T& i, bool allowrev ) { if ( allowrev && isRev() ) { if ( stop >i ) stop=i; if ( starti ) start=i; if ( stop inline void TInterval::include( const TInterval& i, bool allowrev ) { include( i.start, allowrev ); include( i.stop, allowrev ); } template inline T TInterval::atIndex( int idx, const T& step ) const { return start + step * idx; } template void TInterval::sort( bool asc ) { if ( (asc && stop TIntervalStep::TIntervalStep() { step = 1; } template TIntervalStep::TIntervalStep( const T& t1, const T& t2, const T& t3 ) : TInterval(t1,t2) { step = t3; } template TIntervalStep::TIntervalStep( const TInterval& intv ) : TInterval(intv) { step = 1; } template void TIntervalStep::getString(char* str) const { if ( !str ) return; double xx[3]; xx[0] = start; xx[1] = stop; xx[2] = step; AfxGetBaseFunction()->PrintXYZ(str, xx, 3, ' '); } template void TIntervalStep::setString(char* str) { if ( !str ) return; double xx[3]; sscanf_s( str, _T("%lf %lf %lf"), xx, xx+1, xx+2 ); start = (T)xx[0]; stop = (T)xx[1]; step = (T)xx[2]; } template inline TInterval* TIntervalStep::clone() const { return new TIntervalStep( *this ); } template inline void TIntervalStep::set( const T& t1, const T& t2, const T& t3 ) { TInterval::set( t1, t2 ); step = t3; } template inline bool TIntervalStep::isEqual( const TIntervalStep& i, const T& eps ) const { return TInterval::isEqual(i,eps) && mIsEqual(step,i.step,eps); } template inline TIntervalStep& TIntervalStep::operator=(const TInterval& ti) { start = ti.start; stop = ti.stop; return *this; } template inline bool TIntervalStep::operator==( const TIntervalStep& i ) const { return TInterval::operator==(i) && i.step==step; } template inline bool TIntervalStep::operator!=( const TIntervalStep& i ) const { return ! (i == *this); } template inline T TIntervalStep::atIndex( int idx ) const { return TInterval::atIndex(idx,step); } template int TIntervalStep::getIndex( const double& t ) const { return (int)(( t - start ) / step); } template int TIntervalStep::nearestIndex( const double& t ) const { int nr = getIndex(t); const T atindex = atIndex(nr); double reldiff = (t-atindex)/step; if ( reldiff>=0.5 ) return nr+1; else if ( reldiff<=-0.5 ) return nr-1; return nr; } template inline T TIntervalStep::snap( const double& t ) const { return atIndex( nearestIndex( t ) ); } template inline void TIntervalStep::sort( bool asc ) { TInterval::sort(asc); if ( (asc && step < 0) || (!asc && step > 0) ) step = -step; } template inline void TIntervalStep::Normalise() //!< Makes sure start inline void TIntervalStep::scale( const T& factor ) { TInterval::scale( factor ); step *= factor; } template inline T TIntervalStep::snapStep( const T& inputstep ) const { const float relstep = (float) inputstep/step; int nrsteps = AfxGetBaseFunction()->FloatToLong(relstep); if ( nrsteps<1 ) nrsteps = 1; return step*nrsteps; } template inline float TIntervalStep::nrfSteps() const { const float w = (float)TInterval::width( true ); return w/step; } template inline int TIntervalStep::nrSteps() const { if ( !step ) return 0; int ret = (((int)this->start) - this->stop) / step; return ret < 0 ? -ret : ret; } #define mDefFNrSteps(typ,eps) \ template <> \ inline int TIntervalStep::nrSteps() const \ { \ if ( !step ) return 0; \ typ ns = ( (start > stop ? start : stop) \ - (start > stop ? stop : start) ) \ / (step > 0 ? step : -step); \ return (int)(ns * (1. + eps)); \ } mDefFNrSteps(float,1e-4) mDefFNrSteps(double,1e-8) template inline bool TIntervalStep::isCompatible( const TIntervalStep& b, float ) const { if ( step>b.step || b.step%step ) return false; // const T diff = static_cast*>(this)->start - b.start; const T diff = this->start - b.start; return !(diff%step); } #define mDefFltisCompat(typ) \ template <> \ inline bool TIntervalStep::isCompatible( const TIntervalStep& b, float eps ) const \ { \ if ( !mIsEqual(step,b.step,eps) ) return false; \ \ typ nrsteps = (start - b.start) / step; \ int nrstepsi = AfxGetBaseFunction()->FloatToLong( nrsteps ); \ typ diff = nrsteps - nrstepsi; \ return ( (diff) < (eps) && (diff) > (-eps) ); \ } mDefFltisCompat(float) mDefFltisCompat(double) }//namespace using namespace NSet; #endif //INTERVAL_H