From f57bc1ef7840cc8bd9055165fddd25637bd50ba1 Mon Sep 17 00:00:00 2001 From: Steve Checkoway Date: Thu, 17 Aug 2006 17:58:45 +0000 Subject: [PATCH] Use NoteData::iterator instead of a track-row pair. With n nonempty rows in the NoteData and m nonempty rows in the range, iterating over the whole range took O(m log n). Now, it takes O(m). (Saves the map look ups which are amortized log-time.) --- stepmania/src/NoteData.cpp | 44 +++++++++++--------------------------- stepmania/src/NoteData.h | 19 ++++++++-------- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index ae29068c27..c5cb87bdac 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -913,56 +913,39 @@ void NoteData::LoadFromNode( const XNode* pNode ) } template -void NoteData::_all_tracks_iterator::NextRowAllTracks() +void NoteData::_all_tracks_iterator::Find() { - int iMinRow = INT_MAX; + int iMinRow = m_iEndRow+1; for( int iTrack = 0; iTrack < m_NoteData.GetNumTracks(); ++iTrack ) { - int iRow = m_iRow; + iter &i = m_vIters[iTrack]; + if( m_Cond ) + while( i != m_NoteData.end(iTrack) && i->first < iMinRow && !m_Cond(i->second) ) + ++i; - if( m_NoteData.GetNextTapNoteRowForTrack(iTrack, iRow) ) - iMinRow = min( iMinRow, iRow ); - } - m_iRow = iMinRow; -} - -template -void NoteData::_all_tracks_iterator::Find() -{ - m_iRow = max( m_iRow, m_iStartRow ); - while( m_iRow <= m_iEndRow ) - { - while( m_iTrack < m_NoteData.GetNumTracks() ) + if( i != m_NoteData.end(iTrack) && i->first < iMinRow ) { - m_Iterator = m_NoteData.FindTapNote( m_iTrack, m_iRow ); - - if( m_Iterator != m_NoteData.end(m_iTrack) && (!m_Cond || m_Cond(m_Iterator->second)) ) - return; - ++m_iTrack; + iMinRow = i->first; + m_iTrack = iTrack; } - m_iTrack = 0; - ++m_iRow; - int oldRow = m_iRow; - NextRowAllTracks(); - ASSERT( oldRow < m_iRow ); } } template NoteData::_all_tracks_iterator::_all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, NoteData::IteratorCond cond ) : - m_NoteData(nd), m_iTrack(0), m_iRow(0), m_iStartRow(iStartRow), m_iEndRow(iEndRow), m_Cond(cond) + m_NoteData(nd), m_iTrack(0), m_iEndRow(iEndRow), m_Cond(cond) { ASSERT( m_NoteData.GetNumTracks() > 0 ); - NextRowAllTracks(); + for( int iTrack = 0; iTrack < m_NoteData.GetNumTracks(); ++iTrack ) + m_vIters.push_back( m_NoteData.lower_bound(iTrack, iStartRow) ); Find(); } template NoteData::_all_tracks_iterator &NoteData::_all_tracks_iterator::operator++() // preincrement { - DEBUG_ASSERT( m_iRow <= m_iEndRow ); - ++m_iTrack; + ++m_vIters[m_iTrack]; Find(); return *this; } @@ -970,7 +953,6 @@ NoteData::_all_tracks_iterator &NoteData::_all_tracks_iterator NoteData::_all_tracks_iterator NoteData::_all_tracks_iterator::operator++( int dummy ) // postincrement { - DEBUG_ASSERT( m_iRow <= m_iEndRow ); _all_tracks_iterator ret(*this); operator++(); return ret; diff --git a/stepmania/src/NoteData.h b/stepmania/src/NoteData.h index f9effb38f4..25d54ea338 100644 --- a/stepmania/src/NoteData.h +++ b/stepmania/src/NoteData.h @@ -32,26 +32,23 @@ public: class _all_tracks_iterator { ND &m_NoteData; + vector m_vIters; int m_iTrack; - int m_iRow; - const int m_iStartRow; const int m_iEndRow; - iter m_Iterator; IteratorCond m_Cond; - void NextRowAllTracks(); void Find(); public: _all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, IteratorCond cond ); _all_tracks_iterator &operator++(); // preincrement _all_tracks_iterator operator++( int dummy ); // postincrement inline int Track() const { return m_iTrack; } - inline int Row() const { return m_iRow; } - inline bool IsAtEnd() const { return m_iRow > m_iEndRow; } - inline TN &operator*() { DEBUG_ASSERT( m_iRow <= m_iEndRow ); return m_Iterator->second; } - inline TN *operator->() { DEBUG_ASSERT( m_iRow <= m_iEndRow ); return &m_Iterator->second; } - inline const TN &operator*() const { DEBUG_ASSERT( m_iRow <= m_iEndRow ); return m_Iterator->second; } - inline const TN *operator->() const { DEBUG_ASSERT( m_iRow <= m_iEndRow ); return &m_Iterator->second; } + inline int Row() const { return m_vIters[m_iTrack]->first; } + inline bool IsAtEnd() const { return m_vIters[m_iTrack] == m_NoteData.end( m_iTrack ) || Row() > m_iEndRow; } + inline TN &operator*() { DEBUG_ASSERT( !IsAtEnd() ); return m_vIters[m_iTrack]->second; } + inline TN *operator->() { DEBUG_ASSERT( !IsAtEnd() ); return &m_vIters[m_iTrack]->second; } + inline const TN &operator*() const { DEBUG_ASSERT( !IsAtEnd() ); return m_vIters[m_iTrack]->second; } + inline const TN *operator->() const { DEBUG_ASSERT( !IsAtEnd() ); return &m_vIters[m_iTrack]->second; } }; typedef _all_tracks_iterator all_tracks_iterator; typedef _all_tracks_iterator all_tracks_const_iterator; @@ -86,6 +83,8 @@ public: const_iterator begin( int iTrack ) const { return m_TapNotes[iTrack].begin(); } iterator end( int iTrack ) { return m_TapNotes[iTrack].end(); } const_iterator end( int iTrack ) const { return m_TapNotes[iTrack].end(); } + iterator lower_bound( int iTrack, int iRow ) { return m_TapNotes[iTrack].lower_bound( iRow ); } + const_iterator lower_bound( int iTrack, int iRow ) const { return m_TapNotes[iTrack].lower_bound( iRow ); } void swap( NoteData &nd ) { m_TapNotes.swap( nd.m_TapNotes ); } inline iterator FindTapNote( unsigned iTrack, int iRow ) { return m_TapNotes[iTrack].find( iRow ); }