extendr_api/scalar/
rfloat.rs1use crate::prelude::Rint;
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)]
15#[readonly::make]
16pub struct Rfloat(pub f64);
17
18impl Rfloat {
19 pub fn is_nan(&self) -> bool {
20 self.0.is_nan()
21 }
22 pub fn is_sign_positive(&self) -> bool {
23 self.0.is_sign_positive()
24 }
25 pub fn is_sign_negative(&self) -> bool {
26 self.0.is_sign_negative()
27 }
28 pub fn is_infinite(&self) -> bool {
29 self.0.is_infinite()
30 }
31 pub fn is_subnormal(&self) -> bool {
32 self.0.is_subnormal()
33 }
34 pub fn abs(&self) -> Rfloat {
35 self.0.abs().into()
36 }
37 pub fn sqrt(&self) -> Rfloat {
38 self.0.sqrt().into()
39 }
40
41 pub fn min(&self, other: Self) -> Self {
52 match self.partial_cmp(&other) {
53 Some(Less | Equal) => *self,
54 Some(Greater) => other,
55 _ => Self::na(),
56 }
57 }
58
59 pub fn max(&self, other: Self) -> Self {
70 match self.partial_cmp(&other) {
71 Some(Less) => other,
72 Some(Greater | Equal) => *self,
73 _ => Self::na(),
74 }
75 }
76}
77
78gen_trait_impl!(Rfloat, f64, |x: &Rfloat| x.0.is_na(), f64::na());
81gen_from_primitive!(Rfloat, f64);
82
83impl From<Rfloat> for Option<f64> {
84 fn from(v: Rfloat) -> Self {
85 if v.is_na() {
86 None
87 } else {
88 Some(v.0)
89 }
90 }
91}
92
93impl From<Rfloat> for f64 {
94 fn from(v: Rfloat) -> Self {
95 v.0
96 }
97}
98
99gen_sum_iter!(Rfloat);
100gen_partial_ord!(Rfloat, f64);
101
102gen_binop!(
104 Rfloat,
105 f64,
106 Add,
107 |lhs: f64, rhs: f64| Some(lhs + rhs),
108 "Add two Rfloat values or an option of f64."
109);
110gen_binop!(
111 Rfloat,
112 f64,
113 Sub,
114 |lhs: f64, rhs: f64| Some(lhs - rhs),
115 "Subtract two Rfloat values or an option of f64."
116);
117gen_binop!(
118 Rfloat,
119 f64,
120 Mul,
121 |lhs: f64, rhs: f64| Some(lhs * rhs),
122 "Multiply two Rfloat values or an option of f64."
123);
124gen_binop!(
125 Rfloat,
126 f64,
127 Div,
128 |lhs: f64, rhs: f64| Some(lhs / rhs),
129 "Divide two Rfloat values or an option of f64."
130);
131gen_binopassign!(
132 Rfloat,
133 f64,
134 AddAssign,
135 |lhs: f64, rhs: f64| Some(lhs + rhs),
136 "Add two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
137);
138gen_binopassign!(
139 Rfloat,
140 f64,
141 SubAssign,
142 |lhs: f64, rhs: f64| Some(lhs - rhs),
143 "Subtract two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
144);
145gen_binopassign!(
146 Rfloat,
147 f64,
148 MulAssign,
149 |lhs: f64, rhs: f64| Some(lhs * rhs),
150 "Multiply two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
151);
152gen_binopassign!(
153 Rfloat,
154 f64,
155 DivAssign,
156 |lhs: f64, rhs: f64| Some(lhs / rhs),
157 "Divide two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
158);
159
160gen_unop!(Rfloat, Neg, |lhs: f64| Some(-lhs), "Negate a Rfloat value.");
162
163impl From<i32> for Rfloat {
164 fn from(value: i32) -> Self {
165 Rfloat::from(value as f64)
166 }
167}
168
169impl From<Rint> for Rfloat {
170 fn from(value: Rint) -> Self {
171 if value.is_na() {
172 Rfloat::na()
173 } else {
174 Rfloat::from(value.0)
175 }
176 }
177}
178
179impl TryFrom<&Robj> for Rfloat {
180 type Error = Error;
181
182 fn try_from(robj: &Robj) -> Result<Self> {
183 let f64_val: Result<f64> = robj.try_into();
184 match f64_val {
185 Ok(val) => Ok(Rfloat::from(val)),
186 Err(Error::MustNotBeNA(_)) => Ok(Rfloat::na()),
188 Err(e) => Err(e),
189 }
190 }
191}
192
193impl std::fmt::Debug for Rfloat {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196 if self.is_na() {
197 write!(f, "NA_REAL")
198 } else {
199 self.0.fmt(f)
200 }
201 }
202}