HowManyAreAnalyzed(): use status_user_agent to report progress
[linguistica.git] / CollectionTemplate.tcc
blobd197a56a483cc2c030e79d4348b15ad40c816017
1 // Implementation of TCollection methods
2 // Copyright © 2009 The University of Chicago
3 #ifndef COLLECTIONTEMPLATE_TCC
4 #define COLLECTIONTEMPLATE_TCC
6 #include "CollectionTemplate.h"
8 #include <memory>
9 #include "Trie.h"
10 #include "Parse.h"
11 #include "LParse.h"
12 #include "MiniLexicon.h"
13 #include "Lexicon.h"
14 #include "linguisticamainwindow.h" 
15 #include "ui/Status.h"
16 #include "CompareFunc.h"
18 template<class T>
19 TCollection<T>::TCollection()
21         m_CorpusCount                   = 0;
22         m_DeletePointers                = TRUE;
23         m_DeletionArray                 = NULL;
24         m_HashHasChangedFlag    = FALSE;
25         m_MemberName                    = QString::null;
26         m_PointerArray                  = NULL;
27         m_pLexicon                              = NULL;
28         m_pMiniLex                              = NULL;
29         m_pReverseTrie                  = NULL;
30         m_pTerminalNodeArray    = NULL;
31         m_SortArray                             = NULL;
32         m_SortValidFlag                 = 0;
33         m_SortStyle                             = KEY;
34         m_TotalUseCount                 = 0;
38 template<class T>
39 TCollection<T>::TCollection(CMiniLexicon* Mini, QString MemberName)
40         : CTrie(),
41         m_CorpusCount(0),
42         m_DeletePointers(true),
43         m_DeletionArray(),
44         m_HashHasChangedFlag(false),
45         m_MemberName(MemberName),
46         m_PointerArray(),
47         m_pLexicon((Mini != 0) ? Mini->GetLexicon() : 0),
48         m_pMiniLex(Mini),
49         m_pReverseTrie(),
50         m_pTerminalNodeArray(),
51         m_SortArray(),
52         m_SortValidFlag(false),
53         m_SortStyle(KEY),
54         m_TotalUseCount(0.0) { }
56 template<class T>
57 TCollection<T>::TCollection( CLexicon* Lex, QString MemberName )
59         m_CorpusCount                   = 0;
60         m_DeletePointers                = TRUE;
61         m_DeletionArray                 = NULL;
62         m_HashHasChangedFlag    = FALSE;
63         m_MemberName                    = MemberName;
64         m_PointerArray                  = NULL; 
65         m_pLexicon                              = Lex;
66         m_pMiniLex                              = NULL;
67         m_pReverseTrie                  = NULL;
68         m_pTerminalNodeArray    = NULL;
69         m_SortArray                             = NULL;
70         m_SortValidFlag                 = 0;
71         m_SortStyle                             = KEY;
72         m_TotalUseCount                 = 0;
77 template<class T>
78 TCollection<T>::~TCollection()
80         if ( m_PointerArray )      { delete [] m_PointerArray; m_PointerArray = NULL;  }
81         if ( m_SortArray )         { delete [] m_SortArray; m_SortArray = NULL;  }
82         if ( m_DeletionArray)      { delete [] m_DeletionArray; m_DeletionArray = NULL; }
83         if ( m_pTerminalNodeArray ) { delete [] m_pTerminalNodeArray; m_pTerminalNodeArray = NULL; }
84         if ( m_pReverseTrie )       { delete m_pReverseTrie; m_pReverseTrie = NULL; }
87 template<class T>
88 T*  TCollection<T>::operator<<( CParse* pParse )
89 // Good for everything except CSignatures, which need punctuation.
91         CNode*            pTerminal;
92         int               Result;
93         QString           Key;
94         CStringSurrogate  cssKey;
96         cssKey = pParse->GetKey();
97         pTerminal = Insert (cssKey, &Result);
98         if (Result == 1) {
99                 std::auto_ptr<T> morpheme(new T(pParse));
100                 morpheme->SetIndex(GetCount() - 1);
101                 pTerminal->SetPointer(morpheme.release());
102         }
103         T* pT = static_cast<T*>(pTerminal->Get_T_Pointer());
105         // Add to the reverse trie also
106         if( m_pReverseTrie )
107         {
108                 cssKey.SetBackwards( TRUE );
109                 pTerminal = m_pReverseTrie->Insert( cssKey, &Result );
110                 if( Result == 1 )
111                 {
112                         pTerminal->SetPointer(pT);
113                 }
114         }
116         IncrementCorpusCount(1);
117         pT->IncrementCorpusCount(1);
119         m_SortValidFlag      = FALSE;
120         m_HashHasChangedFlag  = TRUE;
122         return pT;
126 // Used primarily:
127 template<class T>
128 T*  TCollection<T>::operator<< (CStringSurrogate SS)
130   QChar*        szWord = new QChar[SS.GetLength()];
131   CNode*        pTerminal;
132   int          Result;
134   LxStrCpy( &SS, szWord, SS.GetLength() );
135   
136   pTerminal = Insert ( CStringSurrogate(szWord,0,SS.GetLength()), &Result );
138         if (Result == 1) {
139                 std::auto_ptr<T> morpheme(new T(SS, m_pMiniLex));
140                 morpheme->SetIndex(GetCount() - 1);
141                 pTerminal->SetPointer(morpheme.release());
142         }
143         T* pT = static_cast<T*>(pTerminal->Get_T_Pointer());
145   // Add to the reverse trie also
146   if( m_pReverseTrie )
147   {
148     pTerminal = m_pReverseTrie->Insert( CStringSurrogate(szWord,0,SS.GetLength(),TRUE), &Result );
149     if( Result == 1 )
150     {
151       pTerminal->SetPointer(pT);
152     }
153   }
155   IncrementCorpusCount(1);
156   pT->IncrementCorpusCount(1);
158   m_SortValidFlag      = FALSE;
159   m_HashHasChangedFlag  = TRUE;
161   delete [] szWord;
163   return pT;           
167 template<class T>
168 T*  TCollection<T>::operator<< (QString szWord)
170   CNode*    pTerminal;
171   int      Result;
172   QChar*    pKey;
173   if ( szWord.isEmpty() ) { return NULL; }
175   pKey = new QChar [ szWord.length()];
176   LxStrCpy( szWord, pKey, szWord.length() );
178   pTerminal = Insert (CStringSurrogate( pKey, 0, szWord.length() ), &Result);
180         if (Result == 1) {
181                 std::auto_ptr<T> morpheme(new T(szWord, m_pMiniLex));
182                 morpheme->SetIndex(GetCount() - 1);
183                 pTerminal->SetPointer(morpheme.release());
184         }
185         T* pT = static_cast<T*>(pTerminal->Get_T_Pointer());
187   // Add to the reverse trie also
188   if( m_pReverseTrie )
189   {
190     pTerminal = m_pReverseTrie->Insert(CStringSurrogate( pKey, 0, szWord.length() ), &Result);
191     if( Result == 1 )
192     {
193       pTerminal->SetPointer(pT);
194     }
195   }
197   IncrementCorpusCount(1);
198   pT->IncrementCorpusCount(1);
200   m_SortValidFlag      = FALSE;
201   m_HashHasChangedFlag  = TRUE;
202   if (m_ReverseFlag) { delete  pKey; }
204   return pT;
208 template<class T> T* TCollection<T>::operator^=(CParse* string)
210         if (string->GetKeyLength() < 1)
211                 return 0;
212         Q_ASSERT(string->Size() >= 1);
213         if (CNode* node = Find1(m_ReverseFlag ?
214                         CStringSurrogate(string->GetReverse()) :
215                         CStringSurrogate(string)))
216                 return static_cast<T*>(node->Get_T_Pointer());
217         return 0;
220 template<class T> T* TCollection<T>::operator^=(CStringSurrogate string)
222         if (string.GetLength() < 1)
223                 return 0;
224         if (CNode* node = Find1(string))
225                 return static_cast<T*>(node->Get_T_Pointer());
226         return 0;
229 template<class T> T* TCollection<T>::operator^=(QString string)
231         if (string.isEmpty())
232                 return 0;
233         if (CNode* node = Find1(CStringSurrogate(string)))
234                 return static_cast<T*>(node->Get_T_Pointer());
235         return 0;
239 template<class T>
240 T*  TCollection<T>::operator[] ( uint n)
242   if ( m_PointerArray == NULL || m_HashHasChangedFlag == TRUE )
243   {
244     CreatePointerArray();
245   }
247         Q_ASSERT(GetCount() >= 0);
248         Q_ASSERT(n < static_cast<unsigned int>(GetCount()));
250   return m_PointerArray[n];
254 template<class T>
255 void TCollection<T>::AddPointer(T* pT)
257   CNode*    pTerminal;
258   CStringSurrogate    ssWord = pT->GetKey();
260   pTerminal = CTrie::operator<< (ssWord);
261   pTerminal->SetPointer ( pT );
263   // Add to the reverse trie also
264   if( m_pReverseTrie )
265   {
266     ssWord.SetBackwards(TRUE);
267     pTerminal = m_pReverseTrie->Insert( ssWord );
268     pTerminal->SetPointer(pT);
269   }
270   
271   pT->SetIndex ( GetCount() - 1);
272   IncrementCorpusCount(pT->GetCorpusCount());
276 template<class T>
277 T*  TCollection<T>::AddToCollection (const CParse& Word)
279   m_HashHasChangedFlag = TRUE;
280   T* pT;
281   pT = *this << Word;
282   return  pT;
286 template<class T>
287 T*  TCollection<T>::AddToCollection (const CStringSurrogate& Word)
289   T* pT;
290   m_HashHasChangedFlag = TRUE;
291   pT = *this << Word;
292   return pT;
296 template<class T>
297 bool  TCollection<T>::Contains ( CStringSurrogate& string )
299   T* pT = *this ^= string;
300   if ( pT )
301   {
302     return TRUE;
303   }
304   else
305   {
306     return FALSE;
307   }
311 template<class T>
312 void  TCollection<T>::CreatePointerArray()
314         Q_ASSERT(m_DeletionArray == 0);
315         const int size = GetCount();
317         delete[] m_PointerArray;
318         m_PointerArray = new T*[size];
319         delete[] m_pTerminalNodeArray;
320         m_pTerminalNodeArray = new CNode*[size];
322         MakeATerminalPointerArray(m_pTerminalNodeArray);
324         for (int i = 0; i < size; ++i) {
325                 m_PointerArray[i] = static_cast<T*>(
326                         m_pTerminalNodeArray[i]->Get_T_Pointer());
327                 m_PointerArray[i]->SetIndex(i);
328         }
330         m_HashHasChangedFlag = false;
334 template<class T>
335 void TCollection<T>::CreateReverseTrie()
337   CNode*            pTerminal;
338   CStringSurrogate  ssKey;
339   
340   if( m_pReverseTrie ) delete m_pReverseTrie;
341   m_pReverseTrie = new CTrie( TRUE );
342   m_pReverseTrie->SetAutoDelete( FALSE );
344         // Build the reverse trie from the
345         // forward trie
346         for (int i = 0; i < GetCount(); ++i)
347                 if (T* pT = GetAt(i)) {
348                         ssKey = pT->GetKey();
349                         ssKey.SetBackwards();
350                         pTerminal = m_pReverseTrie->Insert(ssKey);
351                         pTerminal->SetPointer(pT);
352                 }
356 template<class T>
357 void TCollection<T>::DeleteMarkedMembers()
359   // we want to do this without tripping the "trie has changed" flag along the way.
361   if ( m_DeletionArray == NULL ) { return; }
363   int count = GetCount();
364   for (int i = 0; i < count; i++)
365   {
366     if ( m_DeletionArray[i] == 1 )
367     {
368       CStringSurrogate key = m_PointerArray[i]->GetKey();
369       Q_ASSERT( RemoveFromTrie( key ) );
370       if( m_pReverseTrie )
371       {
372         key.SetBackwards();
373         Q_ASSERT( "void TCollection<T>::DeleteMarkedMembers() : Type existed in forward trie but not reverse trie." && m_pReverseTrie->RemoveFromTrie( key ) );
374       }
375     }
376   }
378 //  m_LockState        = Unlocked;
379   m_HashHasChangedFlag  = TRUE;
380   delete m_DeletionArray;
381   m_DeletionArray      = NULL;
385 template<class T>
386 void TCollection<T>::DoNotDeletePointers()
388   m_DeletePointers = FALSE;
392 template<class T>
393 void  TCollection<T>::DumpVisibleToLogFile()
395   if (! m_pLexicon->GetLogFileStream()) { return; }
396   GetRoot1()->DumpVisibleToLogFile( m_pLexicon->GetLogFileStream(), m_ReverseFlag );
400 template<class T>
401 void  TCollection<T>::DumpVisibleWords(CWordCollection* Words)
403   GetRoot1()->DumpVisibleWords(Words, FALSE);
407 template<class T>
408 void TCollection<T>::Empty()
410   ResetToEmpty();
411   if( m_pReverseTrie ) m_pReverseTrie->ResetToEmpty();
412   if (m_SortArray) { delete [] m_SortArray; m_SortArray = NULL; }
413   if (m_PointerArray) { delete [] m_PointerArray; m_PointerArray = NULL; }
415   m_CorpusCount        = 0;
416   m_SortValidFlag      = FALSE;
417   m_HashHasChangedFlag = TRUE;
421 template<class T>
422 CStringSurrogate TCollection<T>::FindMaximalMajorityPrefix()
424   CNode* pNode = FindLowestMajorityNode();
426   if (pNode) return pNode->GetKey();
427   else return CStringSurrogate();
431 template<class T>
432 void TCollection<T>::FindMemberExtensions (int SmallestStemSize, TCollection<CLParse>& Output )
435   T*          pMorpheme;
436   CLParse*      pChain = NULL;
438   Sort (KEY);
440   for (int  i = 0; i < GetCount(); i++)
441   {
442     pMorpheme  = GetAtSort(i);
443     if (pMorpheme->GetLength() < SmallestStemSize + 1) { continue; }
444     pChain    = SeekChain (pMorpheme, pChain, SmallestStemSize);
445     if (pChain)
446     {
447       Output.AddPointer (pChain);
448       m_pLexicon->AddToScreen ( pChain->Display() );
449       pChain = NULL;
450     }
451   }
455 template<class T>
456 CStringSurrogate TCollection<T>::FSAGetAtSS(uint n)
458   Q_ASSERT ( n < (uint) GetCount() );
460   if ( m_PointerArray == NULL || m_HashHasChangedFlag == TRUE )
461   {
462     CreatePointerArray();
463     Q_ASSERT ( n == 0 );
464   }
466   return m_pTerminalNodeArray[n]->GetKey();
470 template<class T>
471 T*  TCollection<T>::GetAt ( uint n )
473         Q_ASSERT(GetCount() >= 0);
474         Q_ASSERT(n < static_cast<unsigned int>(GetCount()));
476   if ( m_PointerArray == NULL || m_HashHasChangedFlag == TRUE )
477   {
478     CreatePointerArray();
479     Q_ASSERT ( n == 0 );
480   }
482   return m_PointerArray[n];
486 template<class T>
487 CStringSurrogate TCollection<T>::GetAt_SS( int n )
489   CStringSurrogate Return ( GetAt(n)->GetKeyPointer(), 0, GetAt(n)->GetKeyLength() );
491   return Return;
495 template<class T>
496 T* TCollection<T>::GetAtSort( int n )
498         if( !m_SortArray || !m_SortValidFlag ) Sort( m_SortStyle );
499         return m_SortArray[n];
503 template<class T> CStringSurrogate TCollection<T>::GetAtSort_SS(int n)
505         if (m_SortArray == 0)
506                 Sort(m_SortStyle);
507         return CStringSurrogate(m_SortArray[n]->GetKeyPointer(),
508                         m_SortArray[n]->GetKeyLength());
511 template<class T> int TCollection<T>::GetCorpusCount() const
512 { return m_CorpusCount; }
514 template<class T>
515 CLexicon* TCollection<T>::GetLexicon()
517         return m_pLexicon;
521 template<class T>
522 CMiniLexicon* TCollection<T>::GetMiniLexicon()
524         return m_pMiniLex;
528 template<class T>
529 CTrie* TCollection<T>::GetReverseTrie()
531         if( !m_pReverseTrie ) CreateReverseTrie();
532         return m_pReverseTrie;
536 template<class T>
537 int  TCollection<T>::GetSortValidFlag()
539   return m_SortValidFlag;
543 template<class T>
544 CTrie*  TCollection<T>::GetTrie()
546         return this;
549 template<class T>
550 int TCollection<T>::GetWidth( CStringSurrogate string )// i.e., from Trie
552   CNode *pNode = Find1 ( string );
553   return pNode->GetWidth();
557 template<class T>
558 void TCollection<T>::IncrementCorpusCount( int n )
560         m_CorpusCount += n;
564 template<class T>
565 void TCollection<T>::MarkForDeletion(int n)
567   if ( m_DeletionArray == NULL)
568   {
569      m_DeletionArray = new int [ GetCount() ];
570     for (int i = 0; i < GetCount(); i++)
571     {        
572       m_DeletionArray[i] = 0;
573     }
574   }
575   m_DeletionArray [n] = 1;
579 template<class T>
580 void TCollection<T>::RecomputeCorpusCount()
582   m_CorpusCount = 0;
583   for (int i = 0; i < GetCount(); i++)
584   {
585     m_CorpusCount += GetAt(i)->GetCorpusCount();
586   }
587   return;
591 template<class T>
592 bool TCollection<T>::Remove (T* pT) // this doesn't delete pT
593 {  bool bResult (FALSE);
594   QString display = pT->Display();
595   CStringSurrogate ssDisplay( display );
597   bResult = RemoveFromTrie ( ssDisplay, FALSE );
599   if ( bResult )
600   {
601     m_SortValidFlag      = FALSE;
602     m_HashHasChangedFlag  = TRUE;
604     if( m_pReverseTrie )    {
605       ssDisplay.SetBackwards();
606       Q_ASSERT( "bool TCollection<T>::Remove (T* pT) : Type existed in forward trie but not reverse trie." && m_pReverseTrie->RemoveFromTrie( ssDisplay ) );
607     }
608     return TRUE;
609   }
610   else  {
611     return FALSE;
612   }
613  return FALSE;
617 template<class T>
618 void TCollection<T>::RemoveAll()
620   if ( m_SortArray ) { delete [] m_SortArray; m_SortArray = NULL; }
621   if ( m_PointerArray ) { delete [] m_PointerArray; m_PointerArray = NULL; }
623   ResetToEmpty();
624   if( m_pReverseTrie ) m_pReverseTrie->ResetToEmpty();
628 template<class T>
629 bool TCollection<T>::RemoveMember ( T* pT )  // this deletes pT
631   bool ReturnValue = Remove (pT);
632   delete pT;
633   return ReturnValue;
636 template<class T>
637 bool TCollection<T>::RemoveMember ( const CStringSurrogate& ssT )  // this deletes pT
639   bool    bResult;
641   bResult = RemoveFromTrie ( ssT );
643   if ( bResult )
644   {
645     m_SortValidFlag      = FALSE;
646     m_HashHasChangedFlag  = TRUE;
647     if( m_pReverseTrie )
648     {
649       // XXX. remove from reverse trie
650     }
651     return TRUE;
652   }
653   else
654   {
655     return FALSE;
656   }
660 template<class T>
661 bool TCollection<T>::RemoveMember ( const CStringSurrogate& ssT, bool DeleteFlag )  // this can choose whether or not to delete pT
664   bool    bResult;
666   bResult = RemoveFromTrie ( ssT, DeleteFlag );
668   if ( bResult )
669   {
670     m_SortValidFlag      = FALSE;
671     m_HashHasChangedFlag  = TRUE;
672     if( m_pReverseTrie )
673     {
674       CStringSurrogate ss_copy = ssT;
675       ss_copy.SetBackwards();
676       if (!m_pReverseTrie->RemoveFromTrie(ss_copy))
677         Q_ASSERT( !"bool TCollection<T>::RemoveMember ( CStringSurrogate& ssT ) : Type existed in forward trie but not reverse trie." );
678       ss_copy.SetBackwards(false);
679     }
680     return TRUE;
681     return TRUE;
682   }
683   else
684   {
685     return FALSE;
686   }
691 template<class T>
692 void TCollection<T>::SetKey( T* pT, CParse& NewKey )
694   CNode* pTerminal;
695   CStringSurrogate ssKey = pT->GetKey();
697   RemoveFromTrie ( ssKey, FALSE);
698   pTerminal = Insert ( NewKey.GetKey() );
699   pTerminal->SetPointer (pT);
701   if( m_pReverseTrie )
702   {
703     ssKey.SetBackwards();
704     Q_ASSERT( m_pReverseTrie->RemoveFromTrie( ssKey ) && "bool TCollection<T>::RemoveMember ( CStringSurrogate& ssT ) : Type existed in forward trie but not reverse trie." );
705     ssKey = NewKey.GetKey();
706     ssKey.SetBackwards();
707     pTerminal = m_pReverseTrie->Insert( ssKey );
708     pTerminal->SetPointer(pT);
709   }
713 template<class T>
714 void TCollection<T>::SetKey( T* pT, QString NewKey )
716   CNode* pTerminal;
717   CStringSurrogate ssKey = pT->GetKey();
719   RemoveFromTrie ( ssKey );
720   pTerminal = Insert ( NewKey );
721   pTerminal->SetPointer (pT);
723   if( m_pReverseTrie )
724   {
725     ssKey.SetBackwards();
726     Q_ASSERT( m_pReverseTrie->RemoveFromTrie( ssKey ) && "bool TCollection<T>::RemoveMember ( CStringSurrogate& ssT ) : Type existed in forward trie but not reverse trie." );
727     ssKey = NewKey;
728     ssKey.SetBackwards();
729     pTerminal = m_pReverseTrie->Insert( ssKey );
730     pTerminal->SetPointer(pT);
731   }
735 template<class T>
736 void  TCollection<T>::SetSortStyle(eSortStyle SS)
738   m_SortStyle = SS;
742 template<class T>
743 void  TCollection<T>::SetSortValidFlag(bool value)
745         m_SortValidFlag = value;
749 template<class T>
750 void  TCollection<T>::Sort( eSortStyle SS )
752   int i;
754   if (m_SortStyle == SS && m_SortValidFlag == TRUE)
755   { return; }
757   int Size = GetCount();
759   if (m_SortArray) { delete [] m_SortArray; }
760   m_SortArray = new T*[ Size ];
762   for (i = 0; i < Size; i++)
763   {
764     m_SortArray[i] = GetAt( i );
765   }
767   switch ( SS )
768   {
769   case KEY:
770     {
771       qsort(m_SortArray, Size, sizeof(T*), CompareAlphabetically);
772       break;
773     }
774   case COUNT :
775   case CORPUSCOUNT:
776     {
777     qsort(m_SortArray, Size, sizeof(T*), CompareCorpusCount);
778     break;
779     }
780   case SIGS:    
781   case RULE_USE:
782   case MORPHEME_GOODNESS:
783     {
784       qsort(m_SortArray, Size, sizeof(T*), CompareSortingQuantity);
785       break;
786     }
787   case TEMPLATE_SORT:
788     {
789       qsort(m_SortArray, Size, sizeof(T*), CompareSortingQuantity);
790       break;
791     }
792   case PARSE_SIZE:
793     {
794       qsort(m_SortArray, Size, sizeof(T*), CompareSize);
795       break;
796     }
797   case SIGS_NUMBER_OF_STEMS:
798     {
799       qsort(m_SortArray, Size, sizeof(T*), CompareNumberOfStems);
800       break;
801     }
802   case STEM_SUFFIXES:
803     {
804       qsort(m_SortArray, Size, sizeof(T*), CompareSortingString);
805       break;
806     }
807   case REVERSE_KEY:
808     {
809       qsort(m_SortArray, Size, sizeof(T*), CompareReverseAlphabetically);
810       break;
811     }
812   case LENGTH:
813     {
814       qsort(m_SortArray, Size, sizeof(T*), CompareLength);
815       break;
816     }
817   case DL_SAVINGS:
818     {
819       qsort(m_SortArray, Size, sizeof(T*), CompareDLSavings);
820       break;
821     }
822   case FREQUENCY:
823     {
824       qsort(m_SortArray, Size, sizeof(T*), CompareFrequency);
825       break;
826     }
827   case MORPHEMECOUNT:
828     {
829       qsort(m_SortArray, Size, sizeof(T*), CompareMorphemeCount);
830       break;
831     }
832   case USECOUNT:
833     {
834       qsort(m_SortArray, Size, sizeof(T*), CompareUseCount);
835       break;
836     }
837   case SIG_REMARK:
838     {
839       qsort(m_SortArray, Size, sizeof(T*), CompareSigRemark);
840       break;
841     }
842   case STEM_SOURCE:
843     {
844       qsort(m_SortArray, Size, sizeof(T*), CompareStemSource);
845       break;
846     }
847   default:
848       break;
849   }
851   for ( i = 0; i < Size; i++)
852   {
853     m_SortArray[i]->SetSortIndex(i);
854   }
856   m_SortStyle = SS;
857   m_SortValidFlag = TRUE;
861 template<class T>
862 void TCollection<T>::T_PredecessorFrequency(
863         enum eSuccessorFrequencyMode PFM,
864         CStemCollection* Stems, CPrefixCollection* Prefixes,
865         int MaxNeighborPredecessorCount,
866         int MaximumPrefixLength,
867         int MinimumStemLength,
868         int RightMargin, int LeftMargin)
870         T* pWord;
871         CStringSurrogate ssStem, ssWord, ssPrefix;
872         int WordLength, nRightMargin, nLeftMargin, j;
873         CNode* qNode;
875         if (!m_pReverseTrie)
876                 CreateReverseTrie();
878         linguistica::ui::status_user_agent& status = m_pLexicon->status_display();
880         status.progress.clear();
881         status.progress.set_denominator(GetCount());
882         for (int i = 0; i < GetCount(); i++) {
883                 status.progress = i;
885                 pWord = GetAt(i);
886                 ssWord = *pWord;
887                 ssWord.SetBackwards();
888                 WordLength = pWord->GetKeyLength();
890                 if (pWord->MayBeParsed() == FALSE)
891                         // if it's a compound, or parsed on the PF1 pass through this function.
892                         continue;
894                 if (LeftMargin >= 0)
895                         nLeftMargin = WordLength - LeftMargin;
896                 else
897                         nLeftMargin = WordLength - 1;
899                 if (RightMargin >= 0)
900                         nRightMargin = RightMargin;
901                 else
902                         nRightMargin = nLeftMargin - MaximumPrefixLength;
904                 CNode* pNode = m_pReverseTrie->GetRoot1();
906                 int* SFArray = new int[WordLength + 2];
908                 // This array keeps track in position i of
909                 // how many alternatives to character i there are ( + 1) in the data.
910                 for (j = 0; j < WordLength + 2; j++)
911                         SFArray[j] = 0;
913                 int loc = 0;
914                 while (loc <= WordLength) {
915                         for (; loc < pNode->m_BreakPoint && loc < WordLength; loc++) {
916                                 SFArray[loc] = 1;
917                                 Q_ASSERT (loc < WordLength);
918                         }
919                         if (loc == WordLength) {
920                                 SFArray[loc] = pNode->GetWidth();
921                                 break;
922                         } else {
923                                 SFArray[loc] = pNode->GetWidth();
924                                 qNode = pNode->FindLetter(ssWord[loc]);
925                                 if (qNode == NULL) {
926                                         Q_ASSERT(pNode->GetKey() == ssWord);
927                                         for ( ; loc <= WordLength; loc++)
928                                                 SFArray[loc] = 1;
929                                         break;
930                                 } else
931                                         pNode = qNode;
932                                 loc++;
933                         }
934                 }
936                 for (int w = nLeftMargin; w > nRightMargin && w >= MinimumStemLength ; w--) {
937                         if (PFM == SF1) {
938                                 if (SFArray[w-1] <= MaxNeighborPredecessorCount &&
939                                     SFArray[w] > 1 &&
940                                     SFArray[w+1] <= MaxNeighborPredecessorCount) {
941                                         // use only the smallest prefix --
942                                         // this is wrong in some cases
943                                         // (assist-an-t, assist-an-ce, for example).
945                                         pWord->CutRightBeforeHere(WordLength - w);
946                                         break;
947                                 }
948                         }
950                         // Here the condition is that the first piece must already exist in Stems,
951                         // and the second piece must already exist in Prefixes;
952                         // and the "peak"  need only be not LOWER than the neighbors are.
953                         if (PFM == SF2) {
954                                 if (SFArray[w-1] <= SFArray[w] &&
955                                     SFArray[w] > 1 &&
956                                     SFArray[w+1] <= SFArray[w]) {
957                                         ssStem = ssWord.Left(w - 1);
958                                         if (!(*Stems ^= ssStem))
959                                                 continue;
960                                         ssPrefix = ssWord.Right(ssWord.GetLength() - w);
961 //                                      ssPrefix = ssPrefix.Left(ssPrefix.GetLength()1);
962                                         if (!(*Prefixes ^= ssPrefix))
963                                                 continue;
964                                         // use only the smallest prefix --
965                                         // this is wrong in some cases
966                                         // (assist-an-t, assist-an-ce, for example).
968                                         pWord->CutRightBeforeHere(w);
969                                         break;
970                                 }
971                         }
972                 }
973                 delete [] SFArray;
974         }
975         status.progress.clear();
978 template<class T>
979 void TCollection<T>::T_SuccessorFrequency(
980         enum eSuccessorFrequencyMode SFM,
981         CStemCollection* Stems, CSuffixCollection* Suffixes,
982         int MaxNeighborSuccessorCount,
983         int MaximumSuffixLength,
984         int MinimumStemLength,
985         int LeftMargin, int RightMargin)
987         T* pWord;
988         CStringSurrogate ssStem, ssWord, ssSuffix;
989         int WordLength, nLeftMargin, nRightMargin, j;
990         CNode* qNode;
992         linguistica::ui::status_user_agent& status = m_pLexicon->status_display();
993         status.progress.clear();
994         status.progress.set_denominator(GetCount());
995         for (int i = 0; i < GetCount(); i++) {
996                 status.progress = i;
998                 pWord = GetAt(i);
999                 ssWord = *pWord;
1000                 WordLength = pWord->GetKeyLength();
1002                 if (pWord->MayBeParsed() == FALSE)
1003                         // if it's a compound, or
1004                         // parsed on the SF1 pass through this function.
1005                         continue;
1007                 if (RightMargin >= 0)
1008                         nRightMargin = WordLength - RightMargin;
1009                 else
1010                         nRightMargin = WordLength - 1;
1012                 if (LeftMargin >= 0)
1013                         nLeftMargin = LeftMargin;
1014                 else
1015                         nLeftMargin = nRightMargin - MaximumSuffixLength;
1017                 CNode* pNode = GetRoot1();
1019                 int* SFArray = new int[WordLength + 2];
1021                 // This array keeps track in position i of
1022                 // how many alternatives to character i there are ( + 1) in the data.
1023                 for (j = 0; j < WordLength + 2; j++)
1024                         SFArray[j] = 0;
1026                 int loc = 0;
1027                 while (loc <= WordLength) {
1028                         for (; loc < pNode->m_BreakPoint && loc < WordLength; loc++) {
1029                                 SFArray[loc] = 1;
1030                                 Q_ASSERT (loc < WordLength);
1031                         }
1032                         if (loc == WordLength) {
1033                                 SFArray[loc] = pNode->GetWidth();
1034                                 break;
1035                         } else {
1036                                 SFArray[loc] = pNode->GetWidth();
1037                                 qNode = pNode->FindLetter(ssWord[loc]);
1038                                 if (qNode == NULL) {
1039                                         Q_ASSERT(pNode->GetKey() == ssWord);
1040                                         for ( ; loc <= WordLength; loc++)
1041                                                 SFArray[loc] = 1;
1042                                         break;
1043                                 } else
1044                                         pNode = qNode;
1045                                 loc++;
1046                         }
1047                 }
1049                 for (int w = nRightMargin  ; w > 1 && w > nLeftMargin && w >= MinimumStemLength ; w--) {
1050                         if (SFM == SF1) {
1051                                 if (SFArray[w-1] <= MaxNeighborSuccessorCount &&
1052                                     SFArray[w] > 1 &&
1053                                     SFArray[w+1] <= MaxNeighborSuccessorCount) {
1054                                         // use only the smallest suffix --
1055                                         // this is wrong in some cases
1056                                         // (assist-an-t, assist-an-ce, for example).
1057                                         pWord->CutRightBeforeHere(w);
1058                                         m_pLexicon->UpdateWord(pWord);
1059                                         break;
1060                                 }
1061                         }
1063                         // Here the condition is that the first piece must already exist in Stems,
1064                         // and the second piece must already exist in Suffixes;
1065                         // and the "peak"  need only be not LOWER than the neighbors are.
1066                         if (SFM == SF2) {
1067                                 if (SFArray[w-1] <= SFArray[w] &&
1068                                     SFArray[w] > 1 &&
1069                                     SFArray[w+1] <= SFArray[w]) {
1070                                         ssStem = ssWord.Left(w - 1);
1071                                         if (!(*Stems ^= ssStem))
1072                                                 continue;
1073                                         ssSuffix = ssWord.Right(ssWord.GetLength() - w);
1074 //                                      ssSuffix = ssSuffix.Left(ssSuffix.GetLength() 1);
1075                                         if (!(*Suffixes ^= ssSuffix))
1076                                                 continue;
1078                                         // use only the smallest suffix --
1079                                         // this is wrong in some cases
1080                                         // (assist-an-t, assist-an-ce, for example).
1081                                         pWord->CutRightBeforeHere(w);
1082                                         m_pLexicon->UpdateWord(pWord);
1083                                         break;
1084                                 }
1085                         }
1086                 }
1087                 delete[] SFArray;
1088         }
1089         status.progress.clear();
1092 #endif // COLLECTIONTEMPLATE_TCC