EVOLUTION-MANAGER
Edit File: Vector.h
// // Vector.h: Rcpp R/C++ interface class library -- vectors // // Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois // // This file is part of Rcpp. // // Rcpp is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // Rcpp is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. #ifndef Rcpp__vector__Vector_h #define Rcpp__vector__Vector_h #include <Rcpp/vector/Subsetter.h> namespace Rcpp{ template <int RTYPE, template <class> class StoragePolicy = PreserveStorage > class Vector : public StoragePolicy< Vector<RTYPE,StoragePolicy> >, public SlotProxyPolicy< Vector<RTYPE,StoragePolicy> >, public AttributeProxyPolicy< Vector<RTYPE,StoragePolicy> >, public NamesProxyPolicy< Vector<RTYPE, StoragePolicy> >, public RObjectMethods< Vector<RTYPE, StoragePolicy> >, public VectorBase< RTYPE, true, Vector<RTYPE,StoragePolicy> > { public: typedef StoragePolicy<Vector> Storage ; typename traits::r_vector_cache_type<RTYPE, StoragePolicy>::type cache ; typedef typename traits::r_vector_proxy<RTYPE, StoragePolicy>::type Proxy ; typedef typename traits::r_vector_const_proxy<RTYPE, StoragePolicy>::type const_Proxy ; typedef typename traits::r_vector_name_proxy<RTYPE, StoragePolicy>::type NameProxy ; typedef typename traits::r_vector_proxy<RTYPE, StoragePolicy>::type value_type ; typedef typename traits::r_vector_iterator<RTYPE, StoragePolicy>::type iterator ; typedef typename traits::r_vector_const_iterator<RTYPE, StoragePolicy>::type const_iterator ; typedef typename traits::init_type<RTYPE>::type init_type ; typedef typename traits::r_vector_element_converter<RTYPE>::type converter_type ; typedef typename traits::storage_type<RTYPE>::type stored_type ; /** * Default constructor. Creates a vector of the appropriate type * and 0 length */ Vector() { Storage::set__( Rf_allocVector(RTYPE, 0 ) ); init() ; } /** * copy constructor. shallow copy of the SEXP */ Vector( const Vector& other){ Storage::copy__(other) ; } Vector& operator=(const Vector& rhs) { return Storage::copy__(rhs) ; } Vector( SEXP x ) { Rcpp::Shield<SEXP> safe(x); Storage::set__( r_cast<RTYPE>(safe) ) ; } template <typename Proxy> Vector( const GenericProxy<Proxy>& proxy ){ Rcpp::Shield<SEXP> safe(proxy.get()); Storage::set__( r_cast<RTYPE>(safe) ) ; } explicit Vector( const no_init_vector& obj) { Storage::set__( Rf_allocVector( RTYPE, obj.get() ) ) ; } template<typename T> Vector( const T& size, const stored_type& u, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { RCPP_DEBUG_2( "Vector<%d>( const T& size = %d, const stored_type& u )", RTYPE, size) Storage::set__( Rf_allocVector( RTYPE, size) ) ; fill( u ) ; } Vector( const int& size, const stored_type& u) { RCPP_DEBUG_2( "Vector<%d>( const int& size = %d, const stored_type& u )", RTYPE, size) Storage::set__( Rf_allocVector( RTYPE, size) ) ; fill( u ) ; } // constructor for CharacterVector() Vector( const std::string& st ){ RCPP_DEBUG_2( "Vector<%d>( const std::string& = %s )", RTYPE, st.c_str() ) Storage::set__( internal::vector_from_string<RTYPE>(st) ) ; } // constructor for CharacterVector() Vector( const char* st ) { RCPP_DEBUG_2( "Vector<%d>( const char* = %s )", RTYPE, st ) Storage::set__(internal::vector_from_string<RTYPE>(st) ) ; } template<typename T> Vector( const T& siz, stored_type (*gen)(void), typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { RCPP_DEBUG_2( "Vector<%d>( const int& siz = %s, stored_type (*gen)(void) )", RTYPE, siz ) Storage::set__( Rf_allocVector( RTYPE, siz) ) ; std::generate( begin(), end(), gen ); } // Add template class T and then restict T to arithmetic. template <typename T> Vector(T size, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { Storage::set__( Rf_allocVector( RTYPE, size) ) ; init() ; } Vector( const int& size ) { Storage::set__( Rf_allocVector( RTYPE, size) ) ; init() ; } Vector( const Dimension& dims) { Storage::set__( Rf_allocVector( RTYPE, dims.prod() ) ) ; init() ; if( dims.size() > 1 ){ AttributeProxyPolicy<Vector>::attr( "dim" ) = dims; } } // Enable construction from bool for LogicalVectors // SFINAE only work for template. Add template class T and then restict T to // bool. template <typename T> Vector(T value, typename Rcpp::traits::enable_if<traits::is_bool<T>::value && RTYPE == LGLSXP, void>::type* = 0) { Storage::set__(Rf_allocVector(RTYPE, 1)); fill(value); } template <typename U> Vector( const Dimension& dims, const U& u) { RCPP_DEBUG_2( "Vector<%d>( const Dimension& (%d), const U& )", RTYPE, dims.size() ) Storage::set__( Rf_allocVector( RTYPE, dims.prod() ) ) ; fill(u) ; if( dims.size() > 1 ){ AttributeProxyPolicy<Vector>::attr( "dim" ) = dims; } } template <bool NA, typename VEC> Vector( const VectorBase<RTYPE,NA,VEC>& other ) { RCPP_DEBUG_2( "Vector<%d>( const VectorBase<RTYPE,NA,VEC>& ) [VEC = %s]", RTYPE, DEMANGLE(VEC) ) import_sugar_expression( other, typename traits::same_type<Vector,VEC>::type() ) ; } template <typename T, typename U> Vector( const T& size, const U& u, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { RCPP_DEBUG_2( "Vector<%d>( const T& size, const U& u )", RTYPE, size ) Storage::set__( Rf_allocVector( RTYPE, size) ) ; fill_or_generate( u ) ; } template <bool NA, typename T> Vector( const sugar::SingleLogicalResult<NA,T>& obj ) { Rcpp::Shield<SEXP> safe(const_cast<sugar::SingleLogicalResult<NA,T>&>(obj).get_sexp() ); Storage::set__( r_cast<RTYPE>(safe) ) ; RCPP_DEBUG_2( "Vector<%d>( const sugar::SingleLogicalResult<NA,T>& ) [T = %s]", RTYPE, DEMANGLE(T) ) } template <typename T, typename U1> Vector( const T& siz, stored_type (*gen)(U1), const U1& u1, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { Storage::set__( Rf_allocVector( RTYPE, siz) ) ; RCPP_DEBUG_2( "const T& siz, stored_type (*gen)(U1), const U1& u1 )", RTYPE, siz ) iterator first = begin(), last = end() ; while( first != last ) *first++ = gen(u1) ; } template <typename T, typename U1, typename U2> Vector( const T& siz, stored_type (*gen)(U1,U2), const U1& u1, const U2& u2, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { Storage::set__( Rf_allocVector( RTYPE, siz) ) ; RCPP_DEBUG_2( "const T& siz, stored_type (*gen)(U1,U2), const U1& u1, const U2& u2)", RTYPE, siz ) iterator first = begin(), last = end() ; while( first != last ) *first++ = gen(u1,u2) ; } template <typename T, typename U1, typename U2, typename U3> Vector( const T& siz, stored_type (*gen)(U1,U2,U3), const U1& u1, const U2& u2, const U3& u3, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { Storage::set__( Rf_allocVector( RTYPE, siz) ) ; RCPP_DEBUG_2( "const T& siz, stored_type (*gen)(U1,U2,U3), const U1& u1, const U2& u2, const U3& u3)", RTYPE, siz ) iterator first = begin(), last = end() ; while( first != last ) *first++ = gen(u1,u2,u3) ; } template <typename InputIterator> Vector( InputIterator first, InputIterator last){ RCPP_DEBUG_1( "Vector<%d>( InputIterator first, InputIterator last", RTYPE ) Storage::set__( Rf_allocVector(RTYPE, std::distance(first, last) ) ) ; std::copy( first, last, begin() ) ; } template <typename InputIterator, typename T> Vector( InputIterator first, InputIterator last, T n, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0) { Storage::set__(Rf_allocVector(RTYPE, n)) ; RCPP_DEBUG_2( "Vector<%d>( InputIterator first, InputIterator last, T n = %d)", RTYPE, n ) std::copy( first, last, begin() ) ; } template <typename InputIterator, typename Func> Vector( InputIterator first, InputIterator last, Func func) { Storage::set__( Rf_allocVector( RTYPE, std::distance(first,last) ) ); RCPP_DEBUG_1( "Vector<%d>( InputIterator, InputIterator, Func )", RTYPE ) std::transform( first, last, begin(), func) ; } template <typename InputIterator, typename Func, typename T> Vector( InputIterator first, InputIterator last, Func func, T n, typename Rcpp::traits::enable_if<traits::is_arithmetic<T>::value, void>::type* = 0){ Storage::set__( Rf_allocVector( RTYPE, n ) ); RCPP_DEBUG_2( "Vector<%d>( InputIterator, InputIterator, Func, T n = %d )", RTYPE, n ) std::transform( first, last, begin(), func) ; } #ifdef HAS_CXX0X_INITIALIZER_LIST Vector( std::initializer_list<init_type> list ) { assign( list.begin() , list.end() ) ; } #endif template <typename T> Vector& operator=( const T& x) { assign_object( x, typename traits::is_sugar_expression<T>::type() ) ; return *this ; } static inline stored_type get_na() { return traits::get_na<RTYPE>(); } static inline bool is_na( stored_type x){ return traits::is_na<RTYPE>(x); } #ifdef RCPP_COMMA_INITIALIZATION internal::ListInitialization<iterator,init_type> operator=( init_type x){ iterator start = begin() ; *start = x; return internal::ListInitialization<iterator,init_type>( start + 1 ) ; ; } #endif /** * the length of the vector, uses Rf_xlength */ inline R_xlen_t length() const { return ::Rf_xlength( Storage::get__() ) ; } /** * alias of length */ inline R_xlen_t size() const { return ::Rf_xlength( Storage::get__() ) ; } /** * offset based on the dimensions of this vector */ R_xlen_t offset(const int& i, const int& j) const { if( !::Rf_isMatrix(Storage::get__()) ) throw not_a_matrix() ; /* we need to extract the dimensions */ const int* dim = dims() ; const int nrow = dim[0] ; const int ncol = dim[1] ; if(i < 0|| i >= nrow || j < 0 || j >= ncol ) { const char* fmt = "Location index is out of bounds: " "[row index=%i; row extent=%i; " "column index=%i; column extent=%i]."; throw index_out_of_bounds(fmt, i, nrow, j, ncol); } return i + static_cast<R_xlen_t>(nrow)*j ; } /** * one dimensional offset doing bounds checking to ensure * it is valid */ R_xlen_t offset(const R_xlen_t& i) const { // #nocov start if(i < 0 || i >= ::Rf_xlength(Storage::get__()) ) { const char* fmt = "Index out of bounds: [index=%i; extent=%i]."; throw index_out_of_bounds(fmt, i, ::Rf_xlength(Storage::get__()) ) ; } return i ; // #nocov end } R_xlen_t offset(const std::string& name) const { SEXP names = RCPP_GET_NAMES( Storage::get__() ) ; if( Rf_isNull(names) ) { throw index_out_of_bounds("Object was created without names."); } R_xlen_t n=size() ; for( R_xlen_t i=0; i<n; ++i){ if( ! name.compare( CHAR(STRING_ELT(names, i)) ) ){ return i ; } } const char* fmt = "Index out of bounds: [index='%s']."; throw index_out_of_bounds(fmt, name); return -1 ; /* -Wall */ } template <typename U> void fill( const U& u){ fill__dispatch( typename traits::is_trivial<RTYPE>::type(), u ) ; } inline iterator begin() { return cache.get() ; } inline iterator end() { return cache.get() + size() ; } inline const_iterator begin() const{ return cache.get_const() ; } inline const_iterator end() const{ return cache.get_const() + size() ; } inline const_iterator cbegin() const{ return cache.get_const() ; } inline const_iterator cend() const{ return cache.get_const() + size() ; } inline Proxy operator[]( R_xlen_t i ){ return cache.ref(i) ; } inline const_Proxy operator[]( R_xlen_t i ) const { return cache.ref(i) ; } inline Proxy operator()( const size_t& i) { return cache.ref( offset(i) ) ; } inline const_Proxy operator()( const size_t& i) const { return cache.ref( offset(i) ) ; } inline Proxy at( const size_t& i) { return cache.ref( offset(i) ) ; } inline const_Proxy at( const size_t& i) const { // #nocov start return cache.ref( offset(i) ) ; } // #nocov end inline Proxy operator()( const size_t& i, const size_t& j) { return cache.ref( offset(i,j) ) ; } inline const_Proxy operator()( const size_t& i, const size_t& j) const { return cache.ref( offset(i,j) ) ; } inline NameProxy operator[]( const std::string& name ){ return NameProxy( *this, name ) ; } inline NameProxy operator()( const std::string& name ){ return NameProxy( *this, name ) ; } inline NameProxy operator[]( const std::string& name ) const { return NameProxy( const_cast<Vector&>(*this), name ) ; } inline NameProxy operator()( const std::string& name ) const { return NameProxy( const_cast<Vector&>(*this), name ) ; } inline operator RObject() const { return RObject( Storage::get__() ); } // sugar subsetting requires dispatch on VectorBase template <int RHS_RTYPE, bool RHS_NA, typename RHS_T> SubsetProxy<RTYPE, StoragePolicy, RHS_RTYPE, RHS_NA, RHS_T> operator[](const VectorBase<RHS_RTYPE, RHS_NA, RHS_T>& rhs) { return SubsetProxy<RTYPE, StoragePolicy, RHS_RTYPE, RHS_NA, RHS_T>( *this, rhs ); } template <int RHS_RTYPE, bool RHS_NA, typename RHS_T> const SubsetProxy<RTYPE, StoragePolicy, RHS_RTYPE, RHS_NA, RHS_T> operator[](const VectorBase<RHS_RTYPE, RHS_NA, RHS_T>& rhs) const { return SubsetProxy<RTYPE, StoragePolicy, RHS_RTYPE, RHS_NA, RHS_T>( const_cast< Vector<RTYPE, StoragePolicy>& >(*this), rhs ); } Vector& sort(bool decreasing = false) { // sort() does not apply to List, RawVector or ExpressionVector. // // The function below does nothing for qualified Vector types, // and is undefined for other types. Hence there will be a // compiler error when sorting List, RawVector or ExpressionVector. internal::Sort_is_not_allowed_for_this_type<RTYPE>::do_nothing(); typename traits::storage_type<RTYPE>::type* start = internal::r_vector_start<RTYPE>( Storage::get__() ); if (!decreasing) { std::sort( start, start + size(), internal::NAComparator<typename traits::storage_type<RTYPE>::type>() ); } else { std::sort( start, start + size(), internal::NAComparatorGreater<typename traits::storage_type<RTYPE>::type>() ); } return *this; } template <typename InputIterator> void assign( InputIterator first, InputIterator last){ /* FIXME: we can do better than this r_cast to avoid allocating an unnecessary temporary object */ Shield<SEXP> wrapped(wrap(first, last)); Shield<SEXP> casted(r_cast<RTYPE>(wrapped)); Storage::set__(casted) ; } template <typename InputIterator> static Vector import( InputIterator first, InputIterator last){ Vector v ; v.assign( first , last ) ; return v ; } template <typename InputIterator, typename F> static Vector import_transform( InputIterator first, InputIterator last, F f){ return Vector( first, last, f) ; } template <typename T> void push_back( const T& object){ push_back__impl( converter_type::get(object), typename traits::same_type<stored_type,SEXP>() ) ; } template <typename T> void push_back( const T& object, const std::string& name ){ push_back_name__impl( converter_type::get(object), name, typename traits::same_type<stored_type,SEXP>() ) ; } template <typename T> void push_front( const T& object){ push_front__impl( converter_type::get(object), typename traits::same_type<stored_type,SEXP>() ) ; } template <typename T> void push_front( const T& object, const std::string& name){ push_front_name__impl( converter_type::get(object), name, typename traits::same_type<stored_type,SEXP>() ) ; } template <typename T> iterator insert( iterator position, const T& object){ return insert__impl( position, converter_type::get(object), typename traits::same_type<stored_type,SEXP>() ) ; } template <typename T> iterator insert( int position, const T& object){ return insert__impl( cache.get() + position, converter_type::get(object), typename traits::same_type<stored_type,SEXP>() ); } iterator erase( int position){ return erase_single__impl( cache.get() + position) ; } iterator erase( iterator position){ return erase_single__impl( position ) ; } iterator erase( int first, int last){ iterator start = cache.get() ; return erase_range__impl( start + first, start + last ) ; } iterator erase( iterator first, iterator last){ return erase_range__impl( first, last ) ; } void update(SEXP){ cache.update(*this) ; } template <typename U> static void replace_element( iterator it, SEXP names, R_xlen_t index, const U& u){ replace_element__dispatch( typename traits::is_named<U>::type(), it, names, index, u ) ; } template <typename U> static void replace_element__dispatch( traits::false_type, iterator it, SEXP names, R_xlen_t index, const U& u){ *it = converter_type::get(u); } template <typename U> static void replace_element__dispatch( traits::true_type, iterator it, SEXP names, R_xlen_t index, const U& u){ replace_element__dispatch__isArgument( typename traits::same_type<U,Argument>(), it, names, index, u ) ; } template <typename U> static void replace_element__dispatch__isArgument( traits::false_type, iterator it, SEXP names, R_xlen_t index, const U& u){ RCPP_DEBUG_2( " Vector::replace_element__dispatch<%s>(true, index= %d) ", DEMANGLE(U), index ) ; *it = converter_type::get(u.object ) ; SET_STRING_ELT( names, index, ::Rf_mkChar( u.name.c_str() ) ) ; } template <typename U> static void replace_element__dispatch__isArgument( traits::true_type, iterator it, SEXP names, R_xlen_t index, const U& u){ RCPP_DEBUG_2( " Vector::replace_element__dispatch<%s>(true, index= %d) ", DEMANGLE(U), index ) ; *it = R_MissingArg ; SET_STRING_ELT( names, index, ::Rf_mkChar( u.name.c_str() ) ) ; } typedef internal::RangeIndexer<RTYPE,true,Vector> Indexer ; inline Indexer operator[]( const Range& range ){ return Indexer( const_cast<Vector&>(*this), range ); } template <typename EXPR_VEC> Vector& operator+=( const VectorBase<RTYPE,true,EXPR_VEC>& rhs ) { const EXPR_VEC& ref = rhs.get_ref() ; iterator start = begin() ; R_xlen_t n = size() ; // TODO: maybe unroll this stored_type tmp ; for( R_xlen_t i=0; i<n; i++){ Proxy left = start[i] ; if( ! traits::is_na<RTYPE>( left ) ){ tmp = ref[i] ; left = traits::is_na<RTYPE>( tmp ) ? tmp : ( left + tmp ) ; } } return *this ; } template <typename EXPR_VEC> Vector& operator+=( const VectorBase<RTYPE,false,EXPR_VEC>& rhs ) { const EXPR_VEC& ref = rhs.get_ref() ; iterator start = begin() ; R_xlen_t n = size() ; stored_type tmp ; for( R_xlen_t i=0; i<n; i++){ if( ! traits::is_na<RTYPE>(start[i]) ){ start[i] += ref[i] ; } } return *this ; } /** * Does this vector have an element with the target name */ bool containsElementNamed( const char* target ) const { SEXP names = RCPP_GET_NAMES(Storage::get__()) ; if( Rf_isNull(names) ) return false ; R_xlen_t n = Rf_xlength(names) ; for( R_xlen_t i=0; i<n; i++){ if( !strcmp( target, CHAR(STRING_ELT(names, i)) ) ) return true ; } return false ; } int findName(const std::string& name) const { SEXP names = RCPP_GET_NAMES(Storage::get__()); if (Rf_isNull(names)) stop("'names' attribute is null"); R_xlen_t n = Rf_xlength(names); for (R_xlen_t i=0; i < n; ++i) { if (strcmp(name.c_str(), CHAR(STRING_ELT(names, i))) == 0) { return i; } } std::stringstream ss; ss << "no name '" << name << "' found"; stop(ss.str()); return -1; } protected: inline int* dims() const { if( !::Rf_isMatrix(Storage::get__()) ) throw not_a_matrix() ; return INTEGER( ::Rf_getAttrib( Storage::get__(), R_DimSymbol ) ) ; } void init(){ RCPP_DEBUG_2( "VECTOR<%d>::init( SEXP = <%p> )", RTYPE, Storage::get__() ) internal::r_init_vector<RTYPE>(Storage::get__()) ; } private: void push_back__impl(const stored_type& object, traits::true_type ) { Shield<SEXP> object_sexp( object ) ; R_xlen_t n = size() ; Vector target( n + 1 ) ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; iterator target_it( target.begin() ) ; iterator it(begin()) ; iterator this_end(end()); if( Rf_isNull(names) ){ for( ; it < this_end; ++it, ++target_it ){ *target_it = *it ; // #nocov start } } else { Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n + 1) ) ; int i = 0 ; for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ) ; } SET_STRING_ELT( newnames, i, Rf_mkChar("") ) ; target.attr("names") = newnames ; // #nocov end } *target_it = object_sexp; Storage::set__( target.get__() ) ; } void push_back__impl(const stored_type& object, traits::false_type ) { R_xlen_t n = size() ; Vector target( n + 1 ) ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; iterator target_it( target.begin() ) ; iterator it(begin()) ; iterator this_end(end()); if( Rf_isNull(names) ){ for( ; it < this_end; ++it, ++target_it ){ *target_it = *it ; } } else { Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n + 1) ) ; int i = 0 ; for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ) ; } SET_STRING_ELT( newnames, i, Rf_mkChar("") ) ; target.attr("names") = newnames ; } *target_it = object; Storage::set__( target.get__() ) ; } void push_back_name__impl(const stored_type& object, const std::string& name, traits::true_type ) { Shield<SEXP> object_sexp( object ) ; R_xlen_t n = size() ; Vector target( n + 1 ) ; iterator target_it( target.begin() ) ; iterator it(begin()) ; iterator this_end(end()); SEXP names = RCPP_GET_NAMES(Storage::get__()) ; Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n+1 ) ) ; int i=0; if( Rf_isNull(names) ){ for( ; it < this_end; ++it, ++target_it,i++ ){ *target_it = *it ; // #nocov SET_STRING_ELT( newnames, i , R_BlankString ); // #nocov } } else { for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ) ; } } SET_STRING_ELT( newnames, i, Rf_mkChar( name.c_str() ) ); target.attr("names") = newnames ; *target_it = object_sexp; Storage::set__( target.get__() ) ; } void push_back_name__impl(const stored_type& object, const std::string& name, traits::false_type ) { R_xlen_t n = size() ; Vector target( n + 1 ) ; iterator target_it( target.begin() ) ; iterator it(begin()) ; iterator this_end(end()); SEXP names = RCPP_GET_NAMES(Storage::get__()) ; Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n+1 ) ) ; int i=0; if( Rf_isNull(names) ){ Shield<SEXP> dummy( Rf_mkChar("") ); for( ; it < this_end; ++it, ++target_it,i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i , dummy ); } } else { for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ) ; } } SET_STRING_ELT( newnames, i, Rf_mkChar( name.c_str() ) ); target.attr("names") = newnames ; *target_it = object; Storage::set__( target.get__() ) ; } void push_front__impl(const stored_type& object, traits::true_type ) { Shield<SEXP> object_sexp( object ) ; R_xlen_t n = size() ; Vector target( n+1); iterator target_it(target.begin()); iterator it(begin()); iterator this_end(end()); *target_it = object_sexp ; ++target_it ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; if( Rf_isNull(names) ){ for( ; it<this_end; ++it, ++target_it){ *target_it = *it ; } } else{ Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n + 1) ); int i=1 ; SET_STRING_ELT( newnames, 0, Rf_mkChar("") ) ; for( ; it<this_end; ++it, ++target_it, i++){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i-1 ) ) ; } target.attr("names") = newnames ; } Storage::set__( target.get__() ) ; } void push_front__impl(const stored_type& object, traits::false_type ) { R_xlen_t n = size() ; Vector target( n+1); iterator target_it(target.begin()); iterator it(begin()); iterator this_end(end()); *target_it = object ; ++target_it ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; if( Rf_isNull(names) ){ for( ; it<this_end; ++it, ++target_it){ *target_it = *it ; } } else{ Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n + 1) ); int i=1 ; SET_STRING_ELT( newnames, 0, Rf_mkChar("") ) ; for( ; it<this_end; ++it, ++target_it, i++){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i-1 ) ) ; } target.attr("names") = newnames ; } Storage::set__( target.get__() ) ; } void push_front_name__impl(const stored_type& object, const std::string& name, traits::true_type ) { Shield<SEXP> object_sexp(object) ; R_xlen_t n = size() ; Vector target( n + 1 ) ; iterator target_it( target.begin() ) ; iterator it(begin()) ; iterator this_end(end()); SEXP names = RCPP_GET_NAMES(Storage::get__()) ; Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n+1 ) ) ; int i=1; SET_STRING_ELT( newnames, 0, Rf_mkChar( name.c_str() ) ); *target_it = object_sexp; ++target_it ; if( Rf_isNull(names) ){ for( ; it < this_end; ++it, ++target_it,i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i , R_BlankString ); } } else { for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i-1 ) ) ; } } target.attr("names") = newnames ; Storage::set__( target.get__() ) ; } void push_front_name__impl(const stored_type& object, const std::string& name, traits::false_type ) { R_xlen_t n = size() ; Vector target( n + 1 ) ; iterator target_it( target.begin() ) ; iterator it(begin()) ; iterator this_end(end()); SEXP names = RCPP_GET_NAMES(Storage::get__()) ; Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n+1 ) ) ; int i=1; SET_STRING_ELT( newnames, 0, Rf_mkChar( name.c_str() ) ); *target_it = object; ++target_it ; if( Rf_isNull(names) ){ for( ; it < this_end; ++it, ++target_it,i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i , R_BlankString ); } } else { for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i-1 ) ) ; } } target.attr("names") = newnames ; Storage::set__( target.get__() ) ; } iterator insert__impl( iterator position, const stored_type& object_, traits::true_type ) { Shield<SEXP> object( object_ ) ; R_xlen_t n = size() ; Vector target( n+1 ) ; iterator target_it = target.begin(); iterator it = begin() ; iterator this_end = end() ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; iterator result ; if( Rf_isNull(names) ){ for( ; it < position; ++it, ++target_it){ *target_it = *it ; } result = target_it; *target_it = object ; ++target_it ; for( ; it < this_end; ++it, ++target_it ){ *target_it = *it ; } } else{ Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n + 1 ) ) ; int i=0; for( ; it < position; ++it, ++target_it, i++){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ) ; } result = target_it; *target_it = object ; SET_STRING_ELT( newnames, i, ::Rf_mkChar("") ) ; i++ ; ++target_it ; for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i - 1) ) ; } target.attr( "names" ) = newnames ; } Storage::set__( target.get__() ) ; return result ; } iterator insert__impl( iterator position, const stored_type& object, traits::false_type ) { R_xlen_t n = size() ; Vector target( n+1 ) ; iterator target_it = target.begin(); iterator it = begin() ; iterator this_end = end() ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; iterator result ; if( Rf_isNull(names) ){ for( ; it < position; ++it, ++target_it){ *target_it = *it ; } result = target_it; *target_it = object ; ++target_it ; for( ; it < this_end; ++it, ++target_it ){ *target_it = *it ; } } else{ Shield<SEXP> newnames( ::Rf_allocVector( STRSXP, n + 1 ) ) ; int i=0; for( ; it < position; ++it, ++target_it, i++){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ) ; } result = target_it; *target_it = object ; SET_STRING_ELT( newnames, i, ::Rf_mkChar("") ) ; i++ ; ++target_it ; for( ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i - 1) ) ; } target.attr( "names" ) = newnames ; } Storage::set__( target.get__() ) ; return result ; } iterator erase_single__impl( iterator position ) { if( position < begin() || position > end() ) { R_xlen_t requested_loc; R_xlen_t available_locs = std::distance(begin(), end()); if(position > end()){ requested_loc = std::distance(position, begin()); } else { // This will be a negative number requested_loc = std::distance(begin(), position); } const char* fmt = "Iterator index is out of bounds: " "[iterator index=%i; iterator extent=%i]"; throw index_out_of_bounds(fmt, requested_loc, available_locs ) ; } R_xlen_t n = size() ; Vector target( n - 1 ) ; iterator target_it(target.begin()) ; iterator it(begin()) ; iterator this_end(end()) ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; if( Rf_isNull(names) ){ int i=0; for( ; it < position; ++it, ++target_it, i++){ *target_it = *it; } ++it ; for( ; it < this_end ; ++it, ++target_it){ *target_it = *it; } Storage::set__( target.get__() ) ; return begin()+i ; } else { Shield<SEXP> newnames(::Rf_allocVector( STRSXP, n-1 )); int i= 0 ; for( ; it < position; ++it, ++target_it,i++){ *target_it = *it; SET_STRING_ELT( newnames, i , STRING_ELT(names,i) ) ; } int result=i ; ++it ; i++ ; for( ; it < this_end ; ++it, ++target_it, i++){ *target_it = *it; SET_STRING_ELT( newnames, i-1, STRING_ELT(names,i) ) ; } target.attr( "names" ) = newnames ; Storage::set__( target.get__() ) ; return begin()+result ; } } iterator erase_range__impl( iterator first, iterator last ) { if( first > last ) throw std::range_error("invalid range") ; if( last > end() || first < begin() ) { R_xlen_t requested_loc; R_xlen_t available_locs = std::distance(begin(), end()); std::string iter_problem; if(last > end()){ requested_loc = std::distance(last, begin()); iter_problem = "last"; } else { // This will be a negative number requested_loc = std::distance(begin(), first); iter_problem = "first"; } const char* fmt = "Iterator index is out of bounds: " "[iterator=%s; index=%i; extent=%i]"; throw index_out_of_bounds(fmt, iter_problem, requested_loc, available_locs ) ; } iterator it = begin() ; iterator this_end = end() ; R_xlen_t nremoved = std::distance(first,last) ; R_xlen_t target_size = size() - nremoved ; Vector target( target_size ) ; iterator target_it = target.begin() ; SEXP names = RCPP_GET_NAMES(Storage::get__()) ; int result = 0; if( Rf_isNull(names) ){ int i=0; for( ; it < first; ++it, ++target_it, i++ ){ *target_it = *it ; } result = i; for( it = last ; it < this_end; ++it, ++target_it ){ *target_it = *it ; } } else{ Shield<SEXP> newnames( ::Rf_allocVector(STRSXP, target_size) ) ; int i= 0 ; for( ; it < first; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i ) ); } result = i; for( it = last ; it < this_end; ++it, ++target_it, i++ ){ *target_it = *it ; SET_STRING_ELT( newnames, i, STRING_ELT(names, i + nremoved ) ); } target.attr("names" ) = newnames ; } Storage::set__( target.get__() ) ; return begin() + result; } template <typename T> inline void assign_sugar_expression( const T& x ) { R_xlen_t n = size() ; if( n == x.size() ){ // just copy the data import_expression<T>(x, n ) ; } else{ // different size, so we change the memory Shield<SEXP> wrapped(wrap(x)); Shield<SEXP> casted(r_cast<RTYPE>(wrapped)); Storage::set__(casted); } } // sugar template <typename T> inline void assign_object( const T& x, traits::true_type ) { assign_sugar_expression( x.get_ref() ) ; } // anything else template <typename T> inline void assign_object( const T& x, traits::false_type ) { Shield<SEXP> wrapped(wrap(x)); Shield<SEXP> casted(r_cast<RTYPE>(wrapped)); Storage::set__(casted); } // we are importing a real sugar expression, i.e. not a vector template <bool NA, typename VEC> inline void import_sugar_expression( const Rcpp::VectorBase<RTYPE,NA,VEC>& other, traits::false_type ) { RCPP_DEBUG_4( "Vector<%d>::import_sugar_expression( VectorBase<%d,%d,%s>, false_type )", RTYPE, NA, RTYPE, DEMANGLE(VEC) ) ; R_xlen_t n = other.size() ; Storage::set__( Rf_allocVector( RTYPE, n ) ) ; import_expression<VEC>( other.get_ref() , n ) ; } // we are importing a sugar expression that actually is a vector template <bool NA, typename VEC> inline void import_sugar_expression( const Rcpp::VectorBase<RTYPE,NA,VEC>& other, traits::true_type ) { RCPP_DEBUG_4( "Vector<%d>::import_sugar_expression( VectorBase<%d,%d,%s>, true_type )", RTYPE, NA, RTYPE, DEMANGLE(VEC) ) ; Storage::set__( other.get_ref() ) ; } template <typename T> inline void import_expression( const T& other, R_xlen_t n ) { iterator start = begin() ; RCPP_LOOP_UNROLL(start,other) } template <typename T> inline void fill_or_generate( const T& t) { fill_or_generate__impl( t, typename traits::is_generator<T>::type() ) ; } template <typename T> inline void fill_or_generate__impl( const T& gen, traits::true_type) { iterator first = begin() ; iterator last = end() ; while( first != last ) *first++ = gen() ; } template <typename T> inline void fill_or_generate__impl( const T& t, traits::false_type) { fill(t) ; } template <typename U> void fill__dispatch( traits::false_type, const U& u){ // when this is not trivial, this is SEXP Shield<SEXP> elem( converter_type::get( u ) ); iterator it(begin()); for( R_xlen_t i=0; i<size() ; i++, ++it){ *it = ::Rf_duplicate( elem ) ; } } template <typename U> void fill__dispatch( traits::true_type, const U& u){ std::fill( begin(), end(), converter_type::get( u ) ) ; } public: static Vector create(){ return Vector( 0 ) ; } #include <Rcpp/generated/Vector__create.h> public: inline SEXP eval() const { return Rcpp_fast_eval( Storage::get__(), R_GlobalEnv ) ; } inline SEXP eval(SEXP env) const { return Rcpp_fast_eval( Storage::get__(), env ); } } ; /* Vector */ template <int RTYPE, template <class> class StoragePolicy > inline std::ostream &operator<<(std::ostream & s, const Vector<RTYPE, StoragePolicy> & rhs) { typedef Vector<RTYPE, StoragePolicy> VECTOR; typename VECTOR::iterator i = const_cast<VECTOR &>(rhs).begin(); typename VECTOR::iterator iend = const_cast<VECTOR &>(rhs).end(); if (i != iend) { s << (*i); ++i; for ( ; i != iend; ++i) { s << " " << (*i); } } return s; } template<template <class> class StoragePolicy > inline std::ostream &operator<<(std::ostream & s, const Vector<STRSXP, StoragePolicy> & rhs) { typedef Vector<STRSXP, StoragePolicy> VECTOR; typename VECTOR::iterator i = const_cast<VECTOR &>(rhs).begin(); typename VECTOR::iterator iend = const_cast<VECTOR &>(rhs).end(); if (i != iend) { s << "\"" << (*i) << "\""; ++i; for ( ; i != iend; ++i) { s << " \"" << (*i) << "\""; } } return s; } } #endif