| 
						
						
							
								
							
						
						
					 | 
					@ -7,13 +7,11 @@ std::mutex BasicRanges::building; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					bool BasicRanges::available = false; | 
					 | 
					 | 
					bool BasicRanges::available = false; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					std::vector<uint32_t> BasicRanges::data; | 
					 | 
					 | 
					std::vector<uint32_t> BasicRanges::data; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					inline uint32_t binary_count(uint32_t bin) { // get number of non-zero bits
 | 
					 | 
					 | 
					const std::vector<uint32_t>* BasicRanges::fetch() { // get basic ranges content
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    bin -= (bin >> 1) & 0x55555555; | 
					 | 
					 | 
					    if (status() != AVAILABLE) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    bin = (bin & 0x33333333) + ((bin >> 2) & 0x33333333); | 
					 | 
					 | 
					        BasicRanges::build(); // basic ranges initialize
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    bin = ((bin >> 4) + bin) & 0x0F0F0F0F; | 
					 | 
					 | 
					    } | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    bin += bin >> 8; | 
					 | 
					 | 
					    return &BasicRanges::data; // return const ptr
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					    bin += bin >> 16; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return bin & 0b111111; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					BasicRanges::Status BasicRanges::status() { // get basic ranges status
 | 
					 | 
					 | 
					BasicRanges::Status BasicRanges::status() { // get basic ranges status
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -27,13 +25,6 @@ BasicRanges::Status BasicRanges::status() { // get basic ranges status | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return NO_INIT; | 
					 | 
					 | 
					    return NO_INIT; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					const std::vector<uint32_t>* BasicRanges::fetch() { // get basic ranges content
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    if (status() != AVAILABLE) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        BasicRanges::build(); // basic ranges initialize
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return &BasicRanges::data; // return const ptr
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					void BasicRanges::build() { // ensure that basic ranges available
 | 
					 | 
					 | 
					void BasicRanges::build() { // ensure that basic ranges available
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    if (!BasicRanges::available) { | 
					 | 
					 | 
					    if (!BasicRanges::available) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if (BasicRanges::building.try_lock()) { // mutex lock success
 | 
					 | 
					 | 
					        if (BasicRanges::building.try_lock()) { // mutex lock success
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -46,59 +37,12 @@ void BasicRanges::build() { // ensure that basic ranges available | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <iostream> | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					void BasicRanges::sort_data(std::vector<int> &flags, std::vector<uint32_t> &raw) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    struct heap_node { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        uint32_t value; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        int index; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        int limit; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    }; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    struct compare { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        bool operator() (heap_node n1, heap_node n2) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            return n1.value > n2.value; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    }; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::priority_queue<heap_node, std::vector<heap_node>, compare> min_heap; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    for (auto i = 0; i < flags.size() - 1; ++i) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        min_heap.push({ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            .value = raw[flags[i]], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            .index = flags[i], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            .limit = flags[i + 1] - 1, | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        }); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    while (!min_heap.empty()) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        auto current = min_heap.top(); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        min_heap.pop(); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        data.emplace_back(current.value); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if (current.index != current.limit) { | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            min_heap.push({ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                .value = raw[current.index + 1], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                .index = current.index + 1, | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                .limit = current.limit, | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            }); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					void BasicRanges::build_data() { // build basic ranges
 | 
					 | 
					 | 
					void BasicRanges::build_data() { // build basic ranges
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    BasicRanges::data.reserve(BASIC_RANGES_SIZE); // memory pre-allocated
 | 
					 | 
					 | 
					    BasicRanges::data.reserve(BASIC_RANGES_SIZE); // memory pre-allocated
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::vector<uint32_t> raw_data; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    raw_data.reserve(BASIC_RANGES_SIZE); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::vector<int> start_points; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ 7
 | 
					 | 
					 | 
					    for (int n = 0; n <= 7; ++n) { // number of 1x2 and 2x1 block -> 0 ~ 7
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 2x1 block -> 0 ~ n
 | 
					 | 
					 | 
					        for (int n_2x1 = 0; n_2x1 <= n; ++n_2x1) { // number of 2x1 block -> 0 ~ n
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block -> 0 ~ (14 - 2n)
 | 
					 | 
					 | 
					            for (int n_1x1 = 0; n_1x1 <= (14 - n * 2); ++n_1x1) { // number of 1x1 block -> 0 ~ (14 - 2n)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					                generate(generate_t { // generate target ranges
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                start_points.emplace_back(raw_data.size()); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                generate(raw_data, generate_t { // generate target ranges
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                    .n1 = 16 - n * 2 - n_1x1, /// space -> 00
 | 
					 | 
					 | 
					                    .n1 = 16 - n * 2 - n_1x1, /// space -> 00
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    .n2 = n - n_2x1, /// 1x2 -> 01
 | 
					 | 
					 | 
					                    .n2 = n - n_2x1, /// 1x2 -> 01
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    .n3 = n_2x1, /// 2x1 -> 10
 | 
					 | 
					 | 
					                    .n3 = n_2x1, /// 2x1 -> 10
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -107,47 +51,36 @@ void BasicRanges::build_data() { // build basic ranges | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            } | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					    std::sort(BasicRanges::data.begin(), BasicRanges::data.end()); // sort basic ranges
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    start_points.emplace_back(raw_data.size()); | 
					 | 
					 | 
					    for (auto &range : BasicRanges::data) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					        range = Common::range_reverse(range); // basic ranges reverse
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					//    std::sort(BasicRanges::data.begin(), BasicRanges::data.end()); // sort basic ranges
 | 
					 | 
					 | 
					    } | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    BasicRanges::sort_data(start_points, raw_data); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::cout << "size: " << BasicRanges::data.size() << std::endl; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//    std::sort(raw_data.begin(), raw_data.end());
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//    std::cout << raw_data.size() << std::endl;
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//    for (auto &range : BasicRanges::data) {
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//        range = Common::range_reverse(range); // basic ranges reverse
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//    }
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					void BasicRanges::generate(std::vector<uint32_t> &release, generate_t info) { // generate specific basic ranges
 | 
					 | 
					 | 
					void BasicRanges::generate(generate_t info) { // generate specific basic ranges
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    constexpr uint32_t MASK_01 = (uint32_t)0b01 << 30; | 
					 | 
					 | 
					    constexpr auto MASK_01 = (uint32_t)0b01 << 30; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    constexpr uint32_t MASK_10 = (uint32_t)0b10 << 30; | 
					 | 
					 | 
					    constexpr auto MASK_10 = (uint32_t)0b10 << 30; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    constexpr uint32_t MASK_11 = (uint32_t)0b11 << 30; | 
					 | 
					 | 
					    constexpr auto MASK_11 = (uint32_t)0b11 << 30; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    /// n4       n3       n2       n1
 | 
					 | 
					 | 
					    /// n4       n3       n2       n1
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    /// 00000000 00000000 00000000 00000000 (32-bits)
 | 
					 | 
					 | 
					    /// 00000000 00000000 00000000 00000000 (32-bits)
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    struct build_t { | 
					 | 
					 | 
					    struct build_t { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        uint32_t nx; | 
					 | 
					 | 
					        uint32_t nx; // (n4, n3, n2, n1)
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        uint32_t prefix; | 
					 | 
					 | 
					        uint32_t prefix; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        int offset; | 
					 | 
					 | 
					        int offset; // prefix length
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					    }; | 
					 | 
					 | 
					    }; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::queue<build_t> cache; | 
					 | 
					 | 
					    std::queue<build_t> cache; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    cache.emplace(build_t { | 
					 | 
					 | 
					    cache.emplace(build_t { // setup info
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        .nx = static_cast<uint32_t>(info.n1 | info.n2 << 8 | info.n3 << 16 | info.n4 << 24), | 
					 | 
					 | 
					        .nx = static_cast<uint32_t>(info.n1 | info.n2 << 8 | info.n3 << 16 | info.n4 << 24), | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        .prefix = 0x00000000, | 
					 | 
					 | 
					        .prefix = 0x00000000, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        .offset = 0, | 
					 | 
					 | 
					        .offset = 0, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    }); | 
					 | 
					 | 
					    }); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    while (!cache.empty()) { // queue without elements
 | 
					 | 
					 | 
					    while (!cache.empty()) { // queue without elements -> work complete
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        auto current = cache.front(); | 
					 | 
					 | 
					        auto current = cache.front(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if (!current.nx) { // both n1, n2, n3, n4 -> 0
 | 
					 | 
					 | 
					        if (!current.nx) { // both n1, n2, n3, n4 -> 0
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            release.emplace_back(current.prefix); // release prefix as basic range
 | 
					 | 
					 | 
					            BasicRanges::data.emplace_back(current.prefix); // release prefix as basic range
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            cache.pop(); | 
					 | 
					 | 
					            cache.pop(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            continue; // skip search
 | 
					 | 
					 | 
					            continue; // skip search
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |