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