2021-04-29 01:32:59 +02:00
|
|
|
use {
|
2023-02-13 18:39:45 +01:00
|
|
|
r3vi::{
|
|
|
|
view::{
|
|
|
|
InnerViewPort, Observer, OuterViewPort,
|
|
|
|
sequence::*,
|
|
|
|
},
|
|
|
|
buffer::{vec::*}
|
2021-11-19 12:19:52 +01:00
|
|
|
},
|
|
|
|
std::sync::{Arc, RwLock},
|
2021-04-29 01:32:59 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
pub struct RadixProjection {
|
|
|
|
src_radix: usize,
|
|
|
|
dst_radix: usize,
|
|
|
|
src_digits: Option<Arc<dyn SequenceView<Item = usize>>>,
|
2021-11-19 12:19:52 +01:00
|
|
|
dst_digits: RwLock<VecBuffer<usize>>,
|
2021-04-29 01:32:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl RadixProjection {
|
|
|
|
pub fn new(
|
2022-12-18 01:20:17 +01:00
|
|
|
// static parameters
|
|
|
|
//---
|
2021-04-29 01:32:59 +02:00
|
|
|
src_radix: usize,
|
|
|
|
dst_radix: usize,
|
2022-12-18 01:20:17 +01:00
|
|
|
//---
|
|
|
|
|
|
|
|
// dynamic parameters
|
|
|
|
//---
|
|
|
|
// input
|
2021-04-29 01:32:59 +02:00
|
|
|
src_digits: OuterViewPort<dyn SequenceView<Item = usize>>,
|
2022-12-18 01:20:17 +01:00
|
|
|
// output
|
2021-11-19 12:19:52 +01:00
|
|
|
dst_digits: InnerViewPort<RwLock<Vec<usize>>>,
|
2022-12-18 01:20:17 +01:00
|
|
|
//---
|
2021-04-29 01:32:59 +02:00
|
|
|
) -> Arc<RwLock<Self>> {
|
2021-06-05 23:01:00 +02:00
|
|
|
dst_digits.0.add_update_hook(Arc::new(src_digits.0.clone()));
|
2021-11-19 12:19:52 +01:00
|
|
|
let proj = Arc::new(RwLock::new(RadixProjection {
|
|
|
|
src_radix,
|
|
|
|
dst_radix,
|
|
|
|
src_digits: None,
|
2022-06-17 15:48:13 +02:00
|
|
|
dst_digits: RwLock::new(VecBuffer::with_port(dst_digits)),
|
2021-11-19 12:19:52 +01:00
|
|
|
}));
|
2021-04-29 01:32:59 +02:00
|
|
|
src_digits.add_observer(proj.clone());
|
|
|
|
proj
|
|
|
|
}
|
|
|
|
|
|
|
|
fn machine_int(&self) -> usize {
|
|
|
|
let mut val = 0;
|
|
|
|
let mut r = 1;
|
2021-11-19 12:19:52 +01:00
|
|
|
for i in 0..self.src_digits.len().unwrap_or(0) {
|
2021-04-29 01:32:59 +02:00
|
|
|
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;
|
2021-11-19 12:19:52 +01:00
|
|
|
}
|
2021-04-29 01:32:59 +02:00
|
|
|
}
|
|
|
|
|
2021-05-13 16:22:30 +02:00
|
|
|
fn _update_dst_digit(&mut self, _idx: usize) {
|
2021-04-29 01:32:59 +02:00
|
|
|
/*
|
2021-11-19 12:19:52 +01:00
|
|
|
let v = 0; // calculate new digit value
|
2021-04-29 01:32:59 +02:00
|
|
|
|
2021-11-19 12:19:52 +01:00
|
|
|
// which src-digits are responsible?
|
2021-04-29 01:32:59 +02:00
|
|
|
|
2021-11-19 12:19:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
*/
|
2021-04-29 01:32:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Observer<dyn SequenceView<Item = usize>> for RadixProjection {
|
|
|
|
fn reset(&mut self, view: Option<Arc<dyn SequenceView<Item = usize>>>) {
|
|
|
|
self.src_digits = view;
|
|
|
|
}
|
|
|
|
|
2021-05-22 01:33:58 +02:00
|
|
|
fn notify(&mut self, _idx: &usize) {
|
2021-04-29 01:32:59 +02:00
|
|
|
// todo:
|
|
|
|
// src digit i changed.
|
|
|
|
// which dst-digits does it affect?
|
|
|
|
// update dst-digit j:
|
|
|
|
|
|
|
|
// ...but for now the easy way
|
|
|
|
self.update();
|
|
|
|
}
|
|
|
|
}
|