extendr_api/scalar/
rfloat.rs
1use crate::prelude::{Rint, Scalar};
2use crate::scalar::macros::*;
3use crate::*;
4use std::cmp::Ordering::*;
5use std::convert::TryFrom;
6use std::ops::{Add, Div, Mul, Neg, Sub};
7use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
8
9#[repr(transparent)]
15pub struct Rfloat(f64);
16
17impl Scalar<f64> for Rfloat {
18 fn inner(&self) -> f64 {
19 self.0
20 }
21
22 fn new(val: f64) -> Self {
23 Rfloat(val)
24 }
25}
26
27impl Rfloat {
28 pub fn is_nan(&self) -> bool {
29 self.0.is_nan()
30 }
31 pub fn is_sign_positive(&self) -> bool {
32 self.0.is_sign_positive()
33 }
34 pub fn is_sign_negative(&self) -> bool {
35 self.0.is_sign_negative()
36 }
37 pub fn is_infinite(&self) -> bool {
38 self.0.is_infinite()
39 }
40 pub fn is_subnormal(&self) -> bool {
41 self.0.is_subnormal()
42 }
43 pub fn abs(&self) -> Rfloat {
44 self.0.abs().into()
45 }
46 pub fn sqrt(&self) -> Rfloat {
47 self.0.sqrt().into()
48 }
49
50 pub fn min(&self, other: Self) -> Self {
61 match self.partial_cmp(&other) {
62 Some(Less | Equal) => *self,
63 Some(Greater) => other,
64 _ => Self::na(),
65 }
66 }
67
68 pub fn max(&self, other: Self) -> Self {
79 match self.partial_cmp(&other) {
80 Some(Less) => other,
81 Some(Greater | Equal) => *self,
82 _ => Self::na(),
83 }
84 }
85}
86
87gen_trait_impl!(Rfloat, f64, |x: &Rfloat| x.inner().is_na(), f64::na());
90gen_from_primitive!(Rfloat, f64);
91
92impl From<Rfloat> for Option<f64> {
93 fn from(v: Rfloat) -> Self {
94 if v.is_na() {
95 None
96 } else {
97 Some(v.0)
98 }
99 }
100}
101
102gen_sum_iter!(Rfloat);
103gen_partial_ord!(Rfloat, f64);
104
105gen_binop!(
107 Rfloat,
108 f64,
109 Add,
110 |lhs: f64, rhs: f64| Some(lhs + rhs),
111 "Add two Rfloat values or an option of f64."
112);
113gen_binop!(
114 Rfloat,
115 f64,
116 Sub,
117 |lhs: f64, rhs: f64| Some(lhs - rhs),
118 "Subtract two Rfloat values or an option of f64."
119);
120gen_binop!(
121 Rfloat,
122 f64,
123 Mul,
124 |lhs: f64, rhs: f64| Some(lhs * rhs),
125 "Multiply two Rfloat values or an option of f64."
126);
127gen_binop!(
128 Rfloat,
129 f64,
130 Div,
131 |lhs: f64, rhs: f64| Some(lhs / rhs),
132 "Divide two Rfloat values or an option of f64."
133);
134gen_binopassign!(
135 Rfloat,
136 f64,
137 AddAssign,
138 |lhs: f64, rhs: f64| Some(lhs + rhs),
139 "Add two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
140);
141gen_binopassign!(
142 Rfloat,
143 f64,
144 SubAssign,
145 |lhs: f64, rhs: f64| Some(lhs - rhs),
146 "Subtract two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
147);
148gen_binopassign!(
149 Rfloat,
150 f64,
151 MulAssign,
152 |lhs: f64, rhs: f64| Some(lhs * rhs),
153 "Multiply two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
154);
155gen_binopassign!(
156 Rfloat,
157 f64,
158 DivAssign,
159 |lhs: f64, rhs: f64| Some(lhs / rhs),
160 "Divide two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
161);
162
163gen_unop!(Rfloat, Neg, |lhs: f64| Some(-lhs), "Negate a Rfloat value.");
165
166impl From<i32> for Rfloat {
167 fn from(value: i32) -> Self {
168 Rfloat::from(value as f64)
169 }
170}
171
172impl From<Rint> for Rfloat {
173 fn from(value: Rint) -> Self {
174 if value.is_na() {
175 Rfloat::na()
176 } else {
177 Rfloat::from(value.inner())
178 }
179 }
180}
181
182impl TryFrom<&Robj> for Rfloat {
183 type Error = Error;
184
185 fn try_from(robj: &Robj) -> Result<Self> {
186 let f64_val: Result<f64> = robj.try_into();
187 match f64_val {
188 Ok(val) => Ok(Rfloat::from(val)),
189 Err(Error::MustNotBeNA(_)) => Ok(Rfloat::na()),
191 Err(e) => Err(e),
192 }
193 }
194}
195
196impl std::fmt::Debug for Rfloat {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 if self.is_na() {
200 write!(f, "NA_REAL")
201 } else {
202 self.inner().fmt(f)
203 }
204 }
205}