|
|
|
|
@@ -1,50 +1,6 @@
|
|
|
|
|
use strum::IntoEnumIterator;
|
|
|
|
|
use strum_macros::EnumIter;
|
|
|
|
|
use thiserror::Error as TeError;
|
|
|
|
|
|
|
|
|
|
// /// The error thrown by LCR Connector.
|
|
|
|
|
// #[derive(Debug, TeError)]
|
|
|
|
|
// pub enum LcrConnError {
|
|
|
|
|
// #[error("Device value must be greater than 0")]
|
|
|
|
|
// InvalidDeviceValue,
|
|
|
|
|
|
|
|
|
|
// #[error("Third device cannot exist without second device")]
|
|
|
|
|
// ThirdDeviceWithoutSecond,
|
|
|
|
|
|
|
|
|
|
// #[error("No second device")]
|
|
|
|
|
// NoSecondDevice,
|
|
|
|
|
|
|
|
|
|
// #[error("No third device")]
|
|
|
|
|
// NoThirdDevice,
|
|
|
|
|
|
|
|
|
|
// #[error("Invalid value {0} in dataset")]
|
|
|
|
|
// InvalidDatasetValue(f64),
|
|
|
|
|
|
|
|
|
|
// #[error("Unexpected empty string in dataset item")]
|
|
|
|
|
// EmptyDatasetItem,
|
|
|
|
|
|
|
|
|
|
// #[error("Duplicate item {0} in standard value list")]
|
|
|
|
|
// DuplicateDatasetItem(String),
|
|
|
|
|
|
|
|
|
|
// #[error("Empty standard value list is not allowed")]
|
|
|
|
|
// EmptyDataset,
|
|
|
|
|
|
|
|
|
|
// #[error("Invalid value {0} for target value in request")]
|
|
|
|
|
// InvalidTargetValue(f64),
|
|
|
|
|
|
|
|
|
|
// #[error("Invalid value {0} for tolerance in request")]
|
|
|
|
|
// InvalidTolerance(f64),
|
|
|
|
|
|
|
|
|
|
// #[error("Too large or too less value {0} for response count limit in request")]
|
|
|
|
|
// InvalidCountLimit(usize),
|
|
|
|
|
|
|
|
|
|
// #[error("Invalid human readable value: {0}")]
|
|
|
|
|
// InvalidHumanReadableValue(String),
|
|
|
|
|
|
|
|
|
|
// #[error(transparent)]
|
|
|
|
|
// Io(#[from] std::io::Error),
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
/// The kind of device.
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
|
pub enum DeviceKind {
|
|
|
|
|
@@ -79,6 +35,17 @@ 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 {
|
|
|
|
|
@@ -90,55 +57,47 @@ pub struct SubCircuit {
|
|
|
|
|
|
|
|
|
|
impl SubCircuit {
|
|
|
|
|
/// Initialize subcircuit with given device value and joint kind.
|
|
|
|
|
///
|
|
|
|
|
/// # Panics
|
|
|
|
|
///
|
|
|
|
|
/// This function will panic if given device value is equal or lower than zero.
|
|
|
|
|
pub fn new(device_value: f64, joint_kind: JointKind) -> Self {
|
|
|
|
|
// Make sure value is greater than zero.
|
|
|
|
|
assert!(
|
|
|
|
|
device_value > 0f64,
|
|
|
|
|
"given device value {} should greater than zero",
|
|
|
|
|
device_value
|
|
|
|
|
);
|
|
|
|
|
// Okey, build and return self
|
|
|
|
|
Self {
|
|
|
|
|
device_value,
|
|
|
|
|
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.
|
|
|
|
|
/// Compute the joint value with given previous computed value and device kind.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `value` - The value computed from previous devices.
|
|
|
|
|
/// * `device_kind` - The kind of the device.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The joint value computed.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::InvalidDeviceValue`] if any device value is not greater than 0.
|
|
|
|
|
pub fn compute(&self, value: f64, device_kind: DeviceKind) -> Result<f64, LcrConnError> {
|
|
|
|
|
if self.device_value <= 0.0 || value <= 0.0 {
|
|
|
|
|
return Err(LcrConnError::InvalidDeviceValue);
|
|
|
|
|
/// 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 = if device_kind == DeviceKind::Capacitor {
|
|
|
|
|
self.joint_kind.flip()
|
|
|
|
|
} else {
|
|
|
|
|
self.joint_kind
|
|
|
|
|
let joint_kind = match device_kind {
|
|
|
|
|
DeviceKind::Capacitor => self.joint_kind.flip(),
|
|
|
|
|
_ => self.joint_kind,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(match 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.
|
|
|
|
|
@@ -153,7 +112,7 @@ impl SubCircuit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The scale of devices in the circuit.
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
|
pub enum CircuitDeviceScale {
|
|
|
|
|
/// One device.
|
|
|
|
|
One,
|
|
|
|
|
@@ -165,10 +124,7 @@ pub enum CircuitDeviceScale {
|
|
|
|
|
|
|
|
|
|
impl CircuitDeviceScale {
|
|
|
|
|
/// Convert circuit device scale to device count.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The device count.
|
|
|
|
|
/// The return value only can be 1, 2, and 3.
|
|
|
|
|
pub fn to_device_count(self) -> usize {
|
|
|
|
|
match self {
|
|
|
|
|
CircuitDeviceScale::One => 1,
|
|
|
|
|
@@ -178,6 +134,19 @@ impl CircuitDeviceScale {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Error occurs when manipulating [Circuit].
|
|
|
|
|
#[derive(Debug, TeError)]
|
|
|
|
|
pub enum CircuitError {
|
|
|
|
|
#[error("given circuit device value {0} should greater than zero")]
|
|
|
|
|
BadDeviceValue(f64),
|
|
|
|
|
#[error("third device cannot exist without second device when building circuit")]
|
|
|
|
|
BlankSecondSubCircuit,
|
|
|
|
|
#[error("{0}")]
|
|
|
|
|
SubCircuit(#[from] SubCircuitError),
|
|
|
|
|
#[error("the joint or device with given index is not presented in circuit")]
|
|
|
|
|
NoSuchDevice,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The circuit composed of multiple joints.
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct Circuit {
|
|
|
|
|
@@ -190,27 +159,26 @@ pub struct Circuit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Circuit {
|
|
|
|
|
/// Initialize the circuit.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
/// Initialize the circuit with subcircuit.
|
|
|
|
|
///
|
|
|
|
|
/// * `first_device_value` - The value of the first device.
|
|
|
|
|
/// * `second_device_subckt` - The second device and its joint property.
|
|
|
|
|
/// * `third_device_subckt` - The third device and its joint property.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::ThirdDeviceWithoutSecond`] if a third device is provided
|
|
|
|
|
/// without a second device.
|
|
|
|
|
pub fn new(
|
|
|
|
|
fn new(
|
|
|
|
|
first_device_value: f64,
|
|
|
|
|
second_device_subckt: Option<SubCircuit>,
|
|
|
|
|
third_device_subckt: Option<SubCircuit>,
|
|
|
|
|
) -> Result<Self, LcrConnError> {
|
|
|
|
|
) -> Result<Self, CircuitError> {
|
|
|
|
|
// Check the value of first device
|
|
|
|
|
if !(first_device_value > 0f64) {
|
|
|
|
|
return Err(CircuitError::BadDeviceValue(first_device_value));
|
|
|
|
|
}
|
|
|
|
|
// Check impossible form
|
|
|
|
|
if second_device_subckt.is_none() && third_device_subckt.is_some() {
|
|
|
|
|
return Err(LcrConnError::ThirdDeviceWithoutSecond);
|
|
|
|
|
return Err(CircuitError::BlankSecondSubCircuit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Everything is okey
|
|
|
|
|
Ok(Self {
|
|
|
|
|
first_device_value,
|
|
|
|
|
second_device_subckt,
|
|
|
|
|
@@ -219,12 +187,8 @@ impl Circuit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create a circuit from a single device.
|
|
|
|
|
pub fn from_one_device(device1_value: f64) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
first_device_value: device1_value,
|
|
|
|
|
second_device_subckt: None,
|
|
|
|
|
third_device_subckt: None,
|
|
|
|
|
}
|
|
|
|
|
pub fn from_one_device(device1_value: f64) -> Result<Self, CircuitError> {
|
|
|
|
|
Self::new(device1_value, None, None)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create a circuit from two devices.
|
|
|
|
|
@@ -232,12 +196,12 @@ impl Circuit {
|
|
|
|
|
device1_value: f64,
|
|
|
|
|
device2_value: f64,
|
|
|
|
|
device2_joint: JointKind,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
first_device_value: device1_value,
|
|
|
|
|
second_device_subckt: Some(SubCircuit::new(device2_value, device2_joint)),
|
|
|
|
|
third_device_subckt: None,
|
|
|
|
|
}
|
|
|
|
|
) -> Result<Self, CircuitError> {
|
|
|
|
|
Self::new(
|
|
|
|
|
device1_value,
|
|
|
|
|
Some(SubCircuit::new(device2_value, device2_joint)?),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create a circuit from three devices.
|
|
|
|
|
@@ -247,41 +211,28 @@ impl Circuit {
|
|
|
|
|
device2_joint: JointKind,
|
|
|
|
|
device3_value: f64,
|
|
|
|
|
device3_joint: JointKind,
|
|
|
|
|
) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
first_device_value: device1_value,
|
|
|
|
|
second_device_subckt: Some(SubCircuit::new(device2_value, device2_joint)),
|
|
|
|
|
third_device_subckt: Some(SubCircuit::new(device3_value, device3_joint)),
|
|
|
|
|
}
|
|
|
|
|
) -> Result<Self, CircuitError> {
|
|
|
|
|
Self::new(
|
|
|
|
|
device1_value,
|
|
|
|
|
Some(SubCircuit::new(device2_value, device2_joint)?),
|
|
|
|
|
Some(SubCircuit::new(device3_value, device3_joint)?),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Compute the circuit value.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `device_kind` - The kind of the device.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The circuit value.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::InvalidDeviceValue`] if any device value is not greater than 0.
|
|
|
|
|
pub fn compute(&self, device_kind: DeviceKind) -> Result<f64, LcrConnError> {
|
|
|
|
|
if self.first_device_value <= 0.0 {
|
|
|
|
|
return Err(LcrConnError::InvalidDeviceValue);
|
|
|
|
|
/// Compute the circuit value with given value and device kind
|
|
|
|
|
pub fn compute(&self, device_kind: DeviceKind) -> Result<f64, CircuitError> {
|
|
|
|
|
let mut value = self.first_device_value;
|
|
|
|
|
|
|
|
|
|
match &self.second_device_subckt {
|
|
|
|
|
Some(subckt) => value = subckt.compute(value, device_kind)?,
|
|
|
|
|
None => return Ok(value),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut value = self.first_device_value;
|
|
|
|
|
if let Some(subckt) = &self.second_device_subckt {
|
|
|
|
|
value = subckt.compute(value, device_kind)?;
|
|
|
|
|
} else {
|
|
|
|
|
return Ok(value);
|
|
|
|
|
}
|
|
|
|
|
if let Some(subckt) = &self.third_device_subckt {
|
|
|
|
|
value = subckt.compute(value, device_kind)?;
|
|
|
|
|
match &self.third_device_subckt {
|
|
|
|
|
Some(subckt) => value = subckt.compute(value, device_kind)?,
|
|
|
|
|
None => return Ok(value),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -306,82 +257,76 @@ impl Circuit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get the joint kind of the second device.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::NoSecondDevice`] if there is no second device.
|
|
|
|
|
pub fn second_device_joint(&self) -> Result<JointKind, LcrConnError> {
|
|
|
|
|
pub fn second_device_joint(&self) -> Result<JointKind, CircuitError> {
|
|
|
|
|
self.second_device_subckt
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|s| s.joint_kind())
|
|
|
|
|
.ok_or(LcrConnError::NoSecondDevice)
|
|
|
|
|
.ok_or(CircuitError::NoSuchDevice)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get the value of the second device.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::NoSecondDevice`] if there is no second device.
|
|
|
|
|
pub fn second_device_value(&self) -> Result<f64, LcrConnError> {
|
|
|
|
|
pub fn second_device_value(&self) -> Result<f64, CircuitError> {
|
|
|
|
|
self.second_device_subckt
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|s| s.device_value())
|
|
|
|
|
.ok_or(LcrConnError::NoSecondDevice)
|
|
|
|
|
.ok_or(CircuitError::NoSuchDevice)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get the joint kind of the third device.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::NoThirdDevice`] if there is no third device.
|
|
|
|
|
pub fn third_device_joint(&self) -> Result<JointKind, LcrConnError> {
|
|
|
|
|
pub fn third_device_joint(&self) -> Result<JointKind, CircuitError> {
|
|
|
|
|
self.third_device_subckt
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|s| s.joint_kind())
|
|
|
|
|
.ok_or(LcrConnError::NoThirdDevice)
|
|
|
|
|
.ok_or(CircuitError::NoSuchDevice)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get the value of the third device.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Returns [`LcrConnError::NoThirdDevice`] if there is no third device.
|
|
|
|
|
pub fn third_device_value(&self) -> Result<f64, LcrConnError> {
|
|
|
|
|
pub fn third_device_value(&self) -> Result<f64, CircuitError> {
|
|
|
|
|
self.third_device_subckt
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|s| s.device_value())
|
|
|
|
|
.ok_or(LcrConnError::NoThirdDevice)
|
|
|
|
|
.ok_or(CircuitError::NoSuchDevice)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Error occurs when manipulating [CircuitCalculator].
|
|
|
|
|
#[derive(Debug, TeError)]
|
|
|
|
|
pub enum CircuitCalculatorError {
|
|
|
|
|
#[error("given target value {0} should be greater than zero")]
|
|
|
|
|
BadTargetValue(f64),
|
|
|
|
|
#[error("{0}")]
|
|
|
|
|
Circuit(#[from] CircuitError),
|
|
|
|
|
#[error("bad float point arithmetic")]
|
|
|
|
|
BadArithmetic,
|
|
|
|
|
#[error("provided value {0} reducing computation steps is invalid")]
|
|
|
|
|
BadReuseValue(f64),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The helper for circuit value computation.
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct CircuitValueTrait {
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct CircuitCalculator {
|
|
|
|
|
/// The kind of the device.
|
|
|
|
|
device_kind: DeviceKind,
|
|
|
|
|
/// The target value.
|
|
|
|
|
target_value: f64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CircuitValueTrait {
|
|
|
|
|
pub fn new(device_kind: DeviceKind, target_value: f64) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
device_kind,
|
|
|
|
|
target_value,
|
|
|
|
|
impl CircuitCalculator {
|
|
|
|
|
/// Initialize this calculator with given device kind and target value.
|
|
|
|
|
pub fn new(device_kind: DeviceKind, target_value: f64) -> Result<Self, CircuitCalculatorError> {
|
|
|
|
|
if target_value > 0f64 {
|
|
|
|
|
Ok(Self {
|
|
|
|
|
device_kind,
|
|
|
|
|
target_value,
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
Err(CircuitCalculatorError::BadTargetValue(target_value))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The value of this circuit.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `circuit` - The circuit for computation.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The value.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// See [`Circuit::compute`].
|
|
|
|
|
pub fn value(&self, circuit: &Circuit) -> Result<f64, LcrConnError> {
|
|
|
|
|
circuit.compute(self.device_kind)
|
|
|
|
|
pub fn value(&self, circuit: &Circuit) -> Result<f64, CircuitCalculatorError> {
|
|
|
|
|
Ok(circuit.compute(self.device_kind)?)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The signed difference between the target value and the value of this circuit.
|
|
|
|
|
@@ -389,56 +334,64 @@ impl CircuitValueTrait {
|
|
|
|
|
/// Positive value indicates that the value of this circuit is greater than the target value.
|
|
|
|
|
/// Negative value indicates that the value of this circuit is less than the target value.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `circuit` - The circuit for computation.
|
|
|
|
|
/// * `value` - The value of the circuit computed by the [`value`](Self::value) method
|
|
|
|
|
/// for reducing computation steps, or `None` if you request this method to compute the value.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The signed difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// See [`Circuit::compute`].
|
|
|
|
|
pub fn difference(&self, circuit: &Circuit, value: Option<f64>) -> Result<f64, LcrConnError> {
|
|
|
|
|
pub fn difference(
|
|
|
|
|
&self,
|
|
|
|
|
circuit: &Circuit,
|
|
|
|
|
value: Option<f64>,
|
|
|
|
|
) -> Result<f64, CircuitCalculatorError> {
|
|
|
|
|
let value = match value {
|
|
|
|
|
Some(v) => v,
|
|
|
|
|
Some(v) => {
|
|
|
|
|
if v.is_finite() {
|
|
|
|
|
v
|
|
|
|
|
} else {
|
|
|
|
|
return Err(CircuitCalculatorError::BadReuseValue(v));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => self.value(circuit)?,
|
|
|
|
|
};
|
|
|
|
|
Ok(value - self.target_value)
|
|
|
|
|
|
|
|
|
|
let rv = value - self.target_value;
|
|
|
|
|
if rv.is_finite() {
|
|
|
|
|
Ok(rv)
|
|
|
|
|
} else {
|
|
|
|
|
Err(CircuitCalculatorError::BadArithmetic)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The unsigned difference between the target value and the value of this circuit.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `circuit` - The circuit for computation.
|
|
|
|
|
/// * `value` - The value of the circuit computed by the [`value`](Self::value) method
|
|
|
|
|
/// for reducing computation steps, or `None` if you request this method to compute the value.
|
|
|
|
|
/// * `difference` - The difference of the circuit computed by the
|
|
|
|
|
/// [`difference`](Self::difference) method for reducing computation steps,
|
|
|
|
|
/// or `None` if you request this method to compute the difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The unsigned difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// See [`Circuit::compute`].
|
|
|
|
|
pub fn unsigned_difference(
|
|
|
|
|
&self,
|
|
|
|
|
circuit: &Circuit,
|
|
|
|
|
value: Option<f64>,
|
|
|
|
|
difference: Option<f64>,
|
|
|
|
|
) -> Result<f64, LcrConnError> {
|
|
|
|
|
) -> Result<f64, CircuitCalculatorError> {
|
|
|
|
|
let diff = match difference {
|
|
|
|
|
Some(d) => d,
|
|
|
|
|
Some(d) => {
|
|
|
|
|
if d.is_finite() {
|
|
|
|
|
d
|
|
|
|
|
} else {
|
|
|
|
|
return Err(CircuitCalculatorError::BadReuseValue(d));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => self.difference(circuit, value)?,
|
|
|
|
|
};
|
|
|
|
|
Ok(diff.abs())
|
|
|
|
|
|
|
|
|
|
let rv = diff.abs();
|
|
|
|
|
if rv.is_finite() {
|
|
|
|
|
Ok(rv)
|
|
|
|
|
} else {
|
|
|
|
|
Err(CircuitCalculatorError::BadArithmetic)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The signed relative difference between the target value and the value of this circuit.
|
|
|
|
|
@@ -446,39 +399,39 @@ impl CircuitValueTrait {
|
|
|
|
|
/// Positive value indicates that the value of this circuit is greater than the target value.
|
|
|
|
|
/// Negative value indicates that the value of this circuit is less than the target value.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `circuit` - The circuit for computation.
|
|
|
|
|
/// * `value` - The value of the circuit computed by the [`value`](Self::value) method
|
|
|
|
|
/// for reducing computation steps, or `None` if you request this method to compute the value.
|
|
|
|
|
/// * `difference` - The difference of the circuit computed by the
|
|
|
|
|
/// [`difference`](Self::difference) method for reducing computation steps,
|
|
|
|
|
/// or `None` if you request this method to compute the difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The signed relative difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// See [`Circuit::compute`].
|
|
|
|
|
pub fn relative_difference(
|
|
|
|
|
&self,
|
|
|
|
|
circuit: &Circuit,
|
|
|
|
|
value: Option<f64>,
|
|
|
|
|
difference: Option<f64>,
|
|
|
|
|
) -> Result<f64, LcrConnError> {
|
|
|
|
|
) -> Result<f64, CircuitCalculatorError> {
|
|
|
|
|
let diff = match difference {
|
|
|
|
|
Some(d) => d,
|
|
|
|
|
Some(d) => {
|
|
|
|
|
if d.is_finite() {
|
|
|
|
|
d
|
|
|
|
|
} else {
|
|
|
|
|
return Err(CircuitCalculatorError::BadReuseValue(d));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => self.difference(circuit, value)?,
|
|
|
|
|
};
|
|
|
|
|
Ok(diff / self.target_value)
|
|
|
|
|
|
|
|
|
|
let rv = diff / self.target_value;
|
|
|
|
|
if rv.is_finite() {
|
|
|
|
|
Ok(rv)
|
|
|
|
|
} else {
|
|
|
|
|
Err(CircuitCalculatorError::BadArithmetic)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The unsigned relative difference between the target value and the value of this circuit.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `circuit` - The circuit for computation.
|
|
|
|
|
/// * `value` - The value of the circuit computed by the [`value`](Self::value) method
|
|
|
|
|
/// for reducing computation steps, or `None` if you request this method to compute the value.
|
|
|
|
|
@@ -489,24 +442,29 @@ impl CircuitValueTrait {
|
|
|
|
|
/// [`relative_difference`](Self::relative_difference) method for reducing computation steps,
|
|
|
|
|
/// or `None` if you request this method to compute the relative difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// The unsigned relative difference.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// See [`Circuit::compute`].
|
|
|
|
|
pub fn unsigned_relative_difference(
|
|
|
|
|
&self,
|
|
|
|
|
circuit: &Circuit,
|
|
|
|
|
value: Option<f64>,
|
|
|
|
|
difference: Option<f64>,
|
|
|
|
|
relative_difference: Option<f64>,
|
|
|
|
|
) -> Result<f64, LcrConnError> {
|
|
|
|
|
) -> Result<f64, CircuitCalculatorError> {
|
|
|
|
|
let rel_diff = match relative_difference {
|
|
|
|
|
Some(rd) => rd,
|
|
|
|
|
Some(rd) => {
|
|
|
|
|
if rd.is_finite() {
|
|
|
|
|
rd
|
|
|
|
|
} else {
|
|
|
|
|
return Err(CircuitCalculatorError::BadReuseValue(rd));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => self.relative_difference(circuit, value, difference)?,
|
|
|
|
|
};
|
|
|
|
|
Ok(rel_diff.abs())
|
|
|
|
|
|
|
|
|
|
let rv = rel_diff.abs();
|
|
|
|
|
if rv.is_finite() {
|
|
|
|
|
Ok(rv)
|
|
|
|
|
} else {
|
|
|
|
|
Err(CircuitCalculatorError::BadArithmetic)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|