use core::fmt;
use core::num::NonZeroUsize;
use core::time::Duration;
use crate::progress::ProgressReportingConfig;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Parallelism {
Auto,
Threads(NonZeroUsize),
}
impl Parallelism {
#[must_use]
pub const fn threads(count: usize) -> Option<Self> {
match NonZeroUsize::new(count) {
Some(count) => Some(Self::Threads(count)),
None => None,
}
}
}
#[derive(Clone, Debug, Default)]
pub(crate) struct FactorTuning {
pub(crate) relation_percent: Option<usize>,
pub(crate) small_skip: Option<u32>,
pub(crate) threshold_margin: Option<i32>,
pub(crate) threshold_adjustment: Option<i32>,
pub(crate) factor_base_bound: Option<u32>,
pub(crate) sieve_half_width: Option<u32>,
pub(crate) profile: bool,
}
#[derive(Clone, Debug)]
pub struct FactorConfig {
pub(crate) parallelism: Parallelism,
pub(crate) witness_seed: Option<[u8; 32]>,
pub(crate) tuning: FactorTuning,
pub(crate) progress_reporting: ProgressReportingConfig,
}
impl FactorConfig {
#[must_use]
pub const fn parallelism(&self) -> Parallelism {
self.parallelism
}
#[must_use]
pub fn with_parallelism(mut self, parallelism: Parallelism) -> Self {
self.parallelism = parallelism;
self
}
#[must_use]
pub const fn progress_interval(&self) -> Duration {
self.progress_reporting.minimum_interval
}
#[must_use]
pub fn with_progress_interval(mut self, interval: Duration) -> Self {
self.progress_reporting.minimum_interval = interval;
self
}
#[must_use]
pub fn with_witness_seed(mut self, seed: [u8; 32]) -> Self {
self.witness_seed = Some(seed);
self
}
#[doc(hidden)]
#[must_use]
#[allow(clippy::too_many_arguments)]
pub fn with_tuning_overrides(
mut self,
relation_percent: Option<usize>,
small_skip: Option<u32>,
threshold_margin: Option<i32>,
threshold_adjustment: Option<i32>,
factor_base_bound: Option<u32>,
sieve_half_width: Option<u32>,
profile: bool,
) -> Self {
self.tuning = FactorTuning {
relation_percent,
small_skip,
threshold_margin,
threshold_adjustment,
factor_base_bound,
sieve_half_width,
profile,
};
self
}
}
impl Default for FactorConfig {
fn default() -> Self {
Self {
parallelism: Parallelism::Auto,
witness_seed: None,
tuning: FactorTuning::default(),
progress_reporting: ProgressReportingConfig::default(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ResourceLimitKind {
Memory,
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum FactorError {
ZeroHasNoPrimeFactorization,
CapacityExceeded,
InputTooLarge,
ResourceLimit(ResourceLimitKind),
NoNontrivialFactor,
InsufficientRelations,
PolynomialSelection(String),
InvalidDependency,
WorkerFailure(String),
Cancelled,
InternalFailure,
}
impl fmt::Display for FactorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ZeroHasNoPrimeFactorization => f.write_str("zero has no prime factorization"),
Self::CapacityExceeded => f.write_str("integer capacity exceeded"),
Self::InputTooLarge => f.write_str("SIQS supports inputs of at most 512 bits"),
Self::ResourceLimit(kind) => write!(f, "resource limit exceeded: {kind:?}"),
Self::NoNontrivialFactor => f.write_str("no nontrivial factor found"),
Self::InsufficientRelations => f.write_str("insufficient quadratic-sieve relations"),
Self::PolynomialSelection(message) => f.write_str(message),
Self::InvalidDependency => f.write_str("invalid matrix dependency"),
Self::WorkerFailure(message) => write!(f, "worker failed: {message}"),
Self::Cancelled => f.write_str("factorization cancelled"),
Self::InternalFailure => f.write_str("internal factorization invariant failed"),
}
}
}
impl std::error::Error for FactorError {}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ProgressAction {
Continue,
Cancel,
}