diff --git a/Cargo.toml b/Cargo.toml index c442cab..00261ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "terminal/ansi_parser", "math/str2int", "math/int2str", + "math/radix_transform", "math/fib" ] diff --git a/math/radix_transform/Cargo.toml b/math/radix_transform/Cargo.toml new file mode 100644 index 0000000..678a012 --- /dev/null +++ b/math/radix_transform/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "radix_transform" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nested = { path = "../../nested" } + +[dependencies.async-std] +version = "1.9.0" +features = ["unstable", "attributes"] diff --git a/math/radix_transform/src/main.rs b/math/radix_transform/src/main.rs new file mode 100644 index 0000000..1440884 --- /dev/null +++ b/math/radix_transform/src/main.rs @@ -0,0 +1,105 @@ + +use { + std::sync::{Arc, RwLock}, + nested::{ + core::{ + View, + ViewPort, + Observer, + ObserverBroadcast, + InnerViewPort, + OuterViewPort + }, + sequence::{SequenceView, VecBuffer}, + integer::{RadixProjection} + } +}; + +#[async_std::main] +async fn main() { + nested::magic_header(); + eprintln!(" Convert Radix of Positional Integer"); + nested::magic_header(); + + let mut args = std::env::args(); + args.next().expect("Arg $0 missing!"); + + eprintln!(" +$1: src_radix + ( ℕ ) + ( PositionalInt 10 LittleEndian ) + ( Sequence (Digit 10) ) + ( Sequence Ascii ) + ( ArgString ) +"); + let src_radix_str = args.next().expect("Arg $1 required!"); + + + eprintln!(" +$2: dst_radix + ( ℕ ) + ( PositionalInt 10 LittleEndian ) + ( Sequence (Digit 10) ) + ( Sequence Ascii ) + ( ArgString ) +"); + let dst_radix_str = args.next().expect("Arg $2 required!"); + + eprintln!(" +>0: n + ( ℕ ) ~~ <1 + ( PositionalInt src_radix LittleEndian ) + ( Sequence (Digit src_radix) ) + ( Sequence MachineInt ) + ( PipeStream bincode (SequenceDiff MachineInt) ) +"); + + eprintln!(" +<1: n + ( ℕ ) ~~ >0 + ( PositionalInt dst_radix LittleEndian ) + ( Sequence (Digit dst_radix) ) + ( Sequence MachineInt ) + ( PipeStream bincode (SequenceDiff MachineInt) ) +"); + + nested::magic_header(); + + let src_radix = usize::from_str_radix(&src_radix_str, 10).expect("could not parse src_radix"); + let dst_radix = usize::from_str_radix(&dst_radix_str, 10).expect("could not parse dst_radix"); + + let src_digits_port = ViewPort::new(); + let dst_digits_port = ViewPort::new(); + + let mut src_digits = VecBuffer::::new(src_digits_port.inner()); + + let proj = RadixProjection::new( + src_radix, + dst_radix, + src_digits_port.outer().to_sequence(), + dst_digits_port.inner() + ); + + // output dst digits + let writer = { + use std::{ + fs::File, + io::{Read, Write}, + os::unix::io::FromRawFd + }; + + dst_digits_port.outer().serialize_json(unsafe { std::fs::File::from_raw_fd(1) }) + }; + + // start reading src digits + { + use async_std::{ + fs::File, + io::{Read, Write}, + os::unix::io::FromRawFd + }; + + src_digits.from_json(unsafe { async_std::fs::File::from_raw_fd(0) }).await; + } +} + diff --git a/nested/src/integer/add.rs b/nested/src/integer/add.rs new file mode 100644 index 0000000..9ba42d4 --- /dev/null +++ b/nested/src/integer/add.rs @@ -0,0 +1,75 @@ +use { + std::sync::{Arc, RwLock}, + crate::{ + core::{InnerViewPort, OuterViewPort, ObserverBroadcast}, + sequence::{SequenceView, VecBuffer}, + projection::ProjectionHelper + } +}; + +fn posint_add( + radix: usize, + a: impl SequenceView, + b: impl SequenceView +) -> Vec { + let mut carry = 0; + let mut result = Vec::new(); + + for digit_idx in 0 .. std::cmp::max(a.len().unwrap_or(0), b.len().unwrap_or(0)) { + let sum = + a.get(&digit_idx).unwrap_or(0) + + b.get(&digit_idx).unwrap_or(0) + + carry; + + result.push(sum % radix); + + carry = + if sum > radix { + sum - radix + } else { + 0 + }; + } + + if carry > 0 { + result.push(carry); + } + + result +} + +pub struct Add { + radix: usize, + a: Arc>, // PosInt, Little Endian + b: Arc>, // PosInt, Little Endian + c: VecBuffer, + proj_helper: ProjectionHelper +} + +impl Add { + pub fn new( + radix: usize, + a: OuterViewPort>, + b: OuterViewPort>, + c: InnerViewPort>>//> + ) -> Arc> { + let mut proj_helper = ProjectionHelper::new(); + let add = Arc::new(RwLock::new( + Add { + radix, + a: proj_helper.new_sequence_arg(a, |s: &mut Self, _digit_idx| s.update()), + b: proj_helper.new_sequence_arg(b, |s: &mut Self, _digit_idx| s.update()), + c: VecBuffer::new(c), + proj_helper + } + )); + add + } + + fn update(&mut self) { + self.c.clear(); + for digit in posint_add(self.radix, self.a.clone(), self.b.clone()) { + self.c.push(digit); + } + } +} diff --git a/nested/src/integer/mod.rs b/nested/src/integer/mod.rs new file mode 100644 index 0000000..1c122f8 --- /dev/null +++ b/nested/src/integer/mod.rs @@ -0,0 +1,9 @@ + +pub mod radix; +pub mod add; + +pub use { + radix::RadixProjection, + add::Add +}; + diff --git a/nested/src/integer/radix.rs b/nested/src/integer/radix.rs new file mode 100644 index 0000000..a62876f --- /dev/null +++ b/nested/src/integer/radix.rs @@ -0,0 +1,99 @@ +use { + std::sync::{Arc, RwLock}, + crate::{ + core::{ + View, + ViewPort, + Observer, + ObserverBroadcast, + InnerViewPort, + OuterViewPort + }, + sequence::{SequenceView, VecBuffer} + } +}; + +pub struct RadixProjection { + src_radix: usize, + dst_radix: usize, + src_digits: Option>>, + dst_digits: RwLock> +} + +impl RadixProjection { + pub fn new( + src_radix: usize, + dst_radix: usize, + src_digits: OuterViewPort>, + dst_digits: InnerViewPort>> + ) -> Arc> { + let proj = Arc::new(RwLock::new( + RadixProjection { + src_radix, + dst_radix, + src_digits: None, + dst_digits: RwLock::new(VecBuffer::new(dst_digits)) + } + )); + src_digits.add_observer(proj.clone()); + proj + } + + fn machine_int(&self) -> usize { + let mut val = 0; + let mut r = 1; + for i in 0 .. self.src_digits.len().unwrap_or(0) { + val += r * self.src_digits.get(&i).unwrap(); + r *= self.src_radix; + } + + val + } + + // recalculate everything + fn update(&self) { + let mut dst = self.dst_digits.write().unwrap(); + dst.clear(); + + let mut val = self.machine_int(); + + while val > 0 { + dst.push(val % self.dst_radix); + val /= self.dst_radix; + } + } + + fn update_dst_digit(&mut self, idx: usize) { + /* + let v = 0; // calculate new digit value + + // which src-digits are responsible? + + if idx < self.dst_digits.len() { + self.dst_digits.get_mut(idx) = v; + } else if idx == self.dst_digits.len() { + self.dst_digits.push(v); + } else { + // error + } +*/ + } +} + +impl Observer> for RadixProjection { + fn reset(&mut self, view: Option>>) { + eprintln!("reset"); + + self.src_digits = view; + } + + fn notify(&self, idx: &usize) { + // todo: + // src digit i changed. + // which dst-digits does it affect? + // update dst-digit j: + + // ...but for now the easy way + self.update(); + } +} diff --git a/nested/src/lib.rs b/nested/src/lib.rs index abee199..6d65631 100644 --- a/nested/src/lib.rs +++ b/nested/src/lib.rs @@ -1,39 +1,18 @@ #![feature(trait_alias)] pub mod core; +pub mod projection; + +pub mod singleton; pub mod index; pub mod grid; pub mod sequence; -pub mod singleton; pub mod terminal; -pub mod projection; +pub mod integer; + pub mod string_editor; pub mod leveled_term_view; -/* maybe? -pub use { - cgmath::{Vector2, Point2}, - termion::event::{Event, Key}, - crate::{ - core::{View, Observer, ObserverExt, ObserverBroadcast, ViewPort, OuterViewPort}, - index::{ImplIndexView}, - terminal::{ - TerminalView, - TerminalAtom, - TerminalStyle, - TerminalEvent, - Terminal, - TerminalCompositor - }, - sequence::{VecBuffer, SequenceView}, - grid::{GridOffset, GridWindowIterator}, - singleton::{SingletonView, SingletonBuffer}, - string_editor::{StringEditor, insert_view::StringInsertView}, - leveled_term_view::LeveledTermView - } -}; - */ - pub fn magic_header() { eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>"); }