Minimum buffer size
[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  */
37 TextCollectionBuilder::TextCollectionBuilder(unsigned samplerate, ulong estimatedInputLength)
38     : p_(new struct TCBuilderRep())
39 {
40     p_->n = 0;
41     p_->samplerate = samplerate;
42     p_->numberOfTexts = 0;
43     p_->numberOfSamples = 0;
44     
45     // Current params: 8 bytes, no samples, buffer size n/10 bytes.
46     // Buffer size is always at least 15MB:
47     if (estimatedInputLength < TEXTCOLLECTION_DEFAULT_INPUT_LENGTH)
48         estimatedInputLength = TEXTCOLLECTION_DEFAULT_INPUT_LENGTH;
49     p_->sa = new CSA::RLCSABuilder(8, 0, estimatedInputLength/10);
50     assert(p_->sa->isOk());
51
52 #ifdef TCB_TEST_BWT
53     uchar temp[256];
54     for (unsigned i = 0; i < 255; ++i)
55         temp[i] = i+1;
56     temp[255] = 0;
57     p_->dynFMI = new DynFMI(temp, 1, 255, false);
58 #endif
59 }
60
61 TextCollectionBuilder::~TextCollectionBuilder()
62 {
63 #ifdef TCB_TEST_BWT
64     delete p_->dynFMI;
65 #endif
66
67     delete p_->sa;
68     delete p_;
69 }
70
71 void TextCollectionBuilder::InsertText(uchar const * text)
72 {
73     TextCollection::TextPosition m = std::strlen((char *)text) + 1;
74     if (m > p_->maxTextLength)
75         p_->maxTextLength = m; // Store length of the longest text seen so far.
76
77     if (m > 1)
78     {
79         p_->n += m;
80         p_->numberOfTexts ++;
81         p_->numberOfSamples += (m-1)/p_->samplerate;
82
83 #ifdef TCB_TEST_BWT
84         p_->dynFMI->addText(text, m);
85 #endif
86         p_->sa->insertSequence((char*)text, m-1, 0);
87         assert(p_->sa->isOk());
88     }
89     else
90     {
91         // FIXME indexing empty texts
92         std::cerr << "TextCollectionBuilder::InsertText() error: can not index empty texts!" << std::endl;
93         exit(1);
94     }
95 }
96
97
98 TextCollection * TextCollectionBuilder::InitTextCollection()
99 {
100     uchar * bwt = 0;
101     CSA::usint length = 0;
102     if (p_->numberOfTexts == 0)
103     {
104         p_->numberOfTexts ++; // Add one empty text
105         bwt = new uchar[2];
106         bwt[0] = '\0';
107         bwt[1] = '\0';
108         length = 1;
109         p_->maxTextLength = 1;
110     }
111     else
112     {
113         bwt = (uchar *)p_->sa->getBWT(length);
114         delete p_->sa;
115         p_->sa = 0;
116
117         assert(length == p_->n);
118
119 #ifdef TCB_TEST_BWT
120         { 
121             uchar *bwtTest = p_->dynFMI->getBWT();
122             printf("123456789012345678901234567890123456789\n");
123             for (ulong i = 0; i < p_->n && i < 100; i ++)
124                 if (bwt[i] < 50)
125                     printf("%d", (int)bwt[i]);
126                 else
127                     printf("%c", bwt[i]);
128             printf("\n");
129             for (ulong i = 0; i < p_->n && i < 100; i ++)
130                 if (bwtTest[i] < 50)
131                     printf("%d", (int)bwtTest[i]);
132                 else
133                     printf("%c", bwtTest[i]);
134             printf("\n");
135             
136             // Sanity check
137             assert(p_->numberOfTexts == p_->dynFMI->getCollectionSize());    
138             
139             delete p_->dynFMI;
140             p_->dynFMI = 0;
141             for (ulong i = 0; i < p_->n; ++i)
142                 if (bwt[i] != bwtTest[i])
143                 {
144                     std::cout << "i = " << i << ", bwt = " << (unsigned)bwt[i] << ", " 
145                               << (unsigned)bwtTest[i] << std::endl;
146                     assert(0);
147                 }
148             delete [] bwtTest;
149         }
150 #endif // TCB_TEST_BWT
151     }
152
153     TextCollection *result = new TCImplementation(bwt, (ulong)length, 
154                       p_->samplerate, p_->numberOfTexts, p_->maxTextLength, p_->numberOfSamples);
155     return result;
156 }
157
158
159 } // namespace SXSI