Bläddra i källkod

lotsa updates

devel
Ludovic 'Archivist' Lagouardette 4 år sedan
förälder
incheckning
37175c087e
13 ändrade filer med 511 tillägg och 163 borttagningar
  1. +3
    -3
      Makefile
  2. +9
    -5
      include/gp/allocator/arena.hpp
  3. +211
    -0
      include/gp/allocator/buddy.hpp
  4. +20
    -0
      include/gp/allocator/dummy.hpp
  5. +16
    -6
      include/gp/array.hpp
  6. +6
    -95
      include/gp/buffer.hpp
  7. +10
    -0
      include/gp/flat_tree.hpp
  8. +68
    -0
      include/gp/integer_math.hpp
  9. +93
    -0
      include/gp/iterator.hpp
  10. +26
    -0
      include/gp/subtree_iterator.hpp
  11. +7
    -50
      include/rc6_generic.hpp
  12. +6
    -3
      tests.cpp
  13. +36
    -1
      tests/gp_test.cpp

+ 3
- 3
Makefile Visa fil

@ -1,13 +1,13 @@
CXX= clang++-8
CXXFLAGS= --std=c++17 -g -fprofile-instr-generate -fcoverage-mapping -pthread
CXXFLAGS= --std=c++17 -g -O0 -fprofile-instr-generate -fcoverage-mapping -pthread
all: tests
tests: bin/tests
LLVM_PROFILE_FILE="./bin/tests.profraw" ./bin/tests
@llvm-profdata merge -sparse ./bin/tests.profraw -o ./bin/tests.profdata
@llvm-cov report ./bin/tests -instr-profile=./bin/tests.profdata include/*.hpp include/gp/*.hpp include/gp/algorithm/*.hpp
@llvm-cov report ./bin/tests -instr-profile=./bin/tests.profdata include/*.hpp include/gp/*.hpp include/gp/algorithm/*.hpp | tail -n 1 | tr -s " " | sed -e 's/ /,/g' -- | awk -F "," '{print $$9}' | sed -e 's/^/Untested lines: /g'
@llvm-cov report ./bin/tests -instr-profile=./bin/tests.profdata include/*.hpp include/gp/*.hpp include/gp/algorithm/*.hpp include/gp/allocator/*.hpp
@llvm-cov report ./bin/tests -instr-profile=./bin/tests.profdata include/*.hpp include/gp/*.hpp include/gp/algorithm/*.hpp include/gp/allocator/*.hpp | tail -n 1 | tr -s " " | sed -e 's/ /,/g' -- | awk -F "," '{print $$9}' | sed -e 's/^/Untested lines: /g'
bin/tests: tests.cpp $(wildcard tests/*.cpp) $(wildcard include/*.hpp) ./tests/test_scaffold.h
@mkdir -p $(@D)

include/gp/arena.hpp → include/gp/allocator/arena.hpp Visa fil

@ -10,17 +10,17 @@ namespace gp{
template<typename page_allocator, size_t align = 1>
class arena{
page_allocator allocator;
fel::buffer<char> data;
gp::buffer<char> data;
size_t last;
size_t count;
public:
arena()
:last(0)
,count(0)
,data(fel::buffer<char>(nullptr,nullptr))
,data(gp::buffer<char>(nullptr,nullptr))
{}
template<typename T = typename std::enable_if<fel::has_allocator_interface<page_allocator>::value,int>::type>
template<typename T = typename std::enable_if<gp::has_allocator_interface<page_allocator>::value,int>::type>
arena(size_t sz)
:last(0)
,count(0)
@ -31,7 +31,7 @@ namespace gp{
auto v=allocator.allocate(sz);
if(v!=nullptr)
{
data=fel::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
data=gp::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
}
}
}
@ -66,6 +66,10 @@ namespace gp{
}
}
constexpr bool try_reallocate(void*, size_t) {
return false;
}
bool deallocate(void* ptr)
{
if(data.contains((char*)ptr))
@ -86,7 +90,7 @@ namespace gp{
~arena()
{
if constexpr(fel::has_allocator_interface<page_allocator>::value)
if constexpr(gp::has_allocator_interface<page_allocator>::value)
{
allocator.deallocate(&data[0]);
}

+ 211
- 0
include/gp/allocator/buddy.hpp Visa fil

@ -0,0 +1,211 @@
#pragma once
#include "gp_config.hpp"
#include "gp/buffer.hpp"
#include "gp/array.hpp"
#include "gp/integer_math.hpp"
#include <type_traits>
#include <gp/algorithm/tmp_manip.hpp>
namespace gp{
template<typename page_allocator, size_t max_msb = 24, size_t align = 8>
class buddy{
struct twig {
bool used : 1;
bool used_children : 1;
twig(uint8_t src) {
used = 1 & src;
used_children = 2 & src;
}
operator uint8_t() {
return used + 2 * used_children;
}
};
struct bundle {
uint8_t a : 2;
uint8_t b : 2;
uint8_t c : 2;
uint8_t d : 2;
};
page_allocator allocator;
gp::buffer<char> data;
static constexpr size_t max_depth = max_msb - gp::math::msb(align);
static constexpr size_t required_twigs = (1 << (max_depth + 1)) - 1;
/**
* ((max allocatable size - min allocatable size) ** 2 - 1) / 4 twigs in a bundle
**/
static constexpr size_t span_size = required_twigs / 4 + (required_twigs % 4 != 0);
gp::array<bundle, span_size> stack;
twig get_twig(size_t idx) {
auto far = idx / 4;
auto local = idx % 4;
auto& group = stack[far];
switch(local) {
case 0:
return group.a;
case 1:
return group.b;
case 2:
return group.c;
case 3:
return group.d;
}
}
void set_twig(size_t idx, twig v) {
auto far = idx / 4;
auto local = idx % 4;
auto& group = stack[far];
switch(local) {
case 0:
group.a = v;
return;
case 1:
group.b = v;
return;
case 2:
group.c = v;
return;
case 3:
group.d = v;
return;
}
}
constexpr size_t size_to_depth(size_t sz) {
auto pow2 = gp::math::msb(sz);
return gp::max(max_depth ,max_msb - pow2 - (0 != sz % (1 << pow2)));
}
constexpr size_t depth_to_size(size_t depth) {
return 1 << (max_depth - depth + gp::math::msb(align));
}
size_t get_left(size_t index) {
return ((index + 1) << 1) - 1;
}
size_t get_right(size_t index) {
return ((index + 1) << 1);
}
template<typename function>
void all_under(size_t index, function func) {
size_t left = get_left(index);
size_t right = get_right(index);
all_under(left, func);
all_under(right, func);
func(left);
func(right);
}
template<typename function>
void all_over(size_t index, function func) {
size_t parent = ((index + 1) >> 1) - 1;
func(parent);
if(parent != 0)
all_over(parent, func);
}
template<typename function>
bool is_any_child(size_t index, function func) {
size_t left = get_left(index);
size_t right = get_right(index);
if(func(left)) return true;
if(func(right)) return true;
if(any_child(left, func)) return true;
if(any_child(right, func)) return true;
return false;
}
static constexpr size_t no_twig = -1;
size_t find_free_twig(size_t depth, size_t root = 0, size_t explored = 0) {
if(depth == explored) {
auto v = get_twig(root);
if(v.used || v.used_children)
{
return no_twig;
} else {
return root;
}
} else {
++explored;
auto ret = find_free_twig(depth, get_right(root), explored);
if(ret != no_twig)
{
return ret;
}
ret = find_free_twig(depth, get_left(root), explored);
if(ret != no_twig)
{
return ret;
}
}
return no_twig;
}
public:
buddy()
: data(gp::buffer<char>(nullptr,nullptr))
{}
buddy(size_t sz)
: data(nullptr,nullptr)
{
if(sz!=0 && (sz & (sz - 1)) == 0)
{
auto v=allocator.allocate(sz);
if(v!=nullptr && (static_cast<intptr_t>(v) % align) ==0)
{
data=gp::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz);
}
}
}
buddy(char* pos,size_t sz)
: data(pos,pos+sz)
{
}
void* allocate(size_t sz)
{
auto depth = size_to_depth(sz);
auto index = find_free_twig(depth);
if(index == no_twig)
{
return nullptr;
}
all_over(index, [&](size_t idx){
auto t = get_twig(idx);
t.used_children = true;
set_twig(idx, t);
});
auto t = get_twig(index);
t.used = true;
set_twig(index, t);
return reinterpret_cast<void*>(index*depth_to_size(depth)
+ reinterpret_cast<intptr_t>(&*data.begin()));
}
bool deallocate(void* ptr)
{
if(data.contains((char*)ptr))
{
return true;
}
return false;
}
~buddy()
{
if constexpr(gp::has_allocator_interface<page_allocator>::value)
{
allocator.deallocate(&data[0]);
}
}
};
}

+ 20
- 0
include/gp/allocator/dummy.hpp Visa fil

@ -0,0 +1,20 @@
#pragma once
#include <stddef.h>
namespace gp {
struct dummy_allocator{
void* allocator(size_t)
{
return nullptr;
}
bool deallocate(void*)
{
return false;
}
constexpr bool try_reallocate(void*, size_t) {
return false;
}
};
}

+ 16
- 6
include/gp/array.hpp Visa fil

@ -7,8 +7,8 @@ namespace gp{
class array{
T ary[sz];
public:
using associated_iterator = k">typename buffer<T>::associated_iterator;
using associated_const_iterator = k">typename buffer<const T>::associated_iterator;
using associated_iterator = n">pointer_iterator<T>;
using associated_const_iterator = n">pointer_iterator<T>;
array() = default;
@ -27,14 +27,24 @@ namespace gp{
return sz;
}
constexpr associated_iterator begin() const
constexpr associated_iterator begin()
{
return ">gp::buffer<T>{(T*)ary, (T*)ary+sz}.begin();
return f">associated_iterator(&ary[0]);
}
constexpr associated_iterator end() const
constexpr associated_iterator end()
{
return gp::buffer<T>{(T*)ary, (T*)ary+sz}.end();
return associated_iterator(&ary[sz]);
}
constexpr associated_const_iterator cbegin() const
{
return ary;
}
constexpr associated_const_iterator cend() const
{
return ary+sz;
}
constexpr bool operator==(const array& oth) const

+ 6
- 95
include/gp/buffer.hpp Visa fil

@ -12,100 +12,11 @@ namespace gp{
template<typename T>
class buffer final{
public:
struct buffer_iterator final
{
T* data;
typedef T value_type;
typedef std::size_t difference_type;
static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator;
constexpr buffer_iterator(const buffer_iterator& oth)
: data{oth.data}
{}
constexpr buffer_iterator(T* ptr)
: data{ptr}
{}
constexpr operator T&()
{
return *data;
}
constexpr T& operator*(){
return *data;
}
constexpr buffer_iterator operator++()
{
return buffer_iterator{++data};
}
constexpr buffer_iterator operator++(int)
{
return buffer_iterator{data++};
}
constexpr buffer_iterator operator--()
{
return buffer_iterator{--data};
}
constexpr buffer_iterator operator--(int)
{
return buffer_iterator{data--};
}
constexpr buffer_iterator operator+(const std::size_t offset)
{
return buffer_iterator{data+offset};
}
constexpr buffer_iterator operator+(const int offset)
{
return buffer_iterator{data+offset};
}
constexpr buffer_iterator operator-(const std::size_t offset)
{
return buffer_iterator{data-offset};
}
constexpr buffer_iterator operator-(const int offset)
{
return buffer_iterator{data-offset};
}
constexpr difference_type operator-(const buffer_iterator& oth) const
{
return (T*)data-(T*)oth.data;
}
constexpr bool operator==(const buffer_iterator& oth)
{
return data==oth.data;
}
constexpr bool operator!=(buffer_iterator& oth)
{
return data!=oth.data;
}
constexpr bool before_or_equal(const buffer_iterator& oth)
{
return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool operator<=(const buffer_iterator& oth)
{
return before_or_equal(oth);
}
};
private:
buffer_iterator begin_elem;
buffer_iterator end_elem;
pointer_iterator<T> begin_elem;
pointer_iterator<T> end_elem;
public:
using associated_iterator = buffer_iterator;
using associated_iterator = pointer_iterator<T>;
constexpr buffer(T* beg_ptr, T* end_ptr)
: begin_elem{beg_ptr}
@ -117,7 +28,7 @@ namespace gp{
, end_elem{beg_ptr+sz}
{}
constexpr typename buffer_iterator::difference_type size() const
constexpr typename pointer_iterator<T>::difference_type size() const
{
return end_elem - begin_elem;
}
@ -137,7 +48,7 @@ namespace gp{
return *(begin_elem+offset);
}
optional<buffer_iterator> at(std::size_t offset)
optional<pointer_iterator<T>> at(std::size_t offset)
{
auto elem = begin()+offset;
if(!contains(elem))
@ -147,7 +58,7 @@ namespace gp{
return elem;
}
constexpr bool contains(buffer_iterator ptr)
constexpr bool contains(pointer_iterator<T> ptr)
{
return
ptr.data < end_elem.data

+ 10
- 0
include/gp/flat_tree.hpp Visa fil

@ -0,0 +1,10 @@
#pragma one
#include <gp/array.hpp>
#include <gp/iterator.hpp>
#include <gp/integer_math.hpp>
template<typename T, size_t depth>
class flat_tree {
gp::array<T, ((1 << depth) << 1) & 1> data_;
};

+ 68
- 0
include/gp/integer_math.hpp Visa fil

@ -0,0 +1,68 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
namespace gp {
namespace math {
template<typename word_t>
size_t log2(word_t v);
/**
Sean Eron Anderson
seander@cs.stanford.edu
**/
template<>
constexpr size_t log2<uint32_t>(uint32_t v)
{
constexpr int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
}
template<>
constexpr size_t log2<uint64_t>(uint64_t v)
{
constexpr int MultiplyDeBruijnBitPosition[64] =
{
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63
};
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
return MultiplyDeBruijnBitPosition[(uint64_t)(v * 0x03f6eaf2cd271461) >> 58];
}
template<typename word_t>
constexpr size_t msb(word_t v);
template<>
constexpr size_t msb<uint32_t>(uint32_t v)
{
return log2(v);
}
template<>
constexpr size_t msb<uint64_t>(uint64_t v)
{
return log2(v);
}
}
}

+ 93
- 0
include/gp/iterator.hpp Visa fil

@ -1,7 +1,100 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
enum class iterator_type_t{
contiguous_iterator,
non_contiguous_iterator,
lazy_iterator
};
template<typename T>
struct pointer_iterator final
{
T* data;
typedef T value_type;
typedef std::size_t difference_type;
static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator;
constexpr pointer_iterator(const pointer_iterator& oth)
: data{oth.data}
{}
constexpr pointer_iterator(T* ptr)
: data{ptr}
{}
constexpr operator T&()
{
return *data;
}
constexpr T& operator*(){
return *data;
}
constexpr pointer_iterator operator++()
{
return pointer_iterator{++data};
}
constexpr pointer_iterator operator++(int)
{
return pointer_iterator{data++};
}
constexpr pointer_iterator operator--()
{
return pointer_iterator{--data};
}
constexpr pointer_iterator operator--(int)
{
return pointer_iterator{data--};
}
constexpr pointer_iterator operator+(const std::size_t offset)
{
return pointer_iterator{data+offset};
}
constexpr pointer_iterator operator+(const int offset)
{
return pointer_iterator{data+offset};
}
constexpr pointer_iterator operator-(const std::size_t offset)
{
return pointer_iterator{data-offset};
}
constexpr pointer_iterator operator-(const int offset)
{
return pointer_iterator{data-offset};
}
constexpr difference_type operator-(const pointer_iterator& oth) const
{
return (T*)data-(T*)oth.data;
}
constexpr bool operator==(const pointer_iterator& oth)
{
return data==oth.data;
}
constexpr bool operator!=(pointer_iterator& oth)
{
return data!=oth.data;
}
constexpr bool before_or_equal(const pointer_iterator& oth)
{
return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data);
}
constexpr bool operator<=(const pointer_iterator& oth)
{
return before_or_equal(oth);
}
};

+ 26
- 0
include/gp/subtree_iterator.hpp Visa fil

@ -0,0 +1,26 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <gp/buffer.hpp>
template<typename T>
struct subtree_iterator final
{
gp::buffer<T> target;
size_t idx;
public:
subtree_iterator()
: target{}
, idx{0}
{}
subtree_iterator(gp::buffer<T> data, size_t itr_idx)
: target{data}
, idx{itr_idx}
{}
template<typename func>
void climb_traversal(func& traverser) {
}
};

+ 7
- 50
include/rc6_generic.hpp Visa fil

@ -1,55 +1,10 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <gp/integer_math.hpp>
#include <algorithm>
#include <array>
template<typename word_t>
size_t lg(word_t v);
/**
Sean Eron Anderson
seander@cs.stanford.edu
**/
template<>
constexpr size_t lg<uint32_t>(uint32_t v)
{
constexpr int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
}
template<>
constexpr size_t lg<uint64_t>(uint64_t v)
{
constexpr int MultiplyDeBruijnBitPosition[64] =
{
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63
};
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
return MultiplyDeBruijnBitPosition[(uint64_t)(v * 0x03f6eaf2cd271461) >> 58];
}
template<typename word_t = uint32_t, size_t r = 20, size_t b = 128, word_t P = 0xb7e15163L, word_t Q = 0x9e3779b9L>
@ -132,6 +87,7 @@ public:
{}
constexpr block_type encrypt(block_type plaintext) {
using namespace gp::math;
auto& A = plaintext[0];
auto& B = plaintext[1];
auto& C = plaintext[2];
@ -144,8 +100,8 @@ public:
for(size_t i = 0; i < r; ++i)
{
auto u = r_l( D * ( 2 * D + 1 ), lg(word_size));
auto t = r_l( B * ( 2 * B + 1 ), lg(word_size));
auto u = r_l( D * ( 2 * D + 1 ), msb(word_size));
auto t = r_l( B * ( 2 * B + 1 ), msb(word_size));
A = r_l((A ^ t), u % word_size) + *(it++);
C = r_l((C ^ u), t % word_size) + *(it++);
std::rotate(plaintext.begin(), plaintext.begin()+1, plaintext.end());
@ -158,6 +114,7 @@ public:
}
constexpr block_type decrypt(block_type plaintext) {
using namespace gp::math;
auto& A = plaintext[0];
auto& B = plaintext[1];
auto& C = plaintext[2];
@ -170,8 +127,8 @@ public:
for(size_t i = 0; i < r; ++i)
{
std::rotate(plaintext.begin(), plaintext.end()-1, plaintext.end());
auto u = r_l( D * ( 2 * D + 1 ), lg(word_size));
auto t = r_l( B * ( 2 * B + 1 ), lg(word_size));
auto u = r_l( D * ( 2 * D + 1 ), msb(word_size));
auto t = r_l( B * ( 2 * B + 1 ), msb(word_size));
C = r_r( (C - *(it++)) , t % word_size) ^ u ;
A = r_r( (A - *(it++)) , u % word_size) ^ t ;
}

+ 6
- 3
tests.cpp Visa fil

@ -15,16 +15,19 @@ int main()
{
++runned;
int value;
k">try{
c1">//try{
value = test->run();
if(value)
{
std::cout << std::dec << test->name << " failed with "<< value << std::endl;
}
} catch (...) {
/*} catch (gp::runtime_error err) {
std::cout << test->name << " failed with an exception: " << err.what() << std::endl;
value = -1;
//} catch (...) {
std::cout << test->name << " failed with an exception" << std::endl;
value = -1;
}
}*/
failed += (value != 0);
}
std::cout << std::dec << "Runned "<<runned<<" tests with "<<failed<<" failures" << std::endl;

+ 36
- 1
tests/gp_test.cpp Visa fil

@ -1,7 +1,10 @@
#include "test_scaffold.h"
#include "gp/array.hpp"
#include "gp/allocator/buddy.hpp"
#include "gp/allocator/dummy.hpp"
#include <thread>
#include <chrono>
#include <set>
#include <numeric>
#include <iomanip>
#include <fstream>
@ -75,4 +78,36 @@ struct optional_test : public test_scaffold {
}
};
append_test dummy_mlyusisd3(new optional_test{});
append_test dummy_mlyusisd3(new optional_test{});
struct buddy_test : public test_scaffold {
buddy_test() {
name = __FILE__ ":3";
}
gp::array<char, 4096> store;
virtual int run() {
int res = 0;
{
gp::buddy<gp::dummy_allocator, gp::math::msb<uint64_t>(4096)> bud{&*store.begin(), store.size()};
std::set<void*> ptr_set;
for(int i = 0; i < 4096 / 8; i++)
{
void* v = bud.allocate(8);
if(v == nullptr) throw gp::runtime_error("allocation failed");
ptr_set.insert(v);
}
std::cout << ptr_set.size() << "//" << ptr_set.count(nullptr);
if(ptr_set.count(nullptr)!=0 || ptr_set.size()!=(4096/8)) throw gp::runtime_error("some allocations failed");
res++;
res += nullptr == bud.allocate(8);
if(nullptr != bud.allocate(8)) throw gp::runtime_error("allocation succeeded, failure was expected");
++res;
}
return res;
}
};
append_test dummy_654sisd3(new buddy_test{});

Laddar…
Avbryt
Spara