1
0

fix: update kernel common

This commit is contained in:
2026-06-29 10:06:00 +08:00
parent ccd96e6801
commit 9d9c0473e8
2 changed files with 181 additions and 176 deletions

View File

@@ -1,6 +1,41 @@
use strum_macros::EnumIter; use strum_macros::EnumIter;
use thiserror::Error as TeError; use thiserror::Error as TeError;
// region: Sanitizer
#[derive(Debug, TeError)]
#[error("given floating value {0} is invalid")]
pub struct FloatingPointError(f64);
pub fn sanitize_floating_point(f: f64) -> Result<f64, FloatingPointError> {
if f.is_finite() {
Ok(f)
} else {
Err(FloatingPointError(f))
}
}
#[derive(Debug, TeError)]
pub enum DeviceValueError {
#[error("{0}")]
BadFloatingPoint(#[from] FloatingPointError),
#[error("given device value {0} is out of range")]
OutOfRange(f64),
}
pub fn sanitize_device_value(f: f64) -> Result<f64, DeviceValueError> {
let f = sanitize_floating_point(f)?;
if f > 0f64 {
Ok(f)
} else {
Err(DeviceValueError::OutOfRange(f))
}
}
// endregion
// region: Circuit Utilities
/// The kind of device. /// The kind of device.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum DeviceKind { pub enum DeviceKind {
@@ -35,82 +70,6 @@ impl JointKind {
} }
} }
/// Error occurs when manipulating [SubCircuit].
#[derive(Debug, TeError)]
pub enum SubCircuitError {
#[error("given circuit device value {0} should greater than zero")]
BadDeviceValue(f64),
#[error("the previous computed circuit value {0} should greater than zero")]
BadPreviousValue(f64),
#[error("bad float point arithmetic")]
BadArithmetic,
}
/// The part of circuit composed of two devices and the joint kind.
#[derive(Debug, Clone)]
pub struct SubCircuit {
/// The value of the device.
device_value: f64,
/// The joint kind between this device and the next device.
joint_kind: JointKind,
}
impl SubCircuit {
/// Initialize subcircuit with given device value and joint kind.
///
/// The input device value should greater than zero,
/// otherwise an error will return.
pub fn new(device_value: f64, joint_kind: JointKind) -> Result<Self, SubCircuitError> {
if device_value > 0f64 {
Ok(Self {
device_value,
joint_kind,
})
} else {
Err(SubCircuitError::BadDeviceValue(device_value))
}
}
/// Compute the joint value with given previous computed value and device kind.
///
/// Parameter `value` should be the value computed from previous devices.
/// And it should greater than zero.
/// `device_kind` is the kind of the device.
pub fn compute(&self, value: f64, device_kind: DeviceKind) -> Result<f64, SubCircuitError> {
// Check the range of provided value for computing
if !(value > 0f64) {
return Err(SubCircuitError::BadPreviousValue(value));
}
// We perform series connect for: series resistor, series inductor and parallel capacitor.
// We perform parallel connect for: parallel resistor, parallel inductor and series capacitor.
let joint_kind = match device_kind {
DeviceKind::Capacitor => self.joint_kind.flip(),
_ => self.joint_kind,
};
let rv = match joint_kind {
JointKind::Series => self.device_value + value,
JointKind::Parallel => (self.device_value * value) / (self.device_value + value),
};
if rv.is_finite() {
Ok(rv)
} else {
Err(SubCircuitError::BadArithmetic)
}
}
/// Get the device value.
pub fn device_value(&self) -> f64 {
self.device_value
}
/// Get the joint kind.
pub fn joint_kind(&self) -> JointKind {
self.joint_kind
}
}
/// The scale of devices in the circuit. /// The scale of devices in the circuit.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum CircuitDeviceScale { pub enum CircuitDeviceScale {
@@ -134,11 +93,84 @@ impl CircuitDeviceScale {
} }
} }
// endregion
// region: Circuit Stuff
/// Error occurs when manipulating [SubCircuit].
#[derive(Debug, TeError)]
pub enum SubCircuitError {
#[error("invalid device value in circuit: {0}")]
BadDeviceValue(DeviceValueError),
#[error("bad previous computed circuit value: {0}")]
BadPreviousValue(DeviceValueError),
#[error("arithmetic error: {0}")]
BadArithmetic(FloatingPointError),
}
/// The part of circuit composed of two devices and the joint kind.
#[derive(Debug, Clone)]
pub struct SubCircuit {
/// The value of the device.
device_value: f64,
/// The joint kind between this device and the next device.
joint_kind: JointKind,
}
impl SubCircuit {
/// Initialize subcircuit with given device value and joint kind.
///
/// The input device value should greater than zero,
/// otherwise an error will return.
pub fn new(device_value: f64, joint_kind: JointKind) -> Result<Self, SubCircuitError> {
let device_value = sanitize_device_value(device_value)
.map_err(|err| SubCircuitError::BadDeviceValue(err))?;
Ok(Self {
device_value,
joint_kind,
})
}
/// Compute the joint value with given previous computed value and device kind.
///
/// Parameter `value` should be the value computed from previous devices.
/// And it should greater than zero.
/// `device_kind` is the kind of the device.
pub fn compute(&self, value: f64, device_kind: DeviceKind) -> Result<f64, SubCircuitError> {
// Check the range of provided value for computing
let value =
sanitize_device_value(value).map_err(|err| SubCircuitError::BadPreviousValue(err))?;
// We perform series connect for: series resistor, series inductor and parallel capacitor.
// We perform parallel connect for: parallel resistor, parallel inductor and series capacitor.
let joint_kind = match device_kind {
DeviceKind::Capacitor => self.joint_kind.flip(),
_ => self.joint_kind,
};
sanitize_floating_point(match joint_kind {
JointKind::Series => self.device_value + value,
JointKind::Parallel => (self.device_value * value) / (self.device_value + value),
})
.map_err(|err| SubCircuitError::BadArithmetic(err))
}
/// Get the device value.
pub fn device_value(&self) -> f64 {
self.device_value
}
/// Get the joint kind.
pub fn joint_kind(&self) -> JointKind {
self.joint_kind
}
}
/// Error occurs when manipulating [Circuit]. /// Error occurs when manipulating [Circuit].
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
pub enum CircuitError { pub enum CircuitError {
#[error("given circuit device value {0} should greater than zero")] #[error("invalid device value in circuit: {0}")]
BadDeviceValue(f64), BadDeviceValue(DeviceValueError),
#[error("third device cannot exist without second device when building circuit")] #[error("third device cannot exist without second device when building circuit")]
BlankSecondSubCircuit, BlankSecondSubCircuit,
#[error("{0}")] #[error("{0}")]
@@ -170,9 +202,8 @@ impl Circuit {
third_device_subckt: Option<SubCircuit>, third_device_subckt: Option<SubCircuit>,
) -> Result<Self, CircuitError> { ) -> Result<Self, CircuitError> {
// Check the value of first device // Check the value of first device
if !(first_device_value > 0f64) { let first_device_value = sanitize_device_value(first_device_value)
return Err(CircuitError::BadDeviceValue(first_device_value)); .map_err(|err| CircuitError::BadDeviceValue(err))?;
}
// Check impossible form // Check impossible form
if second_device_subckt.is_none() && third_device_subckt.is_some() { if second_device_subckt.is_none() && third_device_subckt.is_some() {
return Err(CircuitError::BlankSecondSubCircuit); return Err(CircuitError::BlankSecondSubCircuit);
@@ -292,14 +323,14 @@ impl Circuit {
/// Error occurs when manipulating [CircuitCalculator]. /// Error occurs when manipulating [CircuitCalculator].
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
pub enum CircuitCalculatorError { pub enum CircuitCalculatorError {
#[error("given target value {0} should be greater than zero")] #[error("invalid target value: {0}")]
BadTargetValue(f64), BadTargetValue(DeviceValueError),
#[error("{0}")] #[error("{0}")]
Circuit(#[from] CircuitError), Circuit(#[from] CircuitError),
#[error("bad float point arithmetic")] #[error("arithmetic error: {0}")]
BadArithmetic, BadArithmetic(FloatingPointError),
#[error("provided value {0} reducing computation steps is invalid")] #[error("bad provided value reducing computation steps: {0}")]
BadReuseValue(f64), BadReuseValue(FloatingPointError),
} }
/// The helper for circuit value computation. /// The helper for circuit value computation.
@@ -314,14 +345,12 @@ pub struct CircuitCalculator {
impl CircuitCalculator { impl CircuitCalculator {
/// Initialize this calculator with given device kind and target value. /// Initialize this calculator with given device kind and target value.
pub fn new(device_kind: DeviceKind, target_value: f64) -> Result<Self, CircuitCalculatorError> { pub fn new(device_kind: DeviceKind, target_value: f64) -> Result<Self, CircuitCalculatorError> {
if target_value > 0f64 { let target_value = sanitize_device_value(target_value)
Ok(Self { .map_err(|err| CircuitCalculatorError::BadTargetValue(err))?;
device_kind, Ok(Self {
target_value, device_kind,
}) target_value,
} else { })
Err(CircuitCalculatorError::BadTargetValue(target_value))
}
} }
/// The value of this circuit. /// The value of this circuit.
@@ -343,22 +372,13 @@ impl CircuitCalculator {
value: Option<f64>, value: Option<f64>,
) -> Result<f64, CircuitCalculatorError> { ) -> Result<f64, CircuitCalculatorError> {
let value = match value { let value = match value {
Some(v) => { Some(v) => sanitize_floating_point(v)
if v.is_finite() { .map_err(|err| CircuitCalculatorError::BadReuseValue(err))?,
v
} else {
return Err(CircuitCalculatorError::BadReuseValue(v));
}
}
None => self.value(circuit)?, None => self.value(circuit)?,
}; };
let rv = value - self.target_value; sanitize_floating_point(value - self.target_value)
if rv.is_finite() { .map_err(|err| CircuitCalculatorError::BadArithmetic(err))
Ok(rv)
} else {
Err(CircuitCalculatorError::BadArithmetic)
}
} }
/// The unsigned difference between the target value and the value of this circuit. /// The unsigned difference between the target value and the value of this circuit.
@@ -376,22 +396,13 @@ impl CircuitCalculator {
difference: Option<f64>, difference: Option<f64>,
) -> Result<f64, CircuitCalculatorError> { ) -> Result<f64, CircuitCalculatorError> {
let diff = match difference { let diff = match difference {
Some(d) => { Some(d) => sanitize_floating_point(d)
if d.is_finite() { .map_err(|err| CircuitCalculatorError::BadReuseValue(err))?,
d
} else {
return Err(CircuitCalculatorError::BadReuseValue(d));
}
}
None => self.difference(circuit, value)?, None => self.difference(circuit, value)?,
}; };
let rv = diff.abs(); sanitize_floating_point(diff.abs())
if rv.is_finite() { .map_err(|err| CircuitCalculatorError::BadArithmetic(err))
Ok(rv)
} else {
Err(CircuitCalculatorError::BadArithmetic)
}
} }
/// The signed relative difference between the target value and the value of this circuit. /// The signed relative difference between the target value and the value of this circuit.
@@ -412,22 +423,13 @@ impl CircuitCalculator {
difference: Option<f64>, difference: Option<f64>,
) -> Result<f64, CircuitCalculatorError> { ) -> Result<f64, CircuitCalculatorError> {
let diff = match difference { let diff = match difference {
Some(d) => { Some(d) => sanitize_floating_point(d)
if d.is_finite() { .map_err(|err| CircuitCalculatorError::BadReuseValue(err))?,
d
} else {
return Err(CircuitCalculatorError::BadReuseValue(d));
}
}
None => self.difference(circuit, value)?, None => self.difference(circuit, value)?,
}; };
let rv = diff / self.target_value; sanitize_floating_point(diff / self.target_value)
if rv.is_finite() { .map_err(|err| CircuitCalculatorError::BadArithmetic(err))
Ok(rv)
} else {
Err(CircuitCalculatorError::BadArithmetic)
}
} }
/// The unsigned relative difference between the target value and the value of this circuit. /// The unsigned relative difference between the target value and the value of this circuit.
@@ -450,21 +452,14 @@ impl CircuitCalculator {
relative_difference: Option<f64>, relative_difference: Option<f64>,
) -> Result<f64, CircuitCalculatorError> { ) -> Result<f64, CircuitCalculatorError> {
let rel_diff = match relative_difference { let rel_diff = match relative_difference {
Some(rd) => { Some(rd) => sanitize_floating_point(rd)
if rd.is_finite() { .map_err(|err| CircuitCalculatorError::BadReuseValue(err))?,
rd
} else {
return Err(CircuitCalculatorError::BadReuseValue(rd));
}
}
None => self.relative_difference(circuit, value, difference)?, None => self.relative_difference(circuit, value, difference)?,
}; };
let rv = rel_diff.abs(); sanitize_floating_point(rel_diff.abs())
if rv.is_finite() { .map_err(|err| CircuitCalculatorError::BadArithmetic(err))
Ok(rv)
} else {
Err(CircuitCalculatorError::BadArithmetic)
}
} }
} }
// endregion

View File

@@ -1,7 +1,12 @@
use thiserror::Error as TeError;
use std::collections::HashSet; use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use crate::common::LcrConnError; /// Error occurs when building dataset.
#[derive(Debug, TeError)]
pub enum DatasetError {
}
/// An item in the dataset. /// An item in the dataset.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -17,14 +22,14 @@ impl DatasetItem {
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`LcrConnError::InvalidDatasetValue`] if the value is not greater than 0. /// Returns [`DatasetError::InvalidDatasetValue`] if the value is not greater than 0.
/// Returns [`LcrConnError::EmptyDatasetItem`] if the string value is empty. /// Returns [`DatasetError::EmptyDatasetItem`] if the string value is empty.
pub fn new(value: f64, str_value: String) -> Result<Self, LcrConnError> { pub fn new(value: f64, str_value: String) -> Result<Self, DatasetError> {
if value <= 0.0 { if value <= 0.0 {
return Err(LcrConnError::InvalidDatasetValue(value)); return Err(DatasetError::InvalidDatasetValue(value));
} }
if str_value.is_empty() { if str_value.is_empty() {
return Err(LcrConnError::EmptyDatasetItem); return Err(DatasetError::EmptyDatasetItem);
} }
Ok(Self { value, str_value }) Ok(Self { value, str_value })
} }
@@ -46,10 +51,10 @@ impl Dataset {
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`LcrConnError::DuplicateDatasetItem`] if duplicate values are found. /// Returns [`DatasetError::DuplicateDatasetItem`] if duplicate values are found.
/// Returns [`LcrConnError::EmptyDataset`] if the iterable produces no items. /// Returns [`DatasetError::EmptyDataset`] if the iterable produces no items.
/// Returns [`LcrConnError::InvalidHumanReadableValue`] if a value cannot be parsed. /// Returns [`DatasetError::InvalidHumanReadableValue`] if a value cannot be parsed.
pub fn from_iterable<I, S>(str_values: I) -> Result<Self, LcrConnError> pub fn from_iterable<I, S>(str_values: I) -> Result<Self, DatasetError>
where where
I: IntoIterator<Item = S>, I: IntoIterator<Item = S>,
S: Into<String>, S: Into<String>,
@@ -64,7 +69,7 @@ impl Dataset {
let value = from_human_readable_value(&str_value)?; let value = from_human_readable_value(&str_value)?;
// Check and update set // Check and update set
if !seen.insert(value) { if !seen.insert(value) {
return Err(LcrConnError::DuplicateDatasetItem(str_value)); return Err(DatasetError::DuplicateDatasetItem(str_value));
} }
// Add into result // Add into result
items.push(DatasetItem::new(value, str_value)?); items.push(DatasetItem::new(value, str_value)?);
@@ -72,7 +77,7 @@ impl Dataset {
// Check empty case // Check empty case
if items.is_empty() { if items.is_empty() {
return Err(LcrConnError::EmptyDataset); return Err(DatasetError::EmptyDataset);
} }
// Ok, assign it // Ok, assign it
@@ -86,7 +91,7 @@ impl Dataset {
/// # Errors /// # Errors
/// ///
/// See [`Dataset::from_iterable`]. /// See [`Dataset::from_iterable`].
pub fn from_text(text: &str) -> Result<Self, LcrConnError> { pub fn from_text(text: &str) -> Result<Self, DatasetError> {
let lines: Vec<String> = text let lines: Vec<String> = text
.lines() .lines()
.map(|line| line.trim().to_string()) .map(|line| line.trim().to_string())
@@ -99,9 +104,9 @@ impl Dataset {
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`LcrConnError::Io`] if the file cannot be read. /// Returns [`DatasetError::Io`] if the file cannot be read.
/// See [`Dataset::from_iterable`] for other errors. /// See [`Dataset::from_iterable`] for other errors.
pub fn from_file(path: impl AsRef<Path>) -> Result<Self, LcrConnError> { pub fn from_file(path: impl AsRef<Path>) -> Result<Self, DatasetError> {
let text = std::fs::read_to_string(path)?; let text = std::fs::read_to_string(path)?;
Self::from_text(&text) Self::from_text(&text)
} }
@@ -111,7 +116,7 @@ impl Dataset {
/// # Errors /// # Errors
/// ///
/// See [`Dataset::from_iterable`]. /// See [`Dataset::from_iterable`].
pub fn resistor_preset() -> Result<Self, LcrConnError> { pub fn resistor_preset() -> Result<Self, DatasetError> {
Self::from_iterable([ Self::from_iterable([
"100", "220", "270", "390", "470", "680", "1k", "1.2k", "1.5k", "2.2k", "3.3k", "100", "220", "270", "390", "470", "680", "1k", "1.2k", "1.5k", "2.2k", "3.3k",
"4.7k", "6.8k", "10k", "47k", "100k", "1M", "4.7k", "6.8k", "10k", "47k", "100k", "1M",
@@ -123,7 +128,7 @@ impl Dataset {
/// # Errors /// # Errors
/// ///
/// See [`Dataset::from_iterable`]. /// See [`Dataset::from_iterable`].
pub fn capacitor_preset() -> Result<Self, LcrConnError> { pub fn capacitor_preset() -> Result<Self, DatasetError> {
Self::from_iterable([ Self::from_iterable([
"10p", "22p", "33p", "47p", "68p", "100p", "150p", "220p", "330p", "470p", "560p", "10p", "22p", "33p", "47p", "68p", "100p", "150p", "220p", "330p", "470p", "560p",
"1u", "2.2u", "3.3u", "4.7u", "10u", "22u", "47u", "100u", "220u", "470u", "1u", "2.2u", "3.3u", "4.7u", "10u", "22u", "47u", "100u", "220u", "470u",
@@ -135,7 +140,7 @@ impl Dataset {
/// # Errors /// # Errors
/// ///
/// See [`Dataset::from_iterable`]. /// See [`Dataset::from_iterable`].
pub fn inductor_preset() -> Result<Self, LcrConnError> { pub fn inductor_preset() -> Result<Self, DatasetError> {
Self::from_iterable([ Self::from_iterable([
"0.1u", "0.15u", "0.47u", "0.68u", "1u", "1.5u", "2.2u", "3.3u", "4.7u", "6.8u", "0.1u", "0.15u", "0.47u", "0.68u", "1u", "1.5u", "2.2u", "3.3u", "4.7u", "6.8u",
"8.2u", "10u", "15u", "22u", "33u", "47u", "68u", "100u", "8.2u", "10u", "15u", "22u", "33u", "47u", "68u", "100u",
@@ -155,8 +160,8 @@ impl Dataset {
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`LcrConnError::Io`] if the file cannot be written. /// Returns [`DatasetError::Io`] if the file cannot be written.
pub fn save_file(&self, path: impl AsRef<Path>) -> Result<(), LcrConnError> { pub fn save_file(&self, path: impl AsRef<Path>) -> Result<(), DatasetError> {
std::fs::write(path, self.save_text())?; std::fs::write(path, self.save_text())?;
Ok(()) Ok(())
} }
@@ -206,7 +211,7 @@ impl DatasetCollection {
resistor: I1, resistor: I1,
capacitor: I2, capacitor: I2,
inductor: I3, inductor: I3,
) -> Result<Self, LcrConnError> ) -> Result<Self, DatasetError>
where where
I1: IntoIterator<Item = S1>, I1: IntoIterator<Item = S1>,
S1: Into<String>, S1: Into<String>,
@@ -233,7 +238,7 @@ impl DatasetCollection {
/// # Errors /// # Errors
/// ///
/// See [`Dataset::from_text`]. /// See [`Dataset::from_text`].
pub fn from_text(resistor: &str, capacitor: &str, inductor: &str) -> Result<Self, LcrConnError> { pub fn from_text(resistor: &str, capacitor: &str, inductor: &str) -> Result<Self, DatasetError> {
Ok(Self { Ok(Self {
resistor: Dataset::from_text(resistor)?, resistor: Dataset::from_text(resistor)?,
capacitor: Dataset::from_text(capacitor)?, capacitor: Dataset::from_text(capacitor)?,
@@ -256,7 +261,7 @@ impl DatasetCollection {
resistor: impl AsRef<Path>, resistor: impl AsRef<Path>,
capacitor: impl AsRef<Path>, capacitor: impl AsRef<Path>,
inductor: impl AsRef<Path>, inductor: impl AsRef<Path>,
) -> Result<Self, LcrConnError> { ) -> Result<Self, DatasetError> {
Ok(Self { Ok(Self {
resistor: Dataset::from_file(resistor)?, resistor: Dataset::from_file(resistor)?,
capacitor: Dataset::from_file(capacitor)?, capacitor: Dataset::from_file(capacitor)?,
@@ -269,7 +274,7 @@ impl DatasetCollection {
/// # Errors /// # Errors
/// ///
/// See [`Dataset::from_iterable`]. /// See [`Dataset::from_iterable`].
pub fn devices_preset() -> Result<Self, LcrConnError> { pub fn devices_preset() -> Result<Self, DatasetError> {
Ok(Self { Ok(Self {
resistor: Dataset::resistor_preset()?, resistor: Dataset::resistor_preset()?,
capacitor: Dataset::capacitor_preset()?, capacitor: Dataset::capacitor_preset()?,
@@ -300,13 +305,13 @@ impl DatasetCollection {
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`LcrConnError::Io`] if any file cannot be written. /// Returns [`DatasetError::Io`] if any file cannot be written.
pub fn save_file( pub fn save_file(
&self, &self,
resistor: impl AsRef<Path>, resistor: impl AsRef<Path>,
capacitor: impl AsRef<Path>, capacitor: impl AsRef<Path>,
inductor: impl AsRef<Path>, inductor: impl AsRef<Path>,
) -> Result<(), LcrConnError> { ) -> Result<(), DatasetError> {
self.resistor.save_file(resistor)?; self.resistor.save_file(resistor)?;
self.capacitor.save_file(capacitor)?; self.capacitor.save_file(capacitor)?;
self.inductor.save_file(inductor)?; self.inductor.save_file(inductor)?;
@@ -329,6 +334,11 @@ impl DatasetCollection {
} }
} }
#[derive(Debug, TeError)]
pub enum ParseHumanReadableValueError {
}
/// Convert human readable value to float. /// Convert human readable value to float.
/// ///
/// # Arguments /// # Arguments
@@ -341,8 +351,8 @@ impl DatasetCollection {
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`LcrConnError::InvalidHumanReadableValue`] if the input string is not a valid number. /// Returns [`DatasetError::InvalidHumanReadableValue`] if the input string is not a valid number.
pub fn from_human_readable_value(strl: &str) -> Result<f64, LcrConnError> { pub fn from_human_readable_value(strl: &str) -> Result<f64, ParseHumanReadableValueError> {
let strl = strl.trim(); let strl = strl.trim();
let (num_part, multiplier) = if let Some(stripped) = strl.strip_suffix('n') { let (num_part, multiplier) = if let Some(stripped) = strl.strip_suffix('n') {
@@ -366,7 +376,7 @@ pub fn from_human_readable_value(strl: &str) -> Result<f64, LcrConnError> {
num_part num_part
.parse::<f64>() .parse::<f64>()
.map(|v| v * multiplier) .map(|v| v * multiplier)
.map_err(|_| LcrConnError::InvalidHumanReadableValue(strl.to_string())) .map_err(|_| DatasetError::InvalidHumanReadableValue(strl.to_string()))
} }
/// The unit scale for human readable value. /// The unit scale for human readable value.