Skip to content

Commit b4c487b

Browse files
authored
Merge pull request #94 from SGSSGene/feat/new_searches
Feat/new searches
2 parents f8c691d + ff3b217 commit b4c487b

14 files changed

Lines changed: 2015 additions & 5 deletions

File tree

src/fmindex-collection/bitvector/Bitvector.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,11 @@ struct Bitvector {
9595
break;
9696
}
9797

98-
l1[l1_id+1] = l1[l1_id] + std::popcount(bits);
98+
auto ct = size_t{l1[l1_id]} + std::popcount(bits);
99+
l1[l1_id+1] = ct;
99100
// check if next superblock is full
100101
if (totalLength % 256 == 0) {
101-
l0[l0_id+1] = l0[l0_id] + l1[l1_id+1];
102+
l0[l0_id+1] = l0[l0_id] + ct;
102103
l1[l1_id+1] = 0;
103104
}
104105
}
@@ -121,10 +122,11 @@ struct Bitvector {
121122
}
122123
totalLength += 1;
123124
if (totalLength % 64 == 0) { // new block
124-
blocks.emplace_back(blocks.back() + std::popcount(bits.back()));
125+
auto ct = size_t{blocks.back()} + std::popcount(bits.back());
126+
blocks.emplace_back(ct);
125127
bits.emplace_back();
126128
if (totalLength % 256 == 0) { // new super block + new block
127-
superblocks.emplace_back(superblocks.back() + blocks.back());
129+
superblocks.emplace_back(superblocks.back() + ct);
128130
blocks.back() = 0;
129131
}
130132
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// SPDX-FileCopyrightText: 2025 Simon Gene Gottlieb
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
#pragma once
4+
5+
#include "FMIndex.h"
6+
7+
namespace fmc {
8+
9+
/** Special FMIndex, that
10+
* only carries entries with the same length.
11+
*
12+
* It always searches for the first character and then the next in a fixed order and no overlappings
13+
*
14+
*/
15+
template <size_t TSigma, template <size_t> typename String = string::FlattenedBitvectors_512_64k>
16+
requires String_c<String<TSigma>>
17+
struct LinearFMIndex {
18+
static size_t constexpr Sigma = TSigma;
19+
20+
struct Column {
21+
String<Sigma> bwt;
22+
std::array<size_t, Sigma+1> C{0};
23+
};
24+
std::vector<Column> columns;
25+
26+
size_t size_;
27+
size_t depth_;
28+
29+
std::vector<size_t> ordered{};
30+
31+
32+
LinearFMIndex(Sequences auto const& _inputs) {
33+
auto lastOrder = std::vector<size_t>{};
34+
for (size_t i{0}; i < _inputs.size(); ++i) {
35+
lastOrder.push_back(i);
36+
}
37+
38+
// counts characters in a column
39+
auto countColumn = [&](size_t col, size_t begin, size_t end) {
40+
auto count = std::array<size_t, 257>{};
41+
for (auto i{begin}; i < end; ++i) {
42+
auto row = lastOrder[i];
43+
auto c = _inputs[row][col];
44+
count[c] += 1;
45+
}
46+
return count;
47+
};
48+
auto accCount = [](std::array<size_t, 257>& count) {
49+
for (size_t i{1}; i < count.size(); ++i) {
50+
count[i] = count[i-1] + count[i];
51+
}
52+
};
53+
54+
auto target = std::vector<std::vector<uint8_t>>{};
55+
target.resize(_inputs.size(), std::vector<uint8_t>(_inputs[0].size()));
56+
57+
58+
auto sort = std::function<void(size_t, size_t, size_t)>{};
59+
60+
auto pos = std::vector<size_t>{};
61+
pos.resize(lastOrder.size());
62+
63+
columns.resize(_inputs[0].size());
64+
65+
auto temp_input = std::vector<uint8_t>{};
66+
temp_input.resize(_inputs.size());
67+
68+
for (size_t j{0}; j < _inputs[0].size(); ++j) {
69+
size_t col = _inputs[0].size() - j - 1;
70+
auto count = countColumn(col, 0, _inputs.size());
71+
accCount(count);
72+
73+
for (size_t _i{0}; _i < _inputs.size(); ++_i) {
74+
auto i = _inputs.size() - _i - 1;
75+
auto row = lastOrder[i];
76+
auto c = _inputs[row][col];
77+
pos[--count[c]] = row;
78+
}
79+
std::swap(lastOrder, pos);
80+
//fmt::print("pass {}\n", j);
81+
//printPos(lastOrder);
82+
83+
84+
// fill bwts + C
85+
auto tcol = ((col == 0)?columns.size():col)-1;
86+
auto& bwt = columns[tcol].bwt;
87+
auto& C = columns[tcol].C;
88+
89+
// fill temp string for bwt
90+
for (size_t i{0}; i < lastOrder.size(); ++i) {
91+
auto row = lastOrder[i];
92+
auto c = _inputs[row].back();
93+
if (col > 0) c = _inputs[row][col-1];
94+
temp_input[i] = c;
95+
}
96+
bwt = {temp_input};
97+
98+
// fill C
99+
for (size_t i{0}; i <= Sigma; ++i) {
100+
C[i] = bwt.prefix_rank(bwt.size(), i);
101+
}
102+
}
103+
size_ = _inputs.size();
104+
ordered = lastOrder;
105+
}
106+
107+
auto size() const {
108+
return size_;
109+
}
110+
111+
auto depth() const {
112+
return columns.size();
113+
}
114+
115+
auto locate(size_t idx) const -> size_t {
116+
return ordered[idx];
117+
}
118+
};
119+
120+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// SPDX-FileCopyrightText: 2025 Simon Gene Gottlieb
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
#pragma once
4+
5+
#include "LinearFMIndex.h"
6+
7+
#include <compare>
8+
9+
namespace fmc {
10+
11+
template <typename Index>
12+
struct LinearFMIndexCursor {
13+
static constexpr size_t Sigma = Index::Sigma;
14+
static constexpr bool Reversed = false;
15+
16+
Index const* index{};
17+
size_t lb;
18+
size_t len{};
19+
size_t col{};
20+
21+
LinearFMIndexCursor() noexcept = default;
22+
23+
LinearFMIndexCursor(Index const& index) noexcept
24+
: LinearFMIndexCursor{index, 0, index.size(), index.columns.size()-1}
25+
{}
26+
27+
LinearFMIndexCursor(Index const& index, size_t lb, size_t len, size_t col) noexcept
28+
: index{&index}
29+
, lb{lb}
30+
, len{len}
31+
, col{col}
32+
{}
33+
34+
auto extendLeft(uint8_t symb) const -> LinearFMIndexCursor {
35+
auto const& column = index->columns[col];
36+
size_t newLb = column.bwt.rank(lb, symb);
37+
size_t newLen = column.bwt.rank(lb+len, symb) - newLb;
38+
return {*index, newLb + column.C[symb], newLen, col-1};
39+
}
40+
auto extendLeft() const -> std::array<LinearFMIndexCursor, Sigma> {
41+
auto const& column = index->columns[col];
42+
auto [rs1, prs1] = column.bwt.all_ranks_and_prefix_ranks(lb);
43+
auto [rs2, prs2] = column.bwt.all_ranks_and_prefix_ranks(lb+len);
44+
45+
for (size_t i{0}; i < rs1.size(); ++i) {
46+
rs1[i] += column.C[i];
47+
rs2[i] += column.C[i];
48+
}
49+
50+
auto cursors = std::array<LinearFMIndexCursor, Sigma>{};
51+
cursors[0] = LinearFMIndexCursor{*index, rs1[0], rs2[0] - rs1[0], col-1};
52+
for (size_t i{1}; i < Sigma; ++i) {
53+
cursors[i] = LinearFMIndexCursor{*index, rs1[i], rs2[i] - rs1[i], col-1};
54+
}
55+
return cursors;
56+
}
57+
58+
bool empty() const {
59+
return len == 0;
60+
}
61+
62+
size_t count() const {
63+
return len;
64+
}
65+
66+
};
67+
68+
template <typename Index>
69+
auto begin(LinearFMIndexCursor<Index> const& _cursor) {
70+
return IntIterator{_cursor.lb};
71+
}
72+
template <typename Index>
73+
auto end(LinearFMIndexCursor<Index> const& _cursor) {
74+
return IntIterator{_cursor.lb + _cursor.len};
75+
}
76+
77+
}

src/fmindex-collection/fmindex/all.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "fmindex/BiFMIndexCursor.h"
88
#include "fmindex/FMIndex.h"
99
#include "fmindex/FMIndexCursor.h"
10+
#include "fmindex/LinearFMIndex.h"
11+
#include "fmindex/LinearFMIndexCursor.h"
1012
#include "fmindex/MirroredBiFMIndex.h"
1113
#include "fmindex/MirroredBiFMIndexCursor.h"
1214
#include "fmindex/ReverseFMIndex.h"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-FileCopyrightText: 2025 Simon Gene Gottlieb
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
#pragma once
4+
5+
#include <cstddef>
6+
7+
template <typename T, typename T2=std::nullptr_t>
8+
struct Restore {
9+
T* value;
10+
T oldValue;
11+
Restore(T& _value)
12+
: value{&_value}
13+
, oldValue{*value}
14+
{}
15+
Restore(T& _value, T2 newValue)
16+
: value{&_value}
17+
, oldValue{*value}
18+
{
19+
*value = static_cast<T>(newValue);
20+
}
21+
Restore(Restore const&) = delete;
22+
Restore(Restore&&) = delete;
23+
~Restore() {
24+
*value = oldValue;
25+
}
26+
};

0 commit comments

Comments
 (0)