extendr_api/scalar/
rint.rs
1use crate::scalar::macros::*;
2use crate::scalar::Scalar;
3use crate::*;
4use std::cmp::Ordering::*;
5use std::convert::TryFrom;
6use std::ops::{Add, Div, Mul, Neg, Not, Sub};
7use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
8
9#[repr(transparent)]
17pub struct Rint(i32);
18
19impl Scalar<i32> for Rint {
20 fn inner(&self) -> i32 {
21 self.0
22 }
23
24 fn new(val: i32) -> Self {
25 Rint(val)
26 }
27}
28
29impl Rint {
30 pub fn min(&self, other: Self) -> Self {
41 match self.partial_cmp(&other) {
42 Some(Less | Equal) => *self,
43 Some(Greater) => other,
44 _ => Self::na(),
45 }
46 }
47
48 pub fn max(&self, other: Self) -> Self {
59 match self.partial_cmp(&other) {
60 Some(Less) => other,
61 Some(Greater | Equal) => *self,
62 _ => Self::na(),
63 }
64 }
65}
66
67gen_trait_impl!(Rint, i32, |x: &Rint| x.0 == i32::MIN, i32::MIN);
68gen_from_primitive!(Rint, i32);
69
70impl From<Rint> for Option<i32> {
71 fn from(v: Rint) -> Self {
72 if v.is_na() {
73 None
74 } else {
75 Some(v.0)
76 }
77 }
78}
79
80gen_sum_iter!(Rint);
81gen_partial_ord!(Rint, i32);
82
83gen_binop!(
85 Rint,
86 i32,
87 Add,
88 |lhs: i32, rhs| lhs.checked_add(rhs),
89 "Add two Rint values or an option of i32, overflows to NA."
90);
91gen_binop!(
92 Rint,
93 i32,
94 Sub,
95 |lhs: i32, rhs| lhs.checked_sub(rhs),
96 "Subtract two Rint values or an option of i32, overflows to NA."
97);
98gen_binop!(
99 Rint,
100 i32,
101 Mul,
102 |lhs: i32, rhs| lhs.checked_mul(rhs),
103 "Multiply two Rint values or an option of i32, overflows to NA."
104);
105gen_binop!(
106 Rint,
107 i32,
108 Div,
109 |lhs: i32, rhs| lhs.checked_div(rhs),
110 "Divide two Rint values or an option of i32, overflows to NA."
111);
112gen_binopassign!(
113 Rint,
114 i32,
115 AddAssign,
116 |lhs: i32, rhs| lhs.checked_add(rhs),
117 "Add two Rint values or an option of i32, modifying the left-hand side in place. Overflows to NA."
118);
119gen_binopassign!(
120 Rint,
121 i32,
122 SubAssign,
123 |lhs: i32, rhs| lhs.checked_sub(rhs),
124 "Subtract two Rint values or an option of i32, modifying the left-hand side in place. Overflows to NA."
125);
126gen_binopassign!(
127 Rint,
128 i32,
129 MulAssign,
130 |lhs: i32, rhs| lhs.checked_mul(rhs),
131 "Multiply two Rint values or an option of i32, modifying the left-hand side in place. Overflows to NA."
132);
133gen_binopassign!(
134 Rint,
135 i32,
136 DivAssign,
137 |lhs: i32, rhs| lhs.checked_div(rhs),
138 "Divide two Rint values or an option of i32, modifying the left-hand side in place. Overflows to NA."
139);
140
141gen_unop!(
143 Rint,
144 Neg,
145 |lhs: i32| Some(-lhs),
146 "Negate a Rint value, overflows to NA."
147);
148gen_unop!(
149 Rint,
150 Not,
151 |lhs: i32| Some(!lhs),
152 "Logical not a Rint value, overflows to NA."
153);
154
155impl TryFrom<&Robj> for Rint {
156 type Error = Error;
157
158 fn try_from(robj: &Robj) -> Result<Self> {
159 let i32_val: Result<i32> = robj.try_into();
160 match i32_val {
161 Ok(v) => Ok(Rint::from(v)),
162 Err(Error::MustNotBeNA(_)) => Ok(Rint::na()),
164 Err(e) => Err(e),
165 }
166 }
167}
168
169impl std::fmt::Debug for Rint {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 if self.is_na() {
173 write!(f, "NA_INTEGER")
174 } else {
175 self.inner().fmt(f)
176 }
177 }
178}