1//! # Calculator Library
  2//!
  3//! A simple calculator library demonstrating Rust documentation with sphinx-rust.
  4//!
  5//! This crate provides basic arithmetic operations and a calculator struct
  6//! that maintains a history of operations.
  7//!
  8//! ## Example
  9//!
 10//! ```rust
 11//! use calculator::{Calculator, Operation};
 12//!
 13//! let mut calc = Calculator::new();
 14//! let result = calc.calculate(5.0, 3.0, Operation::Add);
 15//! assert_eq!(result, 8.0);
 16//! ```
 17
 18mod operations;
 19
 20pub use operations::{Operation, OperationResult};
 21
 22/// A calculator that performs basic arithmetic operations.
 23///
 24/// The `Calculator` struct maintains a history of all operations performed,
 25/// allowing users to review previous calculations.
 26///
 27/// # Examples
 28///
 29/// ```rust
 30/// use calculator::Calculator;
 31///
 32/// let mut calc = Calculator::new();
 33/// let sum = calc.add(10.0, 5.0);
 34/// assert_eq!(sum, 15.0);
 35/// ```
 36#[derive(Debug, Default)]
 37pub struct Calculator {
 38    /// History of operations performed
 39    history: Vec<OperationResult>,
 40}
 41
 42impl Calculator {
 43    /// Creates a new Calculator instance with an empty history.
 44    ///
 45    /// # Returns
 46    ///
 47    /// A new `Calculator` with no operation history.
 48    ///
 49    /// # Examples
 50    ///
 51    /// ```rust
 52    /// use calculator::Calculator;
 53    ///
 54    /// let calc = Calculator::new();
 55    /// assert!(calc.history().is_empty());
 56    /// ```
 57    #[must_use]
 58    pub fn new() -> Self {
 59        Self {
 60            history: Vec::new(),
 61        }
 62    }
 63
 64    /// Adds two numbers together.
 65    ///
 66    /// # Arguments
 67    ///
 68    /// * `a` - The first operand
 69    /// * `b` - The second operand
 70    ///
 71    /// # Returns
 72    ///
 73    /// The sum of `a` and `b`.
 74    ///
 75    /// # Examples
 76    ///
 77    /// ```rust
 78    /// use calculator::Calculator;
 79    ///
 80    /// let mut calc = Calculator::new();
 81    /// assert_eq!(calc.add(2.0, 3.0), 5.0);
 82    /// ```
 83    pub fn add(&mut self, a: f64, b: f64) -> f64 {
 84        let result = a + b;
 85        self.record(a, b, Operation::Add, result);
 86        result
 87    }
 88
 89    /// Subtracts the second number from the first.
 90    ///
 91    /// # Arguments
 92    ///
 93    /// * `a` - The minuend
 94    /// * `b` - The subtrahend
 95    ///
 96    /// # Returns
 97    ///
 98    /// The difference `a - b`.
 99    ///
100    /// # Examples
101    ///
102    /// ```rust
103    /// use calculator::Calculator;
104    ///
105    /// let mut calc = Calculator::new();
106    /// assert_eq!(calc.subtract(10.0, 4.0), 6.0);
107    /// ```
108    pub fn subtract(&mut self, a: f64, b: f64) -> f64 {
109        let result = a - b;
110        self.record(a, b, Operation::Subtract, result);
111        result
112    }
113
114    /// Multiplies two numbers together.
115    ///
116    /// # Arguments
117    ///
118    /// * `a` - The first factor
119    /// * `b` - The second factor
120    ///
121    /// # Returns
122    ///
123    /// The product of `a` and `b`.
124    ///
125    /// # Examples
126    ///
127    /// ```rust
128    /// use calculator::Calculator;
129    ///
130    /// let mut calc = Calculator::new();
131    /// assert_eq!(calc.multiply(3.0, 4.0), 12.0);
132    /// ```
133    pub fn multiply(&mut self, a: f64, b: f64) -> f64 {
134        let result = a * b;
135        self.record(a, b, Operation::Multiply, result);
136        result
137    }
138
139    /// Divides the first number by the second.
140    ///
141    /// # Arguments
142    ///
143    /// * `a` - The dividend
144    /// * `b` - The divisor
145    ///
146    /// # Returns
147    ///
148    /// The quotient `a / b`, or an error if `b` is zero.
149    ///
150    /// # Errors
151    ///
152    /// Returns a `DivisionByZero` error if `b` is zero.
153    ///
154    /// # Examples
155    ///
156    /// ```rust
157    /// use calculator::Calculator;
158    ///
159    /// let mut calc = Calculator::new();
160    /// assert_eq!(calc.divide(10.0, 2.0).unwrap(), 5.0);
161    /// assert!(calc.divide(10.0, 0.0).is_err());
162    /// ```
163    pub fn divide(&mut self, a: f64, b: f64) -> Result<f64, CalculatorError> {
164        if b == 0.0 {
165            return Err(CalculatorError::DivisionByZero);
166        }
167        let result = a / b;
168        self.record(a, b, Operation::Divide, result);
169        Ok(result)
170    }
171
172    /// Performs a calculation using the specified operation.
173    ///
174    /// # Arguments
175    ///
176    /// * `a` - The first operand
177    /// * `b` - The second operand
178    /// * `op` - The operation to perform
179    ///
180    /// # Returns
181    ///
182    /// The result of the operation.
183    ///
184    /// # Panics
185    ///
186    /// Panics if dividing by zero. Use [`Calculator::divide`] for safe division.
187    pub fn calculate(&mut self, a: f64, b: f64, op: Operation) -> f64 {
188        match op {
189            Operation::Add => self.add(a, b),
190            Operation::Subtract => self.subtract(a, b),
191            Operation::Multiply => self.multiply(a, b),
192            Operation::Divide => self.divide(a, b).expect("Division by zero"),
193        }
194    }
195
196    /// Returns a reference to the operation history.
197    ///
198    /// # Returns
199    ///
200    /// A slice containing all operations performed by this calculator.
201    #[must_use]
202    pub fn history(&self) -> &[OperationResult] {
203        &self.history
204    }
205
206    /// Clears the operation history.
207    ///
208    /// # Examples
209    ///
210    /// ```rust
211    /// use calculator::Calculator;
212    ///
213    /// let mut calc = Calculator::new();
214    /// calc.add(1.0, 2.0);
215    /// assert!(!calc.history().is_empty());
216    /// calc.clear_history();
217    /// assert!(calc.history().is_empty());
218    /// ```
219    pub fn clear_history(&mut self) {
220        self.history.clear();
221    }
222
223    /// Records an operation in the history.
224    fn record(&mut self, a: f64, b: f64, op: Operation, result: f64) {
225        self.history.push(OperationResult {
226            operand_a: a,
227            operand_b: b,
228            operation: op,
229            result,
230        });
231    }
232}
233
234/// Errors that can occur during calculator operations.
235#[derive(Debug, Clone, PartialEq, Eq)]
236pub enum CalculatorError {
237    /// Attempted to divide by zero.
238    DivisionByZero,
239    /// The result overflowed.
240    Overflow,
241}
242
243impl std::fmt::Display for CalculatorError {
244    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245        match self {
246            Self::DivisionByZero => write!(f, "Cannot divide by zero"),
247            Self::Overflow => write!(f, "Calculation resulted in overflow"),
248        }
249    }
250}
251
252impl std::error::Error for CalculatorError {}
253
254/// A scientific calculator with additional mathematical functions.
255///
256/// Extends the basic [`Calculator`] with trigonometric, logarithmic,
257/// and other advanced mathematical operations.
258#[derive(Debug, Default)]
259pub struct ScientificCalculator {
260    /// The underlying basic calculator
261    basic: Calculator,
262    /// Whether to use degrees (true) or radians (false) for trig functions
263    use_degrees: bool,
264}
265
266impl ScientificCalculator {
267    /// Creates a new ScientificCalculator.
268    ///
269    /// By default, trigonometric functions use radians.
270    #[must_use]
271    pub fn new() -> Self {
272        Self {
273            basic: Calculator::new(),
274            use_degrees: false,
275        }
276    }
277
278    /// Sets whether to use degrees for trigonometric functions.
279    ///
280    /// # Arguments
281    ///
282    /// * `use_degrees` - If true, trig functions expect degrees; if false, radians.
283    pub fn set_use_degrees(&mut self, use_degrees: bool) {
284        self.use_degrees = use_degrees;
285    }
286
287    /// Calculates the sine of an angle.
288    ///
289    /// # Arguments
290    ///
291    /// * `angle` - The angle (in degrees or radians based on settings)
292    ///
293    /// # Returns
294    ///
295    /// The sine of the angle.
296    #[must_use]
297    pub fn sin(&self, angle: f64) -> f64 {
298        let radians = if self.use_degrees {
299            angle.to_radians()
300        } else {
301            angle
302        };
303        radians.sin()
304    }
305
306    /// Calculates the cosine of an angle.
307    ///
308    /// # Arguments
309    ///
310    /// * `angle` - The angle (in degrees or radians based on settings)
311    ///
312    /// # Returns
313    ///
314    /// The cosine of the angle.
315    #[must_use]
316    pub fn cos(&self, angle: f64) -> f64 {
317        let radians = if self.use_degrees {
318            angle.to_radians()
319        } else {
320            angle
321        };
322        radians.cos()
323    }
324
325    /// Calculates the natural logarithm of a number.
326    ///
327    /// # Arguments
328    ///
329    /// * `x` - The number (must be positive)
330    ///
331    /// # Returns
332    ///
333    /// The natural logarithm of x, or an error if x <= 0.
334    pub fn ln(&self, x: f64) -> Result<f64, CalculatorError> {
335        if x <= 0.0 {
336            return Err(CalculatorError::Overflow);
337        }
338        Ok(x.ln())
339    }
340
341    /// Calculates the square root of a number.
342    ///
343    /// # Arguments
344    ///
345    /// * `x` - The number (must be non-negative)
346    ///
347    /// # Returns
348    ///
349    /// The square root of x, or NaN if x is negative.
350    #[must_use]
351    pub fn sqrt(&self, x: f64) -> f64 {
352        x.sqrt()
353    }
354
355    /// Raises a number to a power.
356    ///
357    /// # Arguments
358    ///
359    /// * `base` - The base number
360    /// * `exponent` - The exponent
361    ///
362    /// # Returns
363    ///
364    /// `base` raised to the power of `exponent`.
365    #[must_use]
366    pub fn pow(&self, base: f64, exponent: f64) -> f64 {
367        base.powf(exponent)
368    }
369
370    /// Returns a reference to the underlying basic calculator.
371    #[must_use]
372    pub fn basic(&self) -> &Calculator {
373        &self.basic
374    }
375
376    /// Returns a mutable reference to the underlying basic calculator.
377    pub fn basic_mut(&mut self) -> &mut Calculator {
378        &mut self.basic
379    }
380}
381
382#[cfg(test)]
383mod tests {
384    use super::*;
385
386    #[test]
387    fn test_add() {
388        let mut calc = Calculator::new();
389        assert_eq!(calc.add(2.0, 3.0), 5.0);
390    }
391
392    #[test]
393    fn test_subtract() {
394        let mut calc = Calculator::new();
395        assert_eq!(calc.subtract(10.0, 4.0), 6.0);
396    }
397
398    #[test]
399    fn test_multiply() {
400        let mut calc = Calculator::new();
401        assert_eq!(calc.multiply(3.0, 4.0), 12.0);
402    }
403
404    #[test]
405    fn test_divide() {
406        let mut calc = Calculator::new();
407        assert_eq!(calc.divide(10.0, 2.0).unwrap(), 5.0);
408    }
409
410    #[test]
411    fn test_divide_by_zero() {
412        let mut calc = Calculator::new();
413        assert!(calc.divide(10.0, 0.0).is_err());
414    }
415
416    #[test]
417    fn test_history() {
418        let mut calc = Calculator::new();
419        calc.add(1.0, 2.0);
420        calc.subtract(5.0, 3.0);
421        assert_eq!(calc.history().len(), 2);
422    }
423}