UPDATE: Dump of initial files

This commit is contained in:
Nicolás Hatcher
2023-11-18 21:26:18 +01:00
commit c5b8efd83d
279 changed files with 42654 additions and 0 deletions

View File

@@ -0,0 +1,546 @@
use crate::{
calc_result::{CalcResult, CellReference},
expressions::parser::Node,
expressions::token::Error,
model::Model,
};
// 8_i64.pow(10);
const OCT_MAX: i64 = 1_073_741_824;
const OCT_MAX_HALF: i64 = 536_870_912;
// 16_i64.pow(10)
const HEX_MAX: i64 = 1_099_511_627_776;
const HEX_MAX_HALF: i64 = 549_755_813_888;
// Binary numbers are 10 bits and the most significant bit is the sign
fn from_binary_to_decimal(value: f64) -> Result<i64, String> {
let value = format!("{value}");
let result = match i64::from_str_radix(&value, 2) {
Ok(b) => b,
Err(_) => {
return Err("cannot parse into binary".to_string());
}
};
if !(0..=1023).contains(&result) {
// 2^10
return Err("too large".to_string());
} else if result > 511 {
// 2^9
return Ok(result - 1024);
};
Ok(result)
}
impl Model {
// BIN2DEC(number)
pub(crate) fn fn_bin2dec(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if args.len() != 1 {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_number_no_bools(&args[0], cell) {
Ok(f) => f,
Err(s) => return s,
};
match from_binary_to_decimal(value) {
Ok(n) => CalcResult::Number(n as f64),
Err(message) => CalcResult::new_error(Error::NUM, cell, message),
}
}
// BIN2HEX(number, [places])
pub(crate) fn fn_bin2hex(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_number_no_bools(&args[0], cell) {
Ok(f) => f,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let value = match from_binary_to_decimal(value) {
Ok(n) => n,
Err(message) => return CalcResult::new_error(Error::NUM, cell, message),
};
if value < 0 {
CalcResult::String(format!("{:0width$X}", HEX_MAX + value, width = 9))
} else {
let result = format!("{:X}", value);
if let Some(places) = places {
if places < result.len() as i32 {
return CalcResult::new_error(
Error::NUM,
cell,
"Not enough places".to_string(),
);
}
return CalcResult::String(format!("{:0width$X}", value, width = places as usize));
}
CalcResult::String(result)
}
}
// BIN2OCT(number, [places])
pub(crate) fn fn_bin2oct(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_number_no_bools(&args[0], cell) {
Ok(f) => f,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
let value = match from_binary_to_decimal(value) {
Ok(n) => n,
Err(message) => return CalcResult::new_error(Error::NUM, cell, message),
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
if value < 0 {
CalcResult::String(format!("{:0width$o}", OCT_MAX + value, width = 9))
} else {
let result = format!("{:o}", value);
if let Some(places) = places {
if places < result.len() as i32 {
return CalcResult::new_error(
Error::NUM,
cell,
"Not enough places".to_string(),
);
}
return CalcResult::String(format!("{:0width$o}", value, width = places as usize));
}
CalcResult::String(result)
}
}
pub(crate) fn fn_dec2bin(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value_raw = match self.get_number_no_bools(&args[0], cell) {
Ok(f) => f,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let mut value = value_raw.trunc() as i64;
if !(-512..=511).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += 1024;
}
let result = format!("{:b}", value);
if let Some(places) = places {
if value_raw > 0.0 && places < result.len() as i32 {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$b}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
pub(crate) fn fn_dec2hex(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value_raw = match self.get_number_no_bools(&args[0], cell) {
Ok(f) => f.trunc(),
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let mut value = value_raw.trunc() as i64;
if !(-HEX_MAX_HALF..=HEX_MAX_HALF - 1).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += HEX_MAX;
}
let result = format!("{:X}", value);
if let Some(places) = places {
if value_raw > 0.0 && places < result.len() as i32 {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$X}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
pub(crate) fn fn_dec2oct(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value_raw = match self.get_number_no_bools(&args[0], cell) {
Ok(f) => f,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let mut value = value_raw.trunc() as i64;
if !(-OCT_MAX_HALF..=OCT_MAX_HALF - 1).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += OCT_MAX;
}
let result = format!("{:o}", value);
if let Some(places) = places {
if value_raw > 0.0 && places < result.len() as i32 {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$o}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
// HEX2BIN(number, [places])
pub(crate) fn fn_hex2bin(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_string(&args[0], cell) {
Ok(s) => s,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if value.len() > 10 {
return CalcResult::new_error(Error::NUM, cell, "Value too large".to_string());
}
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let mut value = match i64::from_str_radix(&value, 16) {
Ok(f) => f,
Err(_) => {
return CalcResult::new_error(
Error::NUM,
cell,
"Error parsing hex number".to_string(),
);
}
};
if value < 0 {
return CalcResult::new_error(Error::NUM, cell, "Negative value".to_string());
}
if value >= HEX_MAX_HALF {
value -= HEX_MAX;
}
if !(-512..=511).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += 1024;
}
let result = format!("{:b}", value);
if let Some(places) = places {
if places <= 0 || (value > 0 && places < result.len() as i32) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$b}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
// HEX2DEC(number)
pub(crate) fn fn_hex2dec(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_string(&args[0], cell) {
Ok(s) => s,
Err(s) => return s,
};
if value.len() > 10 {
return CalcResult::new_error(Error::NUM, cell, "Value too large".to_string());
}
let mut value = match i64::from_str_radix(&value, 16) {
Ok(f) => f,
Err(_) => {
return CalcResult::new_error(
Error::NUM,
cell,
"Error parsing hex number".to_string(),
);
}
};
if value < 0 {
return CalcResult::new_error(Error::NUM, cell, "Negative value".to_string());
}
if value >= HEX_MAX_HALF {
value -= HEX_MAX;
}
CalcResult::Number(value as f64)
}
pub(crate) fn fn_hex2oct(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_string(&args[0], cell) {
Ok(s) => s,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
if value.len() > 10 {
return CalcResult::new_error(Error::NUM, cell, "Value too large".to_string());
}
let mut value = match i64::from_str_radix(&value, 16) {
Ok(f) => f,
Err(_) => {
return CalcResult::new_error(
Error::NUM,
cell,
"Error parsing hex number".to_string(),
);
}
};
if value < 0 {
return CalcResult::new_error(Error::NUM, cell, "Negative value".to_string());
}
if value > HEX_MAX_HALF {
value -= HEX_MAX;
}
if !(-OCT_MAX_HALF..=OCT_MAX_HALF - 1).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += OCT_MAX;
}
let result = format!("{:o}", value);
if let Some(places) = places {
if places <= 0 || (value > 0 && places < result.len() as i32) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$o}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
pub(crate) fn fn_oct2bin(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_string(&args[0], cell) {
Ok(s) => s,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let mut value = match i64::from_str_radix(&value, 8) {
Ok(f) => f,
Err(_) => {
return CalcResult::new_error(
Error::NUM,
cell,
"Error parsing hex number".to_string(),
);
}
};
if value < 0 {
return CalcResult::new_error(Error::NUM, cell, "Negative value".to_string());
}
if value >= OCT_MAX_HALF {
value -= OCT_MAX;
}
if !(-512..=511).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += 1024;
}
let result = format!("{:b}", value);
if let Some(places) = places {
if value < 512 && places < result.len() as i32 {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$b}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
pub(crate) fn fn_oct2dec(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_string(&args[0], cell) {
Ok(s) => s,
Err(s) => return s,
};
let mut value = match i64::from_str_radix(&value, 8) {
Ok(f) => f,
Err(_) => {
return CalcResult::new_error(
Error::NUM,
cell,
"Error parsing hex number".to_string(),
);
}
};
if value < 0 {
return CalcResult::new_error(Error::NUM, cell, "Negative value".to_string());
}
if value >= OCT_MAX_HALF {
value -= OCT_MAX
}
CalcResult::Number(value as f64)
}
pub(crate) fn fn_oct2hex(&mut self, args: &[Node], cell: CellReference) -> CalcResult {
if !(1..=2).contains(&args.len()) {
return CalcResult::new_args_number_error(cell);
}
let value = match self.get_string(&args[0], cell) {
Ok(s) => s,
Err(s) => return s,
};
let places = if args.len() == 2 {
match self.get_number_no_bools(&args[1], cell) {
Ok(f) => Some(f.trunc() as i32),
Err(s) => return s,
}
} else {
None
};
// There is not a default value for places
// But if there is a value it needs to be positive and less than 11
if let Some(p) = places {
if p <= 0 || p > 10 {
return CalcResult::new_error(Error::NUM, cell, "Not enough places".to_string());
}
}
let mut value = match i64::from_str_radix(&value, 8) {
Ok(f) => f,
Err(_) => {
return CalcResult::new_error(
Error::NUM,
cell,
"Error parsing hex number".to_string(),
);
}
};
if value < 0 {
return CalcResult::new_error(Error::NUM, cell, "Negative value".to_string());
}
if value >= OCT_MAX_HALF {
value -= OCT_MAX;
}
if !(-HEX_MAX_HALF..=HEX_MAX_HALF - 1).contains(&value) {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
if value < 0 {
value += HEX_MAX;
}
let result = format!("{:X}", value);
if let Some(places) = places {
if value < HEX_MAX_HALF && places < result.len() as i32 {
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
}
let result = format!("{:0width$X}", value, width = places as usize);
return CalcResult::String(result);
}
CalcResult::String(result)
}
}