rustr/vector/
boolvec.rs

1use ::rdll::*;
2use ::storage::*;
3use ::traits::*;
4use ::rtype::*;
5use ::protect::stackp::*;
6use error::*;
7use error::REKind::NotCompatible;
8use std::ops::Range;
9use std::os::raw::c_int;
10pub type BoolVec = BoolVecM<Preserve>;
11
12impl<T: SEXPbucket> BoolVecM<T> {
13    pub fn new(x: SEXP) -> RResult<BoolVecM<T>> {
14        if RTYPEOF(x) != LGLSXP {
15            return rerror(NotCompatible("expecting a numeric vector".into()));
16        }
17        Ok(BoolVecM { data: T::new(x) })
18    }
19    pub fn alloc(x: usize) -> BoolVecM<T> {
20        BoolVecM { data: T::new(unsafe { Rf_allocVector(LGLSXP, x as R_xlen_t) }) }
21    }
22    pub fn alloc_matrix(x: usize, y: usize) -> BoolVecM<T> {
23        BoolVecM {
24            data: T::new(unsafe {
25                Rf_allocMatrix(LGLSXP,
26                               x as ::std::os::raw::c_int,
27                               y as ::std::os::raw::c_int)
28            }),
29        }
30    }
31    pub fn at(&self, ind: usize) -> Option<bool> {
32        unsafe {
33            if Rf_xlength(self.s()) <= ind as R_xlen_t {
34                return None;
35            }
36            let ptr = LOGICAL(self.s());
37
38            Some(*ptr.offset(ind as isize) == 1)
39        }
40    }
41    pub unsafe fn uat(&self, ind: usize) -> bool {
42        let ptr = LOGICAL(self.s());
43        *ptr.offset(ind as isize) == 1
44    }
45    pub unsafe fn uset(&mut self, ind: usize, value: bool) {
46        let ptr = LOGICAL(self.s());
47        *ptr.offset(ind as isize) = value as c_int;
48    }
49    pub fn set(&mut self, ind: usize, value: bool) -> RResult<()> {
50        unsafe {
51            if Rf_xlength(self.s()) < ind as R_xlen_t {
52                return rraise("index out of bound");
53            }
54            let ptr = LOGICAL(self.s());
55            *ptr.offset(ind as isize) = value as c_int;
56            Ok(())
57        }
58    }
59    pub fn range(&self, ind: Range<usize>) -> Option<Vec<bool>> {
60        unsafe {
61            if Rf_xlength(self.s()) <= ind.end as R_xlen_t {
62                return None;
63            }
64            let mut vecs = Vec::with_capacity(ind.len() as usize);
65            let ptr = LOGICAL(self.s());
66            for ii in ind {
67                vecs.push(*ptr.offset(ii as isize) == 1);
68            }
69            Some(vecs)
70        }
71    }
72    pub fn is_duplicated(&self, from_last: bool) -> R_xlen_t {
73        let last = if from_last {
74            Rboolean::TRUE
75        } else {
76            Rboolean::FALSE
77        };
78        unsafe { Rf_any_duplicated(self.s(), last) }
79    }
80}
81
82
83
84impl<T: SEXPbucket, E: Into<bool> + Clone> From<Vec<E>> for BoolVecM<T> {
85    fn from(x: Vec<E>) -> BoolVecM<T> {
86        let size_x = x.len();
87        unsafe {
88            let rvec = Shield::new(Rf_allocVector(LGLSXP, size_x as R_xlen_t));
89            let rptr = LOGICAL(rvec.s());
90            for ii in 0..size_x {
91                *rptr.offset(ii as isize) =
92                    (*x.get_unchecked(ii as usize)).clone().into() as ::std::os::raw::c_int;
93            }
94            BoolVecM { data: T::new(rvec.s()) }
95        }
96    }
97}
98
99impl<T: SEXPbucket> From<BoolVecM<T>> for Vec<bool> {
100    fn from(x: BoolVecM<T>) -> Vec<bool> {
101        unsafe {
102            let lens = Rf_xlength(x.s());
103            let mut vecs = Vec::with_capacity(lens as usize);
104            let rptr = LOGICAL(x.s());
105            for ii in 0..lens {
106                vecs.push(*rptr.offset(ii as isize) == 1);
107            }
108            vecs
109        }
110    }
111}
112
113impl<T: SEXPbucket> URNew for BoolVecM<T> {
114    unsafe fn urnew(x: SEXP) -> Self {
115        BoolVecM { data: T::new(x) }
116    }
117}
118
119impl<T: SEXPbucket> RNew for BoolVecM<T> {
120    fn rnew(x: SEXP) -> RResult<Self> {
121        Self::new(x)
122    }
123}
124
125impl<T: SEXPbucket> RSize for BoolVecM<T> {
126    fn rsize(&self) -> R_xlen_t {
127        unsafe { Rf_xlength(self.s()) }
128    }
129}
130
131gen_traits_sexp!(BoolVecM);
132
133
134impl<T: SEXPbucket> RName for BoolVecM<T> {}
135impl<T: SEXPbucket> RDim for BoolVecM<T> {
136    type Output = bool;
137}
138
139#[derive(Debug)]
140pub struct BoolVecIter<T: SEXPbucket> {
141    data: *mut ::std::os::raw::c_int,
142    size: R_xlen_t,
143    next: R_xlen_t,
144    ty: BoolVecM<T>,
145}
146
147impl<T: SEXPbucket> Iterator for BoolVecIter<T> {
148    // we will be counting with usize
149    type Item = bool;
150
151    // next() is the only required method
152    fn next(&mut self) -> Option<bool> {
153        // increment our count. This is why we started at zero.
154        // check to see if we've finished counting or not.
155        if self.next < self.size {
156            self.next += 1;
157            unsafe { Some(*self.data.offset((self.next - 1) as isize) == 1) }
158        } else {
159            None
160        }
161
162    }
163}
164
165impl<T: SEXPbucket> IntoIterator for BoolVecM<T> {
166    type Item = bool;
167    type IntoIter = BoolVecIter<T>;
168
169    fn into_iter(self) -> Self::IntoIter {
170        unsafe {
171            BoolVecIter {
172                data: LOGICAL(self.s()),
173                size: self.rsize(),
174                next: 0,
175                ty: self,
176            }
177        }
178    }
179}
180
181impl<T: SEXPbucket> ExactSizeIterator for BoolVecIter<T> {
182    // We already have the number of iterations, so we can use it directly.
183    fn len(&self) -> usize {
184        self.size as usize
185    }
186}
187
188
189
190/// Create a BoolVec
191///
192#[macro_export]
193macro_rules! boolvec {
194    ($($tts:expr),*) => {
195      // count macro parameter learn from rust macro book	
196      {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
197      	
198      // init 
199      let mut res = BoolVec::alloc(size as usize);
200	  unsafe{
201      let mut x = 0;
202      $(
203			// skip a warning message 
204			x += 1;
205      		res.uset(x-1 as usize, $tts);
206      		
207      )*      
208	}
209      res
210      }
211    };
212    
213    ($($id:ident ~ $tts:expr),*) => {
214      // count macro parameter learn from rust macro book	
215      {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
216      	
217      // init 
218      let mut res = BoolVec::alloc(size as usize);
219	  let mut name = CharVec::alloc(size as usize);
220	  unsafe{
221      let mut x = 0;
222      $(
223			// skip a warning message 
224			x += 1;
225      		res.uset(x-1 as usize , $tts);
226      		name.uset(x-1, stringify!($id));
227      )*
228	}
229	  unsafe{Rf_setAttrib(res.s(), R_NamesSymbol,name.s());}
230      res
231      }
232    }
233}