1use std::ops::{Add,Sub,Mul,Div,AddAssign,SubAssign,MulAssign,DivAssign};
2
3use std::cmp::max;
4use std::num::ParseFloatError;
5
6use arkley_traits::Power;
7
8use crate::ParsingStandardFormError;
9
10#[derive(Debug,PartialEq)]
15pub struct StandardForm {
16 mantissa : f64,
17 exponent : i8
18}
19
20impl StandardForm {
21 pub fn new(mantissa : f64,exponent : i8) -> Self {
23 let mut instance = Self { mantissa , exponent};
24 instance.adjust();
25 instance
26 }
27
28
29 fn in_range(&self) -> bool {
30 (self.mantissa >= 1.0 && self.mantissa <= 10.0) || (self.mantissa >= -10.0 && self.mantissa <= -1.0)
31 }
32
33 fn adjust(&mut self) {
34 if self.in_range() || self.mantissa == 0.0 {
35 return;
36 }
37
38 match self.mantissa > -1.0 && self.mantissa < 1.0 {
40 true => while !self.in_range() {
41 self.mantissa *= 10.0;
42 self.exponent -= 1;
43 },
44 false => while !self.in_range() {
45 self.mantissa /= 10.0;
46 self.exponent += 1;
47 }
48 }
49 }
50
51 pub const fn mantissa(&self) -> &f64 {
53 &self.mantissa
54 }
55
56 pub const fn exponent(&self) -> &i8 {
58 &self.exponent
59 }
60
61 pub fn to_scientific_notation(&self) -> String {
63 format!("{}e{}", self.mantissa, self.exponent)
64 }
65
66 pub fn to_engineering_notation(&self) -> String {
68 format!("{}*10^{}", self.mantissa, self.exponent)
69 }
70
71 pub fn as_decimal(&self) -> Result<f64, ParseFloatError>{
75 self.to_engineering_notation().parse()
76 }
77
78}
79
80impl Default for StandardForm {
81 fn default() -> Self {
82 Self { mantissa : 1.0, exponent : 0 }
83 }
84}
85
86impl std::fmt::Display for StandardForm {
87 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
88 if self.exponent > 4 {
89 return write!(f,"{}",self.to_scientific_notation());
90 };
91
92 write!(f,"{}",self.mantissa * 10_i32.pow(self.exponent as u32) as f64)
93 }
94}
95
96impl PartialOrd for StandardForm {
97 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
98 match self.exponent == other.exponent {
99 true => self.mantissa.partial_cmp(&other.mantissa),
100 false => self.exponent.partial_cmp(&other.exponent)
101 }
102 }
103}
104
105impl TryFrom<&str> for StandardForm {
106 type Error = ParsingStandardFormError;
107
108 fn try_from(value: &str) -> Result<Self, Self::Error> {
109 if let Ok(number) = value.parse::<f64>() {
110 return Ok(number.into());
111 }
112
113 if let Some(index) = value.find('e') {
114 let m_str : f64 = value[0..index].parse().map_err(|error| ParsingStandardFormError::Mantissa(error) )?;
115 let e_str : i8 = value[index + 1..].parse().map_err(|error| ParsingStandardFormError::Exponent(error) )?;
116 return Ok(StandardForm::new(m_str,e_str));
117 }
118
119 if let Some(index) = value.find('^') {
120 let m_str : f64 = value[0..index - 2].parse().map_err(|error| ParsingStandardFormError::Mantissa(error) )?;
121 let e_str : i8 = value[index + 1..].parse().map_err(|error| ParsingStandardFormError::Exponent(error) )?;
122 return Ok(StandardForm::new(m_str,e_str));
123 }
124
125 Err(ParsingStandardFormError::InvalidFormat)
126 }
127}
128
129impl Add for StandardForm {
130 type Output = Self;
131 fn add(self, other: Self) -> Self {
132 let max_power = max(self.exponent, other.exponent);
133 let num_sum = self.mantissa * 10.0_f64.to_the_power_of((self.exponent - max_power) as f64) + other.mantissa * 10.0_f64.to_the_power_of((other.exponent - max_power) as f64);
134 StandardForm::new(num_sum, max_power)
135 }
136}
137
138impl AddAssign for StandardForm {
139 fn add_assign(&mut self, other: Self) {
140 let max_power = max(self.exponent, other.exponent);
141 let num_sum = self.mantissa * 10.0_f64.to_the_power_of((self.exponent - max_power) as f64) + other.mantissa * 10.0_f64.to_the_power_of((other.exponent - max_power) as f64);
142
143 self.mantissa = num_sum;
144 self.exponent = max_power;
145
146 self.adjust();
147 }
148}
149
150impl Sub for StandardForm {
151 type Output = Self;
152 fn sub(self, other: Self) -> Self {
153 let min = self.exponent.min(other.exponent);
154
155 let x = self.mantissa * 10_i32.pow((self.exponent - min) as u32) as f64;
156 let y = other.mantissa * 10_i32.pow((other.exponent - min) as u32) as f64;
157
158 let result = x - y;
159 let rounded = (result * 1.0e6).round() / 1.0e6;
160
161 StandardForm::new(rounded,min)
162 }
163}
164
165impl SubAssign for StandardForm {
166 fn sub_assign(&mut self, other: Self) {
167 let min = self.exponent.min(other.exponent);
168
169 let x = self.mantissa * 10_i32.pow((self.exponent - min) as u32) as f64;
170 let y = other.mantissa * 10_i32.pow((other.exponent - min) as u32) as f64;
171
172 let result = x - y;
173 let rounded = (result * 1.0e6).round() / 1.0e6;
174
175 self.mantissa = rounded;
176 self.exponent = min;
177 self.adjust();
178 }
179}
180
181impl Mul for StandardForm {
182 type Output = Self;
183 fn mul(self, other: Self) -> Self {
184 let exponent = self.exponent + other.exponent;
185 let mantissa = self.mantissa * other.mantissa;
186 let rounded = (mantissa * 1.0e6).round() / 1.0e6;
187 StandardForm::new(rounded,exponent)
188 }
189}
190
191impl MulAssign for StandardForm {
192 fn mul_assign(&mut self, other: Self) {
193 let exponent = self.exponent + other.exponent;
194 let mantissa = self.mantissa * other.mantissa;
195 let rounded = (mantissa * 1.0e6).round() / 1.0e6;
196
197 self.mantissa = rounded;
198 self.exponent = exponent;
199
200 self.adjust();
201 }
202}
203
204impl Div for StandardForm {
205 type Output = Self;
206 fn div(self, other: Self) -> Self {
207 StandardForm::new(self.mantissa / other.mantissa,self.exponent - other.exponent)
208 }
209}
210
211impl DivAssign for StandardForm {
212 fn div_assign(&mut self, other: Self) {
213 self.mantissa /= other.mantissa;
214 self.exponent /= other.exponent;
215 self.adjust();
216 }
217}
218
219macro_rules! primitives {
220 (form => $($t:ty),*) => {
221 $(
222 impl From<$t> for StandardForm {
223 fn from(value: $t) -> Self {
224 StandardForm::new(value as f64,0)
225 }
226 }
227 )*
228 };
229
230 (eq => $($t:ty),*) => {
231 $(
232 impl PartialEq<$t> for StandardForm {
233 fn eq(&self,other: &$t) -> bool {
234 let rhs : Self = (*other).into();
235 *self == rhs
236 }
237 }
238 )*
239 };
240 (ord => $($t:ty),*) => {
241 $(
242 impl PartialOrd<$t> for StandardForm {
243 fn partial_cmp(&self, other: &$t) -> Option<std::cmp::Ordering> {
244 let rhs : Self = (*other).into();
245 self.partial_cmp(&rhs)
246 }
247 }
248 )*
249 };
250
251
252 (add => $($t : ty),*) => {
253 $(
254 impl Add<$t> for StandardForm {
255 type Output = Self;
256 fn add(self, other: $t) -> Self {
257 let rhs : Self = other.into();
258 self + rhs
259 }
260 }
261
262 impl AddAssign<$t> for StandardForm {
263 fn add_assign(&mut self, other: $t) {
264 let rhs : Self = other.into();
265 *self += rhs;
266 }
267 }
268 )*
269 };
270
271 (sub => $($t : ty),*) => {
272 $(
273 impl Sub<$t> for StandardForm {
274 type Output = Self;
275 fn sub(self, other: $t) -> Self {
276 let rhs : Self = other.into();
277 self - rhs
278 }
279 }
280
281 impl SubAssign<$t> for StandardForm {
282 fn sub_assign(&mut self, other: $t) {
283 let rhs : Self = other.into();
284 *self -= rhs;
285 }
286 }
287 )*
288 };
289 (mul => $($t : ty),*) => {
290 $(
291 impl Mul<$t> for StandardForm {
292 type Output = Self;
293 fn mul(self, other: $t) -> Self {
294 let rhs : Self = other.into();
295 self * rhs
296 }
297 }
298
299 impl MulAssign<$t> for StandardForm {
300 fn mul_assign(&mut self, other: $t) {
301 let rhs : Self = other.into();
302 *self *= rhs;
303 }
304 }
305 )*
306 };
307 (div => $($t : ty),*) => {
308 $(
309 impl Div<$t> for StandardForm {
310 type Output = Self;
311 fn div(self, other: $t) -> Self {
312 let rhs : Self = other.into();
313 self / rhs
314 }
315 }
316
317 impl DivAssign<$t> for StandardForm {
318 fn div_assign(&mut self, other: $t) {
319 let rhs : Self = other.into();
320 *self /= rhs;
321 }
322 }
323 )*
324 };
325 (operations => $($t:ty),*) => {
326 $(
327 primitives!(add => $t);
328 primitives!(sub => $t);
329 primitives!(mul => $t);
330 primitives!(div => $t);
331 )*
332 }
333}
334
335primitives!(operations => i8, i16, i32, i64, u8, u16, u32, u64,f32,f64);
336primitives!(form => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
337primitives!(eq => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
338primitives!(ord => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
339
340#[cfg(test)]
341mod tests {
342 use super::*;
343 use std::cmp::Ordering;
344
345 #[test]
346 fn assignment_issue() {
347 let sf1 = StandardForm::new(1.0,5);
348 assert_eq!(*sf1.mantissa(),1.0);
349 assert_eq!(*sf1.exponent(),5);
350 }
351
352 #[test]
353 fn from_u8_standardform(){
354 let n = 2u8;
355 let r : StandardForm = n.into();
356
357 assert_eq!(r,StandardForm { mantissa : 2.0,exponent : 0 });
358 }
359
360 #[test]
361 fn test_normalize_with_valid_range() {
362 let mut sf = StandardForm::new(2.5, 3);
363 sf.adjust();
364 assert_eq!(sf.mantissa, 2.5);
365 assert_eq!(sf.exponent, 3);
366 }
367
368 #[test]
369 fn test_normalize_with_invalid_range() {
370 let mut sf = StandardForm::new(20.0, 3);
371 sf.adjust();
372 assert_eq!(sf.mantissa, 2.0);
373 assert_eq!(sf.exponent, 4);
374 }
375
376 #[test]
377 fn test_normalize_with_small_mantissa() {
378 let mut sf = StandardForm::new(-0.25, 2);
379 sf.adjust();
380 assert_eq!(sf.mantissa, -2.5);
381 assert_eq!(sf.exponent, 1);
382 }
383
384 #[test]
385 fn test_normalize_with_large_negative_mantissa() {
386 let mut sf = StandardForm::new(-750.0, 4);
387 sf.adjust();
388 assert_eq!(sf.mantissa, -7.5);
389 assert_eq!(sf.exponent, 6);
390 }
391
392 #[test]
393 fn addition() {
394 let a = StandardForm::new(1.2, 3);
396 let b = StandardForm::new(3.4, 2);
397 let result = a + b;
398 assert_eq!(result, StandardForm::new(1.54,3) );
399 }
400
401 #[test]
402 fn addition_u8() {
403 let a = StandardForm::new(1.0, 1);
405 let b = 2u8;
406 let result = a + b;
407 assert_eq!(result, StandardForm::new(1.2,1));
408 }
409
410 #[test]
411 fn test_subtraction() {
412 let a = StandardForm::new(4.6, 2);
414 let b = StandardForm::new(3.4, 2);
415 let result = a - b;
416 assert_eq!(result, StandardForm::new(1.2,2));
417 }
418
419 #[test]
420 fn subtraction_u8() {
421 let a = StandardForm::new(21.0, 1);
423 println!("{a}");
424 let b = 2u8;
426 let result = a - b;
427 assert_eq!(result.mantissa, 2.18);
428 assert_eq!(result.exponent, 2);
429 }
430
431 #[test]
432 fn multiplication() {
433 let a = StandardForm::new(1.2, 3);
435 let b = StandardForm::new(3.0, 2);
436 let result = a * b;
437 assert_eq!(result.mantissa, 3.6);
438 assert_eq!(result.exponent, 5);
439 }
440
441 #[test]
442 fn multiplication_u8() {
443 let a = StandardForm::new(1.0, 1);
445 let b = 2u8;
446 let result = a * b;
447 assert_eq!(result.mantissa, 2.0);
448 assert_eq!(result.exponent, 1);
449 }
450
451 #[test]
452 fn division() {
453 let a = StandardForm::new(4.0, 2);
455 let b = StandardForm::new(2.0, 1);
456 let result = a / b;
457 assert_eq!(result.mantissa, 2.0);
458 assert_eq!(result.exponent, 1);
459 }
460
461 #[test]
462 fn division_u8() {
463 let a = StandardForm::new(2.0, 1);
465 let b = 2u8;
466 let result = a / b;
467 assert_eq!(result.mantissa, 1.0);
468 assert_eq!(result.exponent, 1);
469 }
470
471
472 #[test]
473 fn add_assign() {
474 let mut a = StandardForm::new(1.0, 1);
475 let b = StandardForm::new(2.0, 1);
476 a += b;
477 assert_eq!(a.mantissa, 3.0);
478 assert_eq!(a.exponent, 1);
479 }
480
481 #[test]
482 fn add_assign_u8() {
483 let mut a = StandardForm::new(1.0, 1);
485
486 let b = 2u8;
487
488 a += b;
489 assert_eq!(a.mantissa, 1.2);
490 assert_eq!(a.exponent, 1);
491 }
492
493 #[test]
494 fn test_partial_cmp_equal() {
495 let sf1 = StandardForm::new(1.23, 3);
496 let sf2 = StandardForm::new(1.23, 3);
497
498 assert_eq!(sf1.partial_cmp(&sf2), Some(Ordering::Equal));
499 }
500
501 #[test]
502 fn test_partial_cmp_greater() {
503
504 let sf1 = StandardForm::new(3.0, 2);
506 let sf2 = StandardForm::new(2.5, 2);
508
509 assert_eq!(sf1.partial_cmp(&sf2), Some(Ordering::Greater));
510 }
511
512 #[test]
513 fn test_partial_cmp_less() {
514 let sf1 = StandardForm::new(2.5, 2);
515 let sf2 = StandardForm::new(3.0, 2);
516
517 assert_eq!(sf1.partial_cmp(&sf2), Some(Ordering::Less));
518 }
519
520 #[test]
521 fn test_partial_cmp_different_exponents() {
522 let sf1 = StandardForm::new(1.5, 2);
523 let sf2 = StandardForm::new(1.5, 3);
524
525 assert_eq!(sf1.partial_cmp(&sf2), Some(Ordering::Less));
527 }
528
529 #[test]
530 fn test_partial_cmp_zero() {
531 let sf1 = StandardForm::new(0.0, 0);
532 let sf2 = StandardForm::new(0.0, 0);
533
534 assert_eq!(sf1.partial_cmp(&sf2), Some(Ordering::Equal));
535 }
536
537 #[test]
538 fn test_partial_cmp_mixed_sign() {
539 let sf1 = StandardForm::new(-1.0, 2);
540 let sf2 = StandardForm::new(1.0, 2);
541
542 assert_eq!(sf1.partial_cmp(&sf2), Some(Ordering::Less));
544 }
545}