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
93gen_sum_iter!(Rfloat);
94gen_partial_ord!(Rfloat, f64);
95
96gen_binop!(
98 Rfloat,
99 f64,
100 Add,
101 |lhs: f64, rhs: f64| Some(lhs + rhs),
102 "Add two Rfloat values or an option of f64."
103);
104gen_binop!(
105 Rfloat,
106 f64,
107 Sub,
108 |lhs: f64, rhs: f64| Some(lhs - rhs),
109 "Subtract two Rfloat values or an option of f64."
110);
111gen_binop!(
112 Rfloat,
113 f64,
114 Mul,
115 |lhs: f64, rhs: f64| Some(lhs * rhs),
116 "Multiply two Rfloat values or an option of f64."
117);
118gen_binop!(
119 Rfloat,
120 f64,
121 Div,
122 |lhs: f64, rhs: f64| Some(lhs / rhs),
123 "Divide two Rfloat values or an option of f64."
124);
125gen_binopassign!(
126 Rfloat,
127 f64,
128 AddAssign,
129 |lhs: f64, rhs: f64| Some(lhs + rhs),
130 "Add two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
131);
132gen_binopassign!(
133 Rfloat,
134 f64,
135 SubAssign,
136 |lhs: f64, rhs: f64| Some(lhs - rhs),
137 "Subtract two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
138);
139gen_binopassign!(
140 Rfloat,
141 f64,
142 MulAssign,
143 |lhs: f64, rhs: f64| Some(lhs * rhs),
144 "Multiply two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
145);
146gen_binopassign!(
147 Rfloat,
148 f64,
149 DivAssign,
150 |lhs: f64, rhs: f64| Some(lhs / rhs),
151 "Divide two Rfloat values or an option of f64, modifying the left-hand side in place. Overflows to NA."
152);
153
154gen_unop!(Rfloat, Neg, |lhs: f64| Some(-lhs), "Negate a Rfloat value.");
156
157impl From<i32> for Rfloat {
158 fn from(value: i32) -> Self {
159 Rfloat::from(value as f64)
160 }
161}
162
163impl From<Rint> for Rfloat {
164 fn from(value: Rint) -> Self {
165 if value.is_na() {
166 Rfloat::na()
167 } else {
168 Rfloat::from(value.0)
169 }
170 }
171}
172
173impl TryFrom<&Robj> for Rfloat {
174 type Error = Error;
175
176 fn try_from(robj: &Robj) -> Result<Self> {
177 let f64_val: Result<f64> = robj.try_into();
178 match f64_val {
179 Ok(val) => Ok(Rfloat::from(val)),
180 Err(Error::MustNotBeNA(_)) => Ok(Rfloat::na()),
182 Err(e) => Err(e),
183 }
184 }
185}
186
187impl std::fmt::Debug for Rfloat {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190 if self.is_na() {
191 write!(f, "NA_REAL")
192 } else {
193 self.0.fmt(f)
194 }
195 }
196}