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
74impl From<Rint> for i32 {
75 fn from(v: Rint) -> Self {
76 v.0
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.0.fmt(f)
176 }
177 }
178}