diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b2bb945 --- /dev/null +++ b/CMakeLists.txt @@ -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) diff --git a/al_function.hpp b/al_function.hpp new file mode 100644 index 0000000..a49c451 --- /dev/null +++ b/al_function.hpp @@ -0,0 +1,62 @@ +#ifndef _AL_FUNCTION_HPP +#define _AL_FUNCTION_HPP + +#include + +#include + +template +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 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..2aadace --- /dev/null +++ b/main.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include + +#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 MyFunction; + +void test_function() { + Function f_8(16); + assert(("sizeof(sizeof(Function)", sizeof(Function)==2)); + assert(("f_8(16) = 00010000", "00010000" == f_8.string())); + assert(("f_8(15) = 00001111", "00001111" == Function(15).string())); + + assert(("converting 01001001", Function("01001001").string() == "01001001")); + assert(("converting 00000000", Function("00000000").string() == "00000000")); + assert(("converting 11111111", Function("11111111").string() == "11111111")); + + Function a(12); + Function 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 get_linear_components() { + vector 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 get_linear_combinations(const vector &linear_components) { + set 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(res.begin(), res.end()); +} + +vector get_all_monomials(const vector &linear_combinations) { + set 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(res.begin(), res.end()); +} + +void fill_ranks(vector monomials) { + vector used_map(FUNCTIONS_COUNT, 0); + size_t functions_remains = FUNCTIONS_COUNT; + + ofstream f_out("out.txt"); + + vector< vector > ranks; + ranks.push_back(vector()); // 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()); + 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; +}