sac-base 0.0.7

Base crate of the sac-signal and sac-control crates
Documentation
//! # sac-base (Signal And Control)
//! sac-base is the base crate of its two child crates sac-control and sac-signal.
//! This crate is still under heavy construction and not finished.
//!
//! ---
//!
//! # Idea
//! The sac-* crates help to implement signal processing and control systems in a network based
//! approach. Similar to Simulink as example.
//! The project is designed for a primary usage on embedded systems and is therefore a [no_std]
//! crate. A generic solution such as the used network based approach will never be as fast as a
//! custom system implementation for a specific problem. But it will allow to directly and quickly
//! implement and change systems in code instead of designing it Matlab and exporting it to C.
//! Generation the network and building the topology is relatively expensive. Therefore the crate
//! does all the allocations and setup before the normal operation starts.
//! This base crate is designed in a way that allows the Signal and the Control crate to easily
//! extend it, and allow the operations to be interchangeable between each other.
//! Both the sac-control and the sac-signal are under construction and are not available yet.
//!
//! ## Base crate
//! The base crate provides the following features:
//! - Network description.
//! - Base node implementation which the operations are based on.
//! - Simple math operations such as adding, subtraction. Generally operations that will be used in both the Signal and Control crates.
//! - Generic elements such as buffers.
//!
//! ## no_std
//! The library is built with no_std. Therefore it can be used on embedded systems and while not tested, probably wasm aswell.
//!
//! # Example
//! The following example, can be build by the code given below:
//!
//! ```rust
//! //
//! //    +----+
//! //    |    |
//! // +--+ In +----+
//! //    |    |    |   +-----+
//! //    +----+    +---+     |
//! //                  | Add +----+-------------+
//! //    +----+    +---+     |    |             |
//! //    |    |    |   +-----+    |             |     +-----+
//! // +--+ In +----+              |             +-----+     |
//! //    |    |                   |                   | Mul +------+---+
//! //    +----+                   |             +-----+     |      |
//! //                             |  +-----+    |     +-----+      |
//! //    +----+                   +--+     |    |                  |
//! //    |    |                      | Add |    |                  |
//! // +--+ In +----------------------+     +----+                  |
//! //    |    |                      |     |                       |
//! //    +----+                +-----+     |                       |
//! //                          |     +-----+                       |
//! //                          |              +-----+              |
//! //                          |              |     |              |
//! //                          +--------------+ z^1 +--------------+
//! //                                         |     |
//! //                                         +---- +
//! //
//!
//! use sac_base::network::network::Network;
//! use sac_base::operations::math::add::Add;
//! use sac_base::operations::miscellaneous::buffer::Buffer;
//! use sac_base::operations::math::multiply::Multiply;
//! // Generate the network
//! let mut network = Network::new();
//! // Generate some operations
//! let add1 = network.add_operation(Add::new());
//! let mul1 = network.add_operation(Multiply::new());
//! let add2 = network.add_operation(Add::new());
//! // Add some inputs
//! let in1 = network.add_operation(Buffer::new());
//! let in2 = network.add_operation(Buffer::new());
//! let in3 = network.add_operation(Buffer::new());
//! // Connect the operations with each other
//! network.add_connection(&in1, &add1).unwrap();
//! network.add_connection(&in2, &add1).unwrap();
//! network.add_connection(&add1, &add2).unwrap();
//! network.add_connection(&in3, &add2).unwrap();
//! network.add_connection(&add1, &mul1).unwrap();
//! network.add_connection(&add2, &mul1).unwrap();
//! // Insert a closed loop (Positive feedback loop)
//! network.close_loop(&mul1, &add2);
//! // Generate the network
//! network.build().unwrap();
//! // Main loop operation
//! // Update the inputs
//! network.set_input_sample(&in1, 5.0);
//! network.set_input_sample(&in2, 5.0);
//! network.set_input_sample(&in3, 5.0);
//! // Iterate over the network
//! network.process();
//! let res = network.get_output(&mul1);
//! // Update the inputs
//! network.set_input_sample(&in1, 10.0);
//! network.set_input_sample(&in2, 10.0);
//! network.set_input_sample(&in3, 10.0);
//! // Process twice to let the closed loop propagate
//! network.process();
//! let res = network.get_output(&mul1);
//! ```
//!
//! # Extending the functionality
//! It is likely that the library does not implement all the operations that will be needed in your application.
//! Implementing a new operation is simple and can be added outside of the library.
//!
//! As example:
//! Lets say you want to add a new operation that drops every third element.
//! ```rust
//! // we need a possibility to count. So we need to add a count variable to the struct which will
//! // be boxed and moved into the node
//! use sac_base::network::node::Node;
//! use std::any::Any;
//! use sac_base::network::network::Network;
//! pub struct Third {
//!     count: usize,
//! }
//!
//! // Now define the functionality
//! impl Third {
//!
//!     pub fn new<T>() -> Node<T>
//!         where T: Copy + Default
//!     {
//!         // Generate the storage which is the defined struct in a boxed pointer which will be
//!         // moved into the node
//!         let storage = Box::new(Third{
//!             count: 0,
//!         }) as Box<dyn Any>;
//!         Node::new(storage, |data_input: (Vec<&[T]>, usize), data_buffer: &mut Box<dyn Any>, output: &mut Vec<T>| {
//!             // Get the storage back so we can access the count variable
//!             let storage: &mut Third = data_buffer.downcast_mut::<Third>().unwrap();
//!             let (inputs, max_len) = data_input;
//!             // Start iterating over the inputs. Here we only care about one input,
//!             // so we only take 1.
//!             inputs.into_iter().take(1).into_iter().for_each(|data| {
//!                 // Iterate over all the values of the input slice.
//!                 data.into_iter().take(max_len).into_iter().for_each(|v| {
//!                     // Modulo the count
//!                     storage.count = storage.count % 3;
//!
//!                     // Now we are ready to implement the functionality.
//!                     // The content of the vector will be passed into the next nodes as slice.
//!                     // We are only working with one sample, so we can just put it into the
//!                     // 0 position.
//!                     output.clear();
//!                     if storage.count == 2 {
//!                         // Write default in to the vector if its the third sample.
//!                         output.insert(0, T::default());
//!                     } else {
//!                         // Otherwise just use the normal value
//!                         output.insert(0, *v);
//!                     }
//!
//!                     // Increment the count and modulo it.
//!                     storage.count = storage.count + 1;
//!                 })
//!             })
//!         })
//!     }
//! }
//!
//! let mut network: Network<f32> = Network::new();
//!
//! // Insert the new node into the network
//! let third = network.add_operation(Third::new());
//!
//! network.build();
//!
//! network.set_input_slice(&third, &[1.0, 2.0, 3.0][..]);
//!
//! network.process();
//! let res = network.get_output(&third).unwrap();
//!
//! assert_eq!(res, [1.0, 2.0, 3.0]);
//! ```
//!
//! # Outlook
//! - Base crate:
//!     - Operations:
//!         - To chunk and from chuck operations
//!     - Far future:
//!         - Static operation
//! - Signal processing:
//!     - Checkout https://gitlab.com/signal-and-control/sac-signal
//! - Control:
//!     - Checkout https://gitlab.com/signal-and-control/sac-control

#![no_std]

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(test)]
extern crate assert_approx_eq;

pub mod operations;
pub mod network;
pub mod helper;

extern crate alloc;
extern crate graphlib;
extern crate num;