summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.nix/derivation.nix8
-rw-r--r--README.md50
-rw-r--r--SConstruct1
-rw-r--r--c++/ico.hpp114
-rw-r--r--default.nix14
-rw-r--r--node_neighbours.md13
-rw-r--r--tests/SConscript31
-rw-r--r--tests/ico.cpp68
8 files changed, 291 insertions, 8 deletions
diff --git a/.nix/derivation.nix b/.nix/derivation.nix
index a927e8d..fd41fc1 100644
--- a/.nix/derivation.nix
+++ b/.nix/derivation.nix
@@ -1,5 +1,6 @@
{ stdenv
, scons
+, forstio
}:
stdenv.mkDerivation {
pname = "icosahedrical_destruction";
@@ -9,5 +10,12 @@ stdenv.mkDerivation {
nativeBuildInputs = [
scons
+ forstio.core
];
+
+ doCheck = true;
+ checkPhase = ''
+ scons test
+ ./bin/tests
+ '';
}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d531c6d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+# Icosahedrical Destruction
+
+## Triangle Neighbours
+
+Starting at zero, the described operations match while the remainder "falls out".
+The next level takes over then. And so on ....
+
+### Level - 0
+
+0 x 1 => 1
+0 x 2 => 2
+0 x 3 => 3
+// Mirror
+1 x 1 => 0
+2 x 2 => 0
+3 x 3 => 0
+
+### Level - 1
+
+0-1 x 2 => 2-3
+0-1 x 3 => 3-2
+0-2 x 1 => 1-3
+0-2 x 3 => 3-1
+0-3 x 1 => 1-2
+0-3 x 2 => 2-1
+// Mirror
+1-2 x 1 => 0-3
+1-3 x 1 => 0-2
+2-1 x 2 => 0-3
+2-3 x 2 => 0-1
+3-1 x 3 => 0-2
+3-2 x 3 => 0-1
+
+### Level - 2
+
+0-1-1 x 2 => 2-3-3
+0-1-1 x 3 => 3-2-2
+0-1-2 x 3 => 3-2-1
+0-1-3 x 2 => 2-3-1
+0-2-1 x 3 => 3-1-2
+0-2-2 x 1 => 1-3-3
+0-2-2 x 3 => 3-1-1
+0-2-3 x 1 => 1-3-2
+0-3-1 x 2 => 2-1-3
+0-3-2 x 1 => 1-2-3
+0-3-3 x 1 => 1-2-2
+0-3-3 x 2 => 2-1-1
+...
+
+
diff --git a/SConstruct b/SConstruct
index c07c9b4..26151d4 100644
--- a/SConstruct
+++ b/SConstruct
@@ -59,6 +59,7 @@ env.targets = [];
Export('env')
SConscript('c++/SConscript')
+SConscript('tests/SConscript')
# Aliasing
env.Alias('cdb', env.cdb);
diff --git a/c++/ico.hpp b/c++/ico.hpp
index 0ac1a91..257f12d 100644
--- a/c++/ico.hpp
+++ b/c++/ico.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <array>
+#include <cassert>
#include <cstdint>
namespace kel {
@@ -11,7 +12,7 @@ struct ico_surface_helper {
* triangle. The orientation of the triangle is determined by the horizontal line
* (on the 2D foldout of the icosahedron) which is the down direction.
*/
- static constexpr std::array<std::array<uint8_t,3u>, 20u> neighbour_map {
+ static constexpr std::array<std::array<uint8_t,3u>, 20u> neighbour_map {{
{1,4,5},//0
{2,0,6},//1
{3,1,7},//2
@@ -32,26 +33,112 @@ struct ico_surface_helper {
{16,18,12},//17
{17,19,13},//18
{18,15,14} //19
- };
+ }};
};
}
template<uint64_t SubD>
class ico_addr {
private:
- std::array<uint8_t, SubD+1u> vals_;
+ std::array<uint8_t, SubD> vals_;
public:
- template<uint64_t Div = 1u>
- ico_addr<Div> slice() const {
- return {};
+ uint8_t& at(uint64_t i){
+ return vals_[i];
+ }
+
+ const uint8_t& at(uint64_t i) const {
+ return vals_[i];
+ }
+
+ constexpr uint64_t size() const {
+ return SubD;
+ }
+
+ bool is_equal(const ico_addr<SubD>& rhs) const {
+ bool eq = true;
+
+ for(uint64_t i = 0u; i < size(); ++i){
+ eq &= (at(i) == rhs.at(i));
+ }
+
+ return eq;
+ }
+
+ bool has_zero() const {
+ uint64_t z_ctr = 0u;
+ for(uint64_t i = 1u; i < size(); ++i){
+ z_ctr += (at(i) == 0u ? 1u : 0u);
+ }
+ return (z_ctr > 0u);
+ }
+
+ std::array<uint64_t,4u> count_groups() const {
+ std::array<uint64_t,4u> grps{0,0,0,0};
+
+ for(uint64_t i = 1u; i < size(); ++i){
+ auto& addr_i = vals_[i];
+ assert(addr_i < 4);
+
+ ++grps[addr_i];
+ }
+
+ return grps;
+ }
+
+ uint64_t count_non_zero_groups() const {
+ auto ctr = count_groups();
+
+ uint64_t grp_ctr = 0u;
+ for(uint64_t i = 1u; i < ctr.size(); ++i){
+ grp_ctr += (ctr[i] > 0u ? 1u : 0u);
+ }
+ return grp_ctr;
+ }
+
+ bool has_all_non_zero_groups() const {
+ auto ctr = count_non_zero_groups();
+ return (ctr == 3u);
+ }
+
+ ico_addr<SubD> go_to(uint8_t dir_i){
+ ico_addr<SubD> cpy_addr;
+ cpy_addr.vals_ = vals_;
+
+ if(at(size() - 1u) == 0u){
+ cpy_addr.at(size() - 1u) = dir_i + 1u;
+ }
+ if(at(size() - 1u) == (dir_i + 1u)){
+ cpy_addr.at(size() - 1u) = 0u;
+ }
+
+ return cpy_addr;
+ }
+
+ bool borders_root() const {
+ return not (has_all_non_zero_groups() or has_zero());
}
};
template<typename T, uint64_t D>
class ico_triangle {
private:
- std::array<ico_triangle<T,D-1u>> subdivs_;
+ std::array<ico_triangle<T,D-1u>,4u> subdivs_;
public:
+
+ ico_triangle<T,D-1u>& at(uint8_t i){
+ return subdivs_[i];
+ }
+
+ template<uint64_t AddrOrigLen>
+ ico_triangle<T,0u> at(const ico_addr<AddrOrigLen>& addr, uint64_t next_i){
+ auto& addr_i = addr[next_i];
+
+ auto& sub_triangle = subdivs_[addr_i];
+ if constexpr ( D == 1u){
+ return sub_triangle;
+ }
+ return sub_triangle.at(addr,next_i+1u);
+ }
};
template<typename T>
@@ -61,10 +148,23 @@ private:
public:
};
+namespace impl {
+}
+
template<typename T, uint64_t SubD>
class icosahedron final {
private:
std::array<ico_triangle<T,SubD>,20u> surfaces_;
public:
+
+ template<uint64_t AddrD>
+ ico_triangle<T,SubD+1u-AddrD> at(const ico_addr<AddrD>& addr){
+ static_assert(AddrD <= (SubD+1u), "Addr length to large.");
+ static_assert(AddrD > 0u, "Addr length to small.");
+
+ auto& root_addr = addr[0u];
+ auto& root_triangle = surfaces_[root_addr];
+ return root_triangle.at(addr, 1u);
+ }
};
}
diff --git a/default.nix b/default.nix
index 99e112c..f7c4be7 100644
--- a/default.nix
+++ b/default.nix
@@ -1,3 +1,15 @@
{ pkgs ? import <nixpkgs> {}
+, stdenv ? pkgs.llvmPackages_16.stdenv
+, clang-tools ? pkgs.clang-tools_16
+, forstio ? (import ((builtins.fetchGit {
+ url = "git@git.keldu.de:forstio/forstio";
+ ref = "dev";
+ }).outPath + "/default.nix"){
+ inherit stdenv;
+ inherit clang-tools;
+ }).forstio
}:
-pkgs.callPackage ./.nix/derivation.nix {}
+
+pkgs.callPackage ./.nix/derivation.nix {
+ inherit forstio;
+}
diff --git a/node_neighbours.md b/node_neighbours.md
new file mode 100644
index 0000000..0f3c660
--- /dev/null
+++ b/node_neighbours.md
@@ -0,0 +1,13 @@
+0 - 1,2,3,4,5
+1 - 0,5,10,6,2
+2 - 0,1,6,7,3
+3 - 0,2,7,8,4
+4 - 0,3,8,9,5
+5 - 0,4,9,10,1
+6 - 2,1,10,11,7
+7 - 3,2,6,11,8
+8 - 4,3,7,11,9
+9 - 5,4,8,11,10
+10 - 1,5,9,11,6
+11 - 6,10,9,8,7
+
diff --git a/tests/SConscript b/tests/SConscript
new file mode 100644
index 0000000..8756d5a
--- /dev/null
+++ b/tests/SConscript
@@ -0,0 +1,31 @@
+#!/bin/false
+
+import os
+import os.path
+import glob
+
+
+Import('env')
+
+dir_path = Dir('.').abspath
+
+# Environment for base library
+test_cases_env = env.Clone();
+
+test_cases_env.Append(LIBS=['forstio-test']);
+
+test_cases_env.sources = sorted(glob.glob(dir_path + "/*.cpp"))
+test_cases_env.headers = sorted(glob.glob(dir_path + "/*.hpp"))
+
+env.sources += test_cases_env.sources;
+env.headers += test_cases_env.headers;
+
+objects_static = []
+test_cases_env.add_source_files(objects_static, test_cases_env.sources, shared=False);
+test_cases_env.program = test_cases_env.Program('#bin/tests', [objects_static, env.library_shared]);
+
+# Set Alias
+env.Alias('test', test_cases_env.program);
+env.Alias('check', test_cases_env.program);
+
+env.targets += ['test','check'];
diff --git a/tests/ico.cpp b/tests/ico.cpp
new file mode 100644
index 0000000..021e3c2
--- /dev/null
+++ b/tests/ico.cpp
@@ -0,0 +1,68 @@
+#include <forstio/test/suite.hpp>
+#include "../c++/ico.hpp"
+
+namespace {
+SAW_TEST("Ico Triangle/Border"){
+ using namespace kel;
+
+ {
+ ico_addr<1> addr;
+ addr.at(0u) = 2u;
+
+ SAW_EXPECT(addr.borders_root(), "Triangle address 0 doesn't borders root while it should.");
+ }
+ {
+ ico_addr<2> addr;
+ addr.at(0u) = 1u;
+ addr.at(1u) = 0u;
+
+ SAW_EXPECT(!addr.borders_root(), "Triangle address 1 borders root while it shouldn't.");
+ }
+ {
+ ico_addr<4> addr;
+ addr.at(0u) = 2u;
+ addr.at(1u) = 1u;
+ addr.at(2u) = 2u;
+ addr.at(3u) = 3u;
+
+ SAW_EXPECT(!addr.borders_root(), "Triangle address 2 borders root while it shouldn't.");
+ }
+ {
+ ico_addr<4> addr;
+ addr.at(0u) = 2u;
+ addr.at(1u) = 1u;
+ addr.at(2u) = 1u;
+ addr.at(3u) = 3u;
+
+ SAW_EXPECT(addr.borders_root(), "Triangle address 3 doesn't border root while it should.");
+ }
+ {
+ ico_addr<4> addr;
+ addr.at(0u) = 2u;
+ addr.at(1u) = 1u;
+ addr.at(2u) = 1u;
+ addr.at(3u) = 1u;
+
+ SAW_EXPECT(addr.borders_root(), "Triangle address 4 doesn't border root while it should.");
+ }
+ {
+ ico_addr<4> addr;
+ addr.at(0u) = 2u;
+ addr.at(1u) = 2u;
+ addr.at(2u) = 1u;
+ addr.at(3u) = 1u;
+
+ SAW_EXPECT(addr.borders_root(), "Triangle address 5 doesn't border root while it should.");
+ }
+ {
+ ico_addr<4> addr;
+ addr.at(0u) = 2u;
+ addr.at(1u) = 2u;
+ addr.at(2u) = 1u;
+ addr.at(3u) = 2u;
+
+ SAW_EXPECT(addr.borders_root(), "Triangle address 6 doesn't border root while it should.");
+ }
+}
+
+}