Construction time&space fix
[SXSI/TextCollection.git] / TextCollectionBuilder.cpp
1 #include "incbwt/rlcsa_builder.h"
2 #include "TextCollectionBuilder.h"
3
4 // Un-comment next line to run a comparison of resulting BWT
5 //#define TCB_TEST_BWT
6
7 #ifdef TCB_TEST_BWT
8 #include "dynFMI.h"
9 #endif
10
11 #include "TCImplementation.h"
12
13 namespace SXSI
14 {
15
16 struct TCBuilderRep
17 {
18     unsigned samplerate;
19     CSA::RLCSABuilder * sa;
20
21     ulong n;
22     // Total number of texts in the collection
23     unsigned numberOfTexts;
24     // Length of the longest text
25     ulong maxTextLength;
26     ulong numberOfSamples;
27
28 #ifdef TCB_TEST_BWT
29     DynFMI *dynFMI;
30 #endif
31 };
32
33 /**
34  * Init text collection
35  *
36  * See CSA.h for more details.
37  */
38 TextCollectionBuilder::TextCollectionBuilder(unsigned samplerate)
39     : p_(new struct TCBuilderRep())
40 {
41     p_->n = 0;
42     p_->samplerate = samplerate;
43     p_->numberOfTexts = 0;
44     p_->numberOfSamples = 0;
45     
46     // Current params: 8 bytes, 15 MB, no samples
47     p_->sa = new CSA::RLCSABuilder(8, 0, 15 * 1024 * 1024);
48     assert(p_->sa->isOk());
49
50 #ifdef TCB_TEST_BWT
51     uchar temp[256];
52     for (unsigned i = 0; i < 255; ++i)
53         temp[i] = i+1;
54     temp[255] = 0;
55     p_->dynFMI = new DynFMI(temp, 1, 255, false);
56 #endif
57 }
58
59 TextCollectionBuilder::~TextCollectionBuilder()
60 {
61 #ifdef TCB_TEST_BWT
62     delete p_->dynFMI;
63 #endif
64
65     delete p_->sa;
66     delete p_;
67 }
68
69 void TextCollectionBuilder::InsertText(uchar const * text)
70 {
71     TextCollection::TextPosition m = std::strlen((char *)text) + 1;
72     if (m > p_->maxTextLength)
73         p_->maxTextLength = m; // Store length of the longest text seen so far.
74
75     if (m > 1)
76     {
77         p_->n += m;
78         p_->numberOfTexts ++;
79         p_->numberOfSamples += (m-1)/p_->samplerate;
80
81 #ifdef TCB_TEST_BWT
82         p_->dynFMI->addText(text, m);
83 #endif
84         p_->sa->insertSequence((char*)text, m-1, 0);
85         assert(p_->sa->isOk());
86     }
87     else
88     {
89         // FIXME indexing empty texts
90         std::cerr << "TextCollectionBuilder::InsertText() error: can not index empty texts!" << std::endl;
91         exit(1);
92     }
93 }
94
95
96 TextCollection * TextCollectionBuilder::InitTextCollection()
97 {
98     uchar * bwt = 0;
99     CSA::usint length = 0;
100     if (p_->numberOfTexts == 0)
101     {
102         p_->numberOfTexts ++; // Add one empty text
103         bwt = new uchar[2];
104         bwt[0] = '\0';
105         bwt[1] = '\0';
106         length = 1;
107         p_->maxTextLength = 1;
108     }
109     else
110     {
111         bwt = (uchar *)p_->sa->getBWT(length);
112         delete p_->sa;
113         p_->sa = 0;
114
115         assert(length == p_->n);
116
117 #ifdef TCB_TEST_BWT
118         { 
119             uchar *bwtTest = p_->dynFMI->getBWT();
120             printf("123456789012345678901234567890123456789\n");
121             for (ulong i = 0; i < p_->n && i < 100; i ++)
122                 if (bwt[i] < 50)
123                     printf("%d", (int)bwt[i]);
124                 else
125                     printf("%c", bwt[i]);
126             printf("\n");
127             for (ulong i = 0; i < p_->n && i < 100; i ++)
128                 if (bwtTest[i] < 50)
129                     printf("%d", (int)bwtTest[i]);
130                 else
131                     printf("%c", bwtTest[i]);
132             printf("\n");
133             
134             // Sanity check
135             assert(p_->numberOfTexts == p_->dynFMI->getCollectionSize());    
136             
137             delete p_->dynFMI;
138             p_->dynFMI = 0;
139             for (ulong i = 0; i < p_->n; ++i)
140                 if (bwt[i] != bwtTest[i])
141                 {
142                     std::cout << "i = " << i << ", bwt = " << (unsigned)bwt[i] << ", " 
143                               << (unsigned)bwtTest[i] << std::endl;
144                     assert(0);
145                 }
146             delete [] bwtTest;
147         }
148 #endif // TCB_TEST_BWT
149     }
150
151     TextCollection *result = new TCImplementation(bwt, (ulong)length, 
152                       p_->samplerate, p_->numberOfTexts, p_->maxTextLength, p_->numberOfSamples);
153     return result;
154 }
155
156
157 } // namespace SXSI