Revision 935015fc
Added by dsorber almost 9 years ago
| software/lowercase_util/Makefile | ||
|---|---|---|
|
|
||
|
CXXFLAGS= -std=c++11 -O3
|
||
|
|
||
|
all: main
|
||
|
|
||
|
main: lowercase_util.cc
|
||
|
g++ $(CXXFLAGS) lowercase_util.cc -o lowercase_util
|
||
|
|
||
|
#%.o : %.c %.h
|
||
|
# g++ $(CXXFLAGS) -c $<
|
||
|
|
||
|
clean:
|
||
|
rm -f lowercase_util
|
||
| software/lowercase_util/lowercase_util.cc | ||
|---|---|---|
|
|
||
|
#include <cctype>
|
||
|
#include <chrono>
|
||
|
#include <cstdint>
|
||
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
// https://stackoverflow.com/questions/3883993/how-could-these-case-conversion-functions-be-improved
|
||
|
|
||
|
// g++ -std=c++11 -O3 lowercase_util.cc -o lowercase_util
|
||
|
int main(const int argc, char** argv)
|
||
|
{
|
||
|
if (argc < 2)
|
||
|
{
|
||
|
std::cerr << "USAGE: " << argv[0] << " <filename>" << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
std::cout << "Lowercase Test Util\n" << std::endl;
|
||
|
|
||
|
|
||
|
std::string filePath(argv[1]);
|
||
|
|
||
|
// Stat the file path to get its size
|
||
|
struct stat fs_stat;
|
||
|
const int gotStatOK(stat(filePath.c_str(), &fs_stat));
|
||
|
if (gotStatOK < 0)
|
||
|
{
|
||
|
perror("stat()");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
uint32_t fileSize = fs_stat.st_size;
|
||
|
std::cout << "File size: " << fileSize << "\n" << std::endl;
|
||
|
|
||
|
// Read in file
|
||
|
std::ifstream inFileStream(filePath, std::ios::in | std::ios::binary);
|
||
|
if (! inFileStream)
|
||
|
{
|
||
|
std::cerr << "Unable to open specified file." << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Read file in then close stream
|
||
|
std::vector<char> contents;
|
||
|
contents.resize(fileSize);
|
||
|
inFileStream.read(contents.data(), fileSize);
|
||
|
inFileStream.close();
|
||
|
|
||
|
// TEST1: regular tolower() -----------------------------------------------
|
||
|
std::vector<char> copy1(contents);
|
||
|
|
||
|
auto start = std::chrono::system_clock::now();
|
||
|
|
||
|
for (uint32_t idx = 0; idx < fileSize; ++idx)
|
||
|
{
|
||
|
copy1[idx] = tolower(copy1[idx]);
|
||
|
}
|
||
|
|
||
|
auto end = std::chrono::system_clock::now();
|
||
|
auto diff = end - start;
|
||
|
std::cout << "Test 1 -- duration: "
|
||
|
<< std::chrono::duration<double, std::milli>(diff).count()
|
||
|
<< " ms" << std::endl;
|
||
|
|
||
|
// TEST2: technique 1 -----------------------------------------------------
|
||
|
std::vector<char> copy2(contents);
|
||
|
|
||
|
start = std::chrono::system_clock::now();
|
||
|
|
||
|
for (uint32_t idx = 0; idx < fileSize; ++idx)
|
||
|
{
|
||
|
// *c += (*c - 'A' < 26U) << 5;
|
||
|
copy2[idx] += (copy2[idx] - 'A' < 26U) << 5;
|
||
|
}
|
||
|
|
||
|
end = std::chrono::system_clock::now();
|
||
|
diff = end - start;
|
||
|
std::cout << "Test 2 -- duration: "
|
||
|
<< std::chrono::duration<double, std::milli>(diff).count()
|
||
|
<< " ms" << std::endl;
|
||
|
|
||
|
#if 0
|
||
|
// Verify copy2
|
||
|
std::ofstream outStream1("output_copy2.txt", std::ios::out | std::ios::binary);
|
||
|
outStream1.write(copy2.data(), fileSize);
|
||
|
outStream1.close();
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// TEST3: technque 2 ------------------------------------------------------
|
||
|
std::vector<char> copy3(contents);
|
||
|
|
||
|
start = std::chrono::system_clock::now();
|
||
|
|
||
|
for (uint32_t idx = 0; idx < fileSize; ++idx)
|
||
|
{
|
||
|
// *c += (64U - *c & *c - 91U) >> CHAR_BIT * sizeof(unsigned) - 1 << 5;
|
||
|
// *c += ((64U - *c & *c - 91U) >> 31) << 5;
|
||
|
copy3[idx] += ((64U - copy3[idx] & copy3[idx] - 91U) >> 31) << 5;
|
||
|
}
|
||
|
|
||
|
end = std::chrono::system_clock::now();
|
||
|
diff = end - start;
|
||
|
std::cout << "Test 3 -- duration: "
|
||
|
<< std::chrono::duration<double, std::milli>(diff).count()
|
||
|
<< " ms" << std::endl;
|
||
|
|
||
|
#if 0
|
||
|
// Verify copy3
|
||
|
std::ofstream outStream2("output_copy3.txt", std::ios::out | std::ios::binary);
|
||
|
outStream2.write(copy3.data(), fileSize);
|
||
|
outStream2.close();
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// TEST 4: technique 3 ----------------------------------------------------
|
||
|
std::vector<char> copy4(contents);
|
||
|
|
||
|
start = std::chrono::system_clock::now();
|
||
|
|
||
|
for (uint32_t idx = 0; idx < fileSize; ++idx)
|
||
|
{
|
||
|
// c += (((96-(int)c)&((int)c-123))>>9)&(-32);
|
||
|
copy4[idx] += (((96 - (int)copy4[idx]) & ((int)copy4[idx] - 123)) >> 9) & (-32);
|
||
|
}
|
||
|
|
||
|
end = std::chrono::system_clock::now();
|
||
|
diff = end - start;
|
||
|
std::cout << "Test 4 -- duration: "
|
||
|
<< std::chrono::duration<double, std::milli>(diff).count()
|
||
|
<< " ms" << std::endl;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
Adding example "lowercase util" that tests multiple approaches to lowercasing an entire buffer.