add positional integer radix transform
This commit is contained in:
parent
c53f07e762
commit
0feaee454c
7 changed files with 307 additions and 26 deletions
|
@ -5,5 +5,6 @@ members = [
|
|||
"terminal/ansi_parser",
|
||||
"math/str2int",
|
||||
"math/int2str",
|
||||
"math/radix_transform",
|
||||
"math/fib"
|
||||
]
|
||||
|
|
13
math/radix_transform/Cargo.toml
Normal file
13
math/radix_transform/Cargo.toml
Normal file
|
@ -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"]
|
105
math/radix_transform/src/main.rs
Normal file
105
math/radix_transform/src/main.rs
Normal file
|
@ -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::<usize>::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;
|
||||
}
|
||||
}
|
||||
|
75
nested/src/integer/add.rs
Normal file
75
nested/src/integer/add.rs
Normal file
|
@ -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<Item = usize>,
|
||||
b: impl SequenceView<Item = usize>
|
||||
) -> Vec<usize> {
|
||||
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<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
|
||||
b: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
|
||||
c: VecBuffer<usize>,
|
||||
proj_helper: ProjectionHelper<Self>
|
||||
}
|
||||
|
||||
impl Add {
|
||||
pub fn new(
|
||||
radix: usize,
|
||||
a: OuterViewPort<dyn SequenceView<Item = usize>>,
|
||||
b: OuterViewPort<dyn SequenceView<Item = usize>>,
|
||||
c: InnerViewPort<RwLock<Vec<usize>>>//<dyn SequenceView<Item = usize>>
|
||||
) -> Arc<RwLock<Self>> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
9
nested/src/integer/mod.rs
Normal file
9
nested/src/integer/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
pub mod radix;
|
||||
pub mod add;
|
||||
|
||||
pub use {
|
||||
radix::RadixProjection,
|
||||
add::Add
|
||||
};
|
||||
|
99
nested/src/integer/radix.rs
Normal file
99
nested/src/integer/radix.rs
Normal file
|
@ -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<Arc<dyn SequenceView<Item = usize>>>,
|
||||
dst_digits: RwLock<VecBuffer<usize>>
|
||||
}
|
||||
|
||||
impl RadixProjection {
|
||||
pub fn new(
|
||||
src_radix: usize,
|
||||
dst_radix: usize,
|
||||
src_digits: OuterViewPort<dyn SequenceView<Item = usize>>,
|
||||
dst_digits: InnerViewPort<RwLock<Vec<usize>>>
|
||||
) -> Arc<RwLock<Self>> {
|
||||
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<dyn SequenceView<Item = usize>> for RadixProjection {
|
||||
fn reset(&mut self, view: Option<Arc<dyn SequenceView<Item = usize>>>) {
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -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!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue