use std::{fmt, ops}; pub struct Fraction { num: i64, den: i64, } #[derive(Debug)] pub enum FractionError { DivisionByZero, ZeroDenominator, Overflow, } impl fmt::Display for FractionError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { FractionError::DivisionByZero => write!(f, "Division by zero"), FractionError::ZeroDenominator => write!(f, "Denominator can't be zero"), FractionError::Overflow => write!(f, "Numeric overflow"), } } } impl std::error::Error for FractionError {} impl Fraction { pub fn new(num: i64, den: i64) -> Result { if den == 0 { return Err(FractionError::ZeroDenominator); } Ok(Fraction { num, den }) } pub fn reciprocal(&self) -> Result { todo!() } pub fn abs(&self) -> Self { todo!() } pub fn is_zero(&self) -> bool { todo!() } pub fn is_integer(&self) -> bool { todo!() } fn gcd(a: i64, b: i64) -> i64 { todo!(); } fn reduce(&mut self) { todo!(); } } impl ops::Mul for Fraction { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { todo!() } } impl ops::Add for Fraction { type Output = Self; fn add(self, rhs: Self) -> Self::Output { todo!() } } impl ops::Div for Fraction { type Output = Result; fn div(self, rhs: Self) -> Self::Output { todo!() } } impl ops::Sub for Fraction { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { todo!() } } impl ops::Neg for Fraction { type Output = Self; fn neg(self) -> Self::Output { todo!() } } impl fmt::Display for Fraction { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!() } } impl From for Fraction { fn from(value: i32) -> Self { todo!() } } impl From for Fraction { fn from(value: i64) -> Self { todo!() } } impl TryFrom<(i32, i32)> for Fraction { type Error = FractionError; fn try_from(value: (i32, i32)) -> Result { todo!() } } impl TryFrom<(i64, i64)> for Fraction { type Error = FractionError; fn try_from(value: (i64, i64)) -> Result { todo!() } } #[cfg(test)] mod tests { use super::*; }