add positional integer radix transform

This commit is contained in:
Michael Sippel 2021-04-29 01:32:59 +02:00
parent c53f07e762
commit 0feaee454c
Signed by: senvas
GPG key ID: F96CF119C34B64A6
7 changed files with 307 additions and 26 deletions

View file

@ -5,5 +5,6 @@ members = [
"terminal/ansi_parser",
"math/str2int",
"math/int2str",
"math/radix_transform",
"math/fib"
]

View 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"]

View 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
View 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);
}
}
}

View file

@ -0,0 +1,9 @@
pub mod radix;
pub mod add;
pub use {
radix::RadixProjection,
add::Add
};

View 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();
}
}

View file

@ -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!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
}