From f01b9f37d8bb4f819c7b82c73ffd790887a98829 Mon Sep 17 00:00:00 2001 From: FL03 Date: Tue, 11 Apr 2023 23:32:56 -0500 Subject: [PATCH 01/15] Update --- Cargo.toml | 2 +- algae/Cargo.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d55e01b..346db5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["algorithms", "data-structures"] license = "Apache-2.0" readme = "README.md" repository = "https://github.com/scattered-systems/algae" -version = "0.1.19" +version = "0.1.20" [workspace.dependencies] decanter = { features = ["derive", "wasm"], version = "0.1.5" } diff --git a/algae/Cargo.toml b/algae/Cargo.toml index a60f035..8112f34 100644 --- a/algae/Cargo.toml +++ b/algae/Cargo.toml @@ -35,9 +35,9 @@ test = true [build-dependencies] [dependencies] -algae-graph = { features = [], optional = true, path = "../graph", version = "0.1.19" } -algae-merkle = { features = [], optional = true, path = "../merkle", version = "0.1.19" } -algae-mmr = { features = [], optional = true, path = "../mmr", version = "0.1.19" } +algae-graph = { features = [], optional = true, path = "../graph", version = "0.1.20" } +algae-merkle = { features = [], optional = true, path = "../merkle", version = "0.1.20" } +algae-mmr = { features = [], optional = true, path = "../mmr", version = "0.1.20" } [dev-dependencies] From ab3dbd540a69fcc86b82aaea8e36a3ed2f20c900 Mon Sep 17 00:00:00 2001 From: FL03 Date: Sat, 15 Apr 2023 17:21:11 -0500 Subject: [PATCH 02/15] Update Signed-off-by: FL03 --- graph/src/cmp/edge.rs | 18 +++++++++++++++++- graph/src/cmp/pair.rs | 20 +++++++++++++++++--- graph/src/directed.rs | 1 + graph/src/lib.rs | 36 ++++++++++++++++++++++++++++++++++++ graph/src/store/mod.rs | 3 ++- graph/src/store/table.rs | 17 ++++++++++++++++- 6 files changed, 89 insertions(+), 6 deletions(-) diff --git a/graph/src/cmp/edge.rs b/graph/src/cmp/edge.rs index ac797f5..d969ada 100644 --- a/graph/src/cmp/edge.rs +++ b/graph/src/cmp/edge.rs @@ -4,7 +4,7 @@ Description: an edge consists of two nodes and an optional edge value */ use super::Pair; -use crate::Node; +use crate::{Node, Weight}; use serde::{Deserialize, Serialize}; pub trait Related {} @@ -13,6 +13,7 @@ pub trait Related {} pub struct Edge where N: Node, + V: Weight { pair: Pair, weight: V, @@ -21,6 +22,7 @@ where impl Edge where N: Node, + V: Weight { pub fn new(a: N, b: N, weight: V) -> Self { Self { @@ -36,9 +38,22 @@ where } } +impl AsMut> for Edge where N: Node, V: Weight { + fn as_mut(&mut self) -> &mut Pair { + &mut self.pair + } +} + +impl AsRef> for Edge where N: Node, V: Weight { + fn as_ref(&self) -> &Pair { + &self.pair + } +} + impl From<(N, N, V)> for Edge where N: Node, + V: Weight { fn from(data: (N, N, V)) -> Self { Self::new(data.0, data.1, data.2) @@ -48,6 +63,7 @@ where impl From<(Pair, V)> for Edge where N: Node, + V: Weight { fn from(data: (Pair, V)) -> Self { Self { diff --git a/graph/src/cmp/pair.rs b/graph/src/cmp/pair.rs index a7eb6f7..e0983cc 100644 --- a/graph/src/cmp/pair.rs +++ b/graph/src/cmp/pair.rs @@ -3,25 +3,39 @@ Contrib: FL03 Description: a pair can either be scalar or vector; if vector, than direction matters */ +use crate::Node; use serde::{Deserialize, Serialize}; + + + #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct Pair(pub T, pub T) where - T: Default; + T: Node; impl Pair where - T: Default, + T: Node, { pub fn new(a: T, b: T) -> Self { Self(a, b) } + pub fn reverse(&mut self) { + std::mem::swap(&mut self.0, &mut self.1) + } + pub fn reverse_mut(&mut self) -> &mut Self { + self.reverse(); + self + } + pub fn pair(&self) -> (T, T) { + (self.0.clone(), self.1.clone()) + } } impl From<(T, T)> for Pair where - T: Default, + T: Node, { fn from(data: (T, T)) -> Self { Self(data.0, data.1) diff --git a/graph/src/directed.rs b/graph/src/directed.rs index 1f21105..cec1076 100644 --- a/graph/src/directed.rs +++ b/graph/src/directed.rs @@ -179,5 +179,6 @@ mod tests { graph.add_node("c"); assert!(graph.contains_all(["a", "b", "c"])); assert!(graph.contains_some(["a", "b", "c", "d"])); + assert!(graph.remove_node(&"a").is_ok()); } } diff --git a/graph/src/lib.rs b/graph/src/lib.rs index d90955f..a023295 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -129,6 +129,42 @@ where visited.len() == self.nodes().len() } + /// [Graph::remove_edge] attempts to remove an edge from the graph + fn remove_edge(&mut self, edge: &Edge) -> Result<(), GraphError> { + match self.store_mut().get_mut(&edge.pair().0) { + Some(edges) => { + edges.retain(|(n, _)| n != &edge.pair().1); + Ok(()) + } + None => Err(GraphError::NodeNotInGraph), + } + } + /// [Graph::remove_edges] attempts to remove several edges from the graph + fn remove_edges(&mut self, iter: impl IntoIterator>) -> Result<(), GraphError> { + for i in iter { + self.remove_edge(&i)?; + } + Ok(()) + } + /// [Graph::remove_node] attempts to remove a node from the graph + fn remove_node(&mut self, node: &N) -> Result<(), GraphError> { + if self.contains_node(node) { + self.store_mut().remove(node); + for (_, edges) in self.store_mut().iter_mut() { + edges.retain(|(n, _)| n != node); + } + Ok(()) + } else { + Err(GraphError::NodeNotInGraph) + } + } + /// [Graph::remove_nodes] attempts to remove several nodes from the graph + fn remove_nodes(&mut self, iter: impl IntoIterator) -> Result<(), GraphError> { + for i in iter { + self.remove_node(&i)?; + } + Ok(()) + } /// [Graph::store_mut] returns an owned, mutable instance of the [AdjacencyTable] fn store_mut(&mut self) -> &mut AdjacencyTable; /// [Graph::store] returns an owned instance of the [AdjacencyTable] diff --git a/graph/src/store/mod.rs b/graph/src/store/mod.rs index 4c9173f..c6f8148 100644 --- a/graph/src/store/mod.rs +++ b/graph/src/store/mod.rs @@ -8,7 +8,7 @@ pub use self::{matrix::*, table::*}; mod matrix; mod table; -use crate::{Contain, Edge, Node}; +use crate::{Contain, Edge, Node, Weight}; use serde::{Deserialize, Serialize}; use std::ops::IndexMut; @@ -46,6 +46,7 @@ where pub trait Store: Extend> + IndexMut> where N: Node, + V: Weight, { fn clear(&mut self); fn contains_key(&self, key: &N) -> bool; diff --git a/graph/src/store/table.rs b/graph/src/store/table.rs index 627ad08..d26c2b8 100644 --- a/graph/src/store/table.rs +++ b/graph/src/store/table.rs @@ -3,7 +3,7 @@ Contrib: FL03 Description: an adjacency table */ -use crate::{Node, Weight}; +use crate::{Node, Weight, Edge}; use serde::{Deserialize, Serialize}; use std::collections::{hash_map, HashMap}; use std::iter::Extend; @@ -45,6 +45,15 @@ where pub fn insert(&mut self, key: N, val: Vec<(N, V)>) -> Option> { self.store.insert(key, val) } + pub fn is_empty(&self) -> bool { + self.store.is_empty() + } + pub fn iter(&self) -> hash_map::Iter<'_, N, Vec<(N, V)>> { + self.store.iter() + } + pub fn iter_mut(&mut self) -> hash_map::IterMut<'_, N, Vec<(N, V)>> { + self.store.iter_mut() + } pub fn get(&self, key: &N) -> Option<&Vec<(N, V)>> { self.store.get(key) } @@ -60,6 +69,12 @@ where pub fn len(&self) -> usize { self.store.len() } + pub fn remove(&mut self, key: &N) -> Option> { + self.store.remove(key) + } + pub fn reserve(&mut self, additional: usize) { + self.store.reserve(additional) + } pub fn table(self) -> HashMap> { self.store } From 7f484f425007fcb43c50f4b4e12d472117d30c37 Mon Sep 17 00:00:00 2001 From: FL03 Date: Sun, 16 Jul 2023 06:02:44 -0500 Subject: [PATCH 03/15] update Signed-off-by: FL03 --- Cargo.toml | 8 +++++--- algae/benches/graphs.rs | 2 +- algae/src/lib.rs | 5 +++-- graph/Cargo.toml | 3 +++ graph/src/cmp/edge.rs | 20 ++++++++++++++------ graph/src/cmp/pair.rs | 3 --- graph/src/lib.rs | 15 ++++++++++++--- graph/src/store/table.rs | 3 +-- merkle/Cargo.toml | 8 ++++---- mmr/Cargo.toml | 4 ++-- 10 files changed, 45 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 346db5c..393a151 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,11 @@ version = "0.1.20" decanter = { features = ["derive", "wasm"], version = "0.1.5" } anyhow = "1" -itertools = "0.10" +itertools = "0.11" serde = { features = ["derive"], version = "1" } serde_json = "1" -smart-default = "0.6" -strum = { features = ["derive"], version = "0.24" } +smart-default = "0.7" +strum = { features = ["derive"], version = "0.25" } [workspace] default-members = [ @@ -32,6 +32,8 @@ members = [ "mmr" ] +resolver = "2" + [profile.dev] codegen-units = 256 debug = true diff --git a/algae/benches/graphs.rs b/algae/benches/graphs.rs index 8e4d12c..7cd21a0 100644 --- a/algae/benches/graphs.rs +++ b/algae/benches/graphs.rs @@ -2,7 +2,7 @@ #![feature(test)] extern crate test; -use algae::graph::{DirectedGraph, Edge, Graph,}; +use algae::graph::{DirectedGraph, Edge, Graph}; use test::Bencher; const TEST_EDGES: [(&str, &str, usize); 5] = [ diff --git a/algae/src/lib.rs b/algae/src/lib.rs index f48e1e2..be800c2 100644 --- a/algae/src/lib.rs +++ b/algae/src/lib.rs @@ -1,9 +1,10 @@ /* Appellation: algae Contrib: FL03 - Description: - Algae is a comprehensive collection of algorithms and data-structures */ +/// # Algae +/// +/// Algae is a comprehensive collection of algorithms and data-structures written in Rust. #[cfg(feature = "graph")] pub use algae_graph as graph; #[cfg(feature = "merkle")] diff --git a/graph/Cargo.toml b/graph/Cargo.toml index 2e5efce..c815236 100644 --- a/graph/Cargo.toml +++ b/graph/Cargo.toml @@ -17,7 +17,10 @@ default = [] wasm = [] [lib] +bench = true crate-type = ["cdylib", "rlib"] +doctest = true +test = true [build-dependencies] diff --git a/graph/src/cmp/edge.rs b/graph/src/cmp/edge.rs index d969ada..3d183bb 100644 --- a/graph/src/cmp/edge.rs +++ b/graph/src/cmp/edge.rs @@ -13,7 +13,7 @@ pub trait Related {} pub struct Edge where N: Node, - V: Weight + V: Weight, { pair: Pair, weight: V, @@ -22,7 +22,7 @@ where impl Edge where N: Node, - V: Weight + V: Weight, { pub fn new(a: N, b: N, weight: V) -> Self { Self { @@ -38,13 +38,21 @@ where } } -impl AsMut> for Edge where N: Node, V: Weight { +impl AsMut> for Edge +where + N: Node, + V: Weight, +{ fn as_mut(&mut self) -> &mut Pair { &mut self.pair } } -impl AsRef> for Edge where N: Node, V: Weight { +impl AsRef> for Edge +where + N: Node, + V: Weight, +{ fn as_ref(&self) -> &Pair { &self.pair } @@ -53,7 +61,7 @@ impl AsRef> for Edge where N: Node, V: Weight { impl From<(N, N, V)> for Edge where N: Node, - V: Weight + V: Weight, { fn from(data: (N, N, V)) -> Self { Self::new(data.0, data.1, data.2) @@ -63,7 +71,7 @@ where impl From<(Pair, V)> for Edge where N: Node, - V: Weight + V: Weight, { fn from(data: (Pair, V)) -> Self { Self { diff --git a/graph/src/cmp/pair.rs b/graph/src/cmp/pair.rs index e0983cc..cee78b1 100644 --- a/graph/src/cmp/pair.rs +++ b/graph/src/cmp/pair.rs @@ -6,9 +6,6 @@ use crate::Node; use serde::{Deserialize, Serialize}; - - - #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct Pair(pub T, pub T) where diff --git a/graph/src/lib.rs b/graph/src/lib.rs index a023295..9daf0a3 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -1,8 +1,10 @@ /* Appellation: graphs Contrib: FL03 - Description: This library is dedicated to graphs, explicitly implementing generic directed and undirected data-structures while providing the tools to create new ones. */ +/// # Graphs +/// +/// This library is dedicated to graphs, explicitly implementing generic directed and undirected data-structures while providing the tools to create new ones. pub use self::{cmp::*, directed::*, errors::*, specs::*, undirected::*}; pub(crate) mod cmp; @@ -21,7 +23,11 @@ use store::AdjacencyTable; /// [Graph] describes the basic operations of a graph data-structure pub trait Graph: - Clone + Contain + Contain> + IndexMut> + AsMut> + + Clone + + Contain + + Contain> + + IndexMut> where N: Node, V: Weight, @@ -140,7 +146,10 @@ where } } /// [Graph::remove_edges] attempts to remove several edges from the graph - fn remove_edges(&mut self, iter: impl IntoIterator>) -> Result<(), GraphError> { + fn remove_edges( + &mut self, + iter: impl IntoIterator>, + ) -> Result<(), GraphError> { for i in iter { self.remove_edge(&i)?; } diff --git a/graph/src/store/table.rs b/graph/src/store/table.rs index d26c2b8..ee67fd6 100644 --- a/graph/src/store/table.rs +++ b/graph/src/store/table.rs @@ -1,9 +1,8 @@ /* Appellation: atable Contrib: FL03 - Description: an adjacency table */ -use crate::{Node, Weight, Edge}; +use crate::{Node, Weight}; use serde::{Deserialize, Serialize}; use std::collections::{hash_map, HashMap}; use std::iter::Extend; diff --git a/merkle/Cargo.toml b/merkle/Cargo.toml index 9bd2259..ed73d4e 100644 --- a/merkle/Cargo.toml +++ b/merkle/Cargo.toml @@ -26,7 +26,7 @@ test = true [dependencies] anyhow.workspace = true -blake3 ={ features = [], version = "1.3" } +blake3 ={ features = [], version = "1" } decanter.workspace = true hex = "0.4" itertools.workspace = true @@ -37,7 +37,7 @@ smart-default.workspace = true strum.workspace = true [dev-dependencies] -hex-literal = "0.3" +hex-literal = "0.4" log = "0.4" vrf = "0.2" @@ -45,6 +45,6 @@ vrf = "0.2" all-features = true rustc-args = ["--cfg", "docsrs"] -[target.wasm32-unknown-unknown] +[target.wasm32-unknown-unknown.dependencies] -[target.wasm32-wasi] +[target.wasm32-wasi.dependencies] diff --git a/mmr/Cargo.toml b/mmr/Cargo.toml index 5796c33..e24611f 100644 --- a/mmr/Cargo.toml +++ b/mmr/Cargo.toml @@ -35,8 +35,8 @@ smart-default.workspace = true strum.workspace = true [dev-dependencies] -hex-literal = "0.3.4" -vrf = "0.2.4" +hex-literal = "0.4" +vrf = "0.2" [package.metadata.docs.rs] all-features = true From b37e8d2195d268a36ee719c16abcce1e98659937 Mon Sep 17 00:00:00 2001 From: FL03 Date: Sun, 17 Sep 2023 10:03:36 -0500 Subject: [PATCH 04/15] update Signed-off-by: FL03 --- merkle/Cargo.toml | 2 ++ merkle/benches/merkle.rs | 39 +++++++++++++++++++++++++++ merkle/src/layers.rs | 4 +-- merkle/src/lib.rs | 11 +++++++- merkle/src/nodes.rs | 1 - merkle/src/proofs/mod.rs | 19 +++++++++++-- merkle/src/proofs/path.rs | 1 - merkle/src/proofs/proof.rs | 5 ++-- merkle/src/shape.rs | 34 +++++++++-------------- merkle/src/tree.rs | 20 +++++--------- merkle/src/utils.rs | 6 ++--- merkle/tests/merkle.rs | 55 +++++++++++++++++++++++++------------- 12 files changed, 130 insertions(+), 67 deletions(-) create mode 100644 merkle/benches/merkle.rs diff --git a/merkle/Cargo.toml b/merkle/Cargo.toml index ed73d4e..13fcd07 100644 --- a/merkle/Cargo.toml +++ b/merkle/Cargo.toml @@ -21,6 +21,7 @@ wasm = [ ] [lib] +bench = true crate-type = ["cdylib", "rlib"] test = true @@ -39,6 +40,7 @@ strum.workspace = true [dev-dependencies] hex-literal = "0.4" log = "0.4" +rs_merkle = "1.4" vrf = "0.2" [package.metadata.docs.rs] diff --git a/merkle/benches/merkle.rs b/merkle/benches/merkle.rs new file mode 100644 index 0000000..654cd6a --- /dev/null +++ b/merkle/benches/merkle.rs @@ -0,0 +1,39 @@ +// bench.rs +#![feature(test)] + +extern crate test; +use algae_merkle::MerkleTree; +use decanter::prelude::{H256, Hashable}; + +use test::Bencher; + +const TEST_NODES: [&str; 4] = ["a", "b", "c", "d"]; + +#[bench] +fn bench_merkle_proofs(b: &mut Bencher) { + let leafs = TEST_NODES + .iter() + .map(|i| i.hash()) + .collect::>(); + let tree = MerkleTree::from(leafs.as_slice()); + b.iter(|| { + leafs.iter().enumerate().for_each(|(i, leaf)| assert!(!tree.proof(i).contains(leaf))); + }); +} + +#[bench] +fn bench_rs_merkle(b: &mut Bencher) { + use rs_merkle::MerkleTree as RSMerkleTree; + use rs_merkle::algorithms::Sha256; + use rs_merkle::Hasher; + + let leafs = TEST_NODES + .iter() + .map(|i| Sha256::hash(i.as_bytes())) + .collect::>(); + let tree = RSMerkleTree::::from_leaves(&leafs); + b.iter(|| { + leafs.iter().enumerate().for_each(|(i, leaf)| assert!(!tree.proof(&[i]).proof_hashes().contains(leaf))); + }); +} + diff --git a/merkle/src/layers.rs b/merkle/src/layers.rs index 140be48..8cc044d 100644 --- a/merkle/src/layers.rs +++ b/merkle/src/layers.rs @@ -1,8 +1,6 @@ /* Appellation: layers Contrib: FL03 - Description: - Merkle Tree def... */ use crate::Node; use itertools::Itertools; @@ -19,7 +17,7 @@ impl Layer where T: Default + ToString, { - pub fn new(data: Vec>) -> Self { + pub fn new(data: impl IntoIterator>) -> Self { let layer = data.into_iter().batching(|it| match it.next() { Some(l) => match it.next() { Some(r) => Some(Node::from((l, r))), diff --git a/merkle/src/lib.rs b/merkle/src/lib.rs index 11a21fd..ea374db 100644 --- a/merkle/src/lib.rs +++ b/merkle/src/lib.rs @@ -13,6 +13,15 @@ pub(crate) mod nodes; pub(crate) mod payloads; pub(crate) mod shape; pub(crate) mod tree; -mod utils; +pub(crate) mod utils; pub mod proofs; + +pub mod prelude { + pub use crate::layers::*; + pub use crate::nodes::*; + pub use crate::payloads::*; + pub use crate::shape::*; + pub use crate::tree::*; + pub use crate::utils::*; +} diff --git a/merkle/src/nodes.rs b/merkle/src/nodes.rs index dc8c23b..fbc09a4 100644 --- a/merkle/src/nodes.rs +++ b/merkle/src/nodes.rs @@ -1,7 +1,6 @@ /* Appellation: nodes Contrib: FL03 - Description: ... Summary ... */ use crate::{combine_hash_str, merkle_hash, Payload}; use decanter::prelude::{Hashable, H256}; diff --git a/merkle/src/proofs/mod.rs b/merkle/src/proofs/mod.rs index 44a87d2..8d80547 100644 --- a/merkle/src/proofs/mod.rs +++ b/merkle/src/proofs/mod.rs @@ -1,9 +1,24 @@ /* Appellation: proofs Contrib: FL03 - Description: ... Summary ... */ -pub use self::{path::*, proof::*}; +//! # Merkle Proofs +//! +//! ## Overview +//! +//! Merkle proofs are a way to prove that a given piece of data is part of a Merkle tree. +//! +pub use self::{path::*, proof::*, utils::*}; pub(crate) mod path; pub(crate) mod proof; + +use decanter::prelude::H256; + +pub trait MerkleProof { + fn proof(&self) -> Vec; +} + +pub(crate) mod utils { + +} \ No newline at end of file diff --git a/merkle/src/proofs/path.rs b/merkle/src/proofs/path.rs index 77eb7a8..c30b3d3 100644 --- a/merkle/src/proofs/path.rs +++ b/merkle/src/proofs/path.rs @@ -1,7 +1,6 @@ /* Appellation: path [merkle] Contrib: FL03 - Description: ... Summary ... */ pub fn proof_path(index: usize, size: usize) -> Vec { diff --git a/merkle/src/proofs/proof.rs b/merkle/src/proofs/proof.rs index d1d48f8..09fbd5f 100644 --- a/merkle/src/proofs/proof.rs +++ b/merkle/src/proofs/proof.rs @@ -1,7 +1,6 @@ /* Appellation: proof Contrib: FL03 - Description: ... Summary ... */ use super::path::proof_path; use crate::{MerkleDimension, MerkleTree}; @@ -46,11 +45,11 @@ impl Iterator for Prover { pub fn merkle_proof(dim: MerkleDimension, nodes: Vec, index: usize) -> Vec { let mut proof: Vec = Vec::new(); let mut offset: usize = 0; - let mut leaf_size = dim.leafs; + let mut leaf_size = dim.leafs(); let proof_index = proof_path(index, leaf_size); - for i in 0..dim.depth - 1 { + for i in 0..dim.depth() - 1 { proof.push(nodes[offset + proof_index[i]]); if leaf_size % 2 != 0 { leaf_size += 1; diff --git a/merkle/src/shape.rs b/merkle/src/shape.rs index e8351a9..e48214e 100644 --- a/merkle/src/shape.rs +++ b/merkle/src/shape.rs @@ -5,39 +5,29 @@ */ use serde::{Deserialize, Serialize}; -pub trait MerkleShape { - fn depth(&self) -> usize; - fn leafs(&self) -> usize; - fn shape(&self) -> (usize, usize, usize) { - (self.depth(), self.leafs(), self.size()) - } - fn size(&self) -> usize; -} #[derive( Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, )] pub struct MerkleDimension { - pub depth: usize, - pub leafs: usize, - pub size: usize, + depth: usize, + leafs: usize, + size: usize, } impl MerkleDimension { pub fn new(depth: usize, leafs: usize, size: usize) -> Self { Self { depth, leafs, size } } -} -impl MerkleShape for MerkleDimension { - fn depth(&self) -> usize { + pub fn depth(&self) -> usize { self.depth } - fn leafs(&self) -> usize { + pub fn leafs(&self) -> usize { self.leafs } - fn size(&self) -> usize { + pub fn size(&self) -> usize { self.size } } @@ -48,14 +38,14 @@ impl std::fmt::Display for MerkleDimension { } } -impl From> for MerkleDimension { - fn from(data: Box) -> Self { - Self::from(data.shape()) - } -} - impl From<(usize, usize, usize)> for MerkleDimension { fn from(data: (usize, usize, usize)) -> Self { Self::new(data.0, data.1, data.2) } } + +impl From for (usize, usize, usize) { + fn from(data: MerkleDimension) -> Self { + (data.depth, data.leafs, data.size) + } +} diff --git a/merkle/src/tree.rs b/merkle/src/tree.rs index 941a3c4..20ae8ba 100644 --- a/merkle/src/tree.rs +++ b/merkle/src/tree.rs @@ -1,17 +1,16 @@ /* Appellation: tree Contrib: FL03 - Description: ... Summary ... */ use crate::proofs::merkle_proof; -use crate::{create_merkle_tree, MerkleDimension, MerkleShape}; +use crate::{create_merkle_tree, MerkleDimension}; use decanter::prelude::{Hashable, H256}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct MerkleTree { - pub dim: MerkleDimension, - pub nodes: Vec, + dim: MerkleDimension, + nodes: Vec, } impl MerkleTree { @@ -47,7 +46,10 @@ impl std::fmt::Display for MerkleTree { } } -impl From<&[T]> for MerkleTree { +impl From<&[T]> for MerkleTree +where + T: Hashable, +{ fn from(data: &[T]) -> Self { let (dim, nodes) = create_merkle_tree::(data); Self { @@ -57,11 +59,3 @@ impl From<&[T]> for MerkleTree { } } -impl From<(Box, Vec)> for MerkleTree { - fn from(data: (Box, Vec)) -> Self { - Self { - dim: MerkleDimension::from(data.0), - nodes: data.1, - } - } -} diff --git a/merkle/src/utils.rs b/merkle/src/utils.rs index b35fdbf..2408225 100644 --- a/merkle/src/utils.rs +++ b/merkle/src/utils.rs @@ -4,7 +4,7 @@ Description: */ use crate::proofs::proof_path; -use crate::{MerkleDimension, MerkleShape}; +use crate::MerkleDimension; use decanter::prelude::{hasher, Hashable, H256}; /// Combines two hashes into a single hash @@ -18,7 +18,7 @@ pub fn combine_hash_str(a: &T, b: &T) -> String { format!("{}{}", a.to_string(), b.to_string()) } /// Creates a Merkle tree from a slice of data -pub fn create_merkle_tree(data: &[T]) -> (Box, Vec) +pub fn create_merkle_tree(data: &[T]) -> (MerkleDimension, Vec) where T: Hashable, { @@ -48,7 +48,7 @@ where depth += 1; } let dim = MerkleDimension::new(depth, data.len(), nodes.len()); - (Box::new(dim), nodes) + (dim, nodes) } /// Takes the hash of the given information to the second degree diff --git a/merkle/tests/merkle.rs b/merkle/tests/merkle.rs index f60daf0..07a58e2 100644 --- a/merkle/tests/merkle.rs +++ b/merkle/tests/merkle.rs @@ -7,15 +7,24 @@ def. This notation abbreviates a is the hash of A; more formally, (A) maps to the hash (a) by the hashing function H */ -use algae_merkle::{is_merkle_valid, MerkleTree}; +use algae_merkle::{add_hash, is_merkle_valid, MerkleTree}; use decanter::prelude::{Hashable, H256}; use hex_literal::hex; +macro_rules! hash_leaves { + ($leaves:expr) => { + $leaves + .iter() + .map(|leaf| leaf.hash()) + .collect::>() + }; +} + macro_rules! gen_merkle_tree_data { () => {{ vec![ - (hex!("0a0b0c0d0e0f0e0d0a0b0c0d0e0f0e0d0a0b0c0d0e0f0e0d0a0b0c0d0e0f0e0d")).into(), - (hex!("0101010101010101010101010101010101010101010101010101010101010202")).into(), + (hex!("17762fddd969a453925d65717ac3eea21320b66b54342fde15128d6caf21215f")).into(), + (hex!("10e5cf3d3c8a4f9f3468c8cc58eea84892a22fdadbc1acb22410190044c1d553")).into(), ] }}; } @@ -23,11 +32,11 @@ macro_rules! gen_merkle_tree_data { macro_rules! gen_merkle_tree_data2 { () => {{ vec![ - (hex!("0a0b0c0d0e0f0e0d0a0b0c0d0e0f0e0d0a0b0c0d0e0f0e0d0a0b0c0d0e0f0e0d")).into(), - (hex!("0101010101010101010101010101010101010101010101010101010101010202")).into(), - (hex!("0101010101010101010101010101010101010101010101010101010101010202")).into(), - (hex!("0101010101010101010101010101010101010101010101010101010101010202")).into(), - (hex!("0101010101010101010101010101010101010101010101010101010101010202")).into(), + (hex!("17762fddd969a453925d65717ac3eea21320b66b54342fde15128d6caf21215f")).into(), + (hex!("10e5cf3d3c8a4f9f3468c8cc58eea84892a22fdadbc1acb22410190044c1d553")).into(), + (hex!("ea7aa1fc9efdbe106dbb70369a75e9671fa29d52bd55536711bf197477b8f021")).into(), + (hex!("d5ede538f628f687e5e0422c7755b503653de2dcd7053ca8791afa5d4787d843")).into(), + (hex!("27bb492e108bf5e9c724176d7ae75d4cedc422fe4065020bd6140c3fcad3a9e7")).into(), ] }}; } @@ -39,11 +48,19 @@ macro_rules! gen_merkle_tree_data2 { */ #[test] fn test_merkle_root() { - let data: Vec = gen_merkle_tree_data!(); - let expected = - (hex!("6b787718210e0b3b608814e04e61fde06d0df794319a12162f287412df3ec920")).into(); - let a = MerkleTree::from(data.as_slice()); - assert_ne!(&a.root(), &expected); + let sample = ["a", "b", "c", "d"]; + let leaves = hash_leaves!(sample); + + let exp = { + let a = add_hash(&leaves[0], &leaves[1]); + let b = add_hash(&leaves[2], &leaves[3]); + add_hash(&a, &b) + // add_hash(&a, &leaves[2]) + }; + + let a = MerkleTree::from(leaves.as_slice()); + + assert_eq!(a.root(), exp); } /* @@ -51,12 +68,14 @@ fn test_merkle_root() { */ #[test] fn test_merkle_proof() { - let expected = - vec![hex!("965b093a75a75895a351786dd7a188515173f6928a8af8c9baa4dcff268a4f0f").into()]; - let data: Vec = gen_merkle_tree_data!(); - let a = MerkleTree::from(data.as_slice()); + let sample = ["a", "b", "c", "d"]; + let leaves = hash_leaves!(sample); + + let exp = vec![leaves[1], add_hash(&leaves[2], &leaves[3])]; + + let a = MerkleTree::from(leaves.as_slice()); - assert_ne!(a.proof(0), expected) + assert_eq!(a.proof(0), exp); } /* From ade3e427adb57d6d5ea921e35642efb58f21ccba Mon Sep 17 00:00:00 2001 From: FL03 Date: Sun, 17 Sep 2023 11:10:42 -0500 Subject: [PATCH 05/15] update Signed-off-by: FL03 --- merkle/Cargo.toml | 1 + merkle/src/lib.rs | 1 - merkle/src/shape.rs | 32 +++++++++++++++++++++- merkle/src/tree/builder.rs | 0 merkle/src/{tree.rs => tree/merkle.rs} | 35 ++++++++++++++++++++++-- merkle/src/tree/mod.rs | 8 ++++++ merkle/tests/merkle.rs | 38 ++++++++++++++++++++++++-- 7 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 merkle/src/tree/builder.rs rename merkle/src/{tree.rs => tree/merkle.rs} (66%) create mode 100644 merkle/src/tree/mod.rs diff --git a/merkle/Cargo.toml b/merkle/Cargo.toml index 13fcd07..e4e08ef 100644 --- a/merkle/Cargo.toml +++ b/merkle/Cargo.toml @@ -39,6 +39,7 @@ strum.workspace = true [dev-dependencies] hex-literal = "0.4" +lazy_static = "1.4" log = "0.4" rs_merkle = "1.4" vrf = "0.2" diff --git a/merkle/src/lib.rs b/merkle/src/lib.rs index ea374db..8ac9e2a 100644 --- a/merkle/src/lib.rs +++ b/merkle/src/lib.rs @@ -1,7 +1,6 @@ /* Appellation: algae-merkle Creator: FL03 - Description: */ #[cfg(test)] extern crate hex_literal; diff --git a/merkle/src/shape.rs b/merkle/src/shape.rs index e48214e..54e70e0 100644 --- a/merkle/src/shape.rs +++ b/merkle/src/shape.rs @@ -1,10 +1,28 @@ /* Appellation: shape Contrib: FL03 - Description: ... Summary ... */ use serde::{Deserialize, Serialize}; +fn get_merkle_tree_size(leafs: usize) -> usize { + let mut size = leafs + (leafs % 2); + let mut l = leafs; + while l > 1 { + l = (l as f64 / 2_f64).ceil() as usize; + size += l; + } + size +} + +fn get_merkle_depth(leafs: usize) -> usize { + let mut depth = 1; + let mut l = leafs; + while l > 1 { + l = (l as f64 / 2_f64).ceil() as usize; + depth += 1; + } + depth +} #[derive( Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, @@ -20,6 +38,13 @@ impl MerkleDimension { Self { depth, leafs, size } } + pub fn from_leafs(leafs: usize) -> Self { + let depth = get_merkle_depth(leafs); + let size = get_merkle_tree_size(leafs); + + Self::new(depth, leafs, size) + } + pub fn depth(&self) -> usize { self.depth } @@ -27,6 +52,11 @@ impl MerkleDimension { pub fn leafs(&self) -> usize { self.leafs } + + pub fn shape(&self) -> (usize, usize, usize) { + (self.depth, self.leafs, self.size) + } + pub fn size(&self) -> usize { self.size } diff --git a/merkle/src/tree/builder.rs b/merkle/src/tree/builder.rs new file mode 100644 index 0000000..e69de29 diff --git a/merkle/src/tree.rs b/merkle/src/tree/merkle.rs similarity index 66% rename from merkle/src/tree.rs rename to merkle/src/tree/merkle.rs index 20ae8ba..1c82c40 100644 --- a/merkle/src/tree.rs +++ b/merkle/src/tree/merkle.rs @@ -1,5 +1,7 @@ +use std::ops::{Index, IndexMut, Range}; + /* - Appellation: tree + Appellation: merkle Contrib: FL03 */ use crate::proofs::merkle_proof; @@ -30,7 +32,7 @@ impl MerkleTree { merkle_proof(self.dim(), self.nodes().clone(), index) } pub fn root(&self) -> H256 { - self.nodes()[self.dim().size() - 1] + self[self.dim().size() - 1] } pub fn nodes(&self) -> &Vec { &self.nodes @@ -38,6 +40,8 @@ impl MerkleTree { pub fn nodes_mut(&mut self) -> &mut Vec { &mut self.nodes } + + } impl std::fmt::Display for MerkleTree { @@ -59,3 +63,30 @@ where } } +impl Index for MerkleTree { + type Output = H256; + + fn index(&self, index: usize) -> &Self::Output { + &self.nodes[index] + } +} + +impl IndexMut for MerkleTree { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.nodes[index] + } +} + +impl Index> for MerkleTree { + type Output = [H256]; + + fn index(&self, index: Range) -> &Self::Output { + &self.nodes[index] + } +} + +impl IndexMut> for MerkleTree { + fn index_mut(&mut self, index: Range) -> &mut Self::Output { + &mut self.nodes[index] + } +} diff --git a/merkle/src/tree/mod.rs b/merkle/src/tree/mod.rs new file mode 100644 index 0000000..d2dbec8 --- /dev/null +++ b/merkle/src/tree/mod.rs @@ -0,0 +1,8 @@ +/* + Appellation: tree + Contrib: FL03 +*/ +pub use self::{builder::*, merkle::*}; + +mod builder; +mod merkle; \ No newline at end of file diff --git a/merkle/tests/merkle.rs b/merkle/tests/merkle.rs index 07a58e2..92e0fb5 100644 --- a/merkle/tests/merkle.rs +++ b/merkle/tests/merkle.rs @@ -11,6 +11,30 @@ use algae_merkle::{add_hash, is_merkle_valid, MerkleTree}; use decanter::prelude::{Hashable, H256}; use hex_literal::hex; +// lazy_static::lazy_static!( +// static ref SAMPLE_DATA: Vec = hash_leaves(); +// ); + +fn get_merkle_tree_size(leafs: usize) -> usize { + let mut size = leafs + (leafs % 2); + let mut l = leafs; + while l > 1 { + l = (l as f64 / 2_f64).ceil() as usize; + size += l; + } + size +} + +fn get_merkle_depth(leafs: usize) -> usize { + let mut depth = 1; + let mut l = leafs; + while l > 1 { + l = (l as f64 / 2_f64).ceil() as usize; + depth += 1; + } + depth +} + macro_rules! hash_leaves { ($leaves:expr) => { $leaves @@ -50,7 +74,7 @@ macro_rules! gen_merkle_tree_data2 { fn test_merkle_root() { let sample = ["a", "b", "c", "d"]; let leaves = hash_leaves!(sample); - + let nleafs = leaves.len(); let exp = { let a = add_hash(&leaves[0], &leaves[1]); let b = add_hash(&leaves[2], &leaves[3]); @@ -58,9 +82,19 @@ fn test_merkle_root() { // add_hash(&a, &leaves[2]) }; - let a = MerkleTree::from(leaves.as_slice()); + let a = MerkleTree::from(sample.as_slice()); assert_eq!(a.root(), exp); + assert_eq!(a.dim().shape(), (get_merkle_depth(nleafs), nleafs, get_merkle_tree_size(nleafs))); +} + +#[test] +fn test_merkle_shape() { + let sample = ["a", "b", "c", "d", "e", "f", "g"]; + let leafs = sample.len(); + let a = MerkleTree::from(sample.as_slice()); + + assert_eq!(a.dim().shape(), (get_merkle_depth(leafs), leafs, get_merkle_tree_size(leafs))); } /* From 26f997f712010b29b4e1d36af943d95565697bef Mon Sep 17 00:00:00 2001 From: FL03 Date: Mon, 18 Sep 2023 09:10:21 -0500 Subject: [PATCH 06/15] update Signed-off-by: FL03 --- algae/benches/lists.rs | 21 +++ algae/src/lib.rs | 11 +- algae/src/list/linked/iter.rs | 96 +++++++++++ algae/src/list/linked/mod.rs | 11 +- algae/src/list/linked/persistant.rs | 130 --------------- algae/src/list/linked/singly.rs | 245 ++++++++++++++++++++++++++++ algae/src/list/mod.rs | 5 +- {algae => graph}/benches/graphs.rs | 2 +- merkle/benches/merkle.rs | 20 ++- merkle/src/layers.rs | 10 +- merkle/src/nodes.rs | 10 +- merkle/src/payloads.rs | 24 +-- merkle/src/proofs/mod.rs | 10 +- merkle/src/shape.rs | 2 +- merkle/src/tree/builder.rs | 4 + merkle/src/tree/merkle.rs | 5 +- merkle/src/tree/mod.rs | 5 +- merkle/src/tree/partial.rs | 23 +++ merkle/tests/merkle.rs | 14 +- 19 files changed, 456 insertions(+), 192 deletions(-) create mode 100644 algae/benches/lists.rs create mode 100644 algae/src/list/linked/iter.rs delete mode 100644 algae/src/list/linked/persistant.rs create mode 100644 algae/src/list/linked/singly.rs rename {algae => graph}/benches/graphs.rs (90%) create mode 100644 merkle/src/tree/partial.rs diff --git a/algae/benches/lists.rs b/algae/benches/lists.rs new file mode 100644 index 0000000..5cf136d --- /dev/null +++ b/algae/benches/lists.rs @@ -0,0 +1,21 @@ +// lists.rs +#![feature(test)] + +extern crate test; +use algae::list::linked::singly::*; +use test::Bencher; + +pub const BENCH_SIZE: usize = 10; + +#[bench] +fn basic_bench(b: &mut Bencher) { + let mut list = SinglyLinkedList::new(); + + assert_eq!(list.pop(), None); + + b.iter(|| { + for i in 0..BENCH_SIZE { + list.push(i); + } + }); +} diff --git a/algae/src/lib.rs b/algae/src/lib.rs index be800c2..b8339b3 100644 --- a/algae/src/lib.rs +++ b/algae/src/lib.rs @@ -2,9 +2,9 @@ Appellation: algae Contrib: FL03 */ -/// # Algae -/// -/// Algae is a comprehensive collection of algorithms and data-structures written in Rust. +//! # Algae +//! +//! Algae is a comprehensive collection of algorithms and data-structures written in Rust. #[cfg(feature = "graph")] pub use algae_graph as graph; #[cfg(feature = "merkle")] @@ -16,9 +16,10 @@ pub mod list; pub mod prelude { #[cfg(feature = "graph")] - pub use super::graph::*; + pub use super::graph; + // pub use super::graph::*; #[cfg(feature = "merkle")] - pub use super::merkle::*; + pub use super::merkle::prelude::*; #[cfg(feature = "mmr")] pub use super::mmr::*; } diff --git a/algae/src/list/linked/iter.rs b/algae/src/list/linked/iter.rs new file mode 100644 index 0000000..37bf6b6 --- /dev/null +++ b/algae/src/list/linked/iter.rs @@ -0,0 +1,96 @@ +/* + Appellation: singly + Contrib: FL03 +*/ +// use super::SinglyLinkedList; +use super::singly::{Node, SinglyLinkedList}; + +pub struct IntoIter(SinglyLinkedList); + +impl IntoIter { + pub fn new(list: SinglyLinkedList) -> Self { + Self(list) + } +} + +pub struct Iter<'a, T> { + pub(crate) next: Option<&'a Node>, +} + +impl<'a, T> Iter<'a, T> { + pub unsafe fn new(list: &'a SinglyLinkedList) -> Self { + Self { + next: list.head().as_ref(), + } + } +} + +pub struct IterMut<'a, T> { + pub(crate) next: Option<&'a mut Node>, +} + +impl Iterator for IntoIter { + type Item = T; + fn next(&mut self) -> Option { + self.0.pop() + } +} + +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + unsafe { + self.next.map(|node| { + self.next = node.link().as_ref(); + node.elem() + }) + } + } +} + +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + fn next(&mut self) -> Option { + unsafe { + self.next.take().map(|node| { + self.next = node.link().as_mut(); + node.elem_mut() + }) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_iter() { + let mut list = SinglyLinkedList::new(); + list.push(1); + list.push(2); + list.push(3); + + let mut iter = list.iter(); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.next(), None); + } + + #[test] + fn iter_mut() { + let mut list = SinglyLinkedList::new(); + list.push(1); + list.push(2); + list.push(3); + + let mut iter = list.iter_mut(); + assert_eq!(iter.next(), Some(&mut 1)); + assert_eq!(iter.next(), Some(&mut 2)); + assert_eq!(iter.next(), Some(&mut 3)); + assert_eq!(iter.next(), None); + } +} diff --git a/algae/src/list/linked/mod.rs b/algae/src/list/linked/mod.rs index 5327b5b..11f41ed 100644 --- a/algae/src/list/linked/mod.rs +++ b/algae/src/list/linked/mod.rs @@ -1,7 +1,14 @@ /* Appellation: linked Contrib: FL03 - Description: ... Summary ... */ +pub use self::{iter::*, singly::SinglyLinkedList, utils::*}; -pub mod persistant; +pub(crate) mod iter; + +pub mod singly; + +pub(crate) mod utils {} + +#[cfg(test)] +mod tests {} diff --git a/algae/src/list/linked/persistant.rs b/algae/src/list/linked/persistant.rs deleted file mode 100644 index 54ef537..0000000 --- a/algae/src/list/linked/persistant.rs +++ /dev/null @@ -1,130 +0,0 @@ -/* - Appellation: persistant - Contrib: FL03 - Description: ... Summary ... -*/ -use std::rc::Rc; - -type Link = Option>>; - -struct Node { - elem: T, - next: Link, -} - -impl Node { - pub fn new(elem: T, next: Link) -> Self { - Self { elem, next } - } - pub fn data(&self) -> &T { - &self.elem - } - pub fn link(&self) -> &Link { - &self.next - } -} - -/// Singly-Linked, Persistant List -pub struct SLPList { - head: Link, -} - -impl SLPList { - pub fn new() -> Self { - Self::from(None) - } - pub fn prepend(&self, elem: T) -> Self { - SLPList::from(Some(Rc::new(Node::new(elem, self.head.clone())))) - } - - pub fn tail(&self) -> Self { - SLPList::from(self.head.as_ref().and_then(|node| node.link().clone())) - } - - pub fn head(&self) -> Option<&T> { - self.head.as_ref().map(|node| node.data()) - } - - pub fn iter(&self) -> Iter<'_, T> { - Iter { - next: self.head.as_deref(), - } - } -} - -impl From> for SLPList { - fn from(head: Link) -> SLPList { - SLPList { head } - } -} - -impl Default for SLPList { - fn default() -> Self { - Self::from(None) - } -} - -impl Drop for SLPList { - fn drop(&mut self) { - let mut head = self.head.take(); - while let Some(node) = head { - if let Ok(mut node) = Rc::try_unwrap(node) { - head = node.next.take(); - } else { - break; - } - } - } -} - -pub struct Iter<'a, T> { - next: Option<&'a Node>, -} - -impl<'a, T> Iterator for Iter<'a, T> { - type Item = &'a T; - - fn next(&mut self) -> Option { - self.next.map(|node| { - self.next = node.next.as_deref(); - &node.elem - }) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_linked_list() { - let list = SLPList::default(); - assert_eq!(list.head(), None); - - let list = list.prepend(1).prepend(2).prepend(3); - assert_eq!(list.head(), Some(&3)); - - let list = list.tail(); - assert_eq!(list.head(), Some(&2)); - - let list = list.tail(); - assert_eq!(list.head(), Some(&1)); - - let list = list.tail(); - assert_eq!(list.head(), None); - - // Make sure empty tail works - let list = list.tail(); - assert_eq!(list.head(), None); - } - - #[test] - fn test_linked_list_iter() { - let list = SLPList::default().prepend(1).prepend(2).prepend(3); - - let mut iter = list.iter(); - assert_eq!(iter.next(), Some(&3)); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.next(), Some(&1)); - } -} diff --git a/algae/src/list/linked/singly.rs b/algae/src/list/linked/singly.rs new file mode 100644 index 0000000..e83c550 --- /dev/null +++ b/algae/src/list/linked/singly.rs @@ -0,0 +1,245 @@ +/* + Appellation: singly + Contrib: FL03 +*/ +use super::{IntoIter, Iter, IterMut}; +use std::ptr; + +type Link = *mut Node; + +// pub type LinkMut = Option<*mut Node>; + +pub struct SinglyLinkedList { + head: Link, + tail: *mut Node, +} + +impl SinglyLinkedList { + pub fn new() -> Self { + SinglyLinkedList { + head: ptr::null_mut(), + tail: ptr::null_mut(), + } + } + pub fn head(&self) -> Link { + self.head + } + pub fn push(&mut self, elem: T) { + unsafe { + let new_tail = Box::into_raw(Box::new(Node::new(elem, ptr::null_mut()))); + + if self.tail.is_null() { + self.head = new_tail; + } else { + (*self.tail).next = new_tail; + } + // Update the tail + self.tail = new_tail; + } + } + pub fn pop(&mut self) -> Option { + unsafe { + if self.head.is_null() { + None + } else { + let head = Box::from_raw(self.head); + self.head = head.next; + + if self.head.is_null() { + self.tail = ptr::null_mut(); + } + + Some(head.elem) + } + } + } + + pub fn peek(&self) -> Option<&T> { + unsafe { self.head.as_ref().map(|node| &node.elem) } + } + + pub fn peek_mut(&mut self) -> Option<&mut T> { + unsafe { self.head.as_mut().map(|node| &mut node.elem) } + } + + pub fn iter(&self) -> Iter<'_, T> { + unsafe { Iter::new(self) } + } + + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + unsafe { + IterMut { + next: self.head.as_mut(), + } + } + } +} + +impl Drop for SinglyLinkedList { + fn drop(&mut self) { + while let Some(_) = self.pop() {} + } +} + +impl IntoIterator for SinglyLinkedList { + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self) + } +} + +pub struct Node { + elem: T, + next: Link, +} + +impl Node { + pub fn new(elem: T, next: Link) -> Self { + Node { elem, next } + } + + pub fn elem(&self) -> &T { + &self.elem + } + + pub fn elem_mut(&mut self) -> &mut T { + &mut self.elem + } + + pub fn link(&self) -> Link { + self.next + } + + pub unsafe fn next(&self) -> Option<&Node> { + self.next.as_ref() + } + + pub unsafe fn next_mut(&mut self) -> Option<&mut Node> { + self.next.as_mut() + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_basics() { + let mut list = SinglyLinkedList::new(); + + // Check empty list behaves right + assert_eq!(list.pop(), None); + + // Populate list + list.push(1); + list.push(2); + list.push(3); + + // Check normal removal + assert_eq!(list.pop(), Some(1)); + assert_eq!(list.pop(), Some(2)); + + // Push some more just to make sure nothing's corrupted + list.push(4); + list.push(5); + + // Check normal removal + assert_eq!(list.pop(), Some(3)); + assert_eq!(list.pop(), Some(4)); + + // Check exhaustion + assert_eq!(list.pop(), Some(5)); + assert_eq!(list.pop(), None); + + // Check the exhaustion case fixed the pointer right + list.push(6); + list.push(7); + + // Check normal removal + assert_eq!(list.pop(), Some(6)); + assert_eq!(list.pop(), Some(7)); + assert_eq!(list.pop(), None); + } + + #[test] + fn test_into_iter() { + let mut list = SinglyLinkedList::new(); + list.push(1); + list.push(2); + list.push(3); + + let mut iter = list.into_iter(); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), Some(2)); + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next(), None); + } + + #[test] + fn test_iter() { + let mut list = SinglyLinkedList::new(); + list.push(1); + list.push(2); + list.push(3); + + let mut iter = list.iter(); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.next(), None); + } + + #[test] + fn test_iter_mut() { + let mut list = SinglyLinkedList::new(); + list.push(1); + list.push(2); + list.push(3); + + let mut iter = list.iter_mut(); + assert_eq!(iter.next(), Some(&mut 1)); + assert_eq!(iter.next(), Some(&mut 2)); + assert_eq!(iter.next(), Some(&mut 3)); + assert_eq!(iter.next(), None); + } + + #[test] + fn miri_food() { + let mut list = SinglyLinkedList::new(); + + list.push(1); + list.push(2); + list.push(3); + + assert_eq!(list.pop(), Some(1)); + list.push(4); + assert_eq!(list.pop(), Some(2)); + list.push(5); + + assert_eq!(list.peek(), Some(&3)); + list.push(6); + list.peek_mut().map(|x| *x *= 10); + assert_eq!(list.peek(), Some(&30)); + assert_eq!(list.pop(), Some(30)); + + for elem in list.iter_mut() { + *elem *= 100; + } + + let mut iter = list.iter(); + assert_eq!(iter.next(), Some(&400)); + assert_eq!(iter.next(), Some(&500)); + assert_eq!(iter.next(), Some(&600)); + assert_eq!(iter.next(), None); + assert_eq!(iter.next(), None); + + assert_eq!(list.pop(), Some(400)); + list.peek_mut().map(|x| *x *= 10); + assert_eq!(list.peek(), Some(&5000)); + list.push(7); + + // Drop it on the ground and let the dtor exercise itself + } +} diff --git a/algae/src/list/mod.rs b/algae/src/list/mod.rs index 7f6e183..97dad5b 100644 --- a/algae/src/list/mod.rs +++ b/algae/src/list/mod.rs @@ -1,7 +1,10 @@ /* Appellation: list Contrib: FL03 - Description: ... Summary ... */ +//! # Lists +//! +//! This module contains several 'list' data structures, +//! primarily highlighting singly linked lists pub mod linked; diff --git a/algae/benches/graphs.rs b/graph/benches/graphs.rs similarity index 90% rename from algae/benches/graphs.rs rename to graph/benches/graphs.rs index 7cd21a0..0c60edc 100644 --- a/algae/benches/graphs.rs +++ b/graph/benches/graphs.rs @@ -2,7 +2,7 @@ #![feature(test)] extern crate test; -use algae::graph::{DirectedGraph, Edge, Graph}; +use algae_graph::{DirectedGraph, Edge, Graph}; use test::Bencher; const TEST_EDGES: [(&str, &str, usize); 5] = [ diff --git a/merkle/benches/merkle.rs b/merkle/benches/merkle.rs index 654cd6a..a374c52 100644 --- a/merkle/benches/merkle.rs +++ b/merkle/benches/merkle.rs @@ -3,7 +3,7 @@ extern crate test; use algae_merkle::MerkleTree; -use decanter::prelude::{H256, Hashable}; +use decanter::prelude::{Hashable, H256}; use test::Bencher; @@ -11,21 +11,21 @@ const TEST_NODES: [&str; 4] = ["a", "b", "c", "d"]; #[bench] fn bench_merkle_proofs(b: &mut Bencher) { - let leafs = TEST_NODES - .iter() - .map(|i| i.hash()) - .collect::>(); + let leafs = TEST_NODES.iter().map(|i| i.hash()).collect::>(); let tree = MerkleTree::from(leafs.as_slice()); b.iter(|| { - leafs.iter().enumerate().for_each(|(i, leaf)| assert!(!tree.proof(i).contains(leaf))); + leafs + .iter() + .enumerate() + .for_each(|(i, leaf)| assert!(!tree.proof(i).contains(leaf))); }); } #[bench] fn bench_rs_merkle(b: &mut Bencher) { - use rs_merkle::MerkleTree as RSMerkleTree; use rs_merkle::algorithms::Sha256; use rs_merkle::Hasher; + use rs_merkle::MerkleTree as RSMerkleTree; let leafs = TEST_NODES .iter() @@ -33,7 +33,9 @@ fn bench_rs_merkle(b: &mut Bencher) { .collect::>(); let tree = RSMerkleTree::::from_leaves(&leafs); b.iter(|| { - leafs.iter().enumerate().for_each(|(i, leaf)| assert!(!tree.proof(&[i]).proof_hashes().contains(leaf))); + leafs + .iter() + .enumerate() + .for_each(|(i, leaf)| assert!(!tree.proof(&[i]).proof_hashes().contains(leaf))); }); } - diff --git a/merkle/src/layers.rs b/merkle/src/layers.rs index 8cc044d..b3d2778 100644 --- a/merkle/src/layers.rs +++ b/merkle/src/layers.rs @@ -3,19 +3,19 @@ Contrib: FL03 */ use crate::Node; +use decanter::prelude::Hashable; use itertools::Itertools; use serde::{Deserialize, Serialize}; -use std::string::ToString; // pub fn build_new_merkle_layer(left: MerkleNode, right: MerkleNode) #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct Layer(Vec>) where - T: Default + ToString; + T: Hashable; impl Layer where - T: Default + ToString, + T: Hashable, { pub fn new(data: impl IntoIterator>) -> Self { let layer = data.into_iter().batching(|it| match it.next() { @@ -35,7 +35,7 @@ where impl From>> for Layer where - T: Default + ToString, + T: Hashable, { fn from(data: Vec>) -> Self { Self::new(data) @@ -44,7 +44,7 @@ where impl From<(Node, Node)> for Layer where - T: Default + ToString, + T: Hashable, { fn from(data: (Node, Node)) -> Self { Self::new(vec![data.0, data.1]) diff --git a/merkle/src/nodes.rs b/merkle/src/nodes.rs index fbc09a4..edb5ec5 100644 --- a/merkle/src/nodes.rs +++ b/merkle/src/nodes.rs @@ -10,7 +10,7 @@ use std::string::ToString; #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct Node where - T: Default + ToString, + T: Hashable, { pub data: Payload, pub hash: H256, @@ -18,7 +18,7 @@ where impl Node where - T: Default + ToString, + T: Hashable, { pub fn new(data: Payload, hash: H256) -> Self { Self { data, hash } @@ -27,7 +27,7 @@ where impl Hashable for Node where - T: Default + ToString, + T: Hashable, { fn hash(&self) -> H256 { merkle_hash(self.data.to_string()) @@ -36,7 +36,7 @@ where impl From<(Node, Node)> for Node where - T: Default + ToString, + T: Hashable, { fn from(data: (Node, Node)) -> Self { let hash = merkle_hash(combine_hash_str(&data.0.hash, &data.1.hash)); @@ -47,7 +47,7 @@ where impl std::fmt::Display for Node where - T: Default + ToString, + T: Hashable, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let msg = serde_json::json!({ diff --git a/merkle/src/payloads.rs b/merkle/src/payloads.rs index ff5f254..135fdec 100644 --- a/merkle/src/payloads.rs +++ b/merkle/src/payloads.rs @@ -1,41 +1,27 @@ /* Appellation: nodes Contrib: FL03 - Description: ... Summary ... */ use crate::Node; use decanter::prelude::Hashable; use serde::{Deserialize, Serialize}; -use smart_default::SmartDefault; use std::string::ToString; use strum::Display; #[derive( - Clone, - Debug, - Deserialize, - Display, - Eq, - Hash, - Hashable, - Ord, - PartialEq, - PartialOrd, - Serialize, - SmartDefault, + Clone, Debug, Deserialize, Display, Eq, Hash, Hashable, Ord, PartialEq, PartialOrd, Serialize, )] pub enum Payload where - T: Default + ToString, + T: Hashable, { - #[default] Leaf(T), Node(Box>, Box>), } impl Payload where - T: Default + ToString, + T: Hashable, { pub fn leaf(data: T) -> Self { Self::Leaf(data) @@ -59,7 +45,7 @@ where impl From for Payload where - T: Default + ToString, + T: Hashable, { fn from(data: T) -> Self { Self::Leaf(data) @@ -68,7 +54,7 @@ where impl From<(Box>, Box>)> for Payload where - T: Default + ToString, + T: Hashable, { fn from(data: (Box>, Box>)) -> Self { Self::node(data.0, data.1) diff --git a/merkle/src/proofs/mod.rs b/merkle/src/proofs/mod.rs index 8d80547..bc4c5f7 100644 --- a/merkle/src/proofs/mod.rs +++ b/merkle/src/proofs/mod.rs @@ -3,11 +3,11 @@ Contrib: FL03 */ //! # Merkle Proofs -//! +//! //! ## Overview -//! +//! //! Merkle proofs are a way to prove that a given piece of data is part of a Merkle tree. -//! +//! pub use self::{path::*, proof::*, utils::*}; pub(crate) mod path; @@ -19,6 +19,4 @@ pub trait MerkleProof { fn proof(&self) -> Vec; } -pub(crate) mod utils { - -} \ No newline at end of file +pub(crate) mod utils {} diff --git a/merkle/src/shape.rs b/merkle/src/shape.rs index 54e70e0..bcb7fce 100644 --- a/merkle/src/shape.rs +++ b/merkle/src/shape.rs @@ -41,7 +41,7 @@ impl MerkleDimension { pub fn from_leafs(leafs: usize) -> Self { let depth = get_merkle_depth(leafs); let size = get_merkle_tree_size(leafs); - + Self::new(depth, leafs, size) } diff --git a/merkle/src/tree/builder.rs b/merkle/src/tree/builder.rs index e69de29..44439f7 100644 --- a/merkle/src/tree/builder.rs +++ b/merkle/src/tree/builder.rs @@ -0,0 +1,4 @@ +/* + Appellation: builder + Contrib: FL03 +*/ diff --git a/merkle/src/tree/merkle.rs b/merkle/src/tree/merkle.rs index 1c82c40..5f1d5cc 100644 --- a/merkle/src/tree/merkle.rs +++ b/merkle/src/tree/merkle.rs @@ -1,5 +1,3 @@ -use std::ops::{Index, IndexMut, Range}; - /* Appellation: merkle Contrib: FL03 @@ -8,6 +6,7 @@ use crate::proofs::merkle_proof; use crate::{create_merkle_tree, MerkleDimension}; use decanter::prelude::{Hashable, H256}; use serde::{Deserialize, Serialize}; +use std::ops::{Index, IndexMut, Range}; #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct MerkleTree { @@ -40,8 +39,6 @@ impl MerkleTree { pub fn nodes_mut(&mut self) -> &mut Vec { &mut self.nodes } - - } impl std::fmt::Display for MerkleTree { diff --git a/merkle/src/tree/mod.rs b/merkle/src/tree/mod.rs index d2dbec8..91342ab 100644 --- a/merkle/src/tree/mod.rs +++ b/merkle/src/tree/mod.rs @@ -2,7 +2,8 @@ Appellation: tree Contrib: FL03 */ -pub use self::{builder::*, merkle::*}; +pub use self::{builder::*, merkle::*, partial::*}; mod builder; -mod merkle; \ No newline at end of file +mod merkle; +mod partial; diff --git a/merkle/src/tree/partial.rs b/merkle/src/tree/partial.rs new file mode 100644 index 0000000..49c972c --- /dev/null +++ b/merkle/src/tree/partial.rs @@ -0,0 +1,23 @@ +/* + Appellation: partial + Contrib: FL03 +*/ +use crate::Layer; + +pub struct PartialTree { + layers: Vec, +} + +impl PartialTree { + pub fn new() -> Self { + Self { layers: Vec::new() } + } + + pub fn add_layer(&mut self, layer: Layer) { + self.layers.push(layer); + } + + pub fn layers(&self) -> &[Layer] { + &self.layers + } +} diff --git a/merkle/tests/merkle.rs b/merkle/tests/merkle.rs index 92e0fb5..f08cccd 100644 --- a/merkle/tests/merkle.rs +++ b/merkle/tests/merkle.rs @@ -85,7 +85,14 @@ fn test_merkle_root() { let a = MerkleTree::from(sample.as_slice()); assert_eq!(a.root(), exp); - assert_eq!(a.dim().shape(), (get_merkle_depth(nleafs), nleafs, get_merkle_tree_size(nleafs))); + assert_eq!( + a.dim().shape(), + ( + get_merkle_depth(nleafs), + nleafs, + get_merkle_tree_size(nleafs) + ) + ); } #[test] @@ -94,7 +101,10 @@ fn test_merkle_shape() { let leafs = sample.len(); let a = MerkleTree::from(sample.as_slice()); - assert_eq!(a.dim().shape(), (get_merkle_depth(leafs), leafs, get_merkle_tree_size(leafs))); + assert_eq!( + a.dim().shape(), + (get_merkle_depth(leafs), leafs, get_merkle_tree_size(leafs)) + ); } /* From 236209c8bb3f54642550ea6ef2528e4c0c70e1c6 Mon Sep 17 00:00:00 2001 From: FL03 Date: Mon, 18 Sep 2023 09:18:21 -0500 Subject: [PATCH 07/15] update Signed-off-by: FL03 --- algae/src/list/linked/mod.rs | 4 +- algae/src/list/linked/{ => singly}/iter.rs | 3 +- algae/src/list/linked/singly/mod.rs | 13 +++ .../linked/{singly.rs => singly/store.rs} | 2 +- algae/src/list/linked/stack.rs | 107 ++++++++++++++++++ 5 files changed, 124 insertions(+), 5 deletions(-) rename algae/src/list/linked/{ => singly}/iter.rs (96%) create mode 100644 algae/src/list/linked/singly/mod.rs rename algae/src/list/linked/{singly.rs => singly/store.rs} (99%) create mode 100644 algae/src/list/linked/stack.rs diff --git a/algae/src/list/linked/mod.rs b/algae/src/list/linked/mod.rs index 11f41ed..df7ecd4 100644 --- a/algae/src/list/linked/mod.rs +++ b/algae/src/list/linked/mod.rs @@ -2,11 +2,11 @@ Appellation: linked Contrib: FL03 */ -pub use self::{iter::*, singly::SinglyLinkedList, utils::*}; +pub use self::{singly::SinglyLinkedList, utils::*}; -pub(crate) mod iter; pub mod singly; +pub mod stack; pub(crate) mod utils {} diff --git a/algae/src/list/linked/iter.rs b/algae/src/list/linked/singly/iter.rs similarity index 96% rename from algae/src/list/linked/iter.rs rename to algae/src/list/linked/singly/iter.rs index 37bf6b6..b2316c7 100644 --- a/algae/src/list/linked/iter.rs +++ b/algae/src/list/linked/singly/iter.rs @@ -2,8 +2,7 @@ Appellation: singly Contrib: FL03 */ -// use super::SinglyLinkedList; -use super::singly::{Node, SinglyLinkedList}; +use super::{Node, SinglyLinkedList}; pub struct IntoIter(SinglyLinkedList); diff --git a/algae/src/list/linked/singly/mod.rs b/algae/src/list/linked/singly/mod.rs new file mode 100644 index 0000000..a3ef8f7 --- /dev/null +++ b/algae/src/list/linked/singly/mod.rs @@ -0,0 +1,13 @@ +/* + Appellation: singly + Contrib: FL03 +*/ +pub use self::{iter::*, store::*, utils::*}; + +pub(crate) mod iter; +pub(crate) mod store; + +pub(crate) mod utils {} + +#[cfg(test)] +mod tests {} diff --git a/algae/src/list/linked/singly.rs b/algae/src/list/linked/singly/store.rs similarity index 99% rename from algae/src/list/linked/singly.rs rename to algae/src/list/linked/singly/store.rs index e83c550..449e465 100644 --- a/algae/src/list/linked/singly.rs +++ b/algae/src/list/linked/singly/store.rs @@ -1,5 +1,5 @@ /* - Appellation: singly + Appellation: store Contrib: FL03 */ use super::{IntoIter, Iter, IterMut}; diff --git a/algae/src/list/linked/stack.rs b/algae/src/list/linked/stack.rs new file mode 100644 index 0000000..8885ef0 --- /dev/null +++ b/algae/src/list/linked/stack.rs @@ -0,0 +1,107 @@ +/* + Appellation: stack + Contrib: FL03 +*/ +use std::rc::Rc; + +type Link = Option>>; + +pub struct Stack { + head: Link, +} + + +struct Node { + elem: T, + next: Link, +} + +impl Stack { + pub fn new() -> Self { + Stack { head: None } + } + + pub fn prepend(&self, elem: T) -> Stack { + Stack { head: Some(Rc::new(Node { + elem: elem, + next: self.head.clone(), + }))} + } + + pub fn tail(&self) -> Stack { + Stack { head: self.head.as_ref().and_then(|node| node.next.clone()) } + } + + pub fn head(&self) -> Option<&T> { + self.head.as_ref().map(|node| &node.elem) + } + + pub fn iter(&self) -> Iter<'_, T> { + Iter { next: self.head.as_deref() } + } +} + +impl Drop for Stack { + fn drop(&mut self) { + let mut head = self.head.take(); + while let Some(node) = head { + if let Ok(mut node) = Rc::try_unwrap(node) { + head = node.next.take(); + } else { + break; + } + } + } +} + +pub struct Iter<'a, T> { + next: Option<&'a Node>, +} + +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + self.next.map(|node| { + self.next = node.next.as_deref(); + &node.elem + }) + } +} + +#[cfg(test)] +mod test { + use super::Stack; + + #[test] + fn basics() { + let list = Stack::new(); + assert_eq!(list.head(), None); + + let list = list.prepend(1).prepend(2).prepend(3); + assert_eq!(list.head(), Some(&3)); + + let list = list.tail(); + assert_eq!(list.head(), Some(&2)); + + let list = list.tail(); + assert_eq!(list.head(), Some(&1)); + + let list = list.tail(); + assert_eq!(list.head(), None); + + // Make sure empty tail works + let list = list.tail(); + assert_eq!(list.head(), None); + } + + #[test] + fn iter() { + let list = Stack::new().prepend(1).prepend(2).prepend(3); + + let mut iter = list.iter(); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.next(), Some(&1)); + } +} \ No newline at end of file From c424c1ac0e3c6811bb86155ebc4ba74d05f8aed8 Mon Sep 17 00:00:00 2001 From: FL03 Date: Mon, 18 Sep 2023 09:44:12 -0500 Subject: [PATCH 08/15] update Signed-off-by: FL03 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 393a151..a7345dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/scattered-systems/algae" version = "0.1.20" [workspace.dependencies] -decanter = { features = ["derive", "wasm"], version = "0.1.5" } +decanter = { features = ["derive"], git = "https://github.com/FL03/decanter", branch = "v0.1.6", version = "0.1.6" } anyhow = "1" itertools = "0.11" From 1eff4ad66c0a3ab7d815348eec03a4dd0be9583d Mon Sep 17 00:00:00 2001 From: FL03 Date: Fri, 22 Sep 2023 10:57:01 -0500 Subject: [PATCH 09/15] update Signed-off-by: FL03 --- merkle/benches/merkle.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/merkle/benches/merkle.rs b/merkle/benches/merkle.rs index a374c52..b81c2cc 100644 --- a/merkle/benches/merkle.rs +++ b/merkle/benches/merkle.rs @@ -4,7 +4,7 @@ extern crate test; use algae_merkle::MerkleTree; use decanter::prelude::{Hashable, H256}; - +use rs_merkle::Hasher; use test::Bencher; const TEST_NODES: [&str; 4] = ["a", "b", "c", "d"]; @@ -21,17 +21,31 @@ fn bench_merkle_proofs(b: &mut Bencher) { }); } +#[derive(Clone)] +pub struct BSha256Algorithm { + +} + +impl Hasher for BSha256Algorithm { + type Hash = [u8; 32]; + + fn hash(data: &[u8]) -> Self::Hash { + let mut hasher = blake3::Hasher::new(); + hasher.update(data); + hasher.finalize().into() + } +} + #[bench] fn bench_rs_merkle(b: &mut Bencher) { - use rs_merkle::algorithms::Sha256; use rs_merkle::Hasher; use rs_merkle::MerkleTree as RSMerkleTree; let leafs = TEST_NODES .iter() - .map(|i| Sha256::hash(i.as_bytes())) + .map(|i| BSha256Algorithm::hash(i.as_bytes())) .collect::>(); - let tree = RSMerkleTree::::from_leaves(&leafs); + let tree = RSMerkleTree::::from_leaves(&leafs); b.iter(|| { leafs .iter() From 8d888509e2f73b25a85ee2edb7f332d34363f121 Mon Sep 17 00:00:00 2001 From: FL03 Date: Fri, 22 Sep 2023 11:37:54 -0500 Subject: [PATCH 10/15] update Signed-off-by: FL03 --- merkle/benches/merkle.rs | 4 +--- merkle/src/utils.rs | 22 +++++++++++++++++----- merkle/tests/merkle.rs | 24 +++++++++++++++++++----- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/merkle/benches/merkle.rs b/merkle/benches/merkle.rs index b81c2cc..e26a7f2 100644 --- a/merkle/benches/merkle.rs +++ b/merkle/benches/merkle.rs @@ -22,9 +22,7 @@ fn bench_merkle_proofs(b: &mut Bencher) { } #[derive(Clone)] -pub struct BSha256Algorithm { - -} +pub struct BSha256Algorithm; impl Hasher for BSha256Algorithm { type Hash = [u8; 32]; diff --git a/merkle/src/utils.rs b/merkle/src/utils.rs index 2408225..d13a20b 100644 --- a/merkle/src/utils.rs +++ b/merkle/src/utils.rs @@ -1,7 +1,6 @@ /* - Appellation: generate + Appellation: utils Contrib: FL03 - Description: */ use crate::proofs::proof_path; use crate::MerkleDimension; @@ -13,6 +12,19 @@ pub fn add_hash(a: &H256, b: &H256) -> H256 { let combined = ring::digest::digest(&ring::digest::SHA256, &c); hasher(combined).into() } + +pub fn concat_and_hash(left: &H256, right: Option<&H256>) -> H256 { + let mut concatenated: Vec = (*left).0.to_vec(); + + match right { + Some(right_node) => { + let mut right_node_clone: Vec = (*right_node).0.to_vec(); + concatenated.append(&mut right_node_clone); + hasher(&concatenated).into() + } + None => *left, + } + } /// Merges two hashes into a string pub fn combine_hash_str(a: &T, b: &T) -> String { format!("{}{}", a.to_string(), b.to_string()) @@ -39,7 +51,7 @@ where } let mut temp = Vec::new(); for i in 0..length / 2 { - let h: H256 = add_hash(&last_level[2 * i], &last_level[2 * i + 1]); + let h: H256 = concat_and_hash(&last_level[2 * i], Some(&last_level[2 * i + 1])); temp.push(h); nodes.push(h); } @@ -70,9 +82,9 @@ pub fn is_merkle_valid( let proof_index = proof_path(index, leaf_size); for i in 0..proof.len() { if proof_index[i] % 2 == 0 { - h = add_hash(&proof[i], &h); + h = concat_and_hash(&proof[i], Some(&h)); } else { - h = add_hash(&h, &proof[i]); + h = concat_and_hash(&h, Some(&proof[i])); } } *root == h diff --git a/merkle/tests/merkle.rs b/merkle/tests/merkle.rs index f08cccd..3277b8f 100644 --- a/merkle/tests/merkle.rs +++ b/merkle/tests/merkle.rs @@ -7,14 +7,26 @@ def. This notation abbreviates a is the hash of A; more formally, (A) maps to the hash (a) by the hashing function H */ -use algae_merkle::{add_hash, is_merkle_valid, MerkleTree}; +use algae_merkle::{concat_and_hash, is_merkle_valid, MerkleTree}; use decanter::prelude::{Hashable, H256}; use hex_literal::hex; +use rs_merkle::Hasher; // lazy_static::lazy_static!( // static ref SAMPLE_DATA: Vec = hash_leaves(); // ); +#[derive(Clone)] +pub struct BSha256; + +impl Hasher for BSha256 { + type Hash = [u8; 32]; + + fn hash(data: &[u8]) -> Self::Hash { + blake3::hash(data).into() + } +} + fn get_merkle_tree_size(leafs: usize) -> usize { let mut size = leafs + (leafs % 2); let mut l = leafs; @@ -76,15 +88,17 @@ fn test_merkle_root() { let leaves = hash_leaves!(sample); let nleafs = leaves.len(); let exp = { - let a = add_hash(&leaves[0], &leaves[1]); - let b = add_hash(&leaves[2], &leaves[3]); - add_hash(&a, &b) + let a = concat_and_hash(&leaves[0], Some(&leaves[1])); + let b = concat_and_hash(&leaves[2], Some(&leaves[3])); + concat_and_hash(&a, Some(&b)) // add_hash(&a, &leaves[2]) }; let a = MerkleTree::from(sample.as_slice()); + let b = rs_merkle::MerkleTree::::from_leaves(sample.iter().map(|i| BSha256::hash(i.as_bytes())).collect::>().as_slice()); assert_eq!(a.root(), exp); + assert_eq!(a.root().0, b.root().expect("No Root")); assert_eq!( a.dim().shape(), ( @@ -115,7 +129,7 @@ fn test_merkle_proof() { let sample = ["a", "b", "c", "d"]; let leaves = hash_leaves!(sample); - let exp = vec![leaves[1], add_hash(&leaves[2], &leaves[3])]; + let exp = vec![leaves[1], concat_and_hash(&leaves[2], Some(&leaves[3]))]; let a = MerkleTree::from(leaves.as_slice()); From 45477969a8891c1c70be4d46b0a8d136406fabea Mon Sep 17 00:00:00 2001 From: FL03 Date: Fri, 22 Sep 2023 11:41:29 -0500 Subject: [PATCH 11/15] update Signed-off-by: FL03 --- merkle/src/utils.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/merkle/src/utils.rs b/merkle/src/utils.rs index d13a20b..7106dde 100644 --- a/merkle/src/utils.rs +++ b/merkle/src/utils.rs @@ -14,17 +14,17 @@ pub fn add_hash(a: &H256, b: &H256) -> H256 { } pub fn concat_and_hash(left: &H256, right: Option<&H256>) -> H256 { - let mut concatenated: Vec = (*left).0.to_vec(); + let mut concatenated: Vec = (*left).0.to_vec(); - match right { - Some(right_node) => { - let mut right_node_clone: Vec = (*right_node).0.to_vec(); - concatenated.append(&mut right_node_clone); - hasher(&concatenated).into() - } - None => *left, + match right { + Some(right_node) => { + let mut right_node_clone: Vec = (*right_node).0.to_vec(); + concatenated.append(&mut right_node_clone); + hasher(&concatenated).into() } + None => *left, } +} /// Merges two hashes into a string pub fn combine_hash_str(a: &T, b: &T) -> String { format!("{}{}", a.to_string(), b.to_string()) From 34981e3a60d372d3e596f8e7460f8ecf4e19da53 Mon Sep 17 00:00:00 2001 From: FL03 Date: Thu, 12 Oct 2023 11:36:01 -0500 Subject: [PATCH 12/15] update Signed-off-by: FL03 --- Cargo.toml | 3 ++- algae/src/list/linked/mod.rs | 1 - algae/src/list/linked/stack.rs | 21 +++++++++++++-------- merkle/Cargo.toml | 11 +++++------ merkle/src/payloads.rs | 1 - merkle/src/tree/partial.rs | 2 ++ merkle/src/utils.rs | 10 +++++----- merkle/tests/merkle.rs | 8 +++++++- mmr/Cargo.toml | 5 +++-- 9 files changed, 37 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a7345dc..144b590 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,8 @@ repository = "https://github.com/scattered-systems/algae" version = "0.1.20" [workspace.dependencies] -decanter = { features = ["derive"], git = "https://github.com/FL03/decanter", branch = "v0.1.6", version = "0.1.6" } +decanter = { features = ["derive"], version = "0.1.6" } +# decanter = { features = ["derive"], git = "https://github.com/FL03/decanter", branch = "v0.1.7", version = "0.1.7" } anyhow = "1" itertools = "0.11" diff --git a/algae/src/list/linked/mod.rs b/algae/src/list/linked/mod.rs index df7ecd4..14228fb 100644 --- a/algae/src/list/linked/mod.rs +++ b/algae/src/list/linked/mod.rs @@ -4,7 +4,6 @@ */ pub use self::{singly::SinglyLinkedList, utils::*}; - pub mod singly; pub mod stack; diff --git a/algae/src/list/linked/stack.rs b/algae/src/list/linked/stack.rs index 8885ef0..51adbc1 100644 --- a/algae/src/list/linked/stack.rs +++ b/algae/src/list/linked/stack.rs @@ -10,7 +10,6 @@ pub struct Stack { head: Link, } - struct Node { elem: T, next: Link, @@ -22,14 +21,18 @@ impl Stack { } pub fn prepend(&self, elem: T) -> Stack { - Stack { head: Some(Rc::new(Node { - elem: elem, - next: self.head.clone(), - }))} + Stack { + head: Some(Rc::new(Node { + elem: elem, + next: self.head.clone(), + })), + } } pub fn tail(&self) -> Stack { - Stack { head: self.head.as_ref().and_then(|node| node.next.clone()) } + Stack { + head: self.head.as_ref().and_then(|node| node.next.clone()), + } } pub fn head(&self) -> Option<&T> { @@ -37,7 +40,9 @@ impl Stack { } pub fn iter(&self) -> Iter<'_, T> { - Iter { next: self.head.as_deref() } + Iter { + next: self.head.as_deref(), + } } } @@ -104,4 +109,4 @@ mod test { assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), Some(&1)); } -} \ No newline at end of file +} diff --git a/merkle/Cargo.toml b/merkle/Cargo.toml index e4e08ef..ccec5b8 100644 --- a/merkle/Cargo.toml +++ b/merkle/Cargo.toml @@ -13,11 +13,11 @@ version.workspace = true [features] default = [ - "ring/default" + ] + wasm = [ - "decanter/wasm", - "ring/wasm32_c" + ] [lib] @@ -27,11 +27,10 @@ test = true [dependencies] anyhow.workspace = true -blake3 ={ features = [], version = "1" } +blake3 = { features = [], version = "1" } decanter.workspace = true hex = "0.4" itertools.workspace = true -ring = { features = ["wasm32_c"], version = "0.16" } serde.workspace = true serde_json.workspace = true smart-default.workspace = true @@ -50,4 +49,4 @@ rustc-args = ["--cfg", "docsrs"] [target.wasm32-unknown-unknown.dependencies] -[target.wasm32-wasi.dependencies] +[target.wasm32-wasi.dependencies.dependencies] diff --git a/merkle/src/payloads.rs b/merkle/src/payloads.rs index 135fdec..c3833ec 100644 --- a/merkle/src/payloads.rs +++ b/merkle/src/payloads.rs @@ -5,7 +5,6 @@ use crate::Node; use decanter::prelude::Hashable; use serde::{Deserialize, Serialize}; -use std::string::ToString; use strum::Display; #[derive( diff --git a/merkle/src/tree/partial.rs b/merkle/src/tree/partial.rs index 49c972c..c4bb788 100644 --- a/merkle/src/tree/partial.rs +++ b/merkle/src/tree/partial.rs @@ -4,6 +4,8 @@ */ use crate::Layer; +pub struct MerkleLayer {} + pub struct PartialTree { layers: Vec, } diff --git a/merkle/src/utils.rs b/merkle/src/utils.rs index 7106dde..db0769e 100644 --- a/merkle/src/utils.rs +++ b/merkle/src/utils.rs @@ -7,11 +7,11 @@ use crate::MerkleDimension; use decanter::prelude::{hasher, Hashable, H256}; /// Combines two hashes into a single hash -pub fn add_hash(a: &H256, b: &H256) -> H256 { - let c = [a.as_ref(), b.as_ref()].concat(); - let combined = ring::digest::digest(&ring::digest::SHA256, &c); - hasher(combined).into() -} +// pub fn add_hash(a: &H256, b: &H256) -> H256 { +// let c = [a.as_ref(), b.as_ref()].concat(); +// let combined = ring::digest::digest(&ring::digest::SHA256, &c); +// hasher(combined).into() +// } pub fn concat_and_hash(left: &H256, right: Option<&H256>) -> H256 { let mut concatenated: Vec = (*left).0.to_vec(); diff --git a/merkle/tests/merkle.rs b/merkle/tests/merkle.rs index 3277b8f..551d2b1 100644 --- a/merkle/tests/merkle.rs +++ b/merkle/tests/merkle.rs @@ -95,7 +95,13 @@ fn test_merkle_root() { }; let a = MerkleTree::from(sample.as_slice()); - let b = rs_merkle::MerkleTree::::from_leaves(sample.iter().map(|i| BSha256::hash(i.as_bytes())).collect::>().as_slice()); + let b = rs_merkle::MerkleTree::::from_leaves( + sample + .iter() + .map(|i| BSha256::hash(i.as_bytes())) + .collect::>() + .as_slice(), + ); assert_eq!(a.root(), exp); assert_eq!(a.root().0, b.root().expect("No Root")); diff --git a/mmr/Cargo.toml b/mmr/Cargo.toml index e24611f..d2ea2e5 100644 --- a/mmr/Cargo.toml +++ b/mmr/Cargo.toml @@ -13,10 +13,11 @@ version.workspace = true [features] default = [ - "decanter/derive" + ] + wasm = [ - "decanter/wasm" + ] [lib] From ba99d11a4de15de01ee4cfd02b37ac171542a04a Mon Sep 17 00:00:00 2001 From: FL03 Date: Fri, 20 Oct 2023 12:00:49 -0500 Subject: [PATCH 13/15] update Signed-off-by: FL03 --- Cargo.toml | 5 +- algae/Cargo.toml | 34 +++- algae/src/lib.rs | 7 + math/linalg/Cargo.toml | 42 +++++ math/linalg/src/lib.rs | 22 +++ math/linalg/src/primitives.rs | 14 ++ math/linalg/src/specs.rs | 6 + math/linalg/src/utils.rs | 4 + math/linalg/src/vs/mod.rs | 37 ++++ math/linalg/src/vs/space.rs | 26 +++ math/linalg/tests/default.rs | 8 + math/math/Cargo.toml | 45 +++++ math/math/examples/simple.rs | 16 ++ math/math/src/calculus/derivatives/mod.rs | 8 + math/math/src/calculus/derivatives/nderive.rs | 21 +++ math/math/src/calculus/mod.rs | 7 + math/math/src/factorials.rs | 54 ++++++ math/math/src/lib.rs | 30 ++++ math/math/src/num/arithmetic.rs | 21 +++ math/math/src/num/complex.rs | 167 ++++++++++++++++++ math/math/src/num/mod.rs | 36 ++++ math/math/src/primitives.rs | 14 ++ math/math/src/specs.rs | 31 ++++ math/math/src/utils.rs | 9 + math/math/tests/default.rs | 8 + math/statistics/Cargo.toml | 42 +++++ math/statistics/src/calc/deviation.rs | 63 +++++++ math/statistics/src/calc/mod.rs | 86 +++++++++ math/statistics/src/lib.rs | 25 +++ math/statistics/src/primitives.rs | 14 ++ math/statistics/src/regression/linear.rs | 66 +++++++ math/statistics/src/regression/mod.rs | 19 ++ math/statistics/src/specs.rs | 51 ++++++ math/statistics/src/utils.rs | 4 + math/statistics/tests/default.rs | 8 + 35 files changed, 1042 insertions(+), 8 deletions(-) create mode 100644 math/linalg/Cargo.toml create mode 100644 math/linalg/src/lib.rs create mode 100644 math/linalg/src/primitives.rs create mode 100644 math/linalg/src/specs.rs create mode 100644 math/linalg/src/utils.rs create mode 100644 math/linalg/src/vs/mod.rs create mode 100644 math/linalg/src/vs/space.rs create mode 100644 math/linalg/tests/default.rs create mode 100644 math/math/Cargo.toml create mode 100644 math/math/examples/simple.rs create mode 100644 math/math/src/calculus/derivatives/mod.rs create mode 100644 math/math/src/calculus/derivatives/nderive.rs create mode 100644 math/math/src/calculus/mod.rs create mode 100644 math/math/src/factorials.rs create mode 100644 math/math/src/lib.rs create mode 100644 math/math/src/num/arithmetic.rs create mode 100644 math/math/src/num/complex.rs create mode 100644 math/math/src/num/mod.rs create mode 100644 math/math/src/primitives.rs create mode 100644 math/math/src/specs.rs create mode 100644 math/math/src/utils.rs create mode 100644 math/math/tests/default.rs create mode 100644 math/statistics/Cargo.toml create mode 100644 math/statistics/src/calc/deviation.rs create mode 100644 math/statistics/src/calc/mod.rs create mode 100644 math/statistics/src/lib.rs create mode 100644 math/statistics/src/primitives.rs create mode 100644 math/statistics/src/regression/linear.rs create mode 100644 math/statistics/src/regression/mod.rs create mode 100644 math/statistics/src/specs.rs create mode 100644 math/statistics/src/utils.rs create mode 100644 math/statistics/tests/default.rs diff --git a/Cargo.toml b/Cargo.toml index 144b590..c57e2df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ decanter = { features = ["derive"], version = "0.1.6" } anyhow = "1" itertools = "0.11" +ndarray = "0.15" +num = "0.4" serde = { features = ["derive"], version = "1" } serde_json = "1" smart-default = "0.7" @@ -30,7 +32,8 @@ members = [ "algae", "graph", "merkle", - "mmr" + "mmr", + "math/*" ] resolver = "2" diff --git a/algae/Cargo.toml b/algae/Cargo.toml index 8112f34..c06b796 100644 --- a/algae/Cargo.toml +++ b/algae/Cargo.toml @@ -12,18 +12,36 @@ repository.workspace = true version.workspace = true [features] -default = ["core", "graph", "merkle", "mmr"] +default = [ + "core", + "ds", + "math", +] full = [ "core", - "graph", - "merkle", - "mmr", + "ds", + "math", ] core = [] -graph = ["algae-graph"] -merkle = ["algae-merkle"] -mmr = ["algae-mmr"] +ds = [ + "graph", + "merkle", + "mmr", +] + +graph = [ + "algae-graph" +] +math = [ + "algae-math" +] +merkle = [ + "algae-merkle" +] +mmr = [ + "algae-mmr" +] wasm = [] @@ -35,7 +53,9 @@ test = true [build-dependencies] [dependencies] + algae-graph = { features = [], optional = true, path = "../graph", version = "0.1.20" } +algae-math = { features = [], optional = true, path = "../math/math", version = "0.1.20" } algae-merkle = { features = [], optional = true, path = "../merkle", version = "0.1.20" } algae-mmr = { features = [], optional = true, path = "../mmr", version = "0.1.20" } diff --git a/algae/src/lib.rs b/algae/src/lib.rs index b8339b3..1915985 100644 --- a/algae/src/lib.rs +++ b/algae/src/lib.rs @@ -7,6 +7,8 @@ //! Algae is a comprehensive collection of algorithms and data-structures written in Rust. #[cfg(feature = "graph")] pub use algae_graph as graph; +#[cfg(feature = "math")] +pub use algae_math as math; #[cfg(feature = "merkle")] pub use algae_merkle as merkle; #[cfg(feature = "mmr")] @@ -18,8 +20,13 @@ pub mod prelude { #[cfg(feature = "graph")] pub use super::graph; // pub use super::graph::*; + #[cfg(feature = "math")] + pub use algae_math::prelude::*; #[cfg(feature = "merkle")] pub use super::merkle::prelude::*; #[cfg(feature = "mmr")] pub use super::mmr::*; + + pub use super::list::*; + } diff --git a/math/linalg/Cargo.toml b/math/linalg/Cargo.toml new file mode 100644 index 0000000..d51baa8 --- /dev/null +++ b/math/linalg/Cargo.toml @@ -0,0 +1,42 @@ +[package] +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "algae-linalg" +readme.workspace = true +repository.workspace = true +version.workspace = true + +[features] +default = [] + +[lib] +bench = true +crate-type = ["cdylib", "rlib"] +doctest = false +test = true + +[build-dependencies] + +[dependencies] +ndarray.workspace = true +num.workspace = true +serde.workspace = true +serde_json.workspace = true +smart-default.workspace = true +strum.workspace = true + +[dev-dependencies] +rand = "0.8" + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] + +[target.wasm32-unknown-unknown] + +[target.wasm32-wasi] \ No newline at end of file diff --git a/math/linalg/src/lib.rs b/math/linalg/src/lib.rs new file mode 100644 index 0000000..bbd1643 --- /dev/null +++ b/math/linalg/src/lib.rs @@ -0,0 +1,22 @@ +/* + Appellation: algae-linalg + Contrib: FL03 +*/ +//! # algae-linalg + +pub use self::{primitives::*, specs::*, utils::*}; + +pub mod vs; + +// pub(crate) use concision_core as core; + +pub(crate) mod primitives; +pub(crate) mod specs; +pub(crate) mod utils; + +pub mod prelude { + pub use crate::vs::*; + pub use crate::primitives::*; + pub use crate::specs::*; + pub use crate::utils::*; +} diff --git a/math/linalg/src/primitives.rs b/math/linalg/src/primitives.rs new file mode 100644 index 0000000..f16ac25 --- /dev/null +++ b/math/linalg/src/primitives.rs @@ -0,0 +1,14 @@ +/* + Appellation: primitives + Contrib: FL03 +*/ +pub use self::{constants::*, statics::*, types::*}; + +/// Collection of constants used throughout the system +mod constants {} + +/// Collection of static references used throughout +mod statics {} + +/// Collection of types used throughout the system +mod types {} diff --git a/math/linalg/src/specs.rs b/math/linalg/src/specs.rs new file mode 100644 index 0000000..08a695f --- /dev/null +++ b/math/linalg/src/specs.rs @@ -0,0 +1,6 @@ +/* + Appellation: specs + Contrib: FL03 +*/ + + diff --git a/math/linalg/src/utils.rs b/math/linalg/src/utils.rs new file mode 100644 index 0000000..f8840c6 --- /dev/null +++ b/math/linalg/src/utils.rs @@ -0,0 +1,4 @@ +/* + Appellation: utils + Contrib: FL03 +*/ diff --git a/math/linalg/src/vs/mod.rs b/math/linalg/src/vs/mod.rs new file mode 100644 index 0000000..b5f7ba9 --- /dev/null +++ b/math/linalg/src/vs/mod.rs @@ -0,0 +1,37 @@ +/* + Appellation: vs + Contrib: FL03 +*/ +//! # Vector Space +//! +//! A vector space is defined to be a set V, whose elements are called vectors, on which are defined two operations, +//! called addition and multiplication by scalars (real numbers), subject to the ten axioms listed below. +//! +//! ## Axioms +//! +//! 1. Closure under addition +//! 2. Closure under scalar multiplication +//! 3. Commutativity of addition +//! 4. Associativity of addition +//! 5. Additive identity +//! 6. Additive inverse +//! 7. Distributivity of scalar multiplication with respect to vector addition +//! 8. Distributivity of scalar multiplication with respect to field addition +//! 9. Compatibility of scalar multiplication with field multiplication +//! 10. Identity element of scalar multiplication +pub use self::{space::*, utils::*}; + +pub(crate) mod space; + +pub(crate) mod utils {} + +#[cfg(test)] +mod tests { + #[test] + fn test() { + let f = |x: usize, y: usize| x + y; + let actual = f(4, 4); + let expected: usize = 8; + assert_eq!(actual, expected) + } +} diff --git a/math/linalg/src/vs/space.rs b/math/linalg/src/vs/space.rs new file mode 100644 index 0000000..dfaa073 --- /dev/null +++ b/math/linalg/src/vs/space.rs @@ -0,0 +1,26 @@ +/* + Appellation: space + Contrib: FL03 +*/ + +pub trait Subspace: VectorSpace {} + +pub struct Space { + pub data: Vec, + pub shape: Vec, +} + +pub trait VectorSpace { + type Dim; +} + +#[cfg(test)] +mod tests { + #[test] + fn test() { + let f = |x: usize, y: usize| x + y; + let actual = f(4, 4); + let expected: usize = 8; + assert_eq!(actual, expected) + } +} diff --git a/math/linalg/tests/default.rs b/math/linalg/tests/default.rs new file mode 100644 index 0000000..0cac1eb --- /dev/null +++ b/math/linalg/tests/default.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +#[test] +fn compiles() { + let f = |x: usize, y: usize| x + y; + + assert_eq!(f(10, 10), 20); + assert_ne!(f(1, 1), 3); +} diff --git a/math/math/Cargo.toml b/math/math/Cargo.toml new file mode 100644 index 0000000..833365a --- /dev/null +++ b/math/math/Cargo.toml @@ -0,0 +1,45 @@ +[package] +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "algae-math" +readme.workspace = true +repository.workspace = true +version.workspace = true + +[features] +default = [] + +[lib] +bench = true +crate-type = ["cdylib", "rlib"] +doctest = false +test = true + +[build-dependencies] + +[dependencies] +algae-linalg = { features = [], path = "../linalg", version = "0.1.12" } +algae-statistics = { features = [], path = "../statistics", version = "0.1.12" } + +ndarray.workspace = true +num.workspace = true +serde.workspace = true +serde_json.workspace = true +smart-default.workspace = true +strum.workspace = true + +[dev-dependencies] +rand = "0.8" + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] + +[target.wasm32-unknown-unknown] + +[target.wasm32-wasi] \ No newline at end of file diff --git a/math/math/examples/simple.rs b/math/math/examples/simple.rs new file mode 100644 index 0000000..38a262e --- /dev/null +++ b/math/math/examples/simple.rs @@ -0,0 +1,16 @@ +extern crate concision_math as math; + +use math::prelude::{complex::C, Numerical}; + +// Define a holomorphic function that squares its input. +fn square(z: C) -> C { + z.clone() * z +} + +fn main() { + let c = C::from((1.0, 1.0)); + let res = square(c); + assert_eq!(res.clone(), C::from((0.0, 2.0))); + + println!("{:?}", res); +} diff --git a/math/math/src/calculus/derivatives/mod.rs b/math/math/src/calculus/derivatives/mod.rs new file mode 100644 index 0000000..ac004ea --- /dev/null +++ b/math/math/src/calculus/derivatives/mod.rs @@ -0,0 +1,8 @@ +/* + Appellation: derivatives + Contrib: FL03 + Description: ... Summary ... +*/ +pub use self::nderive::*; + +pub(crate) mod nderive; diff --git a/math/math/src/calculus/derivatives/nderive.rs b/math/math/src/calculus/derivatives/nderive.rs new file mode 100644 index 0000000..9049f61 --- /dev/null +++ b/math/math/src/calculus/derivatives/nderive.rs @@ -0,0 +1,21 @@ +/* + Appellation: num + Contrib: FL03 + Description: ... Summary ... +*/ + +pub fn central(x: T, f: Box T>, h: T) -> T { + (f(x + h) - f(x)) / h +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_central() { + let f = |x: f64| x * x; + let res = central(5.0, Box::new(f), 0.001); + assert_eq!(res.round(), 10.0); + } +} diff --git a/math/math/src/calculus/mod.rs b/math/math/src/calculus/mod.rs new file mode 100644 index 0000000..18d2ab7 --- /dev/null +++ b/math/math/src/calculus/mod.rs @@ -0,0 +1,7 @@ +/* + Appellation: calculus + Contrib: FL03 + Description: ... Summary ... +*/ + +pub mod derivatives; diff --git a/math/math/src/factorials.rs b/math/math/src/factorials.rs new file mode 100644 index 0000000..ef051db --- /dev/null +++ b/math/math/src/factorials.rs @@ -0,0 +1,54 @@ +/* + Appellation: factorials + Contrib: FL03 +*/ +use std::ops::{Mul, Sub}; +use std::str::FromStr; + +#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] +pub struct Factorial + Sub>(T); + +impl + Sub> Factorial +where + ::Err: std::fmt::Debug, +{ + pub fn new(data: T) -> Self { + Self(Self::compute(data)) + } + pub fn compute(data: T) -> T { + let x = data.to_string(); + let b: T = "1".parse().ok().unwrap(); + match x.as_str() { + "0" | "1" => b.clone(), + _ => Self::compute(data.clone() - b) * data, + } + } + pub fn data(&self) -> &T { + &self.0 + } + pub fn from_args(data: Vec) -> Vec { + data.iter() + .map(|i| Self::new(i.clone())) + .collect::>() + } +} + +pub fn factorial(data: T) -> T { + if data.is_zero() || data.is_one() { + return T::one(); + } + factorial(data - T::one()) * data +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_factorial() { + assert_eq!(Factorial::new(0).data().clone(), 1); + assert_eq!(factorial(3), 6); + assert_eq!(factorial(4.0), 24.0); + assert_eq!(factorial(5.0), 120.0); + } +} diff --git a/math/math/src/lib.rs b/math/math/src/lib.rs new file mode 100644 index 0000000..bfeeeaf --- /dev/null +++ b/math/math/src/lib.rs @@ -0,0 +1,30 @@ +/* + Appellation: algae-math + Contrib: FL03 +*/ +//! # algae-math + +pub use self::{factorials::*, primitives::*, specs::*, utils::*}; + +pub mod calculus; +pub mod num; + +pub use algae_linalg as linalg; + +pub use algae_statistics as stats; + +pub(crate) mod factorials; + +// pub(crate) use concision_core as core; + +pub(crate) mod primitives; +pub(crate) mod specs; +pub(crate) mod utils; + +pub mod prelude { + pub use crate::calculus::*; + pub use crate::num::*; + pub use crate::primitives::*; + pub use crate::specs::*; + pub use crate::utils::*; +} diff --git a/math/math/src/num/arithmetic.rs b/math/math/src/num/arithmetic.rs new file mode 100644 index 0000000..5585328 --- /dev/null +++ b/math/math/src/num/arithmetic.rs @@ -0,0 +1,21 @@ +/* + Appellation: arithmetic + Contrib: FL03 +*/ +use std::ops; + +pub trait Addition: ops::Add + ops::AddAssign + Sized {} + +impl Addition for T where T: ops::Add + ops::AddAssign + Sized {} + +pub trait Division: ops::Div + ops::DivAssign + Sized {} + +impl Division for T where T: ops::Div + ops::DivAssign + Sized {} + +pub trait Multiplication: ops::Mul + ops::MulAssign + Sized {} + +impl Multiplication for T where T: ops::Mul + ops::MulAssign + Sized {} + +pub trait Subtraction: ops::Sub + ops::SubAssign + Sized {} + +impl Subtraction for T where T: ops::Sub + ops::SubAssign + Sized {} diff --git a/math/math/src/num/complex.rs b/math/math/src/num/complex.rs new file mode 100644 index 0000000..8c0ee0a --- /dev/null +++ b/math/math/src/num/complex.rs @@ -0,0 +1,167 @@ +/* + Appellation: complex + Contrib: FL03 +*/ +use super::Numerical; +use serde::{Deserialize, Serialize}; +use std::ops; + +// Define a trait for complex numbers. +pub trait Complex { + fn new(re: T, im: T) -> Self; + fn re(&self) -> T; + fn im(&self) -> T; +} + +// Implement the Complex trait for the tuple (f64, f64). +impl Complex for (T, T) { + fn new(re: T, im: T) -> Self { + (re, im) + } + + fn re(&self) -> T { + self.0 + } + + fn im(&self) -> T { + self.1 + } +} + +impl Complex for [T; 2] { + fn new(re: T, im: T) -> Self { + [re, im] + } + + fn re(&self) -> T { + self[0] + } + + fn im(&self) -> T { + self[1] + } +} + +#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)] +pub struct C(T, T); + +impl Complex for C { + fn new(re: T, im: T) -> Self { + Self(re, im) + } + fn re(&self) -> T { + self.0 + } + fn im(&self) -> T { + self.1 + } +} + +impl From<(T, T)> for C { + fn from(data: (T, T)) -> Self { + Self::new(data.0, data.1) + } +} + +impl From> for (T, T) { + fn from(data: C) -> (T, T) { + (data.re(), data.im()) + } +} + +// Implement the Add and Mul traits for complex numbers. +impl ops::Add for C { + type Output = Self; + + fn add(self, other: Self) -> Self { + Self::from((self.re() + other.re(), self.im() + other.im())) + } +} + +impl ops::AddAssign for C +where + T: Numerical + ops::AddAssign, +{ + fn add_assign(&mut self, other: Self) { + self.0 += other.0; + self.1 += other.1; + } +} + +impl ops::Div for C { + type Output = Self; + + fn div(self, other: Self) -> Self { + let denom = other.re() * other.re() + other.im() * other.im(); + Self::from(( + (self.re() * other.re() + self.im() * other.im()) / denom, + (self.im() * other.re() - self.re() * other.im()) / denom, + )) + } +} + +impl ops::DivAssign for C { + fn div_assign(&mut self, other: Self) { + let denom = other.re() * other.re() + other.im() * other.im(); + let re = (self.re() * other.re() + self.im() * other.im()) / denom; + let im = (self.im() * other.re() - self.re() * other.im()) / denom; + self.0 = re; + self.1 = im; + } +} + +impl ops::Mul for C { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Self::from(( + self.re() * other.re() - self.im() * other.im(), + self.re() * other.im() + self.im() * other.re(), + )) + } +} + +impl ops::MulAssign for C { + fn mul_assign(&mut self, other: Self) { + let re = self.re() * other.re() - self.im() * other.im(); + let im = self.re() * other.im() + self.im() * other.re(); + self.0 = re; + self.1 = im; + } +} + +impl ops::Sub for C { + type Output = Self; + + fn sub(self, other: Self) -> Self { + Self::from((self.re() - other.re(), self.im() - other.im())) + } +} + +impl ops::SubAssign for C +where + T: Numerical + ops::SubAssign, +{ + fn sub_assign(&mut self, other: Self) { + self.0 -= other.0; + self.1 -= other.1; + } +} + +#[cfg(test)] +mod tests { + use super::*; + // Define a holomorphic function that squares its input. + fn square(z: C) -> C { + z.clone() * z + } + + #[test] + fn test_square() { + // Create a complex number (1 + i) and square it. + let mut a = C::from((1.0, 1.0)); + a = square(a.clone()); + let b = C::new(0.0, 2.0); + assert_eq!(&a, &b); + } +} diff --git a/math/math/src/num/mod.rs b/math/math/src/num/mod.rs new file mode 100644 index 0000000..e220f63 --- /dev/null +++ b/math/math/src/num/mod.rs @@ -0,0 +1,36 @@ +/* + Appellation: num + Contrib: FL03 +*/ +pub use self::{arithmetic::*, utils::*}; + +pub(crate) mod arithmetic; + +pub mod complex; + +use std::ops::{self, Div, Mul, Sub}; + +pub trait Binary: num::One + num::Zero {} + +impl Binary for T where T: num::One + num::Zero {} + +pub trait Arithmetic: + ops::Add + Div + Mul + Sub + Sized +{ +} + +impl Arithmetic for T where + T: ops::Add + + Div + + Mul + + Sub + + Sized +{ +} + +/// [Numerical] is a basic trait describing numerical objects +pub trait Numerical: Arithmetic + Copy + PartialEq {} + +impl Numerical for T where T: Arithmetic + Copy + PartialEq {} + +pub(crate) mod utils {} diff --git a/math/math/src/primitives.rs b/math/math/src/primitives.rs new file mode 100644 index 0000000..f16ac25 --- /dev/null +++ b/math/math/src/primitives.rs @@ -0,0 +1,14 @@ +/* + Appellation: primitives + Contrib: FL03 +*/ +pub use self::{constants::*, statics::*, types::*}; + +/// Collection of constants used throughout the system +mod constants {} + +/// Collection of static references used throughout +mod statics {} + +/// Collection of types used throughout the system +mod types {} diff --git a/math/math/src/specs.rs b/math/math/src/specs.rs new file mode 100644 index 0000000..31f7762 --- /dev/null +++ b/math/math/src/specs.rs @@ -0,0 +1,31 @@ +/* + Appellation: specs + Contrib: FL03 +*/ + +pub trait RoundTo { + fn round_to(&self, decimals: usize) -> Self; +} + +impl RoundTo for T +where + T: num::Float, +{ + fn round_to(&self, decimals: usize) -> Self { + let val = T::from(self.clone()).expect("Failed to convert to type T"); + let factor = T::from(10).expect("").powi(decimals as i32); + (val * factor).round() / factor + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_round_to() { + let num = 1.23456789_f64; + assert_eq!(num.round_to(2), 1.23_f64); + assert_eq!(num.round_to(3), 1.235_f64); + } +} diff --git a/math/math/src/utils.rs b/math/math/src/utils.rs new file mode 100644 index 0000000..e880e12 --- /dev/null +++ b/math/math/src/utils.rs @@ -0,0 +1,9 @@ +/* + Appellation: utils + Contrib: FL03 +*/ + +pub fn round(num: T, decimals: usize) -> T { + let factor = T::from(10.0).expect("").powi(decimals as i32); + (num * factor).round() / factor +} diff --git a/math/math/tests/default.rs b/math/math/tests/default.rs new file mode 100644 index 0000000..0cac1eb --- /dev/null +++ b/math/math/tests/default.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +#[test] +fn compiles() { + let f = |x: usize, y: usize| x + y; + + assert_eq!(f(10, 10), 20); + assert_ne!(f(1, 1), 3); +} diff --git a/math/statistics/Cargo.toml b/math/statistics/Cargo.toml new file mode 100644 index 0000000..e1f6256 --- /dev/null +++ b/math/statistics/Cargo.toml @@ -0,0 +1,42 @@ +[package] +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "algae-statistics" +readme.workspace = true +repository.workspace = true +version.workspace = true + +[features] +default = [] + +[lib] +bench = true +crate-type = ["cdylib", "rlib"] +doctest = false +test = true + +[build-dependencies] + +[dependencies] +ndarray.workspace = true +num.workspace = true +serde.workspace = true +serde_json.workspace = true +smart-default.workspace = true +strum.workspace = true + +[dev-dependencies] +rand = "0.8" + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] + +[target.wasm32-unknown-unknown] + +[target.wasm32-wasi] \ No newline at end of file diff --git a/math/statistics/src/calc/deviation.rs b/math/statistics/src/calc/deviation.rs new file mode 100644 index 0000000..a38fb9f --- /dev/null +++ b/math/statistics/src/calc/deviation.rs @@ -0,0 +1,63 @@ +/* + Appellation: deviation + Contrib: FL03 +*/ +use super::utils::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)] +pub struct StandardDeviation { + pub deviation: f64, + pub mean: f64, + pub variance: f64, +} + +impl StandardDeviation { + pub fn new(x: &[f64]) -> StandardDeviation { + let mean = mean(x); + let variance = x.iter().map(|&x| x * x).sum::() / x.len() as f64 - mean * mean; + let deviation = variance.sqrt(); + StandardDeviation { + deviation, + mean, + variance, + } + } + + pub fn compute(&mut self, x: &[f64]) -> f64 { + let mean = x.iter().sum::() / x.len() as f64; + let variance = x.iter().map(|&x| x * x).sum::() / x.len() as f64 - mean * mean; + let deviation = variance.sqrt(); + self.deviation = deviation; + self.mean = mean; + self.variance = variance; + deviation + } + + pub fn deviation(&self) -> f64 { + self.deviation + } + + pub fn mean(&self) -> f64 { + self.mean + } + + pub fn variance(&self) -> f64 { + self.variance + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::prelude::{RoundTo, Statistics}; + + #[test] + fn test_std() { + let x = vec![1.0, 2.0, 4.0, 9.0, 3.0, 4.0, 5.0]; + let sd = StandardDeviation::new(&x); + + assert_eq!(x.std().round_to(5), sd.deviation().round_to(5)); + } +} diff --git a/math/statistics/src/calc/mod.rs b/math/statistics/src/calc/mod.rs new file mode 100644 index 0000000..657fb65 --- /dev/null +++ b/math/statistics/src/calc/mod.rs @@ -0,0 +1,86 @@ +/* + Appellation: statistics + Contrib: FL03 +*/ +//! # statistics +pub use self::{deviation::*, utils::*}; + + +pub(crate) mod deviation; + + +pub(crate) mod utils { + use std::iter::Sum; + + /// Covariance is the average of the products of the deviations from the mean. + pub fn covariance(x: &[T], y: &[T]) -> T { + let dx = deviation(&x); + let dy = deviation(&y); + dx.iter().zip(dy.iter()).map(|(&x, &y)| x * y).sum::() / T::from(dx.len()).unwrap() + } + /// Deviation is the distance from the mean. + pub fn deviation(x: &[T]) -> Vec { + let mean = mean(x); + x.iter().map(|&x| x - mean).collect() + } + /// Mean is the average of the data. + pub fn mean(x: &[T]) -> T { + x.iter().cloned().sum::() / T::from(x.len()).unwrap() + } + /// Variance is the average of the squared deviations from the mean. + pub fn variance(x: &[T]) -> T { + let dev = deviation(&x); + dev.iter().map(|&x| x * x).sum::() / T::from(dev.len()).unwrap() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rand::Rng; + + fn random_vec() -> Vec { + let mut rng = rand::thread_rng(); + let mut v = Vec::new(); + for _ in 0..100 { + v.push(rng.gen_range(0.0..25.0)); + } + v + } + + #[test] + fn test_statistics() { + let x = random_vec(); + let y = random_vec(); + assert_eq!(covariance(&x, &y), x.covariance(&y)); + assert_eq!(deviation(&x), x.deviation()); + assert_eq!(mean(&x), x.mean()); + assert_eq!(variance(&x), x.variance()); + } + + #[test] + fn test_covariance() { + let x: Vec = (1..=5).map(|i| i as f64).collect(); + let y = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + assert_eq!(covariance(&x, &y), 2.0); + assert_eq!(x.covariance(&y), 2.0); + } + + #[test] + fn test_deviation() { + let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + assert_eq!(deviation(&x), vec![-2.0, -1.0, 0.0, 1.0, 2.0]); + } + + #[test] + fn test_mean() { + let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + assert_eq!(mean(&x), 3.0); + } + + #[test] + fn test_variance() { + let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + assert_eq!(variance(&x), 2.0); + } +} diff --git a/math/statistics/src/lib.rs b/math/statistics/src/lib.rs new file mode 100644 index 0000000..7309cca --- /dev/null +++ b/math/statistics/src/lib.rs @@ -0,0 +1,25 @@ +/* + Appellation: concision-statistics + Contrib: FL03 +*/ +//! # concision-statistics + +pub use self::{primitives::*, specs::*, utils::*}; + +pub mod calc; +pub mod regression; + +// pub(crate) use concision_core as core; + +pub(crate) mod primitives; +pub(crate) mod specs; +pub(crate) mod utils; + +pub mod prelude { + pub use crate::calc::*; + pub use crate::regression::*; + + pub use crate::primitives::*; + pub use crate::specs::*; + pub use crate::utils::*; +} diff --git a/math/statistics/src/primitives.rs b/math/statistics/src/primitives.rs new file mode 100644 index 0000000..f16ac25 --- /dev/null +++ b/math/statistics/src/primitives.rs @@ -0,0 +1,14 @@ +/* + Appellation: primitives + Contrib: FL03 +*/ +pub use self::{constants::*, statics::*, types::*}; + +/// Collection of constants used throughout the system +mod constants {} + +/// Collection of static references used throughout +mod statics {} + +/// Collection of types used throughout the system +mod types {} diff --git a/math/statistics/src/regression/linear.rs b/math/statistics/src/regression/linear.rs new file mode 100644 index 0000000..10c0612 --- /dev/null +++ b/math/statistics/src/regression/linear.rs @@ -0,0 +1,66 @@ +/* + Appellation: linear + Contrib: FL03 +*/ +use super::Regression; +use crate::calc::{covariance, deviation, mean, variance}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] +pub struct LinearRegression { + intercept: f64, + slope: f64, +} + +impl LinearRegression { + pub fn new(x: &[f64], y: &[f64]) -> LinearRegression { + let (x_mean, y_mean) = (mean(x), mean(y)); + let (x_dev, y_dev) = (deviation(x), deviation(y)); + let slope = covariance(&x_dev, &y_dev) / variance(&x_dev); + let intercept = y_mean - slope * x_mean; + LinearRegression { intercept, slope } + } + + pub fn intercept(&self) -> f64 { + self.intercept + } + + pub fn predict(&self, x: &[f64]) -> Vec { + x.iter().map(|&x| self.slope * x + self.intercept).collect() + } + + pub fn slope(&self) -> f64 { + self.slope + } +} + +impl Regression for LinearRegression { + type Item = f64; + + fn fit(&mut self, args: &[Self::Item], target: &[Self::Item]) { + let (x_mean, y_mean) = (mean(args), mean(target)); + let (x_dev, y_dev) = (deviation(args), deviation(target)); + self.slope = covariance(&x_dev, &y_dev) / variance(&x_dev); + self.intercept = y_mean - self.slope * x_mean; + } + + fn predict(&self, args: &[Self::Item]) -> Vec { + args.iter() + .map(|&x| self.slope * x + self.intercept) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_linear_regression() { + let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + let y = vec![1.0, 2.0, 3.0, 4.0, 5.0]; + let lr = LinearRegression::new(&x, &y); + assert_eq!(lr.slope, 1.0); + assert_eq!(lr.intercept, 0.0); + assert_eq!(lr.predict(&x), y); + } +} diff --git a/math/statistics/src/regression/mod.rs b/math/statistics/src/regression/mod.rs new file mode 100644 index 0000000..9566f19 --- /dev/null +++ b/math/statistics/src/regression/mod.rs @@ -0,0 +1,19 @@ +/* + Appellation: regression + Contrib: FL03 +*/ +//! # regression +//! +pub use self::utils::*; + +pub mod linear; + +pub trait Regression { + type Item: num::Float; + + fn fit(&mut self, args: &[Self::Item], target: &[Self::Item]); + + fn predict(&self, args: &[Self::Item]) -> Vec; +} + +pub(crate) mod utils {} diff --git a/math/statistics/src/specs.rs b/math/statistics/src/specs.rs new file mode 100644 index 0000000..ee0259a --- /dev/null +++ b/math/statistics/src/specs.rs @@ -0,0 +1,51 @@ +/* + Appellation: specs + Contrib: FL03 +*/ + + +pub trait Statistics +where + T: num::Float + std::iter::Sum, + Self: Clone + IntoIterator, +{ + fn covariance(&self, other: &Self) -> T { + let dx = self.deviation(); + let dy = other.deviation(); + dx.iter().zip(dy.iter()).map(|(&x, &y)| x * y).sum::() / T::from(dx.len()).unwrap() + } + + fn deviation(&self) -> Vec { + let mean = self.mean(); + self.clone().into_iter().map(|x| x - mean).collect() + } + fn len(&self) -> usize { + Vec::from_iter(self.clone().into_iter()).len() + } + /// [Statistics::mean] calculates the mean or average of the data + fn mean(&self) -> T { + self.clone().into_iter().sum::() / T::from(self.len()).unwrap() + } + /// [Statistics::std] calculates the standard deviation of the data + fn std(&self) -> T { + let mean = self.mean(); + let mut res = self + .clone() + .into_iter() + .map(|x| (x - mean).powi(2)) + .sum::(); + res = res / T::from(self.len()).unwrap(); + res.sqrt() + } + + fn variance(&self) -> T { + let dev = self.deviation(); + dev.iter().map(|&x| x * x).sum::() / T::from(dev.len()).unwrap() + } +} + +impl Statistics for Vec where T: num::Float + std::iter::Sum {} + +impl Statistics for ndarray::Array1 where T: num::Float + std::iter::Sum {} + + diff --git a/math/statistics/src/utils.rs b/math/statistics/src/utils.rs new file mode 100644 index 0000000..f8840c6 --- /dev/null +++ b/math/statistics/src/utils.rs @@ -0,0 +1,4 @@ +/* + Appellation: utils + Contrib: FL03 +*/ diff --git a/math/statistics/tests/default.rs b/math/statistics/tests/default.rs new file mode 100644 index 0000000..0cac1eb --- /dev/null +++ b/math/statistics/tests/default.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +#[test] +fn compiles() { + let f = |x: usize, y: usize| x + y; + + assert_eq!(f(10, 10), 20); + assert_ne!(f(1, 1), 3); +} From 56b9678523a59d4ccff82dd81c1191ad40f29741 Mon Sep 17 00:00:00 2001 From: FL03 Date: Sat, 21 Oct 2023 08:02:41 -0500 Subject: [PATCH 14/15] update Signed-off-by: FL03 --- .github/dependabot.yml | 4 + .github/workflows/clippy.yml | 23 +-- .github/workflows/publish.yml | 48 +++++ .github/workflows/rust.yml | 81 +++++---- Cargo.toml | 3 - algae/Cargo.toml | 6 - algae/src/lib.rs | 12 +- math/linalg/Cargo.toml | 42 ----- math/linalg/src/lib.rs | 22 --- math/linalg/src/primitives.rs | 14 -- math/linalg/src/specs.rs | 6 - math/linalg/src/utils.rs | 4 - math/linalg/src/vs/mod.rs | 37 ---- math/linalg/src/vs/space.rs | 26 --- math/linalg/tests/default.rs | 8 - math/math/Cargo.toml | 45 ----- math/math/examples/simple.rs | 16 -- math/math/src/calculus/derivatives/mod.rs | 8 - math/math/src/calculus/derivatives/nderive.rs | 21 --- math/math/src/calculus/mod.rs | 7 - math/math/src/factorials.rs | 54 ------ math/math/src/lib.rs | 30 ---- math/math/src/num/arithmetic.rs | 21 --- math/math/src/num/complex.rs | 167 ------------------ math/math/src/num/mod.rs | 36 ---- math/math/src/primitives.rs | 14 -- math/math/src/specs.rs | 31 ---- math/math/src/utils.rs | 9 - math/math/tests/default.rs | 8 - math/statistics/Cargo.toml | 42 ----- math/statistics/src/calc/deviation.rs | 63 ------- math/statistics/src/calc/mod.rs | 86 --------- math/statistics/src/lib.rs | 25 --- math/statistics/src/primitives.rs | 14 -- math/statistics/src/regression/linear.rs | 66 ------- math/statistics/src/regression/mod.rs | 19 -- math/statistics/src/specs.rs | 51 ------ math/statistics/src/utils.rs | 4 - math/statistics/tests/default.rs | 8 - 39 files changed, 115 insertions(+), 1066 deletions(-) create mode 100644 .github/workflows/publish.yml delete mode 100644 math/linalg/Cargo.toml delete mode 100644 math/linalg/src/lib.rs delete mode 100644 math/linalg/src/primitives.rs delete mode 100644 math/linalg/src/specs.rs delete mode 100644 math/linalg/src/utils.rs delete mode 100644 math/linalg/src/vs/mod.rs delete mode 100644 math/linalg/src/vs/space.rs delete mode 100644 math/linalg/tests/default.rs delete mode 100644 math/math/Cargo.toml delete mode 100644 math/math/examples/simple.rs delete mode 100644 math/math/src/calculus/derivatives/mod.rs delete mode 100644 math/math/src/calculus/derivatives/nderive.rs delete mode 100644 math/math/src/calculus/mod.rs delete mode 100644 math/math/src/factorials.rs delete mode 100644 math/math/src/lib.rs delete mode 100644 math/math/src/num/arithmetic.rs delete mode 100644 math/math/src/num/complex.rs delete mode 100644 math/math/src/num/mod.rs delete mode 100644 math/math/src/primitives.rs delete mode 100644 math/math/src/specs.rs delete mode 100644 math/math/src/utils.rs delete mode 100644 math/math/tests/default.rs delete mode 100644 math/statistics/Cargo.toml delete mode 100644 math/statistics/src/calc/deviation.rs delete mode 100644 math/statistics/src/calc/mod.rs delete mode 100644 math/statistics/src/lib.rs delete mode 100644 math/statistics/src/primitives.rs delete mode 100644 math/statistics/src/regression/linear.rs delete mode 100644 math/statistics/src/regression/mod.rs delete mode 100644 math/statistics/src/specs.rs delete mode 100644 math/statistics/src/utils.rs delete mode 100644 math/statistics/tests/default.rs diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 173af4d..8ad703f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,6 +12,10 @@ updates: directory: /algae schedule: interval: daily + - package-ecosystem: cargo + directory: /graph + schedule: + interval: daily - package-ecosystem: cargo directory: /merkle schedule: diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 9a0bec2..b455041 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -2,25 +2,27 @@ name: Clippy on: pull_request: - branches: [ main, master, v*.*.*, ] + branches-ignore: ["beta*", "dev*", "next*"] push: - branches-ignore: [ "beta*", "dev*", "next*" ] - tags: [ "nightly*", "v*.*.*" ] + branches-ignore: ["beta*", "dev*", "next*"] + tags: ["nightly*", "v*.*.*"] release: schedule: - - cron: "30 9 * * *" # 9:30am UTC + - cron: "30 21 * * *" # 9:30pm UTC workflow_dispatch: +permissions: + actions: read + contents: read + security-events: write + jobs: clippy: name: Clippy - permissions: - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - contents: read - security-events: write + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust toolchain uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #@v1 with: @@ -31,8 +33,7 @@ jobs: - name: Setup run: cargo install clippy-sarif sarif-fmt - name: clippy - run: - cargo clippy + run: cargo clippy --all-features --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt continue-on-error: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..f77f277 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,48 @@ +name: Publish + +concurrency: + cancel-in-progress: true + group: ${{ github.event.repository.name }} + +env: + CARGO_TERM_COLOR: always + CRATE_BASENAME: ${{ github.event.repository.name }} + +on: + release: + types: [ created ] + workflow_dispatch: + inputs: + publish: + default: true + description: 'Publish' + required: true + type: boolean + +permissions: + contents: read + packages: write + pull-requests: write + statuses: write + +jobs: + features: + name: Publish (features) + runs-on: ubuntu-latest + strategy: + matrix: + feature: [ graph, merkle, mmr ] + env: + PACKAGE_NAME: ${{ github.event.repository.name }}-${{ matrix.feature }} + steps: + - uses: actions/checkout@v4 + - name: Publish (${{env.PACKAGE_NAME}}) + run: cargo publish --all-features -v -p ${{ env.PACKAGE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} + publish: + name: Publish (sdk) + needs: features + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Publish (sdk) + run: cargo publish --all-features -v -p ${{ github.event.repository.name }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0c3120b..0a0806d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,25 +1,26 @@ name: Rust +concurrency: + cancel-in-progress: false + group: ${{ github.event.repository.name }}-rust + env: CARGO_TERM_COLOR: always on: pull_request: - branches: [ main, master, v*.*.*, ] + branches: [ "main", "v*.*.*" ] push: - branches-ignore: [ "beta*", "dev*", "next*" ] + branches: [ "main" ] tags: [ "nightly*", "v*.*.*" ] release: - types: [created] + repository_dispatch: + types: [ rust ] schedule: - - cron: "30 9 * * *" # 9:30am UTC + - cron: "30 21 * * *" # 9:30pm UTC workflow_dispatch: - inputs: - publish: - default: true - description: 'Publish' - required: true - type: boolean + +permissions: write-all jobs: build: @@ -27,49 +28,61 @@ jobs: strategy: matrix: platform: [ ubuntu-latest ] + target: [ wasm32-unknown-unknown, wasm32-wasi ] toolchain: [ stable, nightly ] runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup (langspace) run: | rustup update rustup default ${{ matrix.toolchain }} + - name: Set target (${{ matrix.target }}) + if: matrix.toolchain == 'nightly' + run: rustup target add ${{ matrix.target }} - name: Build - run: cargo build --release -v --workspace + + run: cargo build -r -v --workspace - name: Cache build uses: actions/cache@v3 with: + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} path: | ~/.cargo/registry ~/.cargo/git target/release - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Test - run: cargo test --all --release -v + run: cargo test --all-features -r -v --workspace - name: Bench if: matrix.toolchain == 'nightly' run: cargo bench --all -v - features: - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.event_name == 'release' && github.event.action == 'created' || github.event.inputs.publish == 'true' - name: Publish (features) - needs: build - runs-on: ubuntu-latest + nightly: + name: Nightly strategy: matrix: - feature: [ "graph", "merkle", "mmr" ] - env: - PACKAGE_NAME: ${{ github.event.repository.name }}-${{ matrix.feature }} - steps: - - uses: actions/checkout@v3 - - name: Publish (${{ env.PACKAGE_NAME }}) - run: cargo publish --all-features -v -p ${{ env.PACKAGE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} - publish: - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.event_name == 'release' && github.event.action == 'created' || github.event.inputs.publish == 'true' - name: Publish (sdk) - needs: features - runs-on: ubuntu-latest + platform: [ ubuntu-latest ] + target: [ wasm32-unknown-unknown, wasm32-wasi ] + runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 - - name: Publish (${{ github.event.repository.name }}) - run: cargo publish --all-features -v -p ${{ github.event.repository.name }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file + - uses: actions/checkout@v4 + - name: setup (langspace) + run: | + rustup toolchain install nightly + rustup default nightly + rustup update + - name: Set target (${{ matrix.target }}) + run: rustup target add ${{ matrix.target }} + - name: Build + run: cargo build -r -v --workspace --target ${{ matrix.target }} + - name: Cache build + uses: actions/cache@v3 + with: + key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} + path: | + ~/.cargo/registry + ~/.cargo/git + target/release + - name: Test + run: cargo test --all-features -r -v --workspace --target ${{ matrix.target }} + - name: Bench + run: cargo bench --all -v --target ${{ matrix.target }} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c57e2df..82e2017 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,6 @@ decanter = { features = ["derive"], version = "0.1.6" } anyhow = "1" itertools = "0.11" -ndarray = "0.15" -num = "0.4" serde = { features = ["derive"], version = "1" } serde_json = "1" smart-default = "0.7" @@ -33,7 +31,6 @@ members = [ "graph", "merkle", "mmr", - "math/*" ] resolver = "2" diff --git a/algae/Cargo.toml b/algae/Cargo.toml index c06b796..8e53a4f 100644 --- a/algae/Cargo.toml +++ b/algae/Cargo.toml @@ -15,12 +15,10 @@ version.workspace = true default = [ "core", "ds", - "math", ] full = [ "core", "ds", - "math", ] core = [] @@ -33,9 +31,6 @@ ds = [ graph = [ "algae-graph" ] -math = [ - "algae-math" -] merkle = [ "algae-merkle" ] @@ -55,7 +50,6 @@ test = true [dependencies] algae-graph = { features = [], optional = true, path = "../graph", version = "0.1.20" } -algae-math = { features = [], optional = true, path = "../math/math", version = "0.1.20" } algae-merkle = { features = [], optional = true, path = "../merkle", version = "0.1.20" } algae-mmr = { features = [], optional = true, path = "../mmr", version = "0.1.20" } diff --git a/algae/src/lib.rs b/algae/src/lib.rs index 1915985..91b744f 100644 --- a/algae/src/lib.rs +++ b/algae/src/lib.rs @@ -7,8 +7,6 @@ //! Algae is a comprehensive collection of algorithms and data-structures written in Rust. #[cfg(feature = "graph")] pub use algae_graph as graph; -#[cfg(feature = "math")] -pub use algae_math as math; #[cfg(feature = "merkle")] pub use algae_merkle as merkle; #[cfg(feature = "mmr")] @@ -18,15 +16,13 @@ pub mod list; pub mod prelude { #[cfg(feature = "graph")] - pub use super::graph; + pub use algae_graph::graph; // pub use super::graph::*; - #[cfg(feature = "math")] - pub use algae_math::prelude::*; #[cfg(feature = "merkle")] - pub use super::merkle::prelude::*; + pub use algae_merkle::prelude::*; #[cfg(feature = "mmr")] - pub use super::mmr::*; + pub use algae_mmr::*; - pub use super::list::*; + pub use crate::list::*; } diff --git a/math/linalg/Cargo.toml b/math/linalg/Cargo.toml deleted file mode 100644 index d51baa8..0000000 --- a/math/linalg/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -authors.workspace = true -categories.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "algae-linalg" -readme.workspace = true -repository.workspace = true -version.workspace = true - -[features] -default = [] - -[lib] -bench = true -crate-type = ["cdylib", "rlib"] -doctest = false -test = true - -[build-dependencies] - -[dependencies] -ndarray.workspace = true -num.workspace = true -serde.workspace = true -serde_json.workspace = true -smart-default.workspace = true -strum.workspace = true - -[dev-dependencies] -rand = "0.8" - -[package.metadata.docs.rs] -all-features = true -rustc-args = ["--cfg", "docsrs"] - -[target.wasm32-unknown-unknown] - -[target.wasm32-wasi] \ No newline at end of file diff --git a/math/linalg/src/lib.rs b/math/linalg/src/lib.rs deleted file mode 100644 index bbd1643..0000000 --- a/math/linalg/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* - Appellation: algae-linalg - Contrib: FL03 -*/ -//! # algae-linalg - -pub use self::{primitives::*, specs::*, utils::*}; - -pub mod vs; - -// pub(crate) use concision_core as core; - -pub(crate) mod primitives; -pub(crate) mod specs; -pub(crate) mod utils; - -pub mod prelude { - pub use crate::vs::*; - pub use crate::primitives::*; - pub use crate::specs::*; - pub use crate::utils::*; -} diff --git a/math/linalg/src/primitives.rs b/math/linalg/src/primitives.rs deleted file mode 100644 index f16ac25..0000000 --- a/math/linalg/src/primitives.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* - Appellation: primitives - Contrib: FL03 -*/ -pub use self::{constants::*, statics::*, types::*}; - -/// Collection of constants used throughout the system -mod constants {} - -/// Collection of static references used throughout -mod statics {} - -/// Collection of types used throughout the system -mod types {} diff --git a/math/linalg/src/specs.rs b/math/linalg/src/specs.rs deleted file mode 100644 index 08a695f..0000000 --- a/math/linalg/src/specs.rs +++ /dev/null @@ -1,6 +0,0 @@ -/* - Appellation: specs - Contrib: FL03 -*/ - - diff --git a/math/linalg/src/utils.rs b/math/linalg/src/utils.rs deleted file mode 100644 index f8840c6..0000000 --- a/math/linalg/src/utils.rs +++ /dev/null @@ -1,4 +0,0 @@ -/* - Appellation: utils - Contrib: FL03 -*/ diff --git a/math/linalg/src/vs/mod.rs b/math/linalg/src/vs/mod.rs deleted file mode 100644 index b5f7ba9..0000000 --- a/math/linalg/src/vs/mod.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* - Appellation: vs - Contrib: FL03 -*/ -//! # Vector Space -//! -//! A vector space is defined to be a set V, whose elements are called vectors, on which are defined two operations, -//! called addition and multiplication by scalars (real numbers), subject to the ten axioms listed below. -//! -//! ## Axioms -//! -//! 1. Closure under addition -//! 2. Closure under scalar multiplication -//! 3. Commutativity of addition -//! 4. Associativity of addition -//! 5. Additive identity -//! 6. Additive inverse -//! 7. Distributivity of scalar multiplication with respect to vector addition -//! 8. Distributivity of scalar multiplication with respect to field addition -//! 9. Compatibility of scalar multiplication with field multiplication -//! 10. Identity element of scalar multiplication -pub use self::{space::*, utils::*}; - -pub(crate) mod space; - -pub(crate) mod utils {} - -#[cfg(test)] -mod tests { - #[test] - fn test() { - let f = |x: usize, y: usize| x + y; - let actual = f(4, 4); - let expected: usize = 8; - assert_eq!(actual, expected) - } -} diff --git a/math/linalg/src/vs/space.rs b/math/linalg/src/vs/space.rs deleted file mode 100644 index dfaa073..0000000 --- a/math/linalg/src/vs/space.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* - Appellation: space - Contrib: FL03 -*/ - -pub trait Subspace: VectorSpace {} - -pub struct Space { - pub data: Vec, - pub shape: Vec, -} - -pub trait VectorSpace { - type Dim; -} - -#[cfg(test)] -mod tests { - #[test] - fn test() { - let f = |x: usize, y: usize| x + y; - let actual = f(4, 4); - let expected: usize = 8; - assert_eq!(actual, expected) - } -} diff --git a/math/linalg/tests/default.rs b/math/linalg/tests/default.rs deleted file mode 100644 index 0cac1eb..0000000 --- a/math/linalg/tests/default.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -#[test] -fn compiles() { - let f = |x: usize, y: usize| x + y; - - assert_eq!(f(10, 10), 20); - assert_ne!(f(1, 1), 3); -} diff --git a/math/math/Cargo.toml b/math/math/Cargo.toml deleted file mode 100644 index 833365a..0000000 --- a/math/math/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -authors.workspace = true -categories.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "algae-math" -readme.workspace = true -repository.workspace = true -version.workspace = true - -[features] -default = [] - -[lib] -bench = true -crate-type = ["cdylib", "rlib"] -doctest = false -test = true - -[build-dependencies] - -[dependencies] -algae-linalg = { features = [], path = "../linalg", version = "0.1.12" } -algae-statistics = { features = [], path = "../statistics", version = "0.1.12" } - -ndarray.workspace = true -num.workspace = true -serde.workspace = true -serde_json.workspace = true -smart-default.workspace = true -strum.workspace = true - -[dev-dependencies] -rand = "0.8" - -[package.metadata.docs.rs] -all-features = true -rustc-args = ["--cfg", "docsrs"] - -[target.wasm32-unknown-unknown] - -[target.wasm32-wasi] \ No newline at end of file diff --git a/math/math/examples/simple.rs b/math/math/examples/simple.rs deleted file mode 100644 index 38a262e..0000000 --- a/math/math/examples/simple.rs +++ /dev/null @@ -1,16 +0,0 @@ -extern crate concision_math as math; - -use math::prelude::{complex::C, Numerical}; - -// Define a holomorphic function that squares its input. -fn square(z: C) -> C { - z.clone() * z -} - -fn main() { - let c = C::from((1.0, 1.0)); - let res = square(c); - assert_eq!(res.clone(), C::from((0.0, 2.0))); - - println!("{:?}", res); -} diff --git a/math/math/src/calculus/derivatives/mod.rs b/math/math/src/calculus/derivatives/mod.rs deleted file mode 100644 index ac004ea..0000000 --- a/math/math/src/calculus/derivatives/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* - Appellation: derivatives - Contrib: FL03 - Description: ... Summary ... -*/ -pub use self::nderive::*; - -pub(crate) mod nderive; diff --git a/math/math/src/calculus/derivatives/nderive.rs b/math/math/src/calculus/derivatives/nderive.rs deleted file mode 100644 index 9049f61..0000000 --- a/math/math/src/calculus/derivatives/nderive.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Appellation: num - Contrib: FL03 - Description: ... Summary ... -*/ - -pub fn central(x: T, f: Box T>, h: T) -> T { - (f(x + h) - f(x)) / h -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_central() { - let f = |x: f64| x * x; - let res = central(5.0, Box::new(f), 0.001); - assert_eq!(res.round(), 10.0); - } -} diff --git a/math/math/src/calculus/mod.rs b/math/math/src/calculus/mod.rs deleted file mode 100644 index 18d2ab7..0000000 --- a/math/math/src/calculus/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* - Appellation: calculus - Contrib: FL03 - Description: ... Summary ... -*/ - -pub mod derivatives; diff --git a/math/math/src/factorials.rs b/math/math/src/factorials.rs deleted file mode 100644 index ef051db..0000000 --- a/math/math/src/factorials.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* - Appellation: factorials - Contrib: FL03 -*/ -use std::ops::{Mul, Sub}; -use std::str::FromStr; - -#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] -pub struct Factorial + Sub>(T); - -impl + Sub> Factorial -where - ::Err: std::fmt::Debug, -{ - pub fn new(data: T) -> Self { - Self(Self::compute(data)) - } - pub fn compute(data: T) -> T { - let x = data.to_string(); - let b: T = "1".parse().ok().unwrap(); - match x.as_str() { - "0" | "1" => b.clone(), - _ => Self::compute(data.clone() - b) * data, - } - } - pub fn data(&self) -> &T { - &self.0 - } - pub fn from_args(data: Vec) -> Vec { - data.iter() - .map(|i| Self::new(i.clone())) - .collect::>() - } -} - -pub fn factorial(data: T) -> T { - if data.is_zero() || data.is_one() { - return T::one(); - } - factorial(data - T::one()) * data -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_factorial() { - assert_eq!(Factorial::new(0).data().clone(), 1); - assert_eq!(factorial(3), 6); - assert_eq!(factorial(4.0), 24.0); - assert_eq!(factorial(5.0), 120.0); - } -} diff --git a/math/math/src/lib.rs b/math/math/src/lib.rs deleted file mode 100644 index bfeeeaf..0000000 --- a/math/math/src/lib.rs +++ /dev/null @@ -1,30 +0,0 @@ -/* - Appellation: algae-math - Contrib: FL03 -*/ -//! # algae-math - -pub use self::{factorials::*, primitives::*, specs::*, utils::*}; - -pub mod calculus; -pub mod num; - -pub use algae_linalg as linalg; - -pub use algae_statistics as stats; - -pub(crate) mod factorials; - -// pub(crate) use concision_core as core; - -pub(crate) mod primitives; -pub(crate) mod specs; -pub(crate) mod utils; - -pub mod prelude { - pub use crate::calculus::*; - pub use crate::num::*; - pub use crate::primitives::*; - pub use crate::specs::*; - pub use crate::utils::*; -} diff --git a/math/math/src/num/arithmetic.rs b/math/math/src/num/arithmetic.rs deleted file mode 100644 index 5585328..0000000 --- a/math/math/src/num/arithmetic.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Appellation: arithmetic - Contrib: FL03 -*/ -use std::ops; - -pub trait Addition: ops::Add + ops::AddAssign + Sized {} - -impl Addition for T where T: ops::Add + ops::AddAssign + Sized {} - -pub trait Division: ops::Div + ops::DivAssign + Sized {} - -impl Division for T where T: ops::Div + ops::DivAssign + Sized {} - -pub trait Multiplication: ops::Mul + ops::MulAssign + Sized {} - -impl Multiplication for T where T: ops::Mul + ops::MulAssign + Sized {} - -pub trait Subtraction: ops::Sub + ops::SubAssign + Sized {} - -impl Subtraction for T where T: ops::Sub + ops::SubAssign + Sized {} diff --git a/math/math/src/num/complex.rs b/math/math/src/num/complex.rs deleted file mode 100644 index 8c0ee0a..0000000 --- a/math/math/src/num/complex.rs +++ /dev/null @@ -1,167 +0,0 @@ -/* - Appellation: complex - Contrib: FL03 -*/ -use super::Numerical; -use serde::{Deserialize, Serialize}; -use std::ops; - -// Define a trait for complex numbers. -pub trait Complex { - fn new(re: T, im: T) -> Self; - fn re(&self) -> T; - fn im(&self) -> T; -} - -// Implement the Complex trait for the tuple (f64, f64). -impl Complex for (T, T) { - fn new(re: T, im: T) -> Self { - (re, im) - } - - fn re(&self) -> T { - self.0 - } - - fn im(&self) -> T { - self.1 - } -} - -impl Complex for [T; 2] { - fn new(re: T, im: T) -> Self { - [re, im] - } - - fn re(&self) -> T { - self[0] - } - - fn im(&self) -> T { - self[1] - } -} - -#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)] -pub struct C(T, T); - -impl Complex for C { - fn new(re: T, im: T) -> Self { - Self(re, im) - } - fn re(&self) -> T { - self.0 - } - fn im(&self) -> T { - self.1 - } -} - -impl From<(T, T)> for C { - fn from(data: (T, T)) -> Self { - Self::new(data.0, data.1) - } -} - -impl From> for (T, T) { - fn from(data: C) -> (T, T) { - (data.re(), data.im()) - } -} - -// Implement the Add and Mul traits for complex numbers. -impl ops::Add for C { - type Output = Self; - - fn add(self, other: Self) -> Self { - Self::from((self.re() + other.re(), self.im() + other.im())) - } -} - -impl ops::AddAssign for C -where - T: Numerical + ops::AddAssign, -{ - fn add_assign(&mut self, other: Self) { - self.0 += other.0; - self.1 += other.1; - } -} - -impl ops::Div for C { - type Output = Self; - - fn div(self, other: Self) -> Self { - let denom = other.re() * other.re() + other.im() * other.im(); - Self::from(( - (self.re() * other.re() + self.im() * other.im()) / denom, - (self.im() * other.re() - self.re() * other.im()) / denom, - )) - } -} - -impl ops::DivAssign for C { - fn div_assign(&mut self, other: Self) { - let denom = other.re() * other.re() + other.im() * other.im(); - let re = (self.re() * other.re() + self.im() * other.im()) / denom; - let im = (self.im() * other.re() - self.re() * other.im()) / denom; - self.0 = re; - self.1 = im; - } -} - -impl ops::Mul for C { - type Output = Self; - - fn mul(self, other: Self) -> Self { - Self::from(( - self.re() * other.re() - self.im() * other.im(), - self.re() * other.im() + self.im() * other.re(), - )) - } -} - -impl ops::MulAssign for C { - fn mul_assign(&mut self, other: Self) { - let re = self.re() * other.re() - self.im() * other.im(); - let im = self.re() * other.im() + self.im() * other.re(); - self.0 = re; - self.1 = im; - } -} - -impl ops::Sub for C { - type Output = Self; - - fn sub(self, other: Self) -> Self { - Self::from((self.re() - other.re(), self.im() - other.im())) - } -} - -impl ops::SubAssign for C -where - T: Numerical + ops::SubAssign, -{ - fn sub_assign(&mut self, other: Self) { - self.0 -= other.0; - self.1 -= other.1; - } -} - -#[cfg(test)] -mod tests { - use super::*; - // Define a holomorphic function that squares its input. - fn square(z: C) -> C { - z.clone() * z - } - - #[test] - fn test_square() { - // Create a complex number (1 + i) and square it. - let mut a = C::from((1.0, 1.0)); - a = square(a.clone()); - let b = C::new(0.0, 2.0); - assert_eq!(&a, &b); - } -} diff --git a/math/math/src/num/mod.rs b/math/math/src/num/mod.rs deleted file mode 100644 index e220f63..0000000 --- a/math/math/src/num/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* - Appellation: num - Contrib: FL03 -*/ -pub use self::{arithmetic::*, utils::*}; - -pub(crate) mod arithmetic; - -pub mod complex; - -use std::ops::{self, Div, Mul, Sub}; - -pub trait Binary: num::One + num::Zero {} - -impl Binary for T where T: num::One + num::Zero {} - -pub trait Arithmetic: - ops::Add + Div + Mul + Sub + Sized -{ -} - -impl Arithmetic for T where - T: ops::Add - + Div - + Mul - + Sub - + Sized -{ -} - -/// [Numerical] is a basic trait describing numerical objects -pub trait Numerical: Arithmetic + Copy + PartialEq {} - -impl Numerical for T where T: Arithmetic + Copy + PartialEq {} - -pub(crate) mod utils {} diff --git a/math/math/src/primitives.rs b/math/math/src/primitives.rs deleted file mode 100644 index f16ac25..0000000 --- a/math/math/src/primitives.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* - Appellation: primitives - Contrib: FL03 -*/ -pub use self::{constants::*, statics::*, types::*}; - -/// Collection of constants used throughout the system -mod constants {} - -/// Collection of static references used throughout -mod statics {} - -/// Collection of types used throughout the system -mod types {} diff --git a/math/math/src/specs.rs b/math/math/src/specs.rs deleted file mode 100644 index 31f7762..0000000 --- a/math/math/src/specs.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* - Appellation: specs - Contrib: FL03 -*/ - -pub trait RoundTo { - fn round_to(&self, decimals: usize) -> Self; -} - -impl RoundTo for T -where - T: num::Float, -{ - fn round_to(&self, decimals: usize) -> Self { - let val = T::from(self.clone()).expect("Failed to convert to type T"); - let factor = T::from(10).expect("").powi(decimals as i32); - (val * factor).round() / factor - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_round_to() { - let num = 1.23456789_f64; - assert_eq!(num.round_to(2), 1.23_f64); - assert_eq!(num.round_to(3), 1.235_f64); - } -} diff --git a/math/math/src/utils.rs b/math/math/src/utils.rs deleted file mode 100644 index e880e12..0000000 --- a/math/math/src/utils.rs +++ /dev/null @@ -1,9 +0,0 @@ -/* - Appellation: utils - Contrib: FL03 -*/ - -pub fn round(num: T, decimals: usize) -> T { - let factor = T::from(10.0).expect("").powi(decimals as i32); - (num * factor).round() / factor -} diff --git a/math/math/tests/default.rs b/math/math/tests/default.rs deleted file mode 100644 index 0cac1eb..0000000 --- a/math/math/tests/default.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -#[test] -fn compiles() { - let f = |x: usize, y: usize| x + y; - - assert_eq!(f(10, 10), 20); - assert_ne!(f(1, 1), 3); -} diff --git a/math/statistics/Cargo.toml b/math/statistics/Cargo.toml deleted file mode 100644 index e1f6256..0000000 --- a/math/statistics/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -authors.workspace = true -categories.workspace = true -description.workspace = true -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "algae-statistics" -readme.workspace = true -repository.workspace = true -version.workspace = true - -[features] -default = [] - -[lib] -bench = true -crate-type = ["cdylib", "rlib"] -doctest = false -test = true - -[build-dependencies] - -[dependencies] -ndarray.workspace = true -num.workspace = true -serde.workspace = true -serde_json.workspace = true -smart-default.workspace = true -strum.workspace = true - -[dev-dependencies] -rand = "0.8" - -[package.metadata.docs.rs] -all-features = true -rustc-args = ["--cfg", "docsrs"] - -[target.wasm32-unknown-unknown] - -[target.wasm32-wasi] \ No newline at end of file diff --git a/math/statistics/src/calc/deviation.rs b/math/statistics/src/calc/deviation.rs deleted file mode 100644 index a38fb9f..0000000 --- a/math/statistics/src/calc/deviation.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* - Appellation: deviation - Contrib: FL03 -*/ -use super::utils::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)] -pub struct StandardDeviation { - pub deviation: f64, - pub mean: f64, - pub variance: f64, -} - -impl StandardDeviation { - pub fn new(x: &[f64]) -> StandardDeviation { - let mean = mean(x); - let variance = x.iter().map(|&x| x * x).sum::() / x.len() as f64 - mean * mean; - let deviation = variance.sqrt(); - StandardDeviation { - deviation, - mean, - variance, - } - } - - pub fn compute(&mut self, x: &[f64]) -> f64 { - let mean = x.iter().sum::() / x.len() as f64; - let variance = x.iter().map(|&x| x * x).sum::() / x.len() as f64 - mean * mean; - let deviation = variance.sqrt(); - self.deviation = deviation; - self.mean = mean; - self.variance = variance; - deviation - } - - pub fn deviation(&self) -> f64 { - self.deviation - } - - pub fn mean(&self) -> f64 { - self.mean - } - - pub fn variance(&self) -> f64 { - self.variance - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use crate::prelude::{RoundTo, Statistics}; - - #[test] - fn test_std() { - let x = vec![1.0, 2.0, 4.0, 9.0, 3.0, 4.0, 5.0]; - let sd = StandardDeviation::new(&x); - - assert_eq!(x.std().round_to(5), sd.deviation().round_to(5)); - } -} diff --git a/math/statistics/src/calc/mod.rs b/math/statistics/src/calc/mod.rs deleted file mode 100644 index 657fb65..0000000 --- a/math/statistics/src/calc/mod.rs +++ /dev/null @@ -1,86 +0,0 @@ -/* - Appellation: statistics - Contrib: FL03 -*/ -//! # statistics -pub use self::{deviation::*, utils::*}; - - -pub(crate) mod deviation; - - -pub(crate) mod utils { - use std::iter::Sum; - - /// Covariance is the average of the products of the deviations from the mean. - pub fn covariance(x: &[T], y: &[T]) -> T { - let dx = deviation(&x); - let dy = deviation(&y); - dx.iter().zip(dy.iter()).map(|(&x, &y)| x * y).sum::() / T::from(dx.len()).unwrap() - } - /// Deviation is the distance from the mean. - pub fn deviation(x: &[T]) -> Vec { - let mean = mean(x); - x.iter().map(|&x| x - mean).collect() - } - /// Mean is the average of the data. - pub fn mean(x: &[T]) -> T { - x.iter().cloned().sum::() / T::from(x.len()).unwrap() - } - /// Variance is the average of the squared deviations from the mean. - pub fn variance(x: &[T]) -> T { - let dev = deviation(&x); - dev.iter().map(|&x| x * x).sum::() / T::from(dev.len()).unwrap() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rand::Rng; - - fn random_vec() -> Vec { - let mut rng = rand::thread_rng(); - let mut v = Vec::new(); - for _ in 0..100 { - v.push(rng.gen_range(0.0..25.0)); - } - v - } - - #[test] - fn test_statistics() { - let x = random_vec(); - let y = random_vec(); - assert_eq!(covariance(&x, &y), x.covariance(&y)); - assert_eq!(deviation(&x), x.deviation()); - assert_eq!(mean(&x), x.mean()); - assert_eq!(variance(&x), x.variance()); - } - - #[test] - fn test_covariance() { - let x: Vec = (1..=5).map(|i| i as f64).collect(); - let y = vec![1.0, 2.0, 3.0, 4.0, 5.0]; - assert_eq!(covariance(&x, &y), 2.0); - assert_eq!(x.covariance(&y), 2.0); - } - - #[test] - fn test_deviation() { - let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; - assert_eq!(deviation(&x), vec![-2.0, -1.0, 0.0, 1.0, 2.0]); - } - - #[test] - fn test_mean() { - let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; - assert_eq!(mean(&x), 3.0); - } - - #[test] - fn test_variance() { - let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; - assert_eq!(variance(&x), 2.0); - } -} diff --git a/math/statistics/src/lib.rs b/math/statistics/src/lib.rs deleted file mode 100644 index 7309cca..0000000 --- a/math/statistics/src/lib.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* - Appellation: concision-statistics - Contrib: FL03 -*/ -//! # concision-statistics - -pub use self::{primitives::*, specs::*, utils::*}; - -pub mod calc; -pub mod regression; - -// pub(crate) use concision_core as core; - -pub(crate) mod primitives; -pub(crate) mod specs; -pub(crate) mod utils; - -pub mod prelude { - pub use crate::calc::*; - pub use crate::regression::*; - - pub use crate::primitives::*; - pub use crate::specs::*; - pub use crate::utils::*; -} diff --git a/math/statistics/src/primitives.rs b/math/statistics/src/primitives.rs deleted file mode 100644 index f16ac25..0000000 --- a/math/statistics/src/primitives.rs +++ /dev/null @@ -1,14 +0,0 @@ -/* - Appellation: primitives - Contrib: FL03 -*/ -pub use self::{constants::*, statics::*, types::*}; - -/// Collection of constants used throughout the system -mod constants {} - -/// Collection of static references used throughout -mod statics {} - -/// Collection of types used throughout the system -mod types {} diff --git a/math/statistics/src/regression/linear.rs b/math/statistics/src/regression/linear.rs deleted file mode 100644 index 10c0612..0000000 --- a/math/statistics/src/regression/linear.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* - Appellation: linear - Contrib: FL03 -*/ -use super::Regression; -use crate::calc::{covariance, deviation, mean, variance}; - -#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)] -pub struct LinearRegression { - intercept: f64, - slope: f64, -} - -impl LinearRegression { - pub fn new(x: &[f64], y: &[f64]) -> LinearRegression { - let (x_mean, y_mean) = (mean(x), mean(y)); - let (x_dev, y_dev) = (deviation(x), deviation(y)); - let slope = covariance(&x_dev, &y_dev) / variance(&x_dev); - let intercept = y_mean - slope * x_mean; - LinearRegression { intercept, slope } - } - - pub fn intercept(&self) -> f64 { - self.intercept - } - - pub fn predict(&self, x: &[f64]) -> Vec { - x.iter().map(|&x| self.slope * x + self.intercept).collect() - } - - pub fn slope(&self) -> f64 { - self.slope - } -} - -impl Regression for LinearRegression { - type Item = f64; - - fn fit(&mut self, args: &[Self::Item], target: &[Self::Item]) { - let (x_mean, y_mean) = (mean(args), mean(target)); - let (x_dev, y_dev) = (deviation(args), deviation(target)); - self.slope = covariance(&x_dev, &y_dev) / variance(&x_dev); - self.intercept = y_mean - self.slope * x_mean; - } - - fn predict(&self, args: &[Self::Item]) -> Vec { - args.iter() - .map(|&x| self.slope * x + self.intercept) - .collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_linear_regression() { - let x = vec![1.0, 2.0, 3.0, 4.0, 5.0]; - let y = vec![1.0, 2.0, 3.0, 4.0, 5.0]; - let lr = LinearRegression::new(&x, &y); - assert_eq!(lr.slope, 1.0); - assert_eq!(lr.intercept, 0.0); - assert_eq!(lr.predict(&x), y); - } -} diff --git a/math/statistics/src/regression/mod.rs b/math/statistics/src/regression/mod.rs deleted file mode 100644 index 9566f19..0000000 --- a/math/statistics/src/regression/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Appellation: regression - Contrib: FL03 -*/ -//! # regression -//! -pub use self::utils::*; - -pub mod linear; - -pub trait Regression { - type Item: num::Float; - - fn fit(&mut self, args: &[Self::Item], target: &[Self::Item]); - - fn predict(&self, args: &[Self::Item]) -> Vec; -} - -pub(crate) mod utils {} diff --git a/math/statistics/src/specs.rs b/math/statistics/src/specs.rs deleted file mode 100644 index ee0259a..0000000 --- a/math/statistics/src/specs.rs +++ /dev/null @@ -1,51 +0,0 @@ -/* - Appellation: specs - Contrib: FL03 -*/ - - -pub trait Statistics -where - T: num::Float + std::iter::Sum, - Self: Clone + IntoIterator, -{ - fn covariance(&self, other: &Self) -> T { - let dx = self.deviation(); - let dy = other.deviation(); - dx.iter().zip(dy.iter()).map(|(&x, &y)| x * y).sum::() / T::from(dx.len()).unwrap() - } - - fn deviation(&self) -> Vec { - let mean = self.mean(); - self.clone().into_iter().map(|x| x - mean).collect() - } - fn len(&self) -> usize { - Vec::from_iter(self.clone().into_iter()).len() - } - /// [Statistics::mean] calculates the mean or average of the data - fn mean(&self) -> T { - self.clone().into_iter().sum::() / T::from(self.len()).unwrap() - } - /// [Statistics::std] calculates the standard deviation of the data - fn std(&self) -> T { - let mean = self.mean(); - let mut res = self - .clone() - .into_iter() - .map(|x| (x - mean).powi(2)) - .sum::(); - res = res / T::from(self.len()).unwrap(); - res.sqrt() - } - - fn variance(&self) -> T { - let dev = self.deviation(); - dev.iter().map(|&x| x * x).sum::() / T::from(dev.len()).unwrap() - } -} - -impl Statistics for Vec where T: num::Float + std::iter::Sum {} - -impl Statistics for ndarray::Array1 where T: num::Float + std::iter::Sum {} - - diff --git a/math/statistics/src/utils.rs b/math/statistics/src/utils.rs deleted file mode 100644 index f8840c6..0000000 --- a/math/statistics/src/utils.rs +++ /dev/null @@ -1,4 +0,0 @@ -/* - Appellation: utils - Contrib: FL03 -*/ diff --git a/math/statistics/tests/default.rs b/math/statistics/tests/default.rs deleted file mode 100644 index 0cac1eb..0000000 --- a/math/statistics/tests/default.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[cfg(test)] -#[test] -fn compiles() { - let f = |x: usize, y: usize| x + y; - - assert_eq!(f(10, 10), 20); - assert_ne!(f(1, 1), 3); -} From 7bbde2cf073b680633c0dbac87b0a5811a278d6f Mon Sep 17 00:00:00 2001 From: Joe McCain III Date: Sat, 16 Mar 2024 08:10:08 -0500 Subject: [PATCH 15/15] update Signed-off-by: Joe McCain III --- .artifacts/license/APACHE.LICENSE | 4 +- .artifacts/license/MIT.LICENSE | 2 +- .github/dependabot.yml | 8 +++ .github/workflows/clippy.yml | 30 +++++---- .github/workflows/{publish.yml => crates.yml} | 21 ++++-- .github/workflows/rust.yml | 52 +++++++-------- .gitignore | 64 ++++++++++++++----- Cargo.toml | 16 ++--- LICENSE | 2 +- README.md | 13 ++-- SECURITY.md | 3 +- algae/Cargo.toml | 38 ++++++++--- algae/examples/graph.rs | 9 +++ algae/src/lib.rs | 8 ++- algae/tests/default.rs | 17 ++++- core/Cargo.toml | 39 +++++++++++ core/src/lib.rs | 9 +++ core/tests/default.rs | 17 +++++ graph/Cargo.toml | 14 +++- graph/benches/graphs.rs | 2 +- graph/src/cmp/edge.rs | 7 +- graph/src/cmp/entry.rs | 41 ++++++++++++ graph/src/cmp/mod.rs | 33 ++++++++-- graph/src/cmp/neighbors.rs | 5 -- graph/src/cmp/pair.rs | 5 +- graph/src/directed.rs | 6 +- graph/src/errors.rs | 16 +++-- graph/src/graph/mod.rs | 17 +++-- graph/src/lib.rs | 13 +++- graph/src/search/bfs.rs | 6 +- graph/src/store/matrix.rs | 24 +++++-- graph/src/store/mod.rs | 37 +---------- graph/src/store/table.rs | 5 +- graph/src/undirected.rs | 5 +- graph/tests/default.rs | 17 ++++- merkle/Cargo.toml | 19 ++++-- merkle/src/layers.rs | 4 +- merkle/src/nodes.rs | 13 ++-- merkle/src/payloads.rs | 6 +- merkle/src/proofs/mod.rs | 5 +- merkle/src/shape.rs | 6 +- merkle/src/tree/builder.rs | 15 +++++ merkle/src/tree/merkle.rs | 4 +- merkle/tests/default.rs | 17 ++++- mmr/Cargo.toml | 6 +- mmr/src/cmp/nodes.rs | 3 - mmr/src/mmr.rs | 2 - mmr/tests/default.rs | 17 ++++- queue/Cargo.toml | 39 +++++++++++ queue/src/lib.rs | 9 +++ queue/tests/default.rs | 17 +++++ 51 files changed, 571 insertions(+), 216 deletions(-) rename .github/workflows/{publish.yml => crates.yml} (67%) create mode 100644 algae/examples/graph.rs create mode 100644 core/Cargo.toml create mode 100644 core/src/lib.rs create mode 100644 core/tests/default.rs create mode 100644 graph/src/cmp/entry.rs delete mode 100644 graph/src/cmp/neighbors.rs create mode 100644 queue/Cargo.toml create mode 100644 queue/src/lib.rs create mode 100644 queue/tests/default.rs diff --git a/.artifacts/license/APACHE.LICENSE b/.artifacts/license/APACHE.LICENSE index b9f3f83..622e1d9 100644 --- a/.artifacts/license/APACHE.LICENSE +++ b/.artifacts/license/APACHE.LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2023 Scattered-Systems, DAO LLC + Copyright 2024 Scattered-Systems, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/.artifacts/license/MIT.LICENSE b/.artifacts/license/MIT.LICENSE index a72851f..2e7ec0f 100644 --- a/.artifacts/license/MIT.LICENSE +++ b/.artifacts/license/MIT.LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2023 Scattered-Systems, DAO LLC +Copyright (c) 2024 Scattered-Systems, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8ad703f..bd930de 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,6 +12,10 @@ updates: directory: /algae schedule: interval: daily + - package-ecosystem: cargo + directory: /core + schedule: + interval: daily - package-ecosystem: cargo directory: /graph schedule: @@ -24,3 +28,7 @@ updates: directory: /mmr schedule: interval: daily + - package-ecosystem: cargo + directory: /queue + schedule: + interval: daily diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index b455041..50eadf4 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -1,25 +1,28 @@ name: Clippy +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + on: - pull_request: - branches-ignore: ["beta*", "dev*", "next*"] push: - branches-ignore: ["beta*", "dev*", "next*"] - tags: ["nightly*", "v*.*.*"] + branches: [ main ] + tags: [ nightly*, v*.*.*] release: + repository_dispatch: + types: [ clippy ] schedule: - - cron: "30 21 * * *" # 9:30pm UTC + - cron: 30 21 * * 0 # Every Sunday at 9:30PM UTC workflow_dispatch: permissions: actions: read contents: read security-events: write - + jobs: clippy: name: Clippy - runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -30,15 +33,16 @@ jobs: toolchain: stable components: clippy override: true - - name: Setup + - name: Setup (langspace) run: cargo install clippy-sarif sarif-fmt - - name: clippy - run: cargo clippy + - name: Analyze + run: + cargo clippy --all-features --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt continue-on-error: true - - name: Upload analysis results to GitHub - uses: github/codeql-action/upload-sarif@v2 + - name: Upload results + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: rust-clippy-results.sarif - wait-for-processing: true + wait-for-processing: true \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/crates.yml similarity index 67% rename from .github/workflows/publish.yml rename to .github/workflows/crates.yml index f77f277..e15f13d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/crates.yml @@ -6,7 +6,6 @@ concurrency: env: CARGO_TERM_COLOR: always - CRATE_BASENAME: ${{ github.event.repository.name }} on: release: @@ -19,19 +18,27 @@ on: required: true type: boolean -permissions: - contents: read - packages: write - pull-requests: write - statuses: write +permissions: write-all jobs: + base: + name: Publish (core) + runs-on: ubuntu-latest + strategy: + matrix: + feature: [ core ] + env: + PACKAGE_NAME: ${{ github.event.repository.name }}-${{ matrix.feature }} + steps: + - uses: actions/checkout@v4 + - name: Publish (${{env.PACKAGE_NAME}}) + run: cargo publish --all-features -v -p ${{ env.PACKAGE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }} features: name: Publish (features) runs-on: ubuntu-latest strategy: matrix: - feature: [ graph, merkle, mmr ] + feature: [ graph, merkle, mmr, queue ] env: PACKAGE_NAME: ${{ github.event.repository.name }}-${{ matrix.feature }} steps: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0a0806d..041d759 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,23 +8,22 @@ env: CARGO_TERM_COLOR: always on: - pull_request: - branches: [ "main", "v*.*.*" ] push: - branches: [ "main" ] - tags: [ "nightly*", "v*.*.*" ] + branches: [ main ] + tags: [ nightly*, v*.*.*] release: + types: [ created ] repository_dispatch: types: [ rust ] schedule: - - cron: "30 21 * * *" # 9:30pm UTC + - cron: 30 21 * * 0 # Every Sunday at 9:30PM UTC workflow_dispatch: permissions: write-all jobs: build: - name: Build and Test + name: Build strategy: matrix: platform: [ ubuntu-latest ] @@ -41,7 +40,6 @@ jobs: if: matrix.toolchain == 'nightly' run: rustup target add ${{ matrix.target }} - name: Build - run: cargo build -r -v --workspace - name: Cache build uses: actions/cache@v3 @@ -51,38 +49,32 @@ jobs: ~/.cargo/registry ~/.cargo/git target/release - - name: Test - run: cargo test --all-features -r -v --workspace - - name: Bench - if: matrix.toolchain == 'nightly' - run: cargo bench --all -v - nightly: - name: Nightly + test: + name: Test + needs: build strategy: matrix: platform: [ ubuntu-latest ] target: [ wasm32-unknown-unknown, wasm32-wasi ] + toolchain: [ stable, nightly ] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 - name: setup (langspace) run: | - rustup toolchain install nightly - rustup default nightly rustup update - - name: Set target (${{ matrix.target }}) - run: rustup target add ${{ matrix.target }} - - name: Build - run: cargo build -r -v --workspace --target ${{ matrix.target }} - - name: Cache build - uses: actions/cache@v3 - with: - key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} - path: | - ~/.cargo/registry - ~/.cargo/git - target/release + rustup default ${{ matrix.toolchain }} - name: Test - run: cargo test --all-features -r -v --workspace --target ${{ matrix.target }} + run: cargo test --all-features -r -v --workspace + benchmark: + name: Bench + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: setup (langspace) + run: | + rustup update + rustup default nightly - name: Bench - run: cargo bench --all -v --target ${{ matrix.target }} \ No newline at end of file + run: cargo bench --features full -v --workspace diff --git a/.gitignore b/.gitignore index f77dcea..e21ff3b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,20 @@ +# Artifacts + +### Cache +**/.artifacts/cache/ +**/.docker/cache/ + +### Data +**/.artifacts/data/ +**/.docker/data/ + +### Logs +**/.artifacts/logs/ +**/.docker/logs/ + +*.log +*.log.* + # Config **/config.* **/*.config.* @@ -5,27 +22,46 @@ **/*.env **/*.env.* -# Directories -**/__pycache__/ -**/__sapper__/ +### Exceptions +!**/default.config.* +!**/*.env.example +!**/*.config.js +!**/*.config.cjs -**/.DS_STORE/ -**/.artifacts/data/ -**/.docker/data/ +# Development + +### IDEs +**/.atom/ **/.idea/ -**/.pytest_cache/ -**/.svelte-kit/ **/.vscode/ +# Languages + +### Node **/build/ **/debug/ **/dist/ **/env/ **/node_modules/ -**/target/ + +### Python +**/__pycache__/ **/venv/ -# File Extensions +*.pyc +*.pyo + +### Rust +**/target/ + +**/Cargo.lock + +*.bk +*.bk.* + +# Misc + +### File Extensions **/*.bk **/*.bk.* @@ -49,10 +85,4 @@ **/*.whl.* **/*.zip -**/*.zip.* - -# Exceptions -!**/default.config.* -!**/*.env.example -!**/*.config.js -!**/*.config.cjs +**/*.zip.* \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 82e2017..d0afdca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,15 +11,13 @@ repository = "https://github.com/scattered-systems/algae" version = "0.1.20" [workspace.dependencies] -decanter = { features = ["derive"], version = "0.1.6" } + # decanter = { features = ["derive"], git = "https://github.com/FL03/decanter", branch = "v0.1.7", version = "0.1.7" } anyhow = "1" -itertools = "0.11" -serde = { features = ["derive"], version = "1" } -serde_json = "1" +itertools = "0.12" smart-default = "0.7" -strum = { features = ["derive"], version = "0.25" } +strum = { features = ["derive"], version = "0.26" } [workspace] default-members = [ @@ -27,10 +25,12 @@ default-members = [ ] members = [ - "algae", + "algae", + "core", "graph", "merkle", - "mmr", + "mmr", + "queue", ] resolver = "2" @@ -53,4 +53,4 @@ incremental = false lto = false panic = "unwind" rpath = false -opt-level = "z" \ No newline at end of file +opt-level = "z" diff --git a/LICENSE b/LICENSE index f25b2b1..622e1d9 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2023 Joe McCain III + Copyright 2024 Scattered-Systems, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 1d0f81a..3be349a 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,21 @@ Welcome to algae, a collection of optimized data-structures and algorithms intended for use within blockchain environments. -## Developers +## Getting Started -### Getting Started +### Build from the source +#### _Clone the repository_ + +```bash git clone https://github.com/FL03/algae +``` -#### Testing +#### _Build the project_ +```bash cargo build --release - cargo test --all-features --release +``` ## Contributors diff --git a/SECURITY.md b/SECURITY.md index 0f79aff..862d741 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,9 +6,10 @@ Checkout the current and supported packages below | Package | Current | Supported | |---------|---------|-----------| -| algae | 0.1.9 | <=0.1.9 | +| algae | 0.1.12 | <=0.1.12 | ## Reporting a Vulnerability + Email me at j3mccain@gmail.com to report any vulnerabilities. [Website](https://pzzld.eth.link/) \ No newline at end of file diff --git a/algae/Cargo.toml b/algae/Cargo.toml index 8e53a4f..92545c5 100644 --- a/algae/Cargo.toml +++ b/algae/Cargo.toml @@ -13,45 +13,63 @@ version.workspace = true [features] default = [ - "core", "ds", ] + full = [ - "core", "ds", + "serde", ] -core = [] ds = [ "graph", "merkle", "mmr", + "queue", ] graph = [ - "algae-graph" + "dep:algae-graph" ] merkle = [ - "algae-merkle" + "dep:algae-merkle" ] mmr = [ - "algae-mmr" + "dep:algae-mmr" +] + +queue = [ + "dep:algae-queue" ] wasm = [] +serde = [ + "algae-core/serde", + "algae-graph/serde", + "algae-merkle/serde", + "algae-queue/serde", +] + [lib] bench = false crate-type = ["cdylib", "rlib"] +doctest = true test = true +[[example]] +name = "graph" +required-features = ["graph"] + + [build-dependencies] [dependencies] - -algae-graph = { features = [], optional = true, path = "../graph", version = "0.1.20" } -algae-merkle = { features = [], optional = true, path = "../merkle", version = "0.1.20" } -algae-mmr = { features = [], optional = true, path = "../mmr", version = "0.1.20" } +algae-core = { path = "../core", version = "0.1.20" } +algae-graph = { optional = true, path = "../graph", version = "0.1.20" } +algae-merkle = { optional = true, path = "../merkle", version = "0.1.20" } +algae-mmr = { optional = true, path = "../mmr", version = "0.1.20" } +algae-queue = { optional = true, path = "../queue", version = "0.1.20" } [dev-dependencies] diff --git a/algae/examples/graph.rs b/algae/examples/graph.rs new file mode 100644 index 0000000..f7edd25 --- /dev/null +++ b/algae/examples/graph.rs @@ -0,0 +1,9 @@ +/* + Appellation: graph + Contrib: FL03 +*/ +extern crate algae; + +fn main() { + println!("Hello, world!"); +} diff --git a/algae/src/lib.rs b/algae/src/lib.rs index 91b744f..058a771 100644 --- a/algae/src/lib.rs +++ b/algae/src/lib.rs @@ -11,18 +11,22 @@ pub use algae_graph as graph; pub use algae_merkle as merkle; #[cfg(feature = "mmr")] pub use algae_mmr as mmr; +#[cfg(feature = "queue")] +pub use algae_queue as queue; +pub use algae_core as core; pub mod list; pub mod prelude { + pub use crate::core::prelude::*; #[cfg(feature = "graph")] pub use algae_graph::graph; - // pub use super::graph::*; #[cfg(feature = "merkle")] pub use algae_merkle::prelude::*; #[cfg(feature = "mmr")] pub use algae_mmr::*; + #[cfg(feature = "queue")] + pub use algae_queue::prelude::*; pub use crate::list::*; - } diff --git a/algae/tests/default.rs b/algae/tests/default.rs index 7dee5fa..5f26546 100644 --- a/algae/tests/default.rs +++ b/algae/tests/default.rs @@ -1,6 +1,17 @@ +/* + Appellation: default + Contrib: FL03 +*/ #[cfg(test)] + +fn addition(a: A, b: B) -> C +where + A: std::ops::Add, +{ + a + b +} + #[test] -fn lib_compiles() { - let f = |i| i + 1; - assert_eq!(f(10), 11) +fn compiles() { + assert_eq!(addition(10, 1), 11) } diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 0000000..3fd4559 --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,39 @@ +[package] +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "algae-core" +readme.workspace = true +repository.workspace = true +version.workspace = true + +[features] +default = [] + +serde = [ + "dep:serde", + "serde-ext" +] + +serde-ext = [ + "dep:serde_json" +] + +[dependencies] +serde = { optional = true, features = ["derive"], version = "1" } +serde_json = { optional = true, version = "1" } + + +[dev-dependencies] + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] + +[target.wasm32-unknown-unknown] + +[target.wasm32-wasi] diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100644 index 0000000..2b603db --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,9 @@ +/* + Appellation: algae-core + Contrib: FL03 +*/ +//! # Algae Core +//! +//! Algae is a comprehensive collection of algorithms and data-structures written in Rust. + +pub mod prelude {} diff --git a/core/tests/default.rs b/core/tests/default.rs new file mode 100644 index 0000000..5f26546 --- /dev/null +++ b/core/tests/default.rs @@ -0,0 +1,17 @@ +/* + Appellation: default + Contrib: FL03 +*/ +#[cfg(test)] + +fn addition(a: A, b: B) -> C +where + A: std::ops::Add, +{ + a + b +} + +#[test] +fn compiles() { + assert_eq!(addition(10, 1), 11) +} diff --git a/graph/Cargo.toml b/graph/Cargo.toml index c815236..b7bf5b0 100644 --- a/graph/Cargo.toml +++ b/graph/Cargo.toml @@ -16,6 +16,15 @@ default = [] wasm = [] +serde = [ + "dep:serde", + "serde-ext" +] + +serde-ext = [ + "dep:serde_json" +] + [lib] bench = true crate-type = ["cdylib", "rlib"] @@ -25,10 +34,9 @@ test = true [build-dependencies] [dependencies] -decanter.workspace = true itertools.workspace = true -serde.workspace = true -serde_json.workspace = true +serde = { optional = true, features = ["derive"], version = "1" } +serde_json = { optional = true, version = "1" } smart-default.workspace = true strum.workspace = true diff --git a/graph/benches/graphs.rs b/graph/benches/graphs.rs index 0c60edc..e788538 100644 --- a/graph/benches/graphs.rs +++ b/graph/benches/graphs.rs @@ -2,7 +2,7 @@ #![feature(test)] extern crate test; -use algae_graph::{DirectedGraph, Edge, Graph}; +use algae_graph::prelude::{DirectedGraph, Edge, Graph}; use test::Bencher; const TEST_EDGES: [(&str, &str, usize); 5] = [ diff --git a/graph/src/cmp/edge.rs b/graph/src/cmp/edge.rs index 3d183bb..670d5db 100644 --- a/graph/src/cmp/edge.rs +++ b/graph/src/cmp/edge.rs @@ -3,13 +3,18 @@ Contrib: FL03 Description: an edge consists of two nodes and an optional edge value */ +//! # Edge +//! +//! use super::Pair; use crate::{Node, Weight}; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; pub trait Related {} -#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct Edge where N: Node, diff --git a/graph/src/cmp/entry.rs b/graph/src/cmp/entry.rs new file mode 100644 index 0000000..ae3b246 --- /dev/null +++ b/graph/src/cmp/entry.rs @@ -0,0 +1,41 @@ +/* + Appellation: entry + Contrib: FL03 +*/ +//! # Entry +//! +//! +use crate::prelude::Contain; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +pub struct Entry { + key: N, + value: Vec<(N, V)>, +} + +impl Entry { + pub fn new(key: N, value: Vec<(N, V)>) -> Self { + Self { key, value } + } + pub fn key(&self) -> &N { + &self.key + } + pub fn value(&self) -> &Vec<(N, V)> { + &self.value + } + pub fn value_mut(&mut self) -> &mut Vec<(N, V)> { + &mut self.value + } +} + +impl Contain for Entry +where + N: PartialEq, +{ + fn contains(&self, node: &N) -> bool { + self.value.iter().any(|(n, _)| n == node) + } +} diff --git a/graph/src/cmp/mod.rs b/graph/src/cmp/mod.rs index d00028c..67da408 100644 --- a/graph/src/cmp/mod.rs +++ b/graph/src/cmp/mod.rs @@ -3,8 +3,33 @@ Contrib: FL03 Description: components (cmp) for building effecient graph data-structures */ -pub use self::{edge::*, neighbors::*, pair::*}; +//! # Components (cmp) +//! +//! +pub use self::{edge::*, pair::*}; -mod edge; -mod neighbors; -mod pair; +pub(crate) mod edge; +pub(crate) mod pair; + +pub mod entry; + +pub(crate) mod prelude { + pub use super::edge::*; + pub use super::entry::*; + pub use super::pair::*; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_edge() { + let a = "a"; + let b = "b"; + let weight = 1; + let edge = Edge::new(a, b, weight); + assert_eq!(edge.pair(), Pair::new(a, b)); + assert_eq!(edge.value(), &weight); + } +} diff --git a/graph/src/cmp/neighbors.rs b/graph/src/cmp/neighbors.rs deleted file mode 100644 index d6269ca..0000000 --- a/graph/src/cmp/neighbors.rs +++ /dev/null @@ -1,5 +0,0 @@ -/* - Appellation: neighbors - Contrib: FL03 - Description: ... summary ... -*/ diff --git a/graph/src/cmp/pair.rs b/graph/src/cmp/pair.rs index cee78b1..4d3f013 100644 --- a/graph/src/cmp/pair.rs +++ b/graph/src/cmp/pair.rs @@ -3,10 +3,13 @@ Contrib: FL03 Description: a pair can either be scalar or vector; if vector, than direction matters */ +//! # Pair use crate::Node; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct Pair(pub T, pub T) where T: Node; diff --git a/graph/src/directed.rs b/graph/src/directed.rs index cec1076..57d2982 100644 --- a/graph/src/directed.rs +++ b/graph/src/directed.rs @@ -1,13 +1,14 @@ /* Appellation: directed Contrib: FL03 - Description: ... Summary ... */ use crate::{store::AdjacencyTable, Edge, Node, Weight}; use crate::{Contain, Graph, GraphExt, Subgraph}; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct DirectedGraph where N: Node, @@ -135,7 +136,6 @@ where #[cfg(test)] mod tests { use super::*; - use crate::cmp::Edge; const TEST_EDGES: [(&str, &str, usize); 3] = [("a", "b", 5), ("c", "a", 7), ("b", "c", 10)]; diff --git a/graph/src/errors.rs b/graph/src/errors.rs index 4519fe3..5fff8e2 100644 --- a/graph/src/errors.rs +++ b/graph/src/errors.rs @@ -1,29 +1,35 @@ /* Appellation: errors Contrib: FL03 - Description: ... Summary ... */ +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use smart_default::SmartDefault; -use strum::{Display, EnumString, EnumVariantNames}; +use strum::{Display, EnumCount, EnumIs, EnumIter, EnumString, VariantNames}; #[derive( Clone, Copy, Debug, - Deserialize, Display, + EnumCount, + EnumIs, + EnumIter, EnumString, - EnumVariantNames, Eq, Hash, Ord, PartialEq, PartialOrd, - Serialize, SmartDefault, + VariantNames, )] #[strum(serialize_all = "snake_case")] +#[cfg_attr( + feature = "serde", + derive(Deserialize, Serialize), + serde(rename_all = "snake_case") +)] pub enum GraphError { NodeInGraph, #[default] diff --git a/graph/src/graph/mod.rs b/graph/src/graph/mod.rs index 05d9b74..6a7235d 100644 --- a/graph/src/graph/mod.rs +++ b/graph/src/graph/mod.rs @@ -3,9 +3,10 @@ Contrib: FL03 Description: This module implements an abstract graph data structure */ -use crate::store::Entry; +use crate::cmp::entry::Entry; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use strum::{Display, EnumString, EnumVariantNames}; +use strum::{Display, EnumCount, EnumIs, EnumIter, EnumString, VariantNames}; pub trait GraphStore: Default { fn capacity(&self) -> usize; @@ -19,19 +20,25 @@ pub trait GraphStore: Default { Copy, Debug, Default, - Deserialize, Display, + EnumCount, + EnumIs, + EnumIter, EnumString, - EnumVariantNames, Eq, Hash, Ord, PartialEq, PartialOrd, - Serialize, + VariantNames, )] #[repr(u8)] #[strum(serialize_all = "snake_case")] +#[cfg_attr( + feature = "serde", + derive(Deserialize, Serialize), + serde(rename_all = "lowercase", untagged) +)] pub enum GraphType { Directed, #[default] diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 9daf0a3..5187815 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -5,19 +5,19 @@ /// # Graphs /// /// This library is dedicated to graphs, explicitly implementing generic directed and undirected data-structures while providing the tools to create new ones. -pub use self::{cmp::*, directed::*, errors::*, specs::*, undirected::*}; +pub use self::{directed::*, errors::*, specs::*, undirected::*}; -pub(crate) mod cmp; pub(crate) mod directed; mod errors; mod specs; pub(crate) mod undirected; +pub mod cmp; pub mod graph; pub mod search; pub mod store; -use errors::GraphError; +use cmp::Edge; use std::{collections::HashSet, ops::IndexMut}; use store::AdjacencyTable; @@ -208,3 +208,10 @@ where self.nodes().is_subset(&graph.nodes()) } } + +pub mod prelude { + pub use crate::cmp::prelude::*; + pub use crate::directed::*; + pub use crate::errors::*; + pub use crate::{Contain, Graph, Node, Subgraph, Weight}; +} diff --git a/graph/src/search/bfs.rs b/graph/src/search/bfs.rs index 717ad1e..e92a748 100644 --- a/graph/src/search/bfs.rs +++ b/graph/src/search/bfs.rs @@ -1,10 +1,9 @@ /* Appellation: bfs Contrib: FL03 - Description: ... Summary ... */ use super::Searcher; -use crate::{Contain, Graph, Node, Weight}; +use crate::prelude::{Contain, Graph, Node, Weight}; use std::collections::{HashSet, VecDeque}; #[derive(Clone, Debug, Default, Eq, PartialEq)] @@ -59,7 +58,8 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{DirectedGraph, Edge}; + use crate::cmp::Edge; + use crate::DirectedGraph; const TEST_EDGES: [(&str, &str, usize); 5] = [ ("a", "b", 5), diff --git a/graph/src/store/matrix.rs b/graph/src/store/matrix.rs index 74825c5..9b5a4f0 100644 --- a/graph/src/store/matrix.rs +++ b/graph/src/store/matrix.rs @@ -1,13 +1,15 @@ /* Appellation: atable Contrib: FL03 - Description: an adjacency table */ +//! # Adjacency Table use crate::Node; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use std::iter::Extend; +use std::ops::{Index, IndexMut}; -#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct AdjacencyMatrix where N: Node, @@ -76,7 +78,7 @@ impl Extend<(N, Vec<(N, V)>)> for AdjacencyMatrix } } -impl std::ops::Index for AdjacencyMatrix +impl Index for AdjacencyMatrix where N: Node, V: Clone + PartialEq, @@ -88,7 +90,19 @@ where } } -impl std::ops::IndexMut for AdjacencyMatrix +impl Index<&N> for AdjacencyMatrix +where + N: Node, + V: Clone + PartialEq, +{ + type Output = Vec<(N, V)>; + + fn index(&self, index: &N) -> &Self::Output { + self.get(index).unwrap() + } +} + +impl IndexMut for AdjacencyMatrix where N: Node, V: Clone + PartialEq, diff --git a/graph/src/store/mod.rs b/graph/src/store/mod.rs index c6f8148..7021c07 100644 --- a/graph/src/store/mod.rs +++ b/graph/src/store/mod.rs @@ -1,47 +1,16 @@ /* Appellation: store Contrib: FL03 - Description: */ +//! # Store pub use self::{matrix::*, table::*}; mod matrix; mod table; -use crate::{Contain, Edge, Node, Weight}; -use serde::{Deserialize, Serialize}; -use std::ops::IndexMut; - -#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -pub struct Entry { - key: N, - value: Vec<(N, V)>, -} - -impl Entry { - pub fn new(key: N, value: Vec<(N, V)>) -> Self { - Self { key, value } - } - pub fn key(&self) -> &N { - &self.key - } - pub fn value(&self) -> &Vec<(N, V)> { - &self.value - } - pub fn value_mut(&mut self) -> &mut Vec<(N, V)> { - &mut self.value - } -} +use crate::{Edge, Node, Weight}; -impl Contain<(N, V)> for Entry -where - N: PartialEq, - V: PartialEq, -{ - fn contains(&self, elem: &(N, V)) -> bool { - self.value.contains(elem) - } -} +use std::ops::IndexMut; pub trait Store: Extend> + IndexMut> where diff --git a/graph/src/store/table.rs b/graph/src/store/table.rs index ee67fd6..da26ada 100644 --- a/graph/src/store/table.rs +++ b/graph/src/store/table.rs @@ -3,11 +3,12 @@ Contrib: FL03 */ use crate::{Node, Weight}; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use std::collections::{hash_map, HashMap}; -use std::iter::Extend; -#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct AdjacencyTable where N: Node, diff --git a/graph/src/undirected.rs b/graph/src/undirected.rs index 5058d49..6e2c58e 100644 --- a/graph/src/undirected.rs +++ b/graph/src/undirected.rs @@ -5,10 +5,11 @@ */ use crate::{cmp::Edge, store::AdjacencyTable}; use crate::{Contain, Graph, GraphExt, Node, Subgraph, Weight}; - +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct UndirectedGraph where N: Node, diff --git a/graph/tests/default.rs b/graph/tests/default.rs index 7dee5fa..5f26546 100644 --- a/graph/tests/default.rs +++ b/graph/tests/default.rs @@ -1,6 +1,17 @@ +/* + Appellation: default + Contrib: FL03 +*/ #[cfg(test)] + +fn addition(a: A, b: B) -> C +where + A: std::ops::Add, +{ + a + b +} + #[test] -fn lib_compiles() { - let f = |i| i + 1; - assert_eq!(f(10), 11) +fn compiles() { + assert_eq!(addition(10, 1), 11) } diff --git a/merkle/Cargo.toml b/merkle/Cargo.toml index ccec5b8..bcf4c70 100644 --- a/merkle/Cargo.toml +++ b/merkle/Cargo.toml @@ -20,6 +20,15 @@ wasm = [ ] +serde = [ + "dep:serde", + "serde-ext" +] + +serde-ext = [ + "dep:serde_json" +] + [lib] bench = true crate-type = ["cdylib", "rlib"] @@ -28,11 +37,11 @@ test = true [dependencies] anyhow.workspace = true blake3 = { features = [], version = "1" } -decanter.workspace = true +decanter = { features = ["derive"], version = "0.1.6" } hex = "0.4" itertools.workspace = true -serde.workspace = true -serde_json.workspace = true +serde = { optional = true, features = ["derive"], version = "1" } +serde_json = { optional = true, version = "1" } smart-default.workspace = true strum.workspace = true @@ -47,6 +56,6 @@ vrf = "0.2" all-features = true rustc-args = ["--cfg", "docsrs"] -[target.wasm32-unknown-unknown.dependencies] +[target.wasm32-unknown-unknown] -[target.wasm32-wasi.dependencies.dependencies] +[target.wasm32-wasi] diff --git a/merkle/src/layers.rs b/merkle/src/layers.rs index b3d2778..75fe1dd 100644 --- a/merkle/src/layers.rs +++ b/merkle/src/layers.rs @@ -5,10 +5,12 @@ use crate::Node; use decanter::prelude::Hashable; use itertools::Itertools; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; // pub fn build_new_merkle_layer(left: MerkleNode, right: MerkleNode) -#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct Layer(Vec>) where T: Hashable; diff --git a/merkle/src/nodes.rs b/merkle/src/nodes.rs index edb5ec5..18568c4 100644 --- a/merkle/src/nodes.rs +++ b/merkle/src/nodes.rs @@ -4,10 +4,11 @@ */ use crate::{combine_hash_str, merkle_hash, Payload}; use decanter::prelude::{Hashable, H256}; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use std::string::ToString; -#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct Node where T: Hashable, @@ -47,13 +48,9 @@ where impl std::fmt::Display for Node where - T: Hashable, + T: Hashable + ToString, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let msg = serde_json::json!({ - "data": self.data.to_string(), - "hash": self.hash, - }); - write!(f, "{}", msg) + write!(f, "data: {}, hash: {}", self.data.to_string(), self.hash) } } diff --git a/merkle/src/payloads.rs b/merkle/src/payloads.rs index c3833ec..cfd8823 100644 --- a/merkle/src/payloads.rs +++ b/merkle/src/payloads.rs @@ -4,12 +4,12 @@ */ use crate::Node; use decanter::prelude::Hashable; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use strum::Display; -#[derive( - Clone, Debug, Deserialize, Display, Eq, Hash, Hashable, Ord, PartialEq, PartialOrd, Serialize, -)] +#[derive(Clone, Debug, Display, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Hashable, Serialize))] pub enum Payload where T: Hashable, diff --git a/merkle/src/proofs/mod.rs b/merkle/src/proofs/mod.rs index bc4c5f7..caf85d8 100644 --- a/merkle/src/proofs/mod.rs +++ b/merkle/src/proofs/mod.rs @@ -8,7 +8,7 @@ //! //! Merkle proofs are a way to prove that a given piece of data is part of a Merkle tree. //! -pub use self::{path::*, proof::*, utils::*}; +pub use self::{path::*, proof::*}; pub(crate) mod path; pub(crate) mod proof; @@ -19,4 +19,5 @@ pub trait MerkleProof { fn proof(&self) -> Vec; } -pub(crate) mod utils {} +#[cfg(test)] +mod tests {} diff --git a/merkle/src/shape.rs b/merkle/src/shape.rs index bcb7fce..3736a05 100644 --- a/merkle/src/shape.rs +++ b/merkle/src/shape.rs @@ -2,6 +2,7 @@ Appellation: shape Contrib: FL03 */ +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; fn get_merkle_tree_size(leafs: usize) -> usize { @@ -24,9 +25,8 @@ fn get_merkle_depth(leafs: usize) -> usize { depth } -#[derive( - Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, -)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct MerkleDimension { depth: usize, leafs: usize, diff --git a/merkle/src/tree/builder.rs b/merkle/src/tree/builder.rs index 44439f7..9fd220c 100644 --- a/merkle/src/tree/builder.rs +++ b/merkle/src/tree/builder.rs @@ -2,3 +2,18 @@ Appellation: builder Contrib: FL03 */ + +pub struct MerkleTreeBuilder { + leafs: Vec, +} + +impl MerkleTreeBuilder { + pub fn new() -> Self { + Self { leafs: Vec::new() } + } + + pub fn with_leafs(mut self, leafs: Vec) -> Self { + self.leafs = leafs; + self + } +} diff --git a/merkle/src/tree/merkle.rs b/merkle/src/tree/merkle.rs index 5f1d5cc..8c4cc57 100644 --- a/merkle/src/tree/merkle.rs +++ b/merkle/src/tree/merkle.rs @@ -5,10 +5,12 @@ use crate::proofs::merkle_proof; use crate::{create_merkle_tree, MerkleDimension}; use decanter::prelude::{Hashable, H256}; +#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use std::ops::{Index, IndexMut, Range}; -#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct MerkleTree { dim: MerkleDimension, nodes: Vec, diff --git a/merkle/tests/default.rs b/merkle/tests/default.rs index 7dee5fa..5f26546 100644 --- a/merkle/tests/default.rs +++ b/merkle/tests/default.rs @@ -1,6 +1,17 @@ +/* + Appellation: default + Contrib: FL03 +*/ #[cfg(test)] + +fn addition(a: A, b: B) -> C +where + A: std::ops::Add, +{ + a + b +} + #[test] -fn lib_compiles() { - let f = |i| i + 1; - assert_eq!(f(10), 11) +fn compiles() { + assert_eq!(addition(10, 1), 11) } diff --git a/mmr/Cargo.toml b/mmr/Cargo.toml index d2ea2e5..96963ab 100644 --- a/mmr/Cargo.toml +++ b/mmr/Cargo.toml @@ -26,12 +26,12 @@ test = true [dependencies] anyhow.workspace = true -decanter.workspace = true +decanter = { features = ["derive"], version = "0.1.6" } digest = "0.10" hex = "0.4" itertools.workspace = true -serde.workspace = true -serde_json.workspace = true +serde = { features = ["derive"], version = "1" } +serde_json = "1" smart-default.workspace = true strum.workspace = true diff --git a/mmr/src/cmp/nodes.rs b/mmr/src/cmp/nodes.rs index ce531fc..e345141 100644 --- a/mmr/src/cmp/nodes.rs +++ b/mmr/src/cmp/nodes.rs @@ -1,12 +1,9 @@ /* Appellation: cmps Contrib: FL03 - Description: ... summary ... */ - use decanter::prelude::{Hashable, H256}; use serde::{Deserialize, Serialize}; -use std::convert::From; #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct Node { diff --git a/mmr/src/mmr.rs b/mmr/src/mmr.rs index b39fa6d..87cce42 100644 --- a/mmr/src/mmr.rs +++ b/mmr/src/mmr.rs @@ -1,14 +1,12 @@ /* Appellation: mmr Contrib: FL03 - Description: ... summary ... */ use crate::cmp::{Node, Position}; use crate::{is_node_right, sibling_index, RangeMap}; use decanter::prelude::{hasher, Hashable, H256}; use digest::Digest; use serde::{Deserialize, Serialize}; -use std::convert::From; #[derive(Clone, Debug, Default, Deserialize, Eq, Hashable, PartialEq, Serialize)] pub struct MerkleMountainRange diff --git a/mmr/tests/default.rs b/mmr/tests/default.rs index 7dee5fa..5f26546 100644 --- a/mmr/tests/default.rs +++ b/mmr/tests/default.rs @@ -1,6 +1,17 @@ +/* + Appellation: default + Contrib: FL03 +*/ #[cfg(test)] + +fn addition(a: A, b: B) -> C +where + A: std::ops::Add, +{ + a + b +} + #[test] -fn lib_compiles() { - let f = |i| i + 1; - assert_eq!(f(10), 11) +fn compiles() { + assert_eq!(addition(10, 1), 11) } diff --git a/queue/Cargo.toml b/queue/Cargo.toml new file mode 100644 index 0000000..7d4d605 --- /dev/null +++ b/queue/Cargo.toml @@ -0,0 +1,39 @@ +[package] +authors.workspace = true +categories.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "algae-queue" +readme.workspace = true +repository.workspace = true +version.workspace = true + +[features] +default = [] + +serde = [ + "dep:serde", + "serde-ext" +] + +serde-ext = [ + "dep:serde_json" +] + +[dependencies] +serde = { optional = true, features = ["derive"], version = "1" } +serde_json = { optional = true, version = "1" } + + +[dev-dependencies] + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] + +[target.wasm32-unknown-unknown] + +[target.wasm32-wasi] diff --git a/queue/src/lib.rs b/queue/src/lib.rs new file mode 100644 index 0000000..86c732e --- /dev/null +++ b/queue/src/lib.rs @@ -0,0 +1,9 @@ +/* + Appellation: algae-queue + Contrib: FL03 +*/ +//! # Algae Queue +//! +//! + +pub mod prelude {} diff --git a/queue/tests/default.rs b/queue/tests/default.rs new file mode 100644 index 0000000..5f26546 --- /dev/null +++ b/queue/tests/default.rs @@ -0,0 +1,17 @@ +/* + Appellation: default + Contrib: FL03 +*/ +#[cfg(test)] + +fn addition(a: A, b: B) -> C +where + A: std::ops::Add, +{ + a + b +} + +#[test] +fn compiles() { + assert_eq!(addition(10, 1), 11) +}