improvements

General code improvements and optimizations.
This commit is contained in:
Simon Gardling 2022-05-12 20:03:53 -04:00
parent 1c8198103e
commit f916de7524
12 changed files with 94 additions and 60 deletions

6
Cargo.lock generated
View File

@ -143,11 +143,6 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.20.0-alpha.1"
source = "git+https://github.com/marshallpierce/rust-base64.git#a675443d327e175f735a37f574de803d6a332591"
[[package]] [[package]]
name = "benchmarks" name = "benchmarks"
version = "0.1.0" version = "0.1.0"
@ -2780,7 +2775,6 @@ name = "ytbn_graphing_software"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-lock", "async-lock",
"base64",
"benchmarks", "benchmarks",
"bincode", "bincode",
"byte-unit", "byte-unit",

View File

@ -24,7 +24,7 @@ panic = "abort"
debug = true debug = true
codegen-units = 8 codegen-units = 8
opt-level = 0 opt-level = 0
lto = "thin" lto = false
strip = false strip = false
[profile.bench] [profile.bench]
@ -56,7 +56,6 @@ static_assertions = "1.1"
uuid = { version = "1", features = ["v4", "fast-rng", "js"] } uuid = { version = "1", features = ["v4", "fast-rng", "js"] }
bincode = "1.3" bincode = "1.3"
serde = "1" serde = "1"
base64 = { git = "https://github.com/marshallpierce/rust-base64.git" }
byte-unit = { version = "4", default-features = false } byte-unit = { version = "4", default-features = false }
[dev-dependencies] [dev-dependencies]

View File

@ -13,7 +13,7 @@ pub use crate::{
autocomplete_hashmap::compile_hashmap, autocomplete_hashmap::compile_hashmap,
parsing::{process_func_str, BackingFunction}, parsing::{process_func_str, BackingFunction},
suggestions::{ suggestions::{
generate_hint, get_last_term, split_function, split_function_chars, Hint, HINT_EMPTY, generate_hint, get_last_term, split_function, split_function_chars, Hint, SplitType,
SUPPORTED_FUNCTIONS, HINT_EMPTY, SUPPORTED_FUNCTIONS,
}, },
}; };

View File

@ -191,5 +191,6 @@ pub fn process_func_str(function_in: &str) -> String {
return String::new(); return String::new();
} }
crate::suggestions::split_function(&function_in).join("*") crate::suggestions::split_function(&function_in, crate::suggestions::SplitType::Multiplication)
.join("*")
} }

View File

@ -14,7 +14,7 @@ macro_rules! test_print {
}; };
} }
pub fn split_function(input: &str) -> Vec<String> { pub fn split_function(input: &str, split: SplitType) -> Vec<String> {
split_function_chars( split_function_chars(
&input &input
.replace("pi", "π") // replace "pi" text with pi symbol .replace("pi", "π") // replace "pi" text with pi symbol
@ -22,7 +22,7 @@ pub fn split_function(input: &str) -> Vec<String> {
.replace("exp", "\u{1fc93}") // stop-gap solution to fix the `exp` function .replace("exp", "\u{1fc93}") // stop-gap solution to fix the `exp` function
.chars() .chars()
.collect::<Vec<char>>(), .collect::<Vec<char>>(),
SplitType::Multiplication, split,
) )
.iter() .iter()
.map(|x| x.replace("\u{1fc93}", "exp")) // Convert back to `exp` text .map(|x| x.replace("\u{1fc93}", "exp")) // Convert back to `exp` text

View File

@ -143,6 +143,8 @@ impl FunctionEntry {
settings_opened: false, settings_opened: false,
}; };
pub const fn is_some(&self) -> bool { !self.function.is_none() }
pub fn settings_window(&mut self, ctx: &Context) { pub fn settings_window(&mut self, ctx: &Context) {
let mut invalidate_nth = false; let mut invalidate_nth = false;
egui::Window::new(format!("Settings: {}", self.raw_func_str)) egui::Window::new(format!("Settings: {}", self.raw_func_str))
@ -310,34 +312,37 @@ impl FunctionEntry {
.as_slice() .as_slice()
.into(); .into();
let back_data: Vec<Value> = dyn_iter(&resolution_iter) let (back_data, derivative_data_1): (Vec<Value>, Vec<Option<Value>>) =
.map(|x| { dyn_iter(&resolution_iter)
if let Some(i) = x_data.get_index(x) { .map(|x| {
self.back_data[i] if let Some(i) = x_data.get_index(x) {
} else { (
Value::new(*x, self.function.get(*x)) self.back_data[i],
} derivative_required.then(|| self.derivative_data[i]),
}) )
.collect(); } else {
(
Value::new(*x, self.function.get(*x)),
derivative_required
.then(|| Value::new(*x, self.function.get_derivative_1(*x))),
)
}
})
.collect::<Vec<(Value, Option<Value>)>>()
.into_iter()
.unzip();
debug_assert_eq!(back_data.len(), settings.plot_width + 1); debug_assert_eq!(back_data.len(), settings.plot_width + 1);
debug_assert_eq!(derivative_data_1.len(), settings.plot_width + 1);
self.back_data = back_data; self.back_data = back_data;
if derivative_required { if derivative_required {
let new_derivative_data: Vec<Value> = dyn_iter(&resolution_iter) debug_assert!(derivative_data_1[0].is_some());
.map(|x| { self.derivative_data = derivative_data_1
if let Some(i) = x_data.get_index(x) { .into_iter()
self.derivative_data[i] .map(|ele| unsafe { ele.unwrap_unchecked() })
} else { .collect::<Vec<Value>>();
Value::new(*x, self.function.get_derivative_1(*x))
}
})
.collect();
debug_assert_eq!(new_derivative_data.len(), settings.plot_width + 1);
self.derivative_data = new_derivative_data;
} else { } else {
self.invalidate_derivative(); self.invalidate_derivative();
} }

View File

@ -196,7 +196,7 @@ impl FunctionManager {
// Toggle integral being enabled or not // Toggle integral being enabled or not
function.integral.bitxor_assign( function.integral.bitxor_assign(
ui.add(button_area_button("")) ui.add_enabled(function.is_some(), button_area_button(""))
.on_hover_text(match function.integral { .on_hover_text(match function.integral {
true => "Don't integrate", true => "Don't integrate",
false => "Integrate", false => "Integrate",
@ -206,7 +206,7 @@ impl FunctionManager {
// Toggle showing the derivative (even though it's already calculated this option just toggles if it's displayed or not) // Toggle showing the derivative (even though it's already calculated this option just toggles if it's displayed or not)
function.derivative.bitxor_assign( function.derivative.bitxor_assign(
ui.add(button_area_button("d/dx")) ui.add_enabled(function.is_some(), button_area_button("d/dx"))
.on_hover_text(match function.derivative { .on_hover_text(match function.derivative {
true => "Don't Differentiate", true => "Don't Differentiate",
false => "Differentiate", false => "Differentiate",
@ -215,7 +215,7 @@ impl FunctionManager {
); );
function.settings_opened.bitxor_assign( function.settings_opened.bitxor_assign(
ui.add(button_area_button("")) ui.add_enabled(function.is_some(), button_area_button(""))
.on_hover_text(match function.settings_opened { .on_hover_text(match function.settings_opened {
true => "Close Settings", true => "Close Settings",
false => "Open Settings", false => "Open Settings",

View File

@ -148,26 +148,23 @@ impl MathApp {
const DATA_NAME: &str = "YTBN-DECOMPRESSED"; const DATA_NAME: &str = "YTBN-DECOMPRESSED";
fn get_storage_decompressed() -> Option<Vec<u8>> { fn get_storage_decompressed() -> Option<Vec<u8>> {
if let Ok(Some(data)) = get_localstorage().get_item(DATA_NAME) { let data = get_localstorage().get_item(DATA_NAME).ok()??;
let (commit, cached_data) = crate::misc::hashed_storage_read(data); let (commit, cached_data) = crate::misc::hashed_storage_read(data);
if commit == build::SHORT_COMMIT { if commit == build::SHORT_COMMIT {
tracing::info!("Reading decompression cache. Bytes: {}, or: {}", cached_data.len(), crate::misc::format_bytes(cached_data.len())); tracing::info!("Reading decompression cache. Bytes: {}, or: {}", cached_data.len(), crate::misc::format_bytes(cached_data.len()));
return Some(cached_data.to_vec()); return Some(cached_data.to_vec());
} else {
tracing::info!("Decompression cache are invalid due to differing commits (build: {}, previous: {})", build::SHORT_COMMIT, commit);
// is invalid
None
}
} else { } else {
tracing::info!("Decompression cache are invalid (build: {}, previous: {})", build::SHORT_COMMIT, commit);
// is invalid
None None
} }
} }
fn set_storage_decompressed(data: &Vec<u8>) { fn set_storage_decompressed(data: &[u8]) {
tracing::info!("Setting decompression cache"); tracing::info!("Setting decompression cache");
let saved_data = &crate::misc::hashed_storage_create(&build::SHORT_COMMIT.chars().map(|c| c as u8).collect::<Vec<u8>>(), data.as_slice()); let saved_data = &crate::misc::hashed_storage_create(&build::SHORT_COMMIT.as_bytes(), data);
tracing::info!("Bytes: {}, or: {}", saved_data.len(), crate::misc::format_bytes(data.len())); tracing::info!("Bytes: {}, or: {}", saved_data.len(), crate::misc::format_bytes(data.len()));
get_localstorage().set_item(DATA_NAME, saved_data).expect("failed to set local storage cache"); get_localstorage().set_item(DATA_NAME, saved_data).expect("failed to set local storage cache");
} }
@ -610,7 +607,7 @@ impl App for MathApp {
.collect::<Vec<u8>>(), .collect::<Vec<u8>>(),
bincode::serialize(&self.functions).unwrap().as_slice(), bincode::serialize(&self.functions).unwrap().as_slice(),
); );
tracing::info!("Bytes: {}", saved_data.len()); // tracing::info!("Bytes: {}", saved_data.len());
local_storage local_storage
.set_item("YTBN-FUNCTIONS", saved_data) .set_item("YTBN-FUNCTIONS", saved_data)
.expect("failed to set local function storage"); .expect("failed to set local function storage");

View File

@ -298,15 +298,29 @@ pub fn hashed_storage_create(hash: &[u8], data: &[u8]) -> String {
debug_assert_eq!(hash.len(), HASH_LENGTH); debug_assert_eq!(hash.len(), HASH_LENGTH);
debug_assert!(data.len() > 0); debug_assert!(data.len() > 0);
unsafe {
assume(data.len() > 0);
assume(!data.is_empty());
assume(hash.len() == HASH_LENGTH);
}
let new_data = [hash, data].concat(); let new_data = [hash, data].concat();
debug_assert_eq!(new_data.len(), data.len() + hash.len()); debug_assert_eq!(new_data.len(), data.len() + hash.len());
base64::encode(new_data)
// cannot use `from_utf8` seems to break on wasm. no clue why
new_data.iter().map(|b| *b as char).collect::<String>()
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn hashed_storage_read(data: String) -> (String, Vec<u8>) { pub fn hashed_storage_read(data: String) -> (String, Vec<u8>) {
let decoded_1 = base64::decode(data).expect("unable to read data"); debug_assert!(data.len() > HASH_LENGTH);
debug_assert!(decoded_1.len() > HASH_LENGTH); unsafe {
assume(!data.is_empty());
assume(data.len() > 0);
}
// can't use data.as_bytes() here for some reason, seems to break on wasm?
let decoded_1 = data.chars().map(|c| c as u8).collect::<Vec<u8>>();
let (hash, cached_data) = decoded_1.split_at(8); let (hash, cached_data) = decoded_1.split_at(8);
debug_assert_eq!(hash.len(), HASH_LENGTH); debug_assert_eq!(hash.len(), HASH_LENGTH);

View File

@ -1,5 +1,7 @@
use std::hash::Hash;
pub fn widgets_ontop<R>( pub fn widgets_ontop<R>(
ui: &egui::Ui, id: String, re: &egui::Response, y_offset: f32, ui: &egui::Ui, id: impl Hash, re: &egui::Response, y_offset: f32,
add_contents: impl FnOnce(&mut egui::Ui) -> R, add_contents: impl FnOnce(&mut egui::Ui) -> R,
) -> R { ) -> R {
let area = egui::Area::new(id) let area = egui::Area::new(id)

View File

@ -95,7 +95,7 @@ fn option_vec_printer() {
} }
#[test] #[test]
fn hash_b64_storage() { fn hashed_storage() {
use ytbn_graphing_software::{hashed_storage_create, hashed_storage_read}; use ytbn_graphing_software::{hashed_storage_create, hashed_storage_read};
let commit = "abcdefeg".chars().map(|c| c as u8).collect::<Vec<u8>>(); let commit = "abcdefeg".chars().map(|c| c as u8).collect::<Vec<u8>>();

View File

@ -159,6 +159,8 @@ fn hint_to_string() {
#[test] #[test]
fn invalid_function() { fn invalid_function() {
use parsing::SplitType;
SUPPORTED_FUNCTIONS SUPPORTED_FUNCTIONS
.iter() .iter()
.flat_map(|func1| { .flat_map(|func1| {
@ -169,7 +171,7 @@ fn invalid_function() {
}) })
.filter(|func| !SUPPORTED_FUNCTIONS.contains(&func.as_str())) .filter(|func| !SUPPORTED_FUNCTIONS.contains(&func.as_str()))
.for_each(|key| { .for_each(|key| {
let split = parsing::split_function(&key); let split = parsing::split_function(&key, SplitType::Multiplication);
if split.len() != 1 { if split.len() != 1 {
panic!("failed: {} (len: {}, split: {:?})", key, split.len(), split); panic!("failed: {} (len: {}, split: {:?})", key, split.len(), split);
@ -185,7 +187,9 @@ fn invalid_function() {
} }
#[test] #[test]
fn split_function() { fn split_function_multiplication() {
use parsing::SplitType;
let values = HashMap::from([ let values = HashMap::from([
("cos(x)", vec!["cos(x)"]), ("cos(x)", vec!["cos(x)"]),
("cos(", vec!["cos("]), ("cos(", vec!["cos("]),
@ -199,10 +203,28 @@ fn split_function() {
("x*x", vec!["x", "x"]), ("x*x", vec!["x", "x"]),
("10*10", vec!["10", "10"]), ("10*10", vec!["10", "10"]),
("a1b2c3d4", vec!["a1b2c3d4"]), ("a1b2c3d4", vec!["a1b2c3d4"]),
("cos(sin(x)cos(x))", vec!["cos(sin(x)", "cos(x))"]),
]); ]);
for (key, value) in values { for (key, value) in values {
assert_eq!(parsing::split_function(key), value); assert_eq!(
parsing::split_function(key, SplitType::Multiplication),
value
);
}
}
#[test]
fn split_function_terms() {
use parsing::SplitType;
let values = HashMap::from([(
"cos(sin(x)cos(x))",
vec!["cos(", "sin(", "x)", "cos(", "x))"],
)]);
for (key, value) in values {
assert_eq!(parsing::split_function(key, SplitType::Term), value);
} }
} }