delta implementation

the delta has a traversable iterator
then we create a deltawriter that gets a reference to delta and data
deltawriter also gets a traverable interator which uses the existing traversables
This commit is contained in:
Marcel Märtens
2019-10-17 00:55:39 +02:00
parent d58b78d92b
commit 91f5ad141c
6 changed files with 241 additions and 181 deletions

View File

@ -1,3 +1,4 @@
#![allow(incomplete_features)]
#![feature(const_generics, test)]
extern crate serde_derive;

View File

@ -23,6 +23,7 @@ use vek::*;
Every Indexstore is a ParentLayer.
- DetailStore: Every layer must implement this for their KEY.
This is used to store the actual DETAIL of every layer.
- DetailStoreMut: allows mut borrow for Vec types (Hash not supported)
!!Calculations will be implemented on these 2 Stores, rather than the actual structs to reduce duplciate coding!!
- ToOptionUsize: to store INDEX in z16/u32 efficiently and move up to usize on calculation
- Traversable: trait is used to get child layer and child Index for a concrete position.
@ -66,13 +67,19 @@ pub trait IndexStore: ParentLayer {
pub trait DetailStore: Layer {
type DETAIL;
fn load(&self, key: Self::KEY) -> &Self::DETAIL;
fn save(&mut self, key: Self::KEY, detail: Self::DETAIL);
}
pub trait DetailStoreMut: DetailStore {
fn load_mut(&mut self, key: Self::KEY) -> &mut Self::DETAIL;
}
pub trait Traversable<C> {
fn get(self) -> C;
pub trait Traversable {
type TRAV_CHILD;
fn get(self) -> Self::TRAV_CHILD;
}
pub trait Materializeable<T> {
fn mat(self) -> T;
pub trait Materializeable {
type MAT_CHILD;
fn mat(self) -> Self::MAT_CHILD;
}
//#######################################################
@ -176,6 +183,16 @@ impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore
fn load(&self, key: Self::KEY) -> &Self::DETAIL {
&self.detail[key]
}
fn save(&mut self, key: Self::KEY, detail: Self::DETAIL) {
self.detail.insert(key, detail);
}
}
impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStoreMut
for VecNestLayer<C, T, I, { L }>
{
fn load_mut(&mut self, key: Self::KEY) -> &mut Self::DETAIL {
&mut self.detail[key]
}
}
impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore
for HashNestLayer<C, T, I, { L }>
@ -185,12 +202,24 @@ impl<C: DetailStore, I: ToOptionUsize, T, const L: u8> DetailStore
debug_assert_eq!(key, key.align_to_level({ L }));
&self.detail_index[&key].0
}
fn save(&mut self, key: LodPos, detail: Self::DETAIL) {
debug_assert_eq!(key, key.align_to_level({ L }));
self.detail_index.insert(key, (detail, I::none()));
}
}
impl<T, const L: u8> DetailStore for VecLayer<T, { L }> {
type DETAIL = T;
fn load(&self, key: usize) -> &Self::DETAIL {
&self.detail[key]
}
fn save(&mut self, key: usize, detail: Self::DETAIL) {
self.detail[key] = detail;
}
}
impl<T, const L: u8> DetailStoreMut for VecLayer<T, { L }> {
fn load_mut(&mut self, key: usize) -> &mut Self::DETAIL {
&mut self.detail[key]
}
}
impl<T, const L: u8> DetailStore for HashLayer<T, { L }> {
type DETAIL = T;
@ -198,13 +227,18 @@ impl<T, const L: u8> DetailStore for HashLayer<T, { L }> {
debug_assert_eq!(key, key.align_to_level({ L }));
&self.detail[&key]
}
fn save(&mut self, key: LodPos, detail: Self::DETAIL) {
debug_assert_eq!(key, key.align_to_level({ L }));
self.detail.insert(key, detail);
}
}
impl<'a, L: DetailStore<KEY = LodPos> + IndexStore> Traversable<VecIter<'a, L::CHILD>>
for HashIter<'a, L>
impl<'a, L: DetailStore<KEY = LodPos> + IndexStore> Traversable for HashIter<'a, L>
where
L::CHILD: DetailStore,
{
type TRAV_CHILD = VecIter<'a, L::CHILD>;
fn get(self) -> VecIter<'a, L::CHILD> {
let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL);
let pos_offset = relative_to_1d(
@ -226,11 +260,12 @@ where
}
}
impl<'a, L: DetailStore<KEY = usize> + IndexStore> Traversable<VecIter<'a, L::CHILD>>
for VecIter<'a, L>
impl<'a, L: DetailStore<KEY = usize> + IndexStore> Traversable for VecIter<'a, L>
where
L::CHILD: DetailStore,
{
type TRAV_CHILD = VecIter<'a, L::CHILD>;
fn get(self) -> VecIter<'a, L::CHILD> {
let child_lod = self.wanted.align_to_level(L::CHILD::LEVEL);
let pos_offset = relative_to_1d(
@ -252,35 +287,39 @@ where
}
}
impl<'a, L: DetailStore<KEY = LodPos>> Materializeable<&'a L::DETAIL> for HashIter<'a, L> {
impl<'a, L: DetailStore<KEY = LodPos>> Materializeable for HashIter<'a, L> {
type MAT_CHILD = &'a L::DETAIL;
fn mat(self) -> &'a L::DETAIL {
DetailStore::load(self.layer, self.layer_lod)
}
}
impl<'a, L: DetailStore<KEY = usize>> Materializeable<&'a L::DETAIL> for VecIter<'a, L> {
impl<'a, L: DetailStore<KEY = usize>> Materializeable for VecIter<'a, L> {
type MAT_CHILD = &'a L::DETAIL;
fn mat(self) -> &'a L::DETAIL {
DetailStore::load(self.layer, self.layer_key)
}
}
#[rustfmt::skip]
pub type ExampleData =
HashNestLayer<
VecNestLayer<
VecNestLayer<
VecLayer<
i8, 0
> ,Option<()>, u16, 2
> ,() , u32, 3
> ,() ,u16, 4
>;
#[cfg(test)]
mod tests {
use crate::lodstore::data::*;
use test::Bencher;
#[rustfmt::skip]
pub type ExampleData =
HashNestLayer<
VecNestLayer<
VecNestLayer<
VecLayer<
i8, 0
> ,Option<()>, u16, 2
> ,() , u32, 3
> ,() ,u16, 4
>;
fn gen_simple_example() -> ExampleData {
let mut detail_index = FxHashMap::default();
detail_index.insert(LodPos::xyz(0, 0, 0), ((), 0));

View File

@ -1,15 +1,7 @@
/*
use super::{
data::{
LodData,
LodConfig,
},
lodpos::LodPos,
area::LodArea,
};
pub type LodIndex = LodPos;
use super::data::{DetailStore, Layer, ParentLayer, Traversable};
use super::index::ToOptionUsize;
use super::lodpos::{multily_with_2_pow_n, relative_to_1d, two_pow_u32, LodPos};
use serde::export::PhantomData;
/*
A LodDelta applies a change to a Lod
The rules for LodDeltas are strict in order to make them as simple as possible.
@ -21,151 +13,148 @@ pub type LodIndex = LodPos;
However i belive that most algorithms only change every Value once.
*/
#[derive(Debug, Clone)]
pub struct LodDelta<X: LodConfig> {
pub layer0: Vec<(LodIndex, Option<X::L0>)>, // 1/16
pub layer1: Vec<(LodIndex, Option<X::L1>)>, // 1/8
pub layer2: Vec<(LodIndex, Option<X::L2>)>, // 1/4
pub layer3: Vec<(LodIndex, Option<X::L3>)>, // 1/2
pub layer4: Vec<(LodIndex, Option<X::L4>)>, // 1
pub layer5: Vec<(LodIndex, Option<X::L5>)>, // 2
pub layer6: Vec<(LodIndex, Option<X::L6>)>, // 4
pub layer7: Vec<(LodIndex, Option<X::L7>)>, // 8
pub layer8: Vec<(LodIndex, Option<X::L8>)>, // 16
pub layer9: Vec<(LodIndex, Option<X::L9>)>, // 32
pub layer10: Vec<(LodIndex, Option<X::L10>)>, // 64
pub layer11: Vec<(LodIndex, Option<X::L11>)>, // 128
pub layer12: Vec<(LodIndex, Option<X::L12>)>, // 256
pub layer13: Vec<(LodIndex, Option<X::L13>)>, // 512
pub layer14: Vec<(LodIndex, Option<X::L14>)>, // 1024
pub layer15: Vec<(LodIndex, Option<X::L15>)>, // 2048
}
impl<X: LodConfig> LodDelta<X> {
pub fn new() -> Self {
Self {
layer0: Vec::new(),
layer1: Vec::new(),
layer2: Vec::new(),
layer3: Vec::new(),
layer4: Vec::new(),
layer5: Vec::new(),
layer6: Vec::new(),
layer7: Vec::new(),
layer8: Vec::new(),
layer9: Vec::new(),
layer10: Vec::new(),
layer11: Vec::new(),
layer12: Vec::new(),
layer13: Vec::new(),
layer14: Vec::new(),
layer15: Vec::new(),
}
}
//TODO: apply that moves out
pub fn apply(&self, data: &mut LodData<X>) {
for (index, item) in &self.layer15 {
if let Some(item) = item {
data.set15(*index, item.clone(), None);
}
}
for (index, item) in &self.layer14 {
if let Some(item) = item {
data.set14(*index, item.clone(), None);
}
}
for (index, item) in &self.layer13 {
if let Some(item) = item {
data.set13(*index, item.clone(), None);
}
}
for (index, item) in &self.layer12 {
if let Some(item) = item {
data.set12(*index, item.clone(), None);
}
}
for (index, item) in &self.layer11 {
if let Some(item) = item {
data.set11(*index, item.clone(), None);
}
}
for (index, item) in &self.layer10 {
if let Some(item) = item {
data.set10(*index, item.clone(), None);
}
}
for (index, item) in &self.layer9 {
if let Some(item) = item {
data.set9(*index, item.clone(), None);
}
}
for (index, item) in &self.layer8 {
if let Some(item) = item {
data.set8(*index, item.clone(), None);
}
}
for (index, item) in &self.layer7 {
if let Some(item) = item {
data.set7(*index, item.clone(), None);
}
}
for (index, item) in &self.layer6 {
if let Some(item) = item {
data.set6(*index, item.clone(), None);
}
}
for (index, item) in &self.layer5 {
if let Some(item) = item {
data.set5(*index, item.clone(), None);
}
}
for (index, item) in &self.layer4 {
if let Some(item) = item {
data.set4(*index, item.clone(), None);
}
}
for (index, item) in &self.layer3 {
if let Some(item) = item {
data.set3(*index, item.clone(), None);
}
}
for (index, item) in &self.layer2 {
if let Some(item) = item {
data.set2(*index, item.clone(), None);
}
}
for (index, item) in &self.layer1 {
if let Some(item) = item {
data.set1(*index, item.clone(), None);
}
}
for (index, item) in &self.layer0 {
if let Some(item) = item {
data.set0(*index, item.clone(), None);
}
}
}
pub fn filter(&self, area: LodArea) -> Self {
Self {
layer0: self.layer0.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer1: self.layer1.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer2: self.layer2.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer3: self.layer3.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer4: self.layer4.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer5: self.layer5.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer6: self.layer6.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer7: self.layer7.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer8: self.layer8.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer9: self.layer9.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer10: self.layer10.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer11: self.layer11.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer12: self.layer12.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer13: self.layer13.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer14: self.layer14.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
layer15: self.layer15.iter().filter(|(index, _)| area.is_inside(index.clone())).cloned().collect(),
}
}
}
/*
The Idea is to create a DeltaWriter that has a mutable Detla and Data and implements the Data interaces.
While it borrows a mutable reference to both it locks both with rusts system
When the writing is done, we destroy the Writer but keep the Delta and Data.
The DeltaWriter will output its own iterator,
We only need a traversable trait
*/
pub trait Delta: Layer {}
#[derive(Default, Clone)]
pub struct VecDelta<T, const L: u8> {
pub detail: Vec<(LodPos, Option<T>)>,
}
#[derive(Default, Clone)]
pub struct VecNestDelta<D: Delta, T, const L: u8> {
pub detail: Vec<(LodPos, Option<T>)>,
pub child: D,
}
pub struct DeltaWriter<'a, C: DetailStore, D: Delta> {
pub delta: &'a mut D,
pub data: &'a mut C,
}
struct VecDataIter<'a, D: Delta> {
layer: &'a D,
}
struct DataWriterIter<DT: Traversable, CT: Traversable> {
delta_iter: DT,
data_iter: CT,
}
//#######################################################
impl<T, const L: u8> Layer for VecDelta<T, { L }> {
type KEY = (usize);
const LEVEL: u8 = { L };
}
impl<D: Delta, T, const L: u8> Layer for VecNestDelta<D, T, { L }> {
type KEY = (usize);
const LEVEL: u8 = { L };
}
impl<D: Delta, T, const L: u8> ParentLayer for VecNestDelta<D, T, { L }> {
type CHILD = D;
fn child(&self) -> &Self::CHILD {
&self.child
}
}
impl<'a, C: DetailStore, D: Delta> DeltaWriter<'a, C, D> {
pub fn new(delta: &'a mut D, data: &'a mut C) -> Self {
DeltaWriter { delta, data }
}
}
impl<'a, C: DetailStore, D: Delta> DeltaWriter<'a, C, D> {
#[allow(dead_code)]
fn trav(&'a self, pos: LodPos) -> VecDataIter<'a, D> {
VecDataIter { layer: &self.delta }
}
}
impl<'a, D: Delta + ParentLayer> Traversable for VecDataIter<'a, D>
where
D::CHILD: Delta,
{
type TRAV_CHILD = VecDataIter<'a, D::CHILD>;
fn get(self) -> VecDataIter<'a, D::CHILD> {
VecDataIter {
layer: self.layer.child(),
}
}
}
impl<'a, DT: Traversable, CT: Traversable> Traversable for DataWriterIter<DT, CT>
where
DT::TRAV_CHILD: Traversable,
CT::TRAV_CHILD: Traversable,
{
type TRAV_CHILD = DataWriterIter<DT::TRAV_CHILD, CT::TRAV_CHILD>;
fn get(self) -> DataWriterIter<DT::TRAV_CHILD, CT::TRAV_CHILD> {
DataWriterIter {
delta_iter: self.delta_iter.get(),
data_iter: self.data_iter.get(),
}
}
}
impl<T, const L: u8> Delta for VecDelta<T, { L }> {}
impl<C: Delta, T, const L: u8> Delta for VecNestDelta<C, T, { L }> {}
//#######################################################
#[cfg(test)]
mod tests {
use crate::lodstore::data::*;
use crate::lodstore::delta::*;
use test::Bencher;
#[rustfmt::skip]
pub type ExampleData =
HashNestLayer<
VecNestLayer<
VecNestLayer<
VecLayer<
i8, 0
> ,Option<()>, u16, 2
> ,() , u32, 3
> ,() ,u16, 4
>;
#[rustfmt::skip]
pub type ExampleDelta =
VecNestDelta<
VecNestDelta<
VecNestDelta<
VecDelta<
i8, 0
>, Option<()>, 2
>, (), 3
>, (), 4
>;
#[test]
fn compilation() {
let mut x = ExampleData::default();
let mut d = ExampleDelta::default();
{
let w = DeltaWriter::new(&mut d, &mut x);
let i = LodPos::xyz(0, 1, 2);
if false {}
}
}
#[test]
fn access_first_element() {
let x = ExampleDelta::default();
let i = LodPos::xyz(0, 0, 0);
}
}

View File

@ -0,0 +1,23 @@
use super::delta::Delta;
use super::index::ToOptionUsize;
use fxhash::FxHashMap;
use std::{u16, u32};
use vek::*;
/*
traits:
- DrillDown
- DrillUp
*/
pub trait DrillDownable {
type DELTA: Delta;
fn drill_down(detail: Self) -> Self::DELTA;
}
pub trait DrillUpable {
type DELTA: Delta;
fn drill_up(detail: Self) -> Self::DELTA;
}
//#######################################################

View File

@ -1,11 +1,15 @@
use std::{u16, u32};
pub trait ToOptionUsize: Copy {
fn none() -> Self;
fn is_some(self) -> bool;
fn into_usize(self) -> usize;
}
impl ToOptionUsize for u32 {
fn none() -> Self {
u32::MAX
}
fn is_some(self) -> bool {
self != u32::MAX
}
@ -15,6 +19,9 @@ impl ToOptionUsize for u32 {
}
impl ToOptionUsize for u16 {
fn none() -> Self {
u16::MAX
}
fn is_some(self) -> bool {
self != u16::MAX
}

View File

@ -1,6 +1,7 @@
pub mod area;
pub mod data;
pub mod delta;
pub mod drill;
pub mod index;
pub mod lodpos;
pub use data::{HashLayer, HashNestLayer, VecLayer, VecNestLayer};