125 lines
4.0 KiB
C++
125 lines
4.0 KiB
C++
#ifndef _AL_FUNCTION_HPP
|
|
#define _AL_FUNCTION_HPP
|
|
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
|
|
#include <limits>
|
|
#include <string>
|
|
|
|
|
|
uint32_t ones = 0b11111111111111111111111111111111;
|
|
|
|
uint32_t mask_1 = 0b01010101010101010101010101010101;
|
|
uint32_t remains_1 = 0b00000000000000000000000000000001;
|
|
uint32_t shift_1 = 1;
|
|
uint32_t mask_2 = 0b00110011001100110011001100110011;
|
|
uint32_t remains_2 = 0b00000000000000000000000000000011;
|
|
uint32_t shift_2 = 2;
|
|
uint32_t mask_3 = 0b00001111000011110000111100001111;
|
|
uint32_t remains_3 = 0b00000000000000000000000000001111;
|
|
uint32_t shift_3 = 4;
|
|
uint32_t mask_4 = 0b00000000111111110000000011111111;
|
|
uint32_t remains_4 = 0b00000000000000000000000011111111;
|
|
uint32_t shift_4 = 8;
|
|
|
|
template<class STORAGE, size_t VALUES_COUNT>
|
|
class Function {
|
|
public:
|
|
Function(): _function_values(0) {
|
|
static_assert(not std::numeric_limits<STORAGE>::is_signed);
|
|
}
|
|
explicit Function(STORAGE val): _function_values(val) {
|
|
static_assert(not std::numeric_limits<STORAGE>::is_signed);
|
|
}
|
|
explicit Function(std::string val): _function_values(0) {
|
|
static_assert(not std::numeric_limits<STORAGE>::is_signed);
|
|
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 at(STORAGE index) const {
|
|
return (_function_values >> index) % 2;
|
|
}
|
|
|
|
Function var_negation(STORAGE var_index) {
|
|
// var_index should be in 1..VARS_COUNT
|
|
STORAGE mask, remains, shift;
|
|
switch (var_index) {
|
|
case 1:
|
|
mask = mask_1;
|
|
remains = remains_1;
|
|
shift = shift_1;
|
|
break;
|
|
case 2:
|
|
mask = mask_2;
|
|
remains = remains_2;
|
|
shift = shift_2;
|
|
break;
|
|
case 3:
|
|
mask = mask_3;
|
|
remains = remains_3;
|
|
shift = shift_3;
|
|
break;
|
|
case 4:
|
|
mask = mask_4;
|
|
remains = remains_4;
|
|
shift = shift_4;
|
|
break;
|
|
default:
|
|
assert(false);
|
|
|
|
}
|
|
|
|
STORAGE first_part = (_function_values & (~mask)) >> shift;
|
|
STORAGE second_part = (_function_values & mask) << shift;
|
|
return Function(first_part | second_part);
|
|
|
|
}
|
|
|
|
STORAGE value() const {
|
|
return _function_values;
|
|
}
|
|
private:
|
|
STORAGE _function_values;
|
|
};
|
|
#endif // _AL_FUNCTION_HPP
|