improvements
General code improvements and optimizations.
This commit is contained in:
parent
1c8198103e
commit
f916de7524
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -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",
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
@ -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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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("*")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
20
src/misc.rs
20
src/misc.rs
@ -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);
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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>>();
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user