Initial version
This commit is contained in:
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.3)
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-g")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-march=native")
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
add_executable(main main.cpp)
|
||||||
|
target_link_libraries(main Threads::Threads)
|
||||||
|
set(SOURCE_EXE main.cpp)
|
||||||
62
al_function.hpp
Normal file
62
al_function.hpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef _AL_FUNCTION_HPP
|
||||||
|
#define _AL_FUNCTION_HPP
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
template<class STORAGE, size_t VALUES_COUNT>
|
||||||
|
class Function {
|
||||||
|
public:
|
||||||
|
Function(): _function_values(0) {}
|
||||||
|
explicit Function(STORAGE val): _function_values(val) {}
|
||||||
|
explicit Function(std::string val): _function_values(0) {
|
||||||
|
assert(("bad input string size", val.size() == VALUES_COUNT));
|
||||||
|
STORAGE cur_dig = 1;
|
||||||
|
for (auto it = val.rbegin(); it != val.rend(); ++it) {
|
||||||
|
if ( *it == '0' ) {
|
||||||
|
// nothing to do here
|
||||||
|
} else if ( *it == '1' ) {
|
||||||
|
_function_values += cur_dig;
|
||||||
|
} else {
|
||||||
|
assert(("bad input string", false));
|
||||||
|
}
|
||||||
|
cur_dig *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string string() const {
|
||||||
|
std::string res(VALUES_COUNT, '0');
|
||||||
|
STORAGE tmp_val = _function_values;
|
||||||
|
for (size_t ind = 0; ind < VALUES_COUNT; ++ind) {
|
||||||
|
char cur_ch = tmp_val % 2 == 0 ? '0' : '1';
|
||||||
|
res[VALUES_COUNT - ind - 1] = cur_ch;
|
||||||
|
tmp_val /= 2;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function operator and (Function other) const {
|
||||||
|
return Function(_function_values & other._function_values);
|
||||||
|
}
|
||||||
|
Function operator or (Function other) const {
|
||||||
|
return Function(_function_values | other._function_values);
|
||||||
|
}
|
||||||
|
Function operator xor(Function other) const {
|
||||||
|
return Function(_function_values ^ other._function_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator < (Function other) const {
|
||||||
|
return _function_values < other._function_values;
|
||||||
|
}
|
||||||
|
bool operator == (Function other) const {
|
||||||
|
return _function_values == other._function_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
STORAGE value() const {
|
||||||
|
return _function_values;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
STORAGE _function_values;
|
||||||
|
};
|
||||||
|
#endif // _AL_FUNCTION_HPP
|
||||||
154
main.cpp
Normal file
154
main.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <cassert>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "al_function.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef uint16_t Storage;
|
||||||
|
const size_t ARGS_COUNT = 4;
|
||||||
|
const size_t FUNCTION_LEN = 1ll << ARGS_COUNT;
|
||||||
|
const size_t FUNCTIONS_COUNT = 1ll << FUNCTION_LEN;
|
||||||
|
typedef Function<Storage, FUNCTION_LEN> MyFunction;
|
||||||
|
|
||||||
|
void test_function() {
|
||||||
|
Function<uint16_t, 8> f_8(16);
|
||||||
|
assert(("sizeof(sizeof(Function<uint16_t, 8>)", sizeof(Function<uint16_t, 8>)==2));
|
||||||
|
assert(("f_8(16) = 00010000", "00010000" == f_8.string()));
|
||||||
|
assert(("f_8(15) = 00001111", "00001111" == Function<uint16_t, 8>(15).string()));
|
||||||
|
|
||||||
|
assert(("converting 01001001", Function<uint16_t, 8>("01001001").string() == "01001001"));
|
||||||
|
assert(("converting 00000000", Function<uint16_t, 8>("00000000").string() == "00000000"));
|
||||||
|
assert(("converting 11111111", Function<uint16_t, 8>("11111111").string() == "11111111"));
|
||||||
|
|
||||||
|
Function<uint16_t, 8> a(12);
|
||||||
|
Function<uint16_t, 8> b(5);
|
||||||
|
assert(("a = 00001100", a.string() == "00001100"));
|
||||||
|
assert(("b = 00000101", b.string() == "00000101"));
|
||||||
|
assert(("a ^ b = 00001001", (a xor b).string() == "00001001"));
|
||||||
|
assert(("a | b = 00001101", (a or b).string() == "00001101"));
|
||||||
|
assert(("a & b = 00000100", (a and b).string() == "00000100"));
|
||||||
|
// no changed in this objects
|
||||||
|
assert(("a = 00001100", a.string() == "00001100"));
|
||||||
|
assert(("b = 00000101", b.string() == "00000101"));
|
||||||
|
cout << "self-test passed" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<MyFunction> get_linear_components() {
|
||||||
|
vector<MyFunction> res;
|
||||||
|
if ( ARGS_COUNT == 3 ) {
|
||||||
|
res.push_back(MyFunction("11111111")); // f = 1
|
||||||
|
res.push_back(MyFunction("00001111")); // f = x_1
|
||||||
|
res.push_back(MyFunction("00110011")); // f = x_2
|
||||||
|
res.push_back(MyFunction("01010101")); // f = x_3
|
||||||
|
} else if ( ARGS_COUNT == 4 ) {
|
||||||
|
res.push_back(MyFunction("1111111111111111")); // f = 1
|
||||||
|
res.push_back(MyFunction("0000000011111111")); // f = x_1
|
||||||
|
res.push_back(MyFunction("0000111100001111")); // f = x_2
|
||||||
|
res.push_back(MyFunction("0011001100110011")); // f = x_3
|
||||||
|
res.push_back(MyFunction("0101010101010101")); // f = x_4
|
||||||
|
} else if ( ARGS_COUNT == 5 ) {
|
||||||
|
res.push_back(MyFunction("11111111111111111111111111111111")); // f = 1
|
||||||
|
res.push_back(MyFunction("00000000000000001111111111111111")); // f = x_1
|
||||||
|
res.push_back(MyFunction("00000000111111110000000011111111")); // f = x_2
|
||||||
|
res.push_back(MyFunction("00001111000011110000111100001111")); // f = x_3
|
||||||
|
res.push_back(MyFunction("00110011001100110011001100110011")); // f = x_4
|
||||||
|
res.push_back(MyFunction("01010101010101010101010101010101")); // f = x_5
|
||||||
|
} else {
|
||||||
|
assert (("bad args_count", false));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<MyFunction> get_linear_combinations(const vector<MyFunction> &linear_components) {
|
||||||
|
set<MyFunction> res(linear_components.begin(), linear_components.end());
|
||||||
|
bool is_added = true;
|
||||||
|
while ( is_added ) {
|
||||||
|
is_added = false;
|
||||||
|
for (auto el_first: res)
|
||||||
|
for (auto el_second: res) {
|
||||||
|
bool is_added_now = res.insert(el_first xor el_second).second;
|
||||||
|
is_added = is_added or is_added_now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vector<MyFunction>(res.begin(), res.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<MyFunction> get_all_monomials(const vector<MyFunction> &linear_combinations) {
|
||||||
|
set<MyFunction> res(linear_combinations.begin(), linear_combinations.end());
|
||||||
|
bool is_added = true;
|
||||||
|
while ( is_added ) {
|
||||||
|
is_added = false;
|
||||||
|
for (auto el_first: res)
|
||||||
|
for (auto el_second: res) {
|
||||||
|
bool is_added_now = res.insert(el_first and el_second).second;
|
||||||
|
is_added = is_added or is_added_now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vector<MyFunction>(res.begin(), res.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_ranks(vector<MyFunction> monomials) {
|
||||||
|
vector<int8_t> used_map(FUNCTIONS_COUNT, 0);
|
||||||
|
size_t functions_remains = FUNCTIONS_COUNT;
|
||||||
|
|
||||||
|
ofstream f_out("out.txt");
|
||||||
|
|
||||||
|
vector< vector<MyFunction> > ranks;
|
||||||
|
ranks.push_back(vector<MyFunction>()); // empty set
|
||||||
|
ranks.push_back(monomials); // empty set
|
||||||
|
|
||||||
|
cout << "rank index = " << 1 << endl;
|
||||||
|
f_out << "rank index = " << 1 << endl;
|
||||||
|
for (auto el: monomials) {
|
||||||
|
--functions_remains;
|
||||||
|
used_map.at(el.value()) = 1;
|
||||||
|
f_out << el.string() << endl;
|
||||||
|
}
|
||||||
|
for (size_t rank_ind = 2; functions_remains; ++rank_ind) {
|
||||||
|
ranks.push_back(vector<MyFunction>());
|
||||||
|
cout << "rank index = " << rank_ind << " remains: " << functions_remains << endl;
|
||||||
|
f_out << "rank index = " << rank_ind << endl;
|
||||||
|
for (auto el_first: ranks.at(rank_ind - 1)) {
|
||||||
|
for (auto el_second: ranks.at(1)) {
|
||||||
|
MyFunction res_el = el_first xor el_second;
|
||||||
|
if ( used_map[res_el.value()] == 0 ) {
|
||||||
|
--functions_remains;
|
||||||
|
used_map[res_el.value()] = 1;
|
||||||
|
ranks.at(rank_ind).push_back(res_el);
|
||||||
|
f_out << res_el.string() << " = "
|
||||||
|
<< el_first.string() << " + " << el_second.string() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( rank_ind - 1 > 1 )
|
||||||
|
ranks.at(rank_ind - 1).clear(); // больше не нужен
|
||||||
|
cout << "size for rank " << rank_ind << " is " << ranks.at(rank_ind).size() << endl;
|
||||||
|
}
|
||||||
|
f_out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_function();
|
||||||
|
cout << "using " << sizeof(Storage) << " bytes for storage" << endl;
|
||||||
|
cout << FUNCTIONS_COUNT << " functions with " << ARGS_COUNT
|
||||||
|
<< " arguments and " << FUNCTION_LEN << " values" << endl;
|
||||||
|
|
||||||
|
auto linear_components = get_linear_components();
|
||||||
|
cout << "Linear components: " << endl;
|
||||||
|
for (auto el: linear_components)
|
||||||
|
cout << el.string() << endl;
|
||||||
|
|
||||||
|
auto linear_combinations = get_linear_combinations(linear_components);
|
||||||
|
cout << "Linear combinations: " << linear_combinations.size() << endl;
|
||||||
|
|
||||||
|
auto monomials = get_all_monomials(linear_combinations);
|
||||||
|
cout << "Monomials: " << monomials.size() << endl;
|
||||||
|
|
||||||
|
fill_ranks(monomials);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user