Skip to content

Commit 1e6a072

Browse files
committed
added a simple example
1 parent 7a1ab76 commit 1e6a072

File tree

8 files changed

+648
-475
lines changed

8 files changed

+648
-475
lines changed

CMakeLists.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ if (NOT CMAKE_BUILD_TYPE)
77
set(CMAKE_BUILD_TYPE "Release")
88
endif()
99

10+
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g -Wall -mpopcnt -pthread -std=c++11")
11+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -mpopcnt -pthread -std=c++11")
12+
1013
option(COVERALLS "Generate coveralls data" OFF)
1114

1215
if (COVERALLS)
13-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -Wall -mpopcnt -pthread -std=c++11")
1416
include("${CMAKE_CURRENT_SOURCE_DIR}/CodeCoverage.cmake")
1517
append_coverage_compiler_flags()
1618
set(COVERAGE_EXCLUDES 'ARF/*' 'bench/*' 'test/*' '/usr/*' '/lib/*')
@@ -19,7 +21,6 @@ if (COVERALLS)
1921
EXECUTABLE make test
2022
)
2123
else()
22-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -mpopcnt -pthread -std=c++11")
2324
add_definitions(-DNDEBUG)
2425
endif()
2526

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ We also host a [demo website](https://www.rangefilter.io/).
1515
cmake ..
1616
make -j
1717

18+
## Simple Example
19+
A simple example can be found [here](https://github.com/efficient/SuRF/blob/master/simple_example.cpp). To run the example:
20+
g++ -mpopcnt -std=c++11 simple_example.cpp
21+
./a.out
22+
1823
## Run Unit Tests
1924
make test
2025

include/config.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define CONFIG_H_
33

44
#include <stdint.h>
5+
#include <string.h>
56

67
namespace surf {
78

include/surf.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ class SuRF {
5353
public:
5454
SuRF() {};
5555

56+
SuRF(const std::vector<std::string>& keys) {
57+
create(keys, kIncludeDense, kSparseDenseRatio, kNone, 0, 0);
58+
}
59+
60+
SuRF(const std::vector<std::string>& keys, const SuffixType suffix_type,
61+
const level_t hash_suffix_len, const level_t real_suffix_len) {
62+
create(keys, kIncludeDense, kSparseDenseRatio, suffix_type, hash_suffix_len, real_suffix_len);
63+
}
64+
5665
SuRF(const std::vector<std::string>& keys,
5766
const bool include_dense, const uint32_t sparse_dense_ratio,
5867
const SuffixType suffix_type, const level_t hash_suffix_len, const level_t real_suffix_len) {

simple_example.cpp

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include <iostream>
2+
#include <vector>
3+
4+
#include "include/surf.hpp"
5+
6+
using namespace surf;
7+
8+
int main() {
9+
std::vector<std::string> keys = {
10+
"f",
11+
"far",
12+
"fast",
13+
"s",
14+
"top",
15+
"toy",
16+
"trie",
17+
};
18+
19+
// basic surf
20+
SuRF* surf = new SuRF(keys);
21+
22+
// use default dense-to-sparse ratio; specify suffix type and length
23+
SuRF* surf_hash = new SuRF(keys, surf::kHash, 8, 0);
24+
SuRF* surf_real = new SuRF(keys, surf::kReal, 0, 8);
25+
26+
// customize dense-to-sparse ratio; specify suffix type and length
27+
SuRF* surf_mixed = new SuRF(keys, true, 16, surf::kMixed, 4, 4);
28+
29+
//----------------------------------------
30+
// point queries
31+
//----------------------------------------
32+
std::cout << "Point Query Example: fase" << std::endl;
33+
34+
std::string key = "fase";
35+
36+
if (surf->lookupKey(key))
37+
std::cout << "False Positive: "<< key << " found in basic SuRF" << std::endl;
38+
else
39+
std::cout << "Correct: " << key << " NOT found in basic SuRF" << std::endl;
40+
41+
if (surf_hash->lookupKey(key))
42+
std::cout << "False Positive: " << key << " found in SuRF hash" << std::endl;
43+
else
44+
std::cout << "Correct: " << key << " NOT found in SuRF hash" << std::endl;
45+
46+
if (surf_real->lookupKey(key))
47+
std::cout << "False Positive: " << key << " found in SuRF real" << std::endl;
48+
else
49+
std::cout << "Correct: " << key << " NOT found in SuRF real" << std::endl;
50+
51+
if (surf_mixed->lookupKey(key))
52+
std::cout << "False Positive: " << key << " found in SuRF mixed" << std::endl;
53+
else
54+
std::cout << "Correct: " << key << " NOT found in SuRF mixed" << std::endl;
55+
56+
//----------------------------------------
57+
// range queries
58+
//----------------------------------------
59+
std::cout << "\nRange Query Example: [fare, fase)" << std::endl;
60+
61+
std::string left_key = "fare";
62+
std::string right_key = "fase";
63+
64+
if (surf->lookupRange(left_key, true, right_key, false))
65+
std::cout << "False Positive: There exist key(s) within range ["
66+
<< left_key << ", " << right_key << ") " << "according to basic SuRF" << std::endl;
67+
else
68+
std::cout << "Correct: No key exists within range ["
69+
<< left_key << ", " << right_key << ") " << "according to basic SuRF" << std::endl;
70+
71+
if (surf_hash->lookupRange(left_key, true, right_key, false))
72+
std::cout << "False Positive: There exist key(s) within range ["
73+
<< left_key << ", " << right_key << ") " << "according to SuRF hash" << std::endl;
74+
else
75+
std::cout << "Correct: No key exists within range ["
76+
<< left_key << ", " << right_key << ") " << "according to SuRF hash" << std::endl;
77+
78+
if (surf_real->lookupRange(left_key, true, right_key, false))
79+
std::cout << "False Positive: There exist key(s) within range ["
80+
<< left_key << ", " << right_key << ") " << "according to SuRF real" << std::endl;
81+
else
82+
std::cout << "Correct: No key exists within range ["
83+
<< left_key << ", " << right_key << ") " << "according to SuRF real" << std::endl;
84+
85+
if (surf_mixed->lookupRange(left_key, true, right_key, false))
86+
std::cout << "False Positive: There exist key(s) within range ["
87+
<< left_key << ", " << right_key << ") " << "according to SuRF mixed" << std::endl;
88+
else
89+
std::cout << "Correct: No key exists within range ["
90+
<< left_key << ", " << right_key << ") " << "according to SuRF mixed" << std::endl;
91+
92+
return 0;
93+
}

test/unitTest/test_louds_dense.cpp

+80-74
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ static const int kIntTestBound = 1000001;
2121
static const uint64_t kIntTestSkip = 10;
2222
static const bool kIncludeDense = true;
2323
static const uint32_t kSparseDenseRatio = 0;
24+
static const int kNumSuffixType = 4;
25+
static const SuffixType kSuffixTypeList[kNumSuffixType] = {kNone, kHash, kReal, kMixed};
26+
static const int kNumSuffixLen = 6;
27+
static const level_t kSuffixLenList[kNumSuffixLen] = {1, 3, 7, 8, 13, 26};
2428
static std::vector<std::string> words;
2529

2630
class DenseUnitTest : public ::testing::Test {
@@ -35,7 +39,7 @@ class DenseUnitTest : public ::testing::Test {
3539
delete[] data_;
3640
}
3741

38-
void newBuilder(level_t suffix_len);
42+
void newBuilder(SuffixType suffix_type, level_t suffix_len);
3943
void truncateWordSuffixes();
4044
void fillinInts();
4145
void testSerialize();
@@ -61,8 +65,17 @@ static int getMax(int a, int b) {
6165
return a;
6266
}
6367

64-
void DenseUnitTest::newBuilder(level_t suffix_len) {
65-
builder_ = new SuRFBuilder(kIncludeDense, kSparseDenseRatio, kReal, 0, suffix_len);
68+
void DenseUnitTest::newBuilder(SuffixType suffix_type, level_t suffix_len) {
69+
if (suffix_type == kNone)
70+
builder_ = new SuRFBuilder(kIncludeDense, kSparseDenseRatio, kNone, 0, 0);
71+
else if (suffix_type == kHash)
72+
builder_ = new SuRFBuilder(kIncludeDense, kSparseDenseRatio, kHash, suffix_len, 0);
73+
else if (suffix_type == kReal)
74+
builder_ = new SuRFBuilder(kIncludeDense, kSparseDenseRatio, kReal, 0, suffix_len);
75+
else if (suffix_type == kMixed)
76+
builder_ = new SuRFBuilder(kIncludeDense, kSparseDenseRatio, kMixed, suffix_len, suffix_len);
77+
else
78+
builder_ = new SuRFBuilder(kIncludeDense, kSparseDenseRatio, kNone, 0, 0);
6679
}
6780

6881
void DenseUnitTest::truncateWordSuffixes() {
@@ -127,36 +140,34 @@ void DenseUnitTest::testLookupWord() {
127140
}
128141

129142
TEST_F (DenseUnitTest, lookupWordTest) {
130-
level_t suffix_len_array[5] = {1, 3, 7, 8, 13};
131-
for (int k = 0; k < 5; k++) {
132-
level_t suffix_len = suffix_len_array[k];
133-
newBuilder(suffix_len);
134-
builder_->build(words);
135-
louds_dense_ = new LoudsDense(builder_);
136-
testLookupWord();
137-
delete builder_;
138-
louds_dense_->destroy();
139-
delete louds_dense_;
143+
for (int t = 0; t < kNumSuffixType; t++) {
144+
for (int k = 0; k < kNumSuffixLen; k++) {
145+
newBuilder(kSuffixTypeList[t], kSuffixLenList[k]);
146+
builder_->build(words);
147+
louds_dense_ = new LoudsDense(builder_);
148+
testLookupWord();
149+
delete builder_;
150+
louds_dense_->destroy();
151+
delete louds_dense_;
152+
}
140153
}
141154
}
142155

143156
TEST_F (DenseUnitTest, serializeTest) {
144-
level_t suffix_len_array[5] = {1, 3, 7, 8, 13};
145-
for (int k = 0; k < 5; k++) {
146-
level_t suffix_len = suffix_len_array[k];
147-
newBuilder(suffix_len);
148-
builder_->build(words);
149-
louds_dense_ = new LoudsDense(builder_);
150-
151-
testSerialize();
152-
testLookupWord();
153-
delete builder_;
157+
for (int t = 0; t < kNumSuffixType; t++) {
158+
for (int k = 0; k < kNumSuffixLen; k++) {
159+
newBuilder(kSuffixTypeList[t], kSuffixLenList[k]);
160+
builder_->build(words);
161+
louds_dense_ = new LoudsDense(builder_);
162+
testSerialize();
163+
testLookupWord();
164+
delete builder_;
165+
}
154166
}
155167
}
156168

157169
TEST_F (DenseUnitTest, lookupIntTest) {
158-
level_t suffix_len = 8;
159-
newBuilder(suffix_len);
170+
newBuilder(kReal, 8);
160171
builder_->build(ints_);
161172
louds_dense_ = new LoudsDense(builder_);
162173
position_t out_node_num = 0;
@@ -177,55 +188,54 @@ TEST_F (DenseUnitTest, lookupIntTest) {
177188
}
178189

179190
TEST_F (DenseUnitTest, moveToKeyGreaterThanWordTest) {
180-
level_t suffix_len_array[5] = {1, 3, 7, 8, 13};
181-
for (int k = 0; k < 5; k++) {
182-
level_t suffix_len = suffix_len_array[k];
183-
newBuilder(suffix_len);
184-
builder_->build(words);
185-
louds_dense_ = new LoudsDense(builder_);
186-
187-
bool inclusive = true;
188-
for (int i = 0; i < 2; i++) {
189-
if (i == 1)
190-
inclusive = false;
191-
for (unsigned j = 0; j < words.size() - 1; j++) {
191+
for (int t = 0; t < kNumSuffixType; t++) {
192+
for (int k = 0; k < kNumSuffixLen; k++) {
193+
newBuilder(kSuffixTypeList[t], kSuffixLenList[k]);
194+
builder_->build(words);
195+
louds_dense_ = new LoudsDense(builder_);
196+
197+
bool inclusive = true;
198+
for (int i = 0; i < 2; i++) {
199+
if (i == 1)
200+
inclusive = false;
201+
for (unsigned j = 0; j < words.size() - 1; j++) {
202+
LoudsDense::Iter iter(louds_dense_);
203+
bool could_be_fp = louds_dense_->moveToKeyGreaterThan(words[j], inclusive, iter);
204+
205+
ASSERT_TRUE(iter.isValid());
206+
ASSERT_TRUE(iter.isComplete());
207+
std::string iter_key = iter.getKey();
208+
std::string word_prefix_fp = words[j].substr(0, iter_key.length());
209+
std::string word_prefix_true = words[j+1].substr(0, iter_key.length());
210+
bool is_prefix = false;
211+
if (could_be_fp)
212+
is_prefix = (word_prefix_fp.compare(iter_key) == 0);
213+
else
214+
is_prefix = (word_prefix_true.compare(iter_key) == 0);
215+
ASSERT_TRUE(is_prefix);
216+
}
217+
192218
LoudsDense::Iter iter(louds_dense_);
193-
bool could_be_fp = louds_dense_->moveToKeyGreaterThan(words[j], inclusive, iter);
194-
195-
ASSERT_TRUE(iter.isValid());
196-
ASSERT_TRUE(iter.isComplete());
197-
std::string iter_key = iter.getKey();
198-
std::string word_prefix_fp = words[j].substr(0, iter_key.length());
199-
std::string word_prefix_true = words[j+1].substr(0, iter_key.length());
200-
bool is_prefix = false;
201-
if (could_be_fp)
202-
is_prefix = (word_prefix_fp.compare(iter_key) == 0);
203-
else
204-
is_prefix = (word_prefix_true.compare(iter_key) == 0);
205-
ASSERT_TRUE(is_prefix);
219+
bool could_be_fp = louds_dense_->moveToKeyGreaterThan(words[words.size() - 1], inclusive, iter);
220+
if (could_be_fp) {
221+
std::string iter_key = iter.getKey();
222+
std::string word_prefix_fp = words[words.size() - 1].substr(0, iter_key.length());
223+
bool is_prefix = (word_prefix_fp.compare(iter_key) == 0);
224+
ASSERT_TRUE(is_prefix);
225+
} else {
226+
ASSERT_FALSE(iter.isValid());
227+
}
206228
}
207229

208-
LoudsDense::Iter iter(louds_dense_);
209-
bool could_be_fp = louds_dense_->moveToKeyGreaterThan(words[words.size() - 1], inclusive, iter);
210-
if (could_be_fp) {
211-
std::string iter_key = iter.getKey();
212-
std::string word_prefix_fp = words[words.size() - 1].substr(0, iter_key.length());
213-
bool is_prefix = (word_prefix_fp.compare(iter_key) == 0);
214-
ASSERT_TRUE(is_prefix);
215-
} else {
216-
ASSERT_FALSE(iter.isValid());
217-
}
230+
delete builder_;
231+
louds_dense_->destroy();
232+
delete louds_dense_;
218233
}
219-
220-
delete builder_;
221-
louds_dense_->destroy();
222-
delete louds_dense_;
223234
}
224235
}
225236

226237
TEST_F (DenseUnitTest, moveToKeyGreaterThanIntTest) {
227-
level_t suffix_len = 8;
228-
newBuilder(suffix_len);
238+
newBuilder(kReal, 8);
229239
builder_->build(ints_);
230240
louds_dense_ = new LoudsDense(builder_);
231241

@@ -271,8 +281,7 @@ TEST_F (DenseUnitTest, moveToKeyGreaterThanIntTest) {
271281
}
272282

273283
TEST_F (DenseUnitTest, IteratorIncrementWordTest) {
274-
level_t suffix_len = 8;
275-
newBuilder(suffix_len);
284+
newBuilder(kReal, 8);
276285
builder_->build(words);
277286
louds_dense_ = new LoudsDense(builder_);
278287
bool inclusive = true;
@@ -295,8 +304,7 @@ TEST_F (DenseUnitTest, IteratorIncrementWordTest) {
295304
}
296305

297306
TEST_F (DenseUnitTest, IteratorIncrementIntTest) {
298-
level_t suffix_len = 8;
299-
newBuilder(suffix_len);
307+
newBuilder(kReal, 8);
300308
builder_->build(ints_);
301309
louds_dense_ = new LoudsDense(builder_);
302310
bool inclusive = true;
@@ -319,8 +327,7 @@ TEST_F (DenseUnitTest, IteratorIncrementIntTest) {
319327
}
320328

321329
TEST_F (DenseUnitTest, IteratorDecrementWordTest) {
322-
level_t suffix_len = 8;
323-
newBuilder(suffix_len);
330+
newBuilder(kReal, 8);
324331
builder_->build(words);
325332
louds_dense_ = new LoudsDense(builder_);
326333
bool inclusive = true;
@@ -343,8 +350,7 @@ TEST_F (DenseUnitTest, IteratorDecrementWordTest) {
343350
}
344351

345352
TEST_F (DenseUnitTest, IteratorDecrementIntTest) {
346-
level_t suffix_len = 8;
347-
newBuilder(suffix_len);
353+
newBuilder(kReal, 8);
348354
builder_->build(ints_);
349355
louds_dense_ = new LoudsDense(builder_);
350356
bool inclusive = true;

0 commit comments

Comments
 (0)