refactor: continue refactoring kernel
This commit is contained in:
+26
-38
@@ -1,12 +1,11 @@
|
||||
use crate::common::{
|
||||
Circuit, CircuitCalculator, CircuitCalculatorError, DeviceKind, DeviceValueError,
|
||||
validate_device_value,
|
||||
Circuit, CircuitError, CircuitEvaluation, DeviceKind, DeviceValueError, validate_device_value,
|
||||
};
|
||||
use ordered_float::OrderedFloat;
|
||||
use thiserror::Error as TeError;
|
||||
|
||||
/// The priority of the result.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ResponsePriority {
|
||||
/// Less devices is the first priority.
|
||||
LessDevices,
|
||||
@@ -76,11 +75,15 @@ impl Request {
|
||||
}
|
||||
|
||||
/// Get the target value of this request.
|
||||
///
|
||||
/// The return value was ensured that it must be valid device value.
|
||||
pub fn get_target_value(&self) -> f64 {
|
||||
self.target_value
|
||||
}
|
||||
|
||||
/// Get the tolerance of this request.
|
||||
///
|
||||
/// The return value was ensured that it must be unsigned non-relative valid device value.
|
||||
pub fn get_tolerance(&self) -> f64 {
|
||||
self.tolerance
|
||||
}
|
||||
@@ -91,6 +94,8 @@ impl Request {
|
||||
}
|
||||
|
||||
/// Get the limited count of results.
|
||||
///
|
||||
/// The return value was ensured that it must >= 0 and < [`MAX_RESPONSE_CNT`].
|
||||
pub fn get_count_limit(&self) -> usize {
|
||||
self.count_limit
|
||||
}
|
||||
@@ -99,8 +104,8 @@ impl Request {
|
||||
/// Error occurs when building [Response] and [ResponseItem].
|
||||
#[derive(Debug, TeError)]
|
||||
pub enum ResponseError {
|
||||
#[error("failed on computing circuit properties: {0}")]
|
||||
CircuitCalculator(#[from] CircuitCalculatorError),
|
||||
#[error("failed on evaluating circuit: {0}")]
|
||||
EvaluateCircuit(#[from] CircuitError),
|
||||
}
|
||||
|
||||
/// The possible solution given by the resolver.
|
||||
@@ -108,39 +113,23 @@ pub enum ResponseError {
|
||||
pub struct ResponseItem {
|
||||
/// The circuit of this response item.
|
||||
circuit: Circuit,
|
||||
/// The value of this circuit.
|
||||
value: f64,
|
||||
/// The signed difference.
|
||||
difference: f64,
|
||||
/// The unsigned difference.
|
||||
unsigned_difference: f64,
|
||||
/// The signed relative difference.
|
||||
relative_difference: f64,
|
||||
/// The unsigned relative difference.
|
||||
unsigned_relative_difference: f64,
|
||||
/// The evaluation result of this circuit.
|
||||
circuit_evaluation: CircuitEvaluation,
|
||||
}
|
||||
|
||||
impl ResponseItem {
|
||||
/// Create a new response item by computing all values eagerly.
|
||||
pub fn new(circuit: Circuit, ccalc: &CircuitCalculator) -> Result<Self, ResponseError> {
|
||||
fn new(circuit: Circuit, request: &Request) -> Result<Self, ResponseError> {
|
||||
// YYC MARK:
|
||||
// I can use OnceLock to implement the behavior closing to Python cached_property.
|
||||
// But I didn't do that due to the increased size of this struct, and inviable error handling.
|
||||
// So I decide to calculate all values in there.
|
||||
let value = ccalc.value(&circuit)?;
|
||||
let difference = ccalc.difference(&circuit, Some(value))?;
|
||||
let unsigned_difference = ccalc.unsigned_difference(&circuit, None, Some(difference))?;
|
||||
let relative_difference = ccalc.relative_difference(&circuit, None, Some(difference))?;
|
||||
let unsigned_relative_difference =
|
||||
ccalc.unsigned_relative_difference(&circuit, None, None, Some(relative_difference))?;
|
||||
|
||||
let circuit_evaluation =
|
||||
circuit.evaluate_with_target(request.get_target_value(), request.get_device_kind())?;
|
||||
// Build self and return
|
||||
Ok(Self {
|
||||
circuit,
|
||||
value,
|
||||
difference,
|
||||
unsigned_difference,
|
||||
relative_difference,
|
||||
unsigned_relative_difference,
|
||||
circuit_evaluation,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -156,7 +145,7 @@ impl ResponseItem {
|
||||
|
||||
/// The value of this circuit.
|
||||
pub fn value(&self) -> f64 {
|
||||
self.value
|
||||
self.circuit_evaluation.value
|
||||
}
|
||||
|
||||
/// The signed difference between the target value and the value of this circuit.
|
||||
@@ -164,12 +153,12 @@ impl ResponseItem {
|
||||
/// 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.
|
||||
pub fn difference(&self) -> f64 {
|
||||
self.difference
|
||||
self.circuit_evaluation.difference
|
||||
}
|
||||
|
||||
/// The unsigned difference between the target value and the value of this circuit.
|
||||
pub fn unsigned_difference(&self) -> f64 {
|
||||
self.unsigned_difference
|
||||
self.circuit_evaluation.unsigned_difference
|
||||
}
|
||||
|
||||
/// The signed relative difference between the target value and the value of this circuit.
|
||||
@@ -177,12 +166,12 @@ impl ResponseItem {
|
||||
/// 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.
|
||||
pub fn relative_difference(&self) -> f64 {
|
||||
self.relative_difference
|
||||
self.circuit_evaluation.relative_difference
|
||||
}
|
||||
|
||||
/// The unsigned relative difference between the target value and the value of this circuit.
|
||||
pub fn unsigned_relative_difference(&self) -> f64 {
|
||||
self.unsigned_relative_difference
|
||||
self.circuit_evaluation.unsigned_relative_difference
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,10 +200,9 @@ impl Response {
|
||||
where
|
||||
I: Iterator<Item = Circuit>,
|
||||
{
|
||||
let ccalc = CircuitCalculator::new(request.device_kind, request.target_value)?;
|
||||
let mut items: Vec<ResponseItem> = candidates
|
||||
.into_iter()
|
||||
.map(|c| ResponseItem::new(c, &ccalc))
|
||||
.map(|c| ResponseItem::new(c, request))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
// Sort by different strategy
|
||||
@@ -222,14 +210,14 @@ impl Response {
|
||||
ResponsePriority::LessDevices => {
|
||||
items.sort_by(|a, b| {
|
||||
a.device_count().cmp(&b.device_count()).then_with(|| {
|
||||
OrderedFloat(a.unsigned_difference)
|
||||
.cmp(&OrderedFloat(b.unsigned_difference))
|
||||
OrderedFloat(a.unsigned_difference())
|
||||
.cmp(&OrderedFloat(b.unsigned_difference()))
|
||||
})
|
||||
});
|
||||
}
|
||||
ResponsePriority::MoreAccuracy => {
|
||||
items.sort_by(|a, b| {
|
||||
OrderedFloat(a.unsigned_difference).cmp(&OrderedFloat(b.unsigned_difference))
|
||||
OrderedFloat(a.unsigned_difference()).cmp(&OrderedFloat(b.unsigned_difference()))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+171
-144
@@ -1,9 +1,7 @@
|
||||
use super::{Resolver, ResolverError};
|
||||
use crate::common::{
|
||||
Circuit, CircuitCalculator, CircuitCalculatorError, CircuitError, DeviceKind, JointKind,
|
||||
};
|
||||
use crate::spec::{SpecGroup, SpecCatalog};
|
||||
use crate::common::{Circuit, CircuitError, DeviceKind, JointKind};
|
||||
use crate::query::{Request, Response, ResponseError};
|
||||
use crate::spec::{SpecCatalog, SpecGroup};
|
||||
use itertools::Itertools;
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::cmp::Ordering;
|
||||
@@ -11,15 +9,13 @@ use std::collections::BinaryHeap;
|
||||
use strum::IntoEnumIterator;
|
||||
use thiserror::Error as TeError;
|
||||
|
||||
// region: BFS Resolver Kernel
|
||||
|
||||
/// Error occurs BFS resolver.
|
||||
#[derive(Debug, TeError)]
|
||||
pub enum BfsResolverError {
|
||||
#[error("failed to build circuit: {0}")]
|
||||
Circuit(#[from] CircuitError),
|
||||
#[error("failed on computing circuit properties: {0}")]
|
||||
CircuitCalculator(#[from] CircuitCalculatorError),
|
||||
#[error("the size of binary heap {0} is invalid")]
|
||||
BadBinHeapSize(usize),
|
||||
#[error("failed on evaluating circuit: {0}")]
|
||||
EvaluateCircuit(#[from] CircuitError),
|
||||
#[error("fail to build response: {0}")]
|
||||
Response(#[from] ResponseError),
|
||||
}
|
||||
@@ -38,15 +34,16 @@ pub struct BfsItem {
|
||||
|
||||
impl BfsItem {
|
||||
/// Create a new BFS item by computing values eagerly.
|
||||
pub fn new(circuit: Circuit, ccalc: &CircuitCalculator) -> Result<Self, BfsResolverError> {
|
||||
pub fn new(circuit: Circuit, request: &Request) -> Result<Self, BfsResolverError> {
|
||||
// YYC MARK:
|
||||
// The same reason for replacing cached_property like I done in `ResponseItem`.
|
||||
let value = ccalc.value(&circuit)?;
|
||||
let unsigned_difference = ccalc.unsigned_difference(&circuit, Some(value), None)?;
|
||||
let eval =
|
||||
circuit.evaluate_with_target(request.get_target_value(), request.get_device_kind())?;
|
||||
|
||||
Ok(Self {
|
||||
circuit,
|
||||
value,
|
||||
unsigned_difference,
|
||||
value: eval.value,
|
||||
unsigned_difference: eval.unsigned_difference,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -73,7 +70,153 @@ impl BfsItem {
|
||||
|
||||
// endregion
|
||||
|
||||
// region Result Bucket
|
||||
// region: BFS Resolver
|
||||
|
||||
/// A resolver that uses breadth first search to find the best matching circuits.
|
||||
pub struct BfsResolver {
|
||||
/// The datasets for all device kinds.
|
||||
datasets: SpecCatalog,
|
||||
}
|
||||
|
||||
impl BfsResolver {
|
||||
// YYC MARK:
|
||||
// Some circuit are equivalent in topology.
|
||||
// If we deduplicate these equaivalent circuit in building result, there are too complex works.
|
||||
// So we should deduplicated these equivalent circuit at the beginning, i.e. when generating them.
|
||||
// So following iterator functions are taking this job.
|
||||
//
|
||||
// Additionally, these device values are coming from `spec`.
|
||||
// All values are verified so the building step must success.
|
||||
// So we can safely unwrap them.
|
||||
|
||||
/// Iterate all possible circuits with one device without repeating equivalent topology.
|
||||
pub fn iter_one_device_circuit(specs: &SpecGroup) -> impl Iterator<Item = Circuit> {
|
||||
// Every single device is unique so we directly output them.
|
||||
// This feature is insured by dataset itself.
|
||||
specs
|
||||
.iter()
|
||||
.map(|v1| Circuit::from_one_device(v1).expect("unexpected failure on building circuit"))
|
||||
}
|
||||
|
||||
/// Iterate all possible circuits with two devices without repeating equivalent topology.
|
||||
pub fn iter_two_devices_circuit(specs: &SpecGroup) -> impl Iterator<Item = Circuit> {
|
||||
// The two devices in this circuit is always swapable,
|
||||
// so we iterate them without repeating.
|
||||
itertools::iproduct!(
|
||||
specs.iter().array_combinations_with_replacement::<2>(),
|
||||
JointKind::iter()
|
||||
)
|
||||
.map(|([v1, v2], j2)| {
|
||||
Circuit::from_two_devices(v1, v2, j2).expect("unexpected failure on building circuit")
|
||||
})
|
||||
}
|
||||
|
||||
/// Iterate all possible circuits with three devices without repeating equivalent topology.
|
||||
pub fn iter_three_devices_circuit(specs: &SpecGroup) -> impl Iterator<Item = Circuit> {
|
||||
// For generating three devices circuit,
|
||||
// it should be consisted by 2 parts.
|
||||
itertools::chain!(
|
||||
// First, the whole circuit has only one joint type.
|
||||
// In this case, 3 devices are swapable and we should iterate them without repeating
|
||||
itertools::iproduct!(
|
||||
specs.iter().array_combinations_with_replacement::<3>(),
|
||||
JointKind::iter()
|
||||
)
|
||||
.map(
|
||||
|([v1, v2, v3], j)| Circuit::from_three_devices(v1, v2, j, v3, j)
|
||||
.expect("unexpected failure on building circuit")
|
||||
),
|
||||
// Second, if the joint type is different, then the first 2 devices are swapable.
|
||||
// So we need iterate them without repeating.
|
||||
itertools::iproduct!(
|
||||
specs.iter().array_combinations_with_replacement::<2>(),
|
||||
specs.iter(),
|
||||
JointKind::iter()
|
||||
)
|
||||
.map(|([v1, v2], v3, j)| Circuit::from_three_devices(
|
||||
v1,
|
||||
v2,
|
||||
j,
|
||||
v3,
|
||||
j.flip()
|
||||
)
|
||||
.expect("unexpected failure on building circuit")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl BfsResolver {
|
||||
/// Create a new BFS resolver with the given datasets.
|
||||
pub fn new(datasets: SpecCatalog) -> Self {
|
||||
Self { datasets }
|
||||
}
|
||||
|
||||
fn pick_specs(&self, device_kind: DeviceKind) -> &SpecGroup {
|
||||
match device_kind {
|
||||
DeviceKind::Resistor => self.datasets.resistor_specs(),
|
||||
DeviceKind::Capacitor => self.datasets.capacitor_specs(),
|
||||
DeviceKind::Inductor => self.datasets.inductor_specs(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bfs_iteration(
|
||||
specs: &SpecGroup,
|
||||
request: &Request,
|
||||
) -> impl Iterator<Item = Result<BfsItem, BfsResolverError>> {
|
||||
itertools::chain!(
|
||||
BfsResolver::iter_one_device_circuit(&specs),
|
||||
BfsResolver::iter_two_devices_circuit(&specs),
|
||||
BfsResolver::iter_three_devices_circuit(&specs)
|
||||
)
|
||||
.map(|circuit| BfsItem::new(circuit, request))
|
||||
}
|
||||
|
||||
fn intern_resolve(&self, request: &Request) -> Result<Response, BfsResolverError> {
|
||||
// Pick dataset from collection
|
||||
let specs = self.pick_specs(request.get_device_kind());
|
||||
|
||||
// Create the result bucket.
|
||||
// The count limit held by request is must be greater than zero, so we can simply unwrap it.
|
||||
let mut bucket =
|
||||
ResultBucket::new(request.get_count_limit()).expect("unexpected blank result bucket");
|
||||
|
||||
// Iterate circuit item one by one
|
||||
for item in BfsResolver::bfs_iteration(specs, request) {
|
||||
let item = item?;
|
||||
// If circuit absolute difference is out of tolerance, skip it directly.
|
||||
if item.unsigned_difference() <= request.get_tolerance() {
|
||||
// Put it into bucket
|
||||
let score = item.unsigned_difference();
|
||||
bucket.insert(item, score);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Return result
|
||||
let circuits = bucket.into_iter().map(|i| i.into_circuit());
|
||||
Ok(Response::new(request, circuits)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolver for BfsResolver {
|
||||
fn resolve(&self, request: &Request) -> Result<Response, ResolverError> {
|
||||
Ok(self.intern_resolve(request)?)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion:
|
||||
|
||||
// region: Result Bucket Helper
|
||||
|
||||
/// The error occurs in [`ResultBucket`] and [`ResultBucketItem`].
|
||||
#[derive(Debug, TeError)]
|
||||
enum ResultBucketError {
|
||||
#[error("the size of binary heap {0} is invalid")]
|
||||
BadBinHeapSize(usize),
|
||||
}
|
||||
|
||||
// region: Result Bucket Item
|
||||
|
||||
/// An item stored in a [`ResultBucket`].
|
||||
struct ResultBucketItem {
|
||||
@@ -128,6 +271,10 @@ impl Ord for ResultBucketItem {
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region: Result Bucket
|
||||
|
||||
/// A bounded bucket that keeps up to N entries with the smallest scores.
|
||||
///
|
||||
/// When the bucket is full, inserting a new item only succeeds if its score
|
||||
@@ -145,10 +292,10 @@ pub struct ResultBucket {
|
||||
|
||||
impl ResultBucket {
|
||||
/// Create a new bucket that holds at most `n` items.
|
||||
pub fn new(n: usize) -> Result<Self, BfsResolverError> {
|
||||
pub fn new(n: usize) -> Result<Self, ResultBucketError> {
|
||||
// Check heap size
|
||||
if n == 0 {
|
||||
Err(BfsResolverError::BadBinHeapSize(n))
|
||||
Err(ResultBucketError::BadBinHeapSize(n))
|
||||
} else {
|
||||
Ok(Self {
|
||||
n,
|
||||
@@ -182,6 +329,11 @@ impl ResultBucket {
|
||||
///
|
||||
/// Returns `true` if the item was inserted, `false` otherwise.
|
||||
pub fn insert(&mut self, item: BfsItem, score: f64) -> bool {
|
||||
// YYC MARK:
|
||||
// Because this struct stored `n` is must greater than zero,
|
||||
// so after the first `if` branch, the length of this binary heap must be greater than zero.
|
||||
// So there must be at least one item in binary heap.
|
||||
// and we can safely use `expect()` to peek from binary heap.
|
||||
let entry = ResultBucketItem::new(score, item, self.counter);
|
||||
if self.heap.len() < self.n {
|
||||
self.heap.push(entry);
|
||||
@@ -205,129 +357,4 @@ impl ResultBucket {
|
||||
|
||||
// endregion
|
||||
|
||||
/// A resolver that uses brute-force search to find the best matching circuits.
|
||||
pub struct BfsResolver {
|
||||
/// The datasets for all device kinds.
|
||||
datasets: SpecCatalog,
|
||||
}
|
||||
|
||||
impl BfsResolver {
|
||||
// YYC MARK:
|
||||
// Some circuit are equivalent in topology.
|
||||
// If we deduplicate these equaivalent circuit in building result,
|
||||
// there are too complex works.
|
||||
// So we should deduplicated these equivalent circuit at the beginning,
|
||||
// i.e. when generating them.
|
||||
// So following iterator structs are taking this job.
|
||||
|
||||
/// Iterate all possible circuits with one device without repeating equivalent topology.
|
||||
pub fn iter_one_device_circuit(
|
||||
dataset: &SpecGroup,
|
||||
) -> impl Iterator<Item = Result<Circuit, CircuitError>> {
|
||||
// Every single device is unique so we directly output them.
|
||||
// This feature is insured by dataset itself.
|
||||
dataset.specs().map(|v1| Circuit::from_one_device(v1))
|
||||
}
|
||||
|
||||
/// Iterate all possible circuits with two devices without repeating equivalent topology.
|
||||
pub fn iter_two_devices_circuit(
|
||||
dataset: &SpecGroup,
|
||||
) -> impl Iterator<Item = Result<Circuit, CircuitError>> {
|
||||
// The two devices in this circuit is always swapable,
|
||||
// so we iterate them without repeating.
|
||||
itertools::iproduct!(
|
||||
dataset.specs().array_combinations_with_replacement::<2>(),
|
||||
JointKind::iter()
|
||||
)
|
||||
.map(|([v1, v2], j2)| Circuit::from_two_devices(v1, v2, j2))
|
||||
}
|
||||
|
||||
/// Iterate all possible circuits with three devices without repeating equivalent topology.
|
||||
pub fn iter_three_devices_circuit(
|
||||
dataset: &SpecGroup,
|
||||
) -> impl Iterator<Item = Result<Circuit, CircuitError>> {
|
||||
// For generating three devices circuit,
|
||||
// it should be consisted by 2 parts.
|
||||
itertools::chain!(
|
||||
// First, the whole circuit has only one joint type.
|
||||
// In this case, 3 devices are swapable and we should iterate them without repeating
|
||||
itertools::iproduct!(
|
||||
dataset.specs().array_combinations_with_replacement::<3>(),
|
||||
JointKind::iter()
|
||||
)
|
||||
.map(|([v1, v2, v3], j)| Circuit::from_three_devices(v1, v2, j, v3, j)),
|
||||
// Second, if the joint type is different, then the first 2 devices are swapable.
|
||||
// So we need iterate them without repeating.
|
||||
itertools::iproduct!(
|
||||
dataset.specs().array_combinations_with_replacement::<2>(),
|
||||
dataset.specs(),
|
||||
JointKind::iter()
|
||||
)
|
||||
.map(|([v1, v2], v3, j)| Circuit::from_three_devices(
|
||||
v1,
|
||||
v2,
|
||||
j,
|
||||
v3,
|
||||
j.flip()
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl BfsResolver {
|
||||
/// Create a new BFS resolver with the given datasets.
|
||||
pub fn new(datasets: SpecCatalog) -> Self {
|
||||
Self { datasets }
|
||||
}
|
||||
|
||||
fn pick_dataset(&self, device_kind: DeviceKind) -> &SpecGroup {
|
||||
match device_kind {
|
||||
DeviceKind::Resistor => self.datasets.resistor_specs(),
|
||||
DeviceKind::Capacitor => self.datasets.capacitor_specs(),
|
||||
DeviceKind::Inductor => self.datasets.inductor_specs(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bfs_iteration(
|
||||
dataset: &SpecGroup,
|
||||
ccalc: &CircuitCalculator,
|
||||
) -> impl Iterator<Item = Result<BfsItem, BfsResolverError>> {
|
||||
itertools::chain!(
|
||||
BfsResolver::iter_one_device_circuit(&dataset),
|
||||
BfsResolver::iter_two_devices_circuit(&dataset),
|
||||
BfsResolver::iter_three_devices_circuit(&dataset)
|
||||
)
|
||||
.map(|circuit| -> Result<BfsItem, BfsResolverError> { BfsItem::new(circuit?, ccalc) })
|
||||
}
|
||||
|
||||
fn intern_resolve(&self, request: &Request) -> Result<Response, BfsResolverError> {
|
||||
// Pick dataset from collection
|
||||
let dataset = self.pick_dataset(request.get_device_kind());
|
||||
|
||||
// Iterate circuit item one by one
|
||||
let mut bucket = ResultBucket::new(request.get_count_limit())?;
|
||||
let ccalc = CircuitCalculator::new(request.get_device_kind(), request.get_target_value())?;
|
||||
|
||||
for item in BfsResolver::bfs_iteration(dataset, &ccalc) {
|
||||
let item = item?;
|
||||
// If circuit absolute difference is out of tolerance, skip it directly.
|
||||
if item.unsigned_difference() <= request.get_tolerance() {
|
||||
// Put it into bucket
|
||||
let score = item.unsigned_difference();
|
||||
bucket.insert(item, score);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Return result
|
||||
let circuits = bucket.into_iter().map(|i| i.into_circuit());
|
||||
Ok(Response::new(request, circuits)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolver for BfsResolver {
|
||||
fn resolve(&self, request: &Request) -> Result<Response, ResolverError> {
|
||||
Ok(self.intern_resolve(request)?)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
@@ -156,7 +156,7 @@ impl SpecGroup {
|
||||
Self::from_iterator([
|
||||
"100", "220", "270", "390", "470", "680", "1k", "1.2k", "1.5k", "2.2k", "3.3k", "4.7k",
|
||||
"6.8k", "10k", "47k", "100k", "1M",
|
||||
]).expect("unexpected bad rated values set")
|
||||
]).expect("unexpected bad rated values preset")
|
||||
}
|
||||
|
||||
/// A commonly used set of capacitor rated values.
|
||||
@@ -164,7 +164,7 @@ impl SpecGroup {
|
||||
Self::from_iterator([
|
||||
"10p", "22p", "33p", "47p", "68p", "100p", "150p", "220p", "330p", "470p", "560p",
|
||||
"1u", "2.2u", "3.3u", "4.7u", "10u", "22u", "47u", "100u", "220u", "470u",
|
||||
]).expect("unexpected bad rated values set")
|
||||
]).expect("unexpected bad rated values preset")
|
||||
}
|
||||
|
||||
/// A commonly used set of inductor rated values.
|
||||
@@ -172,7 +172,7 @@ impl SpecGroup {
|
||||
Self::from_iterator([
|
||||
"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",
|
||||
]).expect("unexpected bad rated values set")
|
||||
]).expect("unexpected bad rated values preset")
|
||||
}
|
||||
|
||||
fn save(&self) -> impl Iterator<Item = &str> {
|
||||
@@ -218,7 +218,7 @@ impl SpecGroup {
|
||||
}
|
||||
|
||||
/// Iterate over all numeric rated values in this group.
|
||||
pub fn specs(&self) -> impl Iterator<Item = f64> + Clone {
|
||||
pub fn iter(&self) -> impl Iterator<Item = f64> + Clone {
|
||||
self.specs.iter().map(|i| i.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
use lcrconn::spec;
|
||||
|
||||
#[test]
|
||||
fn test_spec_preset() {
|
||||
// All individual preset and catalog preset should nit panic
|
||||
let specs = spec::SpecGroup::resistor_preset();
|
||||
let specs = spec::SpecGroup::capacitor_preset();
|
||||
let specs = spec::SpecGroup::inductor_preset();
|
||||
|
||||
let specs = spec::SpecCatalog::devices_preset();
|
||||
}
|
||||
Reference in New Issue
Block a user