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}