1414
1515namespace fmc {
1616
17- template <size_t TSigma, template <size_t > typename String = string::FlattenedBitvectors_512_64k, SparseArray_c SparseArray = suffixarray::SparseArray<std::tuple<uint32_t , uint32_t >>>
17+ template <size_t TSigma, template <size_t > typename String = string::FlattenedBitvectors_512_64k, SparseArray_c SparseArray = suffixarray::SparseArray<std::tuple<uint32_t , uint32_t >>, bool TDelim= true , bool TReuseRev= false >
1818 requires String_c<String<TSigma>>
1919struct BiFMIndex {
2020 using ADEntry = SparseArray::value_t ;
2121
22+ using NoDelim = BiFMIndex<TSigma, String, SparseArray, false , TReuseRev>;
23+ using ReuseRev = BiFMIndex<TSigma, String, SparseArray, TDelim, true >;
24+
2225 static size_t constexpr Sigma = TSigma;
23- static size_t constexpr FirstSymb = 1 ;
26+ static size_t constexpr FirstSymb = TDelim? 1 : 0 ;
2427
28+ // Set RevBwtType to std::nullptr_t to indicate that it should not be used
29+ using RevBwtType = std::conditional_t <TReuseRev, std::nullptr_t , String<Sigma>>;
2530 String<Sigma> bwt;
26- String<Sigma> bwtRev;
31+ RevBwtType bwtRev;
2732 std::array<size_t , Sigma+1 > C{};
2833 SparseArray annotatedArray;
2934
3035 BiFMIndex () = default ;
3136 BiFMIndex (BiFMIndex&&) noexcept = default ;
3237
3338 BiFMIndex (std::span<uint8_t const > _bwt, std::span<uint8_t const > _bwtRev, SparseArray _annotatedArray)
39+ requires (!TReuseRev)
3440 : bwt{_bwt}
3541 , bwtRev{_bwtRev}
3642 , C{computeC (bwt)}
@@ -42,32 +48,46 @@ struct BiFMIndex {
4248 }
4349 }
4450
45- BiFMIndex (Sequence auto const & _sequence, SparseArray const & _annotatedSequence, size_t _threadNbr, bool omegaSorting = false ) {
51+ BiFMIndex (std::span<uint8_t const > _bwt, SparseArray _annotatedArray)
52+ requires (TReuseRev)
53+ : bwt{_bwt}
54+ , C{computeC (bwt)}
55+ , annotatedArray{std::move (_annotatedArray)}
56+ {}
57+
58+
59+ BiFMIndex (Sequence auto const & _sequence, SparseArray const & _annotatedSequence, size_t _threadNbr, bool mirrorInput = false ) {
4660 if (_sequence.size () >= std::numeric_limits<size_t >::max ()/2 ) {
4761 throw std::runtime_error{" sequence is longer than what this system is capable of handling" };
4862 }
4963
64+ bool omegaSorting = !TDelim; // Use omega sorting if no delimiter is being used
65+
5066 // copy text into custom buffer
51- auto inputText = createInputText (_sequence, omegaSorting);
67+ auto inputText = createInputText (_sequence, omegaSorting, mirrorInput );
5268
5369 // create bwt, bwtRev and annotatedArray
5470 auto [_bwt, _annotatedArray] = createBWTAndAnnotatedArray (inputText, _annotatedSequence, _threadNbr, omegaSorting);
55- #if defined(__GNUC__) && !defined(__clang__)
56- #pragma GCC diagnostic push
57- #pragma GCC diagnostic ignored "-Wstringop-overflow"
58- std::ranges::reverse (inputText);
59- #pragma GCC diagnostic pop
6071
61- #else
62- std::ranges::reverse (inputText);
6372
64- #endif
65- auto _bwtRev = createBWT (inputText, _threadNbr, omegaSorting);
66- decltype (inputText){}.swap (inputText); // inputText memory can be deleted
73+ if constexpr (!TReuseRev) {
74+ #if defined(__GNUC__) && !defined(__clang__)
75+ #pragma GCC diagnostic push
76+ #pragma GCC diagnostic ignored "-Wstringop-overflow"
77+ std::ranges::reverse (inputText);
78+ #pragma GCC diagnostic pop
79+
80+ #else
81+ std::ranges::reverse (inputText);
82+
83+ #endif
84+ auto _bwtRev = createBWT (inputText, _threadNbr, omegaSorting);
85+ decltype (inputText){}.swap (inputText); // inputText memory can be deleted
86+ bwtRev = {_bwtRev};
87+ }
6788
6889 // initialize this BiFMIndex properly
6990 bwt = {_bwt};
70- bwtRev = {_bwtRev};
7191 C = computeC (bwt);
7292 annotatedArray = std::move (_annotatedArray);
7393 }
@@ -78,10 +98,9 @@ struct BiFMIndex {
7898 * \param _input a list of sequences
7999 * \param samplingRate rate of the sampling
80100 */
81- BiFMIndex (Sequences auto const & _input, size_t samplingRate, size_t threadNbr, bool useDelimiters = true , size_t seqOffset = 0 ) {
82-
101+ BiFMIndex (Sequences auto const & _input, size_t samplingRate, size_t threadNbr, size_t seqOffset = 0 , bool mirrorInput = false ) {
83102 auto [totalSize, inputText, inputSizes] = [&]() {
84- if (useDelimiters ) {
103+ if (TDelim ) {
85104 return createSequences (_input);
86105 } else {
87106 return createSequencesWithoutDelimiter (_input);
@@ -97,31 +116,58 @@ struct BiFMIndex {
97116 assert (inputSizes.size () < refId);
98117 }
99118
100- auto annotatedSequence = SparseArray {
101- std::views::iota (size_t {0 }, totalSize) | std::views::transform ([&](size_t ) -> std::optional<ADEntry> {
102- assert (refId < inputSizes.size ());
103- assert (pos < inputSizes[refId]);
119+ auto size = totalSize;
120+ if (mirrorInput) size = size*2 ;
104121
105- auto ret = std::optional<ADEntry>{std::nullopt };
106122
107- if (pos % samplingRate == 0 ) {
108- ret = std::make_tuple (refId+seqOffset, pos);
109- }
110-
111- ++pos;
112- if (inputSizes[refId] == pos) {
113- refId += 1 ;
114- pos = 0 ;
123+ auto annotatedSequence = SparseArray {
124+ std::views::iota (size_t {0 }, size) | std::views::transform ([&](size_t phase) -> std::optional<ADEntry> {
125+ if (phase < totalSize) { // going forward
126+ assert (refId < inputSizes.size ());
127+ assert (pos < inputSizes[refId]);
128+
129+ auto ret = std::optional<ADEntry>{std::nullopt };
130+
131+ if (pos % samplingRate == 0 ) {
132+ ret = std::make_tuple (refId+seqOffset, pos);
133+ }
134+
135+ ++pos;
136+ if (inputSizes[refId] == pos) {
137+ refId += 1 ;
138+ pos = 0 ;
139+ }
140+ return ret;
141+ } else { // going backwards
142+ if (phase == totalSize) { // reset values
143+ pos = 0 ;
144+ refId = 0 ;
145+ }
146+
147+ assert (refId < inputSizes.size ());
148+ assert (pos < inputSizes[inputSizes.size () - refId - 1 ]);
149+
150+ auto ret = std::optional<ADEntry>{std::nullopt };
151+
152+ if (pos % samplingRate == 0 ) {
153+ ret = std::make_tuple (inputSizes.size ()*2 - refId+seqOffset-1 , inputSizes[refId] - pos-1 );
154+ }
155+
156+ ++pos;
157+ if (inputSizes[inputSizes.size () - refId - 1 ] == pos) {
158+ refId += 1 ;
159+ pos = 0 ;
160+ }
161+ return ret;
115162 }
116- return ret;
117163 })
118164 };
119165
120- *this = BiFMIndex{inputText, annotatedSequence, threadNbr, !useDelimiters };
166+ *this = BiFMIndex{inputText, annotatedSequence, threadNbr, mirrorInput };
121167 }
122168
123169 auto operator =(BiFMIndex const &) -> BiFMIndex& = delete ;
124- auto operator =(BiFMIndex&&) noexcept -> BiFMIndex& = default ;
170+ auto operator =(BiFMIndex&& _other ) noexcept -> BiFMIndex& = default ;
125171
126172 size_t size () const {
127173 return bwt.size ();
0 commit comments