Created
June 15, 2026 13:44
-
-
Save jmarrec/c16a288da758fecba50894d4063ca89e to your computer and use it in GitHub Desktop.
Flattened single-header ObjexxFCL Array1D + dependencies for Compiler Explorer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Flattened single-header bundle of ObjexxFCL Array1D and its dependencies | |
| // Generated for use on Compiler Explorer | |
| #pragma once | |
| // ===== ObjexxFCL/Array1D.fwd.hh ===== | |
| #ifndef ObjexxFCL_Array1D_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Array1D_fwd_hh_INCLUDED | |
| // Array1D Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Array1D; | |
| // Types | |
| typedef Array1D< bool > Array1D_bool; | |
| typedef Array1D< short int > Array1D_short; | |
| typedef Array1D< int > Array1D_int; | |
| typedef Array1D< unsigned short int > Array1D_ushort; | |
| typedef Array1D< std::size_t > Array1D_size; | |
| typedef Array1D< std::int32_t > Array1D_int32; | |
| typedef Array1D< double > Array1D_double; | |
| typedef Array1D< signed char > Array1D_schar; | |
| typedef Array1D< std::string > Array1D_string; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array1D_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/Array1.fwd.hh ===== | |
| #ifndef ObjexxFCL_Array1_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Array1_fwd_hh_INCLUDED | |
| // Array1 Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Array1; | |
| // Types | |
| typedef Array1< int > Array1_int; | |
| typedef Array1< std::string > Array1_string; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array1_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/Array.fwd.hh ===== | |
| #ifndef ObjexxFCL_Array_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Array_fwd_hh_INCLUDED | |
| // Array Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Array; | |
| // Types | |
| typedef Array< bool > Array_bool; | |
| typedef Array< short int > Array_short; | |
| typedef Array< int > Array_int; | |
| typedef Array< std::size_t > Array_size; | |
| typedef Array< double > Array_double; | |
| typedef Array< signed char > Array_schar; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/Omit.hh ===== | |
| #ifndef ObjexxFCL_Omit_hh_INCLUDED | |
| #define ObjexxFCL_Omit_hh_INCLUDED | |
| // Omit: Sentinel for Omitted Argument | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| namespace ObjexxFCL { | |
| // Omit: Sentinel for Omitted Argument | |
| struct Omit | |
| { | |
| }; // Omit | |
| static constexpr Omit _{}; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Omit_hh_INCLUDED | |
| // ===== ObjexxFCL/Index.hh ===== | |
| #ifndef ObjexxFCL_Index_hh_INCLUDED | |
| #define ObjexxFCL_Index_hh_INCLUDED | |
| // Index: Index Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <iosfwd> | |
| #include <type_traits> | |
| #include <utility> | |
| namespace ObjexxFCL { | |
| // Index: Index Class | |
| class Index | |
| { | |
| public: // Creation | |
| // Default Constructor | |
| Index() : | |
| init_( false ), | |
| i_( 0 ) | |
| {} | |
| // Copy Constructor | |
| Index( Index const & I ) : | |
| init_( I.init_ ), | |
| i_( I.i_ ) | |
| {} | |
| // Index Constructor | |
| Index( int const i ) : | |
| init_( true ), | |
| i_( i ) | |
| {} | |
| // Omit Constructor | |
| Index( Omit ) : | |
| init_( false ), | |
| i_( 0 ) | |
| {} | |
| // Destructor | |
| ~Index() | |
| {} | |
| public: // Assignment | |
| // Scalar Assignment | |
| Index & | |
| operator =( int const i ) | |
| { | |
| init_ = true; | |
| i_ = i; | |
| return *this; | |
| } | |
| public: // Conversion | |
| // int Conversion | |
| operator int() const | |
| { | |
| assert( init_ ); | |
| return i_; | |
| } | |
| public: // Predicate | |
| // Initialized? | |
| bool | |
| initialized() const | |
| { | |
| return init_; | |
| } | |
| public: // Inspector | |
| // Index | |
| int | |
| i() const | |
| { | |
| assert( init_ ); | |
| return i_; | |
| } | |
| public: // Modifier | |
| // Clear | |
| void | |
| clear() | |
| { | |
| init_ = false; | |
| i_ = 0; | |
| } | |
| // Index Set | |
| Index & | |
| i( int const i ) | |
| { | |
| init_ = true; | |
| i_ = i; | |
| return *this; | |
| } | |
| // Swap | |
| void | |
| swap( Index & I ) | |
| { | |
| std::swap( init_, I.init_ ); | |
| std::swap( i_, I.i_ ); | |
| } | |
| private: // Data | |
| bool init_; // Index initialized? | |
| int i_; // Index | |
| }; // Index | |
| // Functions | |
| // Swap | |
| inline | |
| void | |
| swap( Index & a, Index & b ) | |
| { | |
| a.swap( b ); | |
| } | |
| // Comparison | |
| // Index == Index | |
| inline | |
| bool | |
| operator ==( Index const & a, Index const & b ) | |
| { | |
| return ( a.initialized() && b.initialized() ? ( a.i() == b.i() ) : ! ( a.initialized() || b.initialized() ) ); | |
| } | |
| // Index != Index | |
| inline | |
| bool | |
| operator !=( Index const & a, Index const & b ) | |
| { | |
| return !( a == b ); | |
| } | |
| // Index == int | |
| inline | |
| bool | |
| operator ==( Index const & a, int const b ) | |
| { | |
| return ( a.initialized() && ( a.i() == b ) ); | |
| } | |
| // Index != int | |
| inline | |
| bool | |
| operator !=( Index const & a, int const b ) | |
| { | |
| return !( a == b ); | |
| } | |
| // int == Index | |
| inline | |
| bool | |
| operator ==( int const a, Index const & b ) | |
| { | |
| return ( b.initialized() && ( a == b.i() ) ); | |
| } | |
| // int != Index | |
| inline | |
| bool | |
| operator !=( int const a, Index const & b ) | |
| { | |
| return !( a == b ); | |
| } | |
| // I/O | |
| // Stream >> Index | |
| std::istream & | |
| operator >>( std::istream & stream, Index & a ); | |
| // Stream << Index | |
| std::ostream & | |
| operator <<( std::ostream & stream, Index const & a ); | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Index_hh_INCLUDED | |
| // ===== ObjexxFCL/IndexRange.hh ===== | |
| #ifndef ObjexxFCL_IndexRange_hh_INCLUDED | |
| #define ObjexxFCL_IndexRange_hh_INCLUDED | |
| // IndexRange: Index Range Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <initializer_list> | |
| #include <iosfwd> | |
| #include <type_traits> | |
| #include <utility> | |
| namespace ObjexxFCL { | |
| // IndexRange: Index Range Class | |
| // | |
| // Note: | |
| // Zero-size range is indicated by ( l - 1 == u ) and ( size == 0 ) | |
| // Upper-unbounded range is indicated by ( l - 2 == u ) and ( size == npos ) | |
| // Legal ranges have ( l - 2 <= u ) with l and u in their allowed ranges | |
| class IndexRange | |
| { | |
| public: // Types | |
| // STL style | |
| typedef std::size_t size_type; | |
| // C++ style | |
| typedef std::size_t Size; | |
| public: // Creation | |
| // Default Constructor | |
| IndexRange() : | |
| l_( 1 ), | |
| u_( 0 ), | |
| size_( 0u ) | |
| {} | |
| // Copy Constructor | |
| IndexRange( IndexRange const & I ) : | |
| l_( I.l_ ), | |
| u_( I.u_ ), | |
| size_( I.size_ ) | |
| {} | |
| // Upper Index Constructor | |
| IndexRange( int const u ) : | |
| l_( 1 ), | |
| u_( clean_u( u ) ), | |
| size_( u_ ) | |
| { | |
| assert( legal() ); | |
| } | |
| // Index Range Constructor | |
| IndexRange( int const l, int const u ) : | |
| l_( l ), | |
| u_( clean_u( u ) ), | |
| size_( computed_size() ) | |
| { | |
| assert( legal() ); | |
| } | |
| // Initializer List of Integer Constructor | |
| template< typename U, class = typename std::enable_if< std::is_constructible< int, U >::value >::type > | |
| IndexRange( std::initializer_list< U > const lu ) : | |
| l_( 1 ), | |
| u_( 0 ), | |
| size_( 0u ) | |
| { | |
| size_type const n( lu.size() ); | |
| assert( n <= 2 ); | |
| auto i( lu.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| break; | |
| case 1: // {l} | |
| l_ = int( *i ); | |
| u_ = l_ - 2; // Unbounded | |
| break; | |
| case 2: // {l,u} | |
| l_ = int( *i ); | |
| u_ = clean_u( *(++i) ); | |
| break; | |
| } | |
| size_ = computed_size(); | |
| assert( legal() ); | |
| } | |
| // Initializer List of Index Constructor | |
| IndexRange( std::initializer_list< Index > const lu ) : | |
| l_( 1 ), | |
| u_( 0 ), | |
| size_( 0u ) | |
| { | |
| size_type const n( lu.size() ); | |
| assert( n <= 2 ); | |
| auto i( lu.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| break; | |
| case 1: // {l} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = l_ - 2; // Unbounded | |
| break; | |
| case 2: // {l,u} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = (++i)->initialized() ? clean_u( int( *i ) ) : l_ - 2; // Omit => Unbounded | |
| break; | |
| } | |
| size_ = computed_size(); | |
| assert( legal() ); | |
| } | |
| // Omit Constructor | |
| IndexRange( Omit const ) : | |
| l_( 1 ), | |
| u_( -1 ), | |
| size_( npos ) | |
| {} | |
| // Lower Index + Omit Constructor | |
| IndexRange( int const l, Omit const ) : | |
| l_( l ), | |
| u_( l_ - 2 ), | |
| size_( npos ) | |
| {} | |
| // Omit + Upper Index Constructor | |
| IndexRange( Omit const, int const u ) : | |
| l_( u + 2 ), | |
| u_( u ), | |
| size_( npos ) | |
| { | |
| assert( legal() ); | |
| } | |
| // Omit + Omit Constructor | |
| IndexRange( Omit const, Omit const ) : | |
| l_( 1 ), | |
| u_( -1 ), | |
| size_( npos ) | |
| {} | |
| // Destructor | |
| ~IndexRange() | |
| {} | |
| public: // Assignment | |
| // Copy Assignment | |
| IndexRange & | |
| operator =( IndexRange const & I ) | |
| { | |
| if ( this != &I ) { | |
| l_ = I.l_; | |
| u_ = I.u_; | |
| size_ = I.size_; | |
| } | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // Upper Index Assignment | |
| IndexRange & | |
| operator =( int const u ) | |
| { | |
| l_ = 1; | |
| u_ = clean_u( u ); | |
| size_ = u_; | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // Initializer List of int Assignment | |
| template< typename U, class = typename std::enable_if< std::is_assignable< int&, U >::value >::type > | |
| IndexRange & | |
| operator =( std::initializer_list< U > const lu ) | |
| { | |
| size_type const n( lu.size() ); | |
| assert( n <= 2 ); | |
| auto i( lu.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| break; | |
| case 1: // {l} | |
| l_ = int( *i ); | |
| u_ = l_ - 2; // Unbounded | |
| break; | |
| case 2: // {l,u} | |
| l_ = int( *i ); | |
| u_ = clean_u( *(++i) ); | |
| break; | |
| } | |
| size_ = computed_size(); | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // Initializer List of Index Assignment | |
| IndexRange & | |
| operator =( std::initializer_list< Index > const lu ) | |
| { | |
| size_type const n( lu.size() ); | |
| assert( n <= 2 ); | |
| auto i( lu.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| break; | |
| case 1: // {l} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = l_ - 2; // Unbounded | |
| break; | |
| case 2: // {l,u} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = (++i)->initialized() ? clean_u( int( *i ) ) : l_ - 2; // Omit => Unbounded | |
| break; | |
| } | |
| size_ = computed_size(); | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // IndexRange Assignment | |
| IndexRange & | |
| assign( IndexRange const & I ) | |
| { | |
| l_ = I.l_; | |
| u_ = I.u_; | |
| size_ = I.size_; | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // Upper Index Assignment | |
| IndexRange & | |
| assign( int const u ) | |
| { | |
| l_ = 1; | |
| u_ = clean_u( u ); | |
| size_ = u_; | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // Index Range Assignment | |
| IndexRange & | |
| assign( int const l, int const u ) | |
| { | |
| l_ = l; | |
| u_ = clean_u( u ); | |
| size_ = computed_size(); | |
| assert( legal() ); | |
| return *this; | |
| } | |
| public: // Subscript | |
| // IndexRange( i ): Internal Index for i | |
| int | |
| operator ()( int const i ) const | |
| { | |
| return l_ + ( i - 1 ); | |
| } | |
| // IndexRange[ i ]: Internal Index for Zero-Based i | |
| int | |
| operator []( int const i ) const | |
| { | |
| return l_ + i; | |
| } | |
| public: // Predicate | |
| // Legal? | |
| bool | |
| legal() const | |
| { | |
| return ( ( l_ >= l_min ) && ( u_ <= u_max ) && ( l_ - 2 <= u_ ) ); | |
| } | |
| // Bounded? | |
| bool | |
| bounded() const | |
| { | |
| return ( l_ - 1 <= u_ ); | |
| } | |
| // Unbounded? | |
| bool | |
| unbounded() const | |
| { | |
| return ( l_ - 2 == u_ ); | |
| } | |
| // Empty? | |
| bool | |
| empty() const | |
| { | |
| return ( l_ - 1 == u_ ); | |
| } | |
| // Non-Empty? | |
| bool | |
| non_empty() const | |
| { | |
| return ( l_ <= u_ ); | |
| } | |
| // Bounded with Positive Size? | |
| bool | |
| positive() const | |
| { | |
| return ( l_ <= u_ ); | |
| } | |
| // Contains an Index? | |
| bool | |
| contains( int const i ) const | |
| { | |
| return ( ( l_ <= i ) && ( ( i <= u_ ) || ( size_ == npos ) ) ); | |
| } | |
| // Contains Two Indexes? | |
| bool | |
| contains( int const i, int const j ) const | |
| { | |
| return ( contains( i ) && contains( j ) ); | |
| } | |
| // Contains Another IndexRange? | |
| bool | |
| contains( IndexRange const & I ) const; | |
| // Intersects Another IndexRange? | |
| bool | |
| intersects( IndexRange const & I ) const; | |
| public: // Inspector | |
| // Lower Index | |
| int | |
| l() const | |
| { | |
| return l_; | |
| } | |
| // Upper Index | |
| int | |
| u() const | |
| { | |
| return u_; | |
| } | |
| // Size | |
| size_type | |
| size() const | |
| { | |
| return size_; // Unbounded => npos | |
| } | |
| // Size | |
| int | |
| isize() const | |
| { | |
| assert( size_ != npos ); | |
| return static_cast< int >( size_ ); | |
| } | |
| // Offset of an Index | |
| int | |
| offset( int const i ) const | |
| { | |
| return ( i - l_ ); // Doesn't check/require that IndexRange includes i | |
| } | |
| // Last Index | |
| int | |
| last() const | |
| { | |
| return std::max( l_, u_ ); | |
| } | |
| // Next Index | |
| int | |
| next( int const i ) const | |
| { | |
| return i + 1; // Doesn't check that this is a valid index | |
| } | |
| public: // Modifier | |
| // Lower Index Set | |
| IndexRange & | |
| l( int const l ) | |
| { | |
| if ( l_ - 2 == u_ ) { // Unbounded range | |
| l_ = l; | |
| u_ = l_ - 2; // Reset u_ to maintain unbounded state | |
| } else { // Bounded | |
| l_ = l; | |
| size_ = computed_size(); | |
| clean(); | |
| } | |
| return *this; | |
| } | |
| // Upper Index Set | |
| IndexRange & | |
| u( int const u ) | |
| { | |
| u_ = clean_u( u ); | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Grow Upper | |
| IndexRange & | |
| grow( int const n = 1 ) | |
| { | |
| assert( n >= 0 ); | |
| assert( u_ <= u_max - n ); | |
| assert( u_ >= l_ - 1 ); | |
| u_ += n; | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Shrink Upper | |
| IndexRange & | |
| shrink( int const n = 1 ) | |
| { | |
| assert( n >= 0 ); | |
| assert( u_ >= l_ - 1 ); | |
| u_ = clean_u( u_ - n ); | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Expand to Contain an Index | |
| IndexRange & | |
| contain( int const i ) | |
| { | |
| if ( l_ - 1 <= u_ ) { // Bounded | |
| if ( l_ > i ) l_ = i; | |
| if ( u_ < i ) u_ = i; | |
| size_ = computed_size(); | |
| } else { // Unbounded | |
| if ( l_ > i ) { | |
| l_ = i; | |
| u_ = l_ - 2; // Reset u_ to maintain unbounded state | |
| } | |
| } | |
| assert( legal() ); | |
| return *this; | |
| } | |
| // Expand to Contain Another IndexRange | |
| IndexRange & | |
| contain( IndexRange const & I ); | |
| // Intersect with Another IndexRange | |
| IndexRange & | |
| intersect( IndexRange const & I ); | |
| // Clear | |
| IndexRange & | |
| clear() | |
| { | |
| l_ = 1; | |
| u_ = 0; | |
| size_ = 0u; | |
| return *this; | |
| } | |
| // Clean | |
| IndexRange & | |
| clean() | |
| { | |
| if ( l_ > u_ ) { | |
| l_ = 1; | |
| u_ = 0; | |
| size_ = 0u; | |
| } | |
| return *this; | |
| } | |
| // Swap | |
| IndexRange & | |
| swap( IndexRange & I ) | |
| { | |
| if ( this != &I ) { | |
| std::swap( l_, I.l_ ); | |
| std::swap( u_, I.u_ ); | |
| std::swap( size_, I.size_ ); | |
| } | |
| return *this; | |
| } | |
| private: // Methods | |
| // Computed Size | |
| size_type | |
| computed_size() const | |
| { | |
| return std::max( u_ - l_ + 1, -1 ); | |
| } | |
| // Clean Upper Index Value After Lower Index Set | |
| int | |
| clean_u( int const u ) | |
| { | |
| return std::max( u, l_ - 1 ); | |
| } | |
| public: // Data | |
| static size_type const npos; // Unbounded "size" | |
| static int const l_min; // Min lower index | |
| static int const u_max; // Max upper index | |
| private: // Data | |
| int l_; // Lower index | |
| int u_; // Upper index | |
| size_type size_; // Size (npos iff unbounded) | |
| }; // IndexRange | |
| // Functions | |
| // IndexRange == IndexRange | |
| inline | |
| bool | |
| operator ==( IndexRange const & I, IndexRange const & J ) | |
| { | |
| return ( ( I.l() == J.l() ) && ( I.u() == J.u() ) ); | |
| } | |
| // IndexRange != IndexRange | |
| inline | |
| bool | |
| operator !=( IndexRange const & I, IndexRange const & J ) | |
| { | |
| return !( I == J ); | |
| } | |
| // IndexRange < IndexRange | |
| inline | |
| bool | |
| operator <( IndexRange const & I, IndexRange const & J ) | |
| { | |
| return ( I.positive() && J.positive() && ( I.u() < J.l() ) ); | |
| } | |
| // IndexRange <= IndexRange | |
| inline | |
| bool | |
| operator <=( IndexRange const & I, IndexRange const & J ) | |
| { | |
| return ( I.positive() && J.positive() && ( I.u() <= J.l() ) ); | |
| } | |
| // IndexRange > IndexRange | |
| inline | |
| bool | |
| operator >( IndexRange const & I, IndexRange const & J ) | |
| { | |
| return ( I.positive() && J.positive() && ( I.l() > J.u() ) ); | |
| } | |
| // IndexRange >= IndexRange | |
| inline | |
| bool | |
| operator >=( IndexRange const & I, IndexRange const & J ) | |
| { | |
| return ( I.positive() && J.positive() && ( I.l() >= J.u() ) ); | |
| } | |
| // Swap | |
| inline | |
| void | |
| swap( IndexRange & a, IndexRange & b ) | |
| { | |
| a.swap( b ); | |
| } | |
| // Stream >> IndexRange | |
| std::istream & | |
| operator >>( std::istream & stream, IndexRange & I ); | |
| // Stream << IndexRange | |
| std::ostream & | |
| operator <<( std::ostream & stream, IndexRange const & I ); | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_IndexRange_hh_INCLUDED | |
| // ===== ObjexxFCL/IndexSlice.hh ===== | |
| #ifndef ObjexxFCL_IndexSlice_hh_INCLUDED | |
| #define ObjexxFCL_IndexSlice_hh_INCLUDED | |
| // IndexSlice: Index Slice Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <initializer_list> | |
| #include <iosfwd> | |
| #include <type_traits> | |
| #include <utility> | |
| namespace ObjexxFCL { | |
| // IndexSlice: Index Slice Class | |
| class IndexSlice | |
| { | |
| public: // Types | |
| // STL style | |
| typedef std::size_t size_type; | |
| // C++ style | |
| typedef std::size_t Size; | |
| public: // Creation | |
| // Default Constructor | |
| IndexSlice() : | |
| l_init_( false ), | |
| u_init_( false ), | |
| scalar_( false ), | |
| l_( 1 ), | |
| u_( 0 ), | |
| s_( 1 ), | |
| size_( 0u ) | |
| {} | |
| // Copy Constructor | |
| IndexSlice( IndexSlice const & I ) : | |
| l_init_( I.l_init_ ), | |
| u_init_( I.u_init_ ), | |
| scalar_( I.scalar_ ), | |
| l_( I.l_ ), | |
| u_( I.u_ ), | |
| s_( I.s_ ), | |
| size_( I.size_ ) | |
| { | |
| assert( size_ == computed_size() ); | |
| } | |
| // Scalar Constructor | |
| IndexSlice( int const i ) : | |
| l_init_( true ), | |
| u_init_( true ), | |
| scalar_( true ), | |
| l_( i ), | |
| u_( i ), | |
| s_( 1 ), | |
| size_( 1u ) | |
| {} | |
| // Index Slice Constructor | |
| IndexSlice( int const l, int const u, int const s = 1 ) : | |
| l_init_( true ), | |
| u_init_( true ), | |
| scalar_( false ), | |
| l_( l ), | |
| u_( u ), | |
| s_( s ), | |
| size_( computed_size() ) | |
| { | |
| assert( s_ != 0 ); | |
| } | |
| // Initializer List of Integer Constructor | |
| template< typename U, class = typename std::enable_if< std::is_constructible< int, U >::value >::type > | |
| IndexSlice( std::initializer_list< U > const lus ) : | |
| l_init_( lus.size() > 0u ), | |
| u_init_( lus.size() > 1u ), | |
| scalar_( false ), | |
| l_( 1 ), | |
| u_( 0 ), | |
| s_( 1 ), | |
| size_( 0u ) | |
| { | |
| size_type const n( lus.size() ); | |
| assert( n <= 3 ); | |
| auto i( lus.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 1: // {l} | |
| l_ = *i; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 2: // {l,u} | |
| l_ = *i; | |
| u_ = *(++i); | |
| s_ = 1; | |
| break; | |
| case 3: // {l,u,s} | |
| l_ = *i; | |
| u_ = *(++i); | |
| s_ = *(++i); | |
| break; | |
| } | |
| assert( s_ != 0 ); | |
| size_ = computed_size(); | |
| } | |
| // Initializer List of Index Constructor | |
| IndexSlice( std::initializer_list< Index > const lus ) : | |
| l_init_( ( lus.size() > 0u ) && ( lus.begin()->initialized() ) ), | |
| u_init_( ( lus.size() > 1u ) && ( ( lus.begin() + 1 )->initialized() ) ), | |
| scalar_( false ), | |
| l_( 1 ), | |
| u_( 0 ), | |
| s_( 1 ), | |
| size_( 0u ) | |
| { | |
| size_type const n( lus.size() ); | |
| assert( n <= 3 ); | |
| auto i( lus.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 1: // {l} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 2: // {l,u} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = (++i)->initialized() ? int( *i ) : 0; | |
| s_ = 1; | |
| break; | |
| case 3: // {l,u,s} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = (++i)->initialized() ? int( *i ) : 0; | |
| s_ = (++i)->initialized() ? int( *i ) : 1; | |
| break; | |
| } | |
| assert( s_ != 0 ); | |
| size_ = computed_size(); | |
| } | |
| // Omit Constructor | |
| IndexSlice( Omit ) : | |
| l_init_( false ), | |
| u_init_( false ), | |
| scalar_( false ), | |
| l_( 1 ), | |
| u_( 0 ), | |
| s_( 1 ), | |
| size_( 0u ) | |
| { | |
| assert( s_ != 0 ); | |
| } | |
| // Lower Index + Omit Constructor | |
| IndexSlice( int const l, Omit, int const s = 1 ) : | |
| l_init_( true ), | |
| u_init_( false ), | |
| scalar_( false ), | |
| l_( l ), | |
| u_( 0 ), | |
| s_( s ), | |
| size_( 0u ) | |
| { | |
| assert( s_ != 0 ); | |
| } | |
| // Omit + Upper Index Constructor | |
| IndexSlice( Omit, int const u, int const s = 1 ) : | |
| l_init_( false ), | |
| u_init_( true ), | |
| scalar_( false ), | |
| l_( 1 ), | |
| u_( u ), | |
| s_( s ), | |
| size_( 0u ) | |
| { | |
| assert( s_ != 0 ); | |
| } | |
| // Omit + Omit Constructor | |
| IndexSlice( Omit, Omit, int const s = 1 ) : | |
| l_init_( false ), | |
| u_init_( false ), | |
| scalar_( false ), | |
| l_( 1 ), | |
| u_( 0 ), | |
| s_( s ), | |
| size_( 0u ) | |
| { | |
| assert( s_ != 0 ); | |
| } | |
| // Destructor | |
| ~IndexSlice() | |
| {} | |
| public: // Assignment | |
| // Scalar Assignment | |
| IndexSlice & | |
| operator =( int const i ) | |
| { | |
| l_init_ = true; | |
| u_init_ = true; | |
| scalar_ = true; | |
| l_ = i; | |
| u_ = i; | |
| s_ = 1; | |
| size_ = 1u; | |
| return *this; | |
| } | |
| // Initializer List of int Assignment | |
| IndexSlice & | |
| operator =( std::initializer_list< int > const lus ) | |
| { | |
| size_type const n( lus.size() ); | |
| assert( n <= 3 ); | |
| l_init_ = n > 0u; | |
| u_init_ = n > 1u; | |
| scalar_ = false; | |
| auto i( lus.begin() ); | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 1: // {l} | |
| l_ = *i; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 2: // {l,u} | |
| l_ = *i; | |
| u_ = *(++i); | |
| s_ = 1; | |
| break; | |
| case 3: // {l,u,s} | |
| l_ = *i; | |
| u_ = *(++i); | |
| s_ = *(++i); | |
| break; | |
| } | |
| assert( s_ != 0 ); | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Initializer List of Index Assignment | |
| IndexSlice & | |
| operator =( std::initializer_list< Index > const lus ) | |
| { | |
| size_type const n( lus.size() ); | |
| assert( n <= 3 ); | |
| auto i( lus.begin() ); | |
| l_init_ = ( n > 0u ) && ( i->initialized() ); | |
| u_init_ = ( n > 1u ) && ( ( i + 1 )->initialized() ); | |
| scalar_ = false; | |
| switch ( n ) { | |
| case 0: // {} | |
| l_ = 1; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 1: // {l} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = 0; | |
| s_ = 1; | |
| break; | |
| case 2: // {l,u} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = (++i)->initialized() ? int( *i ) : 0; | |
| s_ = 1; | |
| break; | |
| case 3: // {l,u,s} | |
| l_ = i->initialized() ? int( *i ) : 1; | |
| u_ = (++i)->initialized() ? int( *i ) : 0; | |
| s_ = (++i)->initialized() ? int( *i ) : 1; | |
| break; | |
| } | |
| assert( s_ != 0 ); | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Index Slice Assignment | |
| IndexSlice & | |
| assign( int const l, int const u, int const s = 1 ) | |
| { | |
| l_init_ = true; | |
| u_init_ = true; | |
| scalar_ = false; | |
| l_ = l; | |
| u_ = u; | |
| s_ = s; | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| public: // Subscript | |
| // IndexSlice( i ) const: Internal Index for i | |
| int | |
| operator ()( int const i ) const | |
| { | |
| assert( l_init_ ); | |
| return ( scalar_ ? l_ : l_ + ( i - 1 ) * s_ ); // Doesn't check that i <= size of slice | |
| } | |
| public: // Predicate | |
| // Initialized? | |
| bool | |
| initialized() const | |
| { | |
| return ( l_init_ && u_init_ ); | |
| } | |
| // Lower Initialized? | |
| bool | |
| l_initialized() const | |
| { | |
| return l_init_; | |
| } | |
| // Upper Initialized? | |
| bool | |
| u_initialized() const | |
| { | |
| return u_init_; | |
| } | |
| // Scalar? | |
| bool | |
| scalar() const | |
| { | |
| return scalar_; | |
| } | |
| // Contains an Index? | |
| bool | |
| contains( int const i ) const | |
| { | |
| assert( l_init_ && u_init_ ); | |
| return ( scalar_ ? i == l_ : ( std::min( l_, u_ ) <= i ) && ( i <= std::max( l_, u_ ) ) && ( ( ( i - l_ ) % s_ ) == 0 ) ); | |
| } | |
| public: // Inspector | |
| // Lower (Begin) Index | |
| int | |
| l() const | |
| { | |
| assert( l_initialized() ); | |
| return l_; | |
| } | |
| // Upper (End) Index | |
| int | |
| u() const | |
| { | |
| assert( u_initialized() ); | |
| return u_; | |
| } | |
| // Step | |
| int | |
| s() const | |
| { | |
| return s_; | |
| } | |
| // Size | |
| size_type | |
| size() const | |
| { | |
| return size_; | |
| } | |
| // Size | |
| int | |
| isize() const | |
| { | |
| return static_cast< int >( size_ ); | |
| } | |
| // Last Index | |
| int | |
| last() const | |
| { | |
| assert( initialized() ); | |
| assert( s_ != 0 ); | |
| return l_ + ( s_ * ( size_ > 0u ? int( size_ - 1u ) : 0 ) ); // Get l_ if size==0 | |
| } | |
| // Next Index | |
| int | |
| next( int const i ) const | |
| { | |
| assert( l_init_ ); | |
| assert( contains( i ) ); | |
| return ( scalar_ ? l_ : i + s_ ); // Doesn't check that this is a valid index | |
| } | |
| // Min Index | |
| int | |
| min() const | |
| { | |
| assert( initialized() ); | |
| return std::min( l_, last() ); | |
| } | |
| // Max Index | |
| int | |
| max() const | |
| { | |
| assert( initialized() ); | |
| return std::max( l_, last() ); | |
| } | |
| // Empty or Undefined? | |
| bool | |
| empty() const | |
| { | |
| return ( size_ == 0u ); | |
| } | |
| // Non-Empty? | |
| bool | |
| non_empty() const | |
| { | |
| return ( size_ > 0u ); | |
| } | |
| public: // Modifier | |
| // Clear | |
| void | |
| clear() | |
| { | |
| l_init_ = false; | |
| u_init_ = false; | |
| scalar_ = false; | |
| l_ = 1; | |
| u_ = 0; | |
| s_ = 1; | |
| size_ = 0u; | |
| } | |
| // Scalar Index Set | |
| IndexSlice & | |
| i( int const i ) | |
| { | |
| l_init_ = true; | |
| u_init_ = true; | |
| scalar_ = true; | |
| l_ = i; | |
| u_ = i; | |
| s_ = 1; | |
| size_ = 1u; | |
| return *this; | |
| } | |
| // Lower Index Set | |
| IndexSlice & | |
| l( int const l ) | |
| { | |
| l_init_ = true; | |
| scalar_ = false; | |
| l_ = l; | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Upper Index Set | |
| IndexSlice & | |
| u( int const u ) | |
| { | |
| u_init_ = true; | |
| scalar_ = false; | |
| u_ = u; | |
| size_ = computed_size(); | |
| return *this; | |
| } | |
| // Index Set if Uninitialized | |
| void | |
| lud( int const l, int const u ) | |
| { | |
| if ( ! l_init_ ) { | |
| l_ = l; | |
| l_init_ = true; | |
| } | |
| if ( ( ! u_init_ ) && ( l - 1 <= u ) ) { | |
| u_ = u; | |
| u_init_ = true; | |
| } | |
| scalar_ = false; | |
| size_ = computed_size(); | |
| } | |
| // Swap | |
| void | |
| swap( IndexSlice & I ) | |
| { | |
| if ( this != &I ) { | |
| std::swap( l_init_, I.l_init_ ); | |
| std::swap( u_init_, I.u_init_ ); | |
| std::swap( scalar_, I.scalar_ ); | |
| std::swap( l_, I.l_ ); | |
| std::swap( u_, I.u_ ); | |
| std::swap( s_, I.s_ ); | |
| std::swap( size_, I.size_ ); | |
| } | |
| } | |
| public: // Friend | |
| // Swap | |
| friend | |
| void | |
| swap( IndexSlice & a, IndexSlice & b ) | |
| { | |
| a.swap( b ); | |
| } | |
| public: // Comparison | |
| // IndexSlice == IndexSlice | |
| friend | |
| bool | |
| operator ==( IndexSlice const & I, IndexSlice const & J ) | |
| { | |
| return ( ( I.l_init_ == J.l_init_ ) && ( I.u_init_ == J.u_init_ ) && ( I.scalar_ == J.scalar_ ) && ( I.l_ == J.l_ ) && ( I.u_ == J.u_ ) && ( I.s_ == J.s_ ) ); | |
| } | |
| // IndexSlice != IndexSlice | |
| friend | |
| bool | |
| operator !=( IndexSlice const & I, IndexSlice const & J ) | |
| { | |
| return !( I == J ); | |
| } | |
| public: // I/O | |
| // Stream >> IndexSlice | |
| friend | |
| std::istream & | |
| operator >>( std::istream & stream, IndexSlice & I ); | |
| // Stream << IndexSlice | |
| friend | |
| std::ostream & | |
| operator <<( std::ostream & stream, IndexSlice const & I ); | |
| private: // Inspector | |
| // Computed Size | |
| size_type | |
| computed_size() const | |
| { | |
| assert( s_ != 0 || ! l_init_ || ! u_init_ ); | |
| return ( l_init_ && u_init_ ? std::max( ( u_ - l_ + s_ ) / s_, 0 ) : 0 ); | |
| } | |
| private: // Data | |
| bool l_init_; // Lower index initialized? | |
| bool u_init_; // Upper index initialized? | |
| bool scalar_; // Scalar slice? | |
| int l_; // Lower index | |
| int u_; // Upper index | |
| int s_; // Step | |
| size_type size_; // Size (0 if unknown) | |
| }; // IndexSlice | |
| // Types | |
| typedef IndexSlice ISlice; | |
| // IndexSlice == IndexSlice | |
| bool | |
| operator ==( IndexSlice const & I, IndexSlice const & J ); | |
| // IndexSlice != IndexSlice | |
| bool | |
| operator !=( IndexSlice const & I, IndexSlice const & J ); | |
| // Stream >> IndexSlice | |
| std::istream & | |
| operator >>( std::istream & stream, IndexSlice & I ); | |
| // Stream << IndexSlice | |
| std::ostream & | |
| operator <<( std::ostream & stream, IndexSlice const & I ); | |
| // Swap | |
| void | |
| swap( IndexSlice & a, IndexSlice & b ); | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_IndexSlice_hh_INCLUDED | |
| // ===== ObjexxFCL/DimensionSlice.hh ===== | |
| #ifndef ObjexxFCL_DimensionSlice_hh_INCLUDED | |
| #define ObjexxFCL_DimensionSlice_hh_INCLUDED | |
| // DimensionSlice: Dimension Slice Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <cstdlib> | |
| #include <limits> | |
| namespace ObjexxFCL { | |
| // DimensionSlice: Dimension Slice Class | |
| class DimensionSlice | |
| { | |
| public: // Types | |
| // STL style | |
| typedef std::size_t size_type; | |
| // C++ style | |
| typedef std::size_t Size; | |
| public: // Creation | |
| // Default Constructor | |
| DimensionSlice() : | |
| m_( 1 ), | |
| k_( 0 ), | |
| u_( 0 ) | |
| {} | |
| // Index Slice + Multiplier Constructor | |
| DimensionSlice( IndexSlice const & slice, std::int64_t const multiplier = 1 ) : | |
| m_( slice.s() * multiplier ), | |
| k_( slice.l() * multiplier - m_ ), | |
| u_( slice.isize() ) | |
| { | |
| assert( slice.initialized() ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ); | |
| } | |
| // Index Slice + Multiplier Constructor | |
| DimensionSlice( IndexSlice const & slice, size_type const multiplier ) : | |
| m_( slice.s() * multiplier ), | |
| k_( slice.l() * multiplier - m_ ), | |
| u_( slice.isize() ) | |
| { | |
| assert( slice.initialized() ); | |
| assert( multiplier <= size_type( std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ) ); | |
| } | |
| // Index Slice + Multiplier Constructor | |
| template< typename M > | |
| DimensionSlice( IndexSlice const & slice, M const multiplier ) : | |
| m_( slice.s() * multiplier ), | |
| k_( slice.l() * multiplier - m_ ), | |
| u_( slice.isize() ) | |
| { | |
| assert( slice.initialized() ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ); | |
| } | |
| // Index Range + Index Slice + Multiplier Constructor | |
| DimensionSlice( IndexRange const & range, IndexSlice slice, std::int64_t const multiplier = 1 ) | |
| { | |
| slice.lud( range.l(), range.u() ); | |
| assert( slice.initialized() ); | |
| assert( slice.empty() || range.contains( slice.l(), slice.last() ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ); | |
| m_ = slice.s() * multiplier; | |
| k_ = ( slice.l() * multiplier ) - m_; | |
| u_ = slice.isize(); | |
| } | |
| // Index Range + Index Slice + Multiplier Constructor | |
| DimensionSlice( IndexRange const & range, IndexSlice slice, size_type const multiplier ) | |
| { | |
| slice.lud( range.l(), range.u() ); | |
| assert( slice.initialized() ); | |
| assert( slice.empty() || range.contains( slice.l(), slice.last() ) ); | |
| assert( multiplier <= size_type( std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ) ); | |
| m_ = slice.s() * multiplier; | |
| k_ = ( slice.l() * multiplier ) - m_; | |
| u_ = slice.isize(); | |
| } | |
| // Index Range + Index Slice + Multiplier Constructor | |
| template< typename M > | |
| DimensionSlice( IndexRange const & range, IndexSlice slice, M const multiplier ) | |
| { | |
| slice.lud( range.l(), range.u() ); | |
| assert( slice.initialized() ); | |
| assert( slice.empty() || range.contains( slice.l(), slice.last() ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ); | |
| m_ = slice.s() * multiplier; | |
| k_ = ( slice.l() * multiplier ) - m_; | |
| u_ = slice.isize(); | |
| } | |
| // Upper Index + Index Slice + Multiplier Constructor | |
| DimensionSlice( int const u, IndexSlice slice, std::int64_t const multiplier = 1 ) | |
| { | |
| assert( u >= 0 ); | |
| slice.lud( 1, u ); | |
| assert( slice.initialized() ); | |
| assert( slice.empty() || ( in_range( u, slice.l() ) && in_range( u, slice.last() ) ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ); | |
| m_ = slice.s() * multiplier; | |
| k_ = ( slice.l() * multiplier ) - m_; | |
| u_ = slice.isize(); | |
| } | |
| // Upper Index + Index Slice + Multiplier Constructor | |
| DimensionSlice( int const u, IndexSlice slice, size_type const multiplier ) | |
| { | |
| assert( u >= 0 ); | |
| slice.lud( 1, u ); | |
| assert( slice.initialized() ); | |
| assert( slice.empty() || ( in_range( u, slice.l() ) && in_range( u, slice.last() ) ) ); | |
| assert( multiplier <= size_type( std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ) ); | |
| m_ = slice.s() * multiplier; | |
| k_ = ( slice.l() * multiplier ) - m_; | |
| u_ = slice.isize(); | |
| } | |
| // Upper Index + Index Slice + Multiplier Constructor | |
| template< typename M > | |
| DimensionSlice( int const u, IndexSlice slice, M const multiplier ) | |
| { | |
| assert( u >= 0 ); | |
| slice.lud( 1, u ); | |
| assert( slice.initialized() ); | |
| assert( slice.empty() || ( in_range( u, slice.l() ) && in_range( u, slice.last() ) ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( slice.s() ) ); | |
| m_ = slice.s() * multiplier; | |
| k_ = ( slice.l() * multiplier ) - m_; | |
| u_ = slice.isize(); | |
| } | |
| // Index Range + Multiplier Full Range Constructor | |
| DimensionSlice( IndexRange const & range, size_type const multiplier = 1 ) | |
| { | |
| assert( range.bounded() ); | |
| assert( multiplier <= size_type( std::numeric_limits< std::int64_t >::max() ) ); | |
| m_ = multiplier; | |
| k_ = ( static_cast<std::int64_t>(range.l()) - 1 ) * multiplier; | |
| u_ = range.isize(); | |
| } | |
| // Destructor | |
| ~DimensionSlice() | |
| {} | |
| public: // Inspector | |
| // Multiplier | |
| std::int64_t | |
| m() const | |
| { | |
| return m_; | |
| } | |
| // Constant | |
| std::int64_t | |
| k() const | |
| { | |
| return k_; | |
| } | |
| // Upper Index | |
| int | |
| u() const | |
| { | |
| return u_; | |
| } | |
| // Size | |
| size_type | |
| z() const | |
| { | |
| return u_; | |
| } | |
| // Size | |
| size_type | |
| size() const | |
| { | |
| return u_; | |
| } | |
| public: // Modifier | |
| // Clear | |
| void | |
| clear() | |
| { | |
| m_ = 1; | |
| k_ = 0; | |
| u_ = 0; | |
| } | |
| protected: // Static Methods | |
| // Is Index in Range of [1,u] | |
| static | |
| bool | |
| in_range( int const u, int const i ) | |
| { | |
| return ( ( 1 <= i ) && ( i <= u ) ); | |
| } | |
| private: // Data | |
| std::int64_t m_; // Multiplier | |
| std::int64_t k_; // Constant | |
| int u_; // Upper index | |
| }; // DimensionSlice | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_DimensionSlice_hh_INCLUDED | |
| // ===== ObjexxFCL/BArray.hh ===== | |
| #ifndef ObjexxFCL_BArray_hh_INCLUDED | |
| #define ObjexxFCL_BArray_hh_INCLUDED | |
| // BArray: Array Abstract Base Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| namespace ObjexxFCL { | |
| // BArray: Array Abstract Base Class | |
| class BArray | |
| { | |
| public: // Types | |
| typedef IndexRange IR; | |
| typedef IndexSlice IS; | |
| typedef DimensionSlice DS; | |
| // STL style | |
| typedef std::size_t size_type; | |
| typedef std::ptrdiff_t difference_type; | |
| // C++ style | |
| typedef std::size_t Size; | |
| typedef std::ptrdiff_t Difference; | |
| protected: // Creation | |
| // Default Constructor | |
| constexpr BArray() = default; | |
| // Copy Constructor | |
| constexpr BArray( BArray const & ) = default; | |
| // Move Constructor | |
| constexpr BArray( BArray && ) noexcept = default; | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~BArray() = default; | |
| protected: // Assignment | |
| // Copy Assignment | |
| BArray & | |
| operator =( BArray const & ) = default; | |
| // Move Assignment | |
| BArray & | |
| operator =( BArray && ) noexcept = default; | |
| public: // Static Data | |
| static constexpr size_type const npos = static_cast<size_type>(-1); // Unbounded "size" | |
| static constexpr size_type const max_size = static_cast<size_type>(-1) - static_cast<size_type>(1); // Max array size | |
| }; // BArray | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_BArray_hh_INCLUDED | |
| // ===== ObjexxFCL/align.hh ===== | |
| #ifndef ObjexxFCL_align_hh_INCLUDED | |
| #define ObjexxFCL_align_hh_INCLUDED | |
| // Alignment Support | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <cstdint> | |
| // Auto-Selected Alignment | |
| #if defined(__MIC__) | |
| #define OBJEXXFCL_ALIGN_AUTO 64 | |
| #elif defined(__AVX__) | |
| #define OBJEXXFCL_ALIGN_AUTO 32 | |
| #elif defined(__SSE__) | |
| #define OBJEXXFCL_ALIGN_AUTO 16 | |
| #else | |
| #define OBJEXXFCL_ALIGN_AUTO 16 | |
| #endif | |
| // Specified Alignment | |
| #ifdef OBJEXXFCL_ALIGN | |
| #if OBJEXXFCL_ALIGN < OBJEXXFCL_ALIGN_AUTO | |
| #undef OBJEXXFCL_ALIGN | |
| #define OBJEXXFCL_ALIGN OBJEXXFCL_ALIGN_AUTO | |
| #endif | |
| static_assert( ( OBJEXXFCL_ALIGN & ( OBJEXXFCL_ALIGN - 1 ) ) == 0, "OBJEXXFCL_ALIGN must be a power of 2" ); | |
| #endif | |
| #ifdef OBJEXXFCL_ALIGN | |
| namespace ObjexxFCL { | |
| // Byte Address Rounded Up to Satisfy Alignment | |
| template< typename T > | |
| T * | |
| aligned( T * const mem ) // Can add a variant taking a void * if needed | |
| { | |
| static T const ALIGN( OBJEXXFCL_ALIGN ); | |
| static T const zero( 0 ); | |
| static T const one( 1 ); | |
| static_assert( ( ALIGN > zero ) && ( ( ALIGN & ( ALIGN - one ) ) == zero ), "Byte alignment must be a positive power of 2" ); // Positive power of 2 check | |
| return ( ( mem == nullptr ) || ( ALIGN <= T( 0 ) ) ? mem : reinterpret_cast< T * >( ( reinterpret_cast< std::uintptr_t >( mem ) + static_cast< std::uintptr_t >( ALIGN - 1 ) ) & ~static_cast< std::uintptr_t >( ALIGN - 1 ) ) ); | |
| } | |
| // Can Row Length be Padded to Satisfy Alignment? | |
| template< typename T > | |
| bool | |
| paddable() | |
| { | |
| static int const REM( OBJEXXFCL_ALIGN % static_cast< int >( sizeof( T ) ) ); | |
| return REM == 0; | |
| } | |
| // Row Length Rounded up to Satisfy Alignment | |
| template< typename T > | |
| T | |
| padded( int const row ) | |
| { | |
| static_assert( OBJEXXFCL_ALIGN % static_cast< int >( sizeof( T ) ) == 0, "Type is not row-paddable for the byte alignment" ); // Paddable check | |
| assert( row >= 0 ); | |
| static int const MUL( OBJEXXFCL_ALIGN / static_cast< int >( sizeof( T ) ) ); // Aligned multiple of T | |
| int const rem( row % MUL ); | |
| return ( rem > 0 ? row + MUL - rem : row ); | |
| } | |
| } // ObjexxFCL | |
| #endif | |
| #endif // ObjexxFCL_align_hh_INCLUDED | |
| // ===== ObjexxFCL/AlignedAllocator.hh ===== | |
| #ifndef ObjexxFCL_AlignedAllocator_hh_INCLUDED | |
| #define ObjexxFCL_AlignedAllocator_hh_INCLUDED | |
| // Aligned Allocator | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <limits> | |
| #include <new> | |
| namespace ObjexxFCL { | |
| // Aligned Allocator Class Template | |
| template< typename T > | |
| struct AlignedAllocator | |
| { | |
| public: // Types | |
| // STL Style | |
| using size_type = std::size_t; | |
| // C++ Style | |
| using Size = std::size_t; | |
| public: // Static Methods | |
| // Raw allocation size including optional alignment padding | |
| static | |
| size_type | |
| allocation_size( size_type const n ) | |
| { | |
| #ifdef OBJEXXFCL_ALIGN | |
| constexpr size_type alignment_overhead( OBJEXXFCL_ALIGN > 0u ? OBJEXXFCL_ALIGN - 1u : 0u ); | |
| #else | |
| constexpr size_type alignment_overhead( 0u ); | |
| #endif | |
| constexpr size_type max_size( static_cast< size_type >( std::numeric_limits< std::ptrdiff_t >::max() ) ); | |
| if ( n > ( max_size - alignment_overhead ) / sizeof( T ) ) { | |
| throw std::bad_array_new_length(); | |
| } | |
| return ( n * sizeof( T ) ) + alignment_overhead; | |
| } | |
| // Allocate Raw Array Memory with ::operator new | |
| static | |
| void * | |
| allocate( size_type const n ) | |
| { | |
| void * mem( n > 0u ? ::operator new( allocation_size( n ) ) : nullptr ); | |
| assert( ( n == 0u ) || ( mem != nullptr ) ); | |
| return mem; | |
| } | |
| // Allocate Raw Array Memory with ::operator new Even if Size is Zero | |
| static | |
| void * | |
| allocate_zero( size_type const n ) | |
| { | |
| void * mem( ::operator new( allocation_size( n ) ) ); | |
| assert( ( n == 0u ) || ( mem != nullptr ) ); | |
| return mem; | |
| } | |
| // Aligned Data Pointer for a Given Memory Pointer | |
| static | |
| T * | |
| data( void * const mem ) | |
| { | |
| #ifdef OBJEXXFCL_ALIGN | |
| T * p( static_cast< T * >( ( mem == nullptr ) || ( OBJEXXFCL_ALIGN == 0u ) ? mem : reinterpret_cast< void * >( ( reinterpret_cast< std::uintptr_t >( mem ) + static_cast< std::uintptr_t >( OBJEXXFCL_ALIGN - 1 ) ) & ~static_cast< std::uintptr_t >( OBJEXXFCL_ALIGN - 1 ) ) ) ); | |
| assert( p >= mem ); | |
| assert( reinterpret_cast< std::uintptr_t >( p ) % OBJEXXFCL_ALIGN == 0 ); | |
| #else | |
| T * p( static_cast< T * >( mem ) ); | |
| #endif | |
| return p; | |
| } | |
| }; // AlignedAllocator | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_AlignedAllocator_hh_INCLUDED | |
| // ===== ObjexxFCL/ArrayS.fwd.hh ===== | |
| #ifndef ObjexxFCL_ArrayS_fwd_hh_INCLUDED | |
| #define ObjexxFCL_ArrayS_fwd_hh_INCLUDED | |
| // ArrayS Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class ArrayS; | |
| // Types | |
| typedef ArrayS< double > ArrayS_double; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_ArrayS_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/TypeTraits.hh ===== | |
| #ifndef ObjexxFCL_TypeTraits_hh_INCLUDED | |
| #define ObjexxFCL_TypeTraits_hh_INCLUDED | |
| // TypeTraits: Type Traits Template | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <complex> | |
| #include <cstddef> | |
| #include <ios> | |
| #include <limits> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| template< class A, class B > | |
| inline | |
| bool | |
| same_type_as( A const &, B const & ) | |
| { | |
| return std::is_same< A, B >::value; | |
| } | |
| // is_a: Type Test for const Reference Argument | |
| template< class B, class A > | |
| inline | |
| bool | |
| is_a( A const & ) | |
| { | |
| return std::is_same< A, B >::value || std::is_base_of< B, A >::value; | |
| } | |
| // is_a: Type Test for non-const Reference Argument | |
| template< class B, class A > | |
| inline | |
| bool | |
| is_a( A & ) | |
| { | |
| return std::is_same< A, B >::value || std::is_base_of< B, A >::value; | |
| } | |
| // is_a: Type Test for const Pointer Argument | |
| template< class B, class A > | |
| inline | |
| bool | |
| is_a( A const * ) | |
| { | |
| return std::is_same< A, B >::value || std::is_base_of< B, A >::value; | |
| } | |
| // is_a: Type Test for non-const Pointer Argument | |
| template< class B, class A > | |
| inline | |
| bool | |
| is_a( A * ) | |
| { | |
| return std::is_same< A, B >::value || std::is_base_of< B, A >::value; | |
| } | |
| // TypeTraits: Type Traits Template | |
| template< typename T > | |
| struct TypeTraits | |
| { | |
| typedef T traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 0; // Field width | |
| static int const iwidth = 0; // Field width | |
| }; | |
| // TypeTraits: Type Traits char Specialization | |
| template<> | |
| struct TypeTraits< char > | |
| { | |
| typedef char traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return ' '; | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 1; // Field width | |
| static int const iwidth = 1; // Field width | |
| }; | |
| // TypeTraits: Type Traits signed char Specialization | |
| template<> | |
| struct TypeTraits< signed char > | |
| { | |
| typedef signed char traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return ' '; | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 1; // Field width | |
| static int const iwidth = 1; // Field width | |
| }; | |
| // TypeTraits: Type Traits unsigned char Specialization | |
| template<> | |
| struct TypeTraits< unsigned char > | |
| { | |
| typedef unsigned char traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return ' '; | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 1; // Field width | |
| static int const iwidth = 1; // Field width | |
| }; | |
| // TypeTraits: Type Traits bool Specialization | |
| template<> | |
| struct TypeTraits< bool > | |
| { | |
| typedef bool traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 2; // Field width | |
| static int const iwidth = 2; // Field width | |
| }; | |
| // TypeTraits: Type Traits short int Specialization | |
| template<> | |
| struct TypeTraits< short int > | |
| { | |
| typedef short int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 7; // Field width | |
| static int const iwidth = 7; // Field width | |
| }; | |
| // TypeTraits: Type Traits unsigned short int Specialization | |
| template<> | |
| struct TypeTraits< unsigned short int > | |
| { | |
| typedef unsigned short int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 7; // Field width | |
| static int const iwidth = 7; // Field width | |
| }; | |
| // TypeTraits: Type Traits int Specialization | |
| template<> | |
| struct TypeTraits< int > | |
| { | |
| typedef int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 12; // Field width | |
| static int const iwidth = 12; // Field width | |
| }; | |
| // TypeTraits: Type Traits unsigned int Specialization | |
| template<> | |
| struct TypeTraits< unsigned int > | |
| { | |
| typedef unsigned int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 12; // Field width | |
| static int const iwidth = 12; // Field width | |
| }; | |
| // TypeTraits: Type Traits long int Specialization | |
| template<> | |
| struct TypeTraits< long int > | |
| { | |
| typedef long int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 23; // Field width | |
| static int const iwidth = 23; // Field width | |
| }; | |
| // TypeTraits: Type Traits unsigned long int Specialization | |
| template<> | |
| struct TypeTraits< unsigned long int > | |
| { | |
| typedef unsigned long int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 23; // Field width | |
| static int const iwidth = 23; // Field width | |
| }; | |
| // TypeTraits: Type Traits long long int Specialization | |
| template<> | |
| struct TypeTraits< long long int > | |
| { | |
| typedef long long int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 23; // Field width | |
| static int const iwidth = 23; // Field width | |
| }; | |
| // TypeTraits: Type Traits unsigned long long int Specialization | |
| template<> | |
| struct TypeTraits< unsigned long long int > | |
| { | |
| typedef unsigned long long int traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return std::numeric_limits< traits_type >::max(); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| static std::streamsize const precision = 0; // Precision | |
| static Size const width = 23; // Field width | |
| static int const iwidth = 23; // Field width | |
| }; | |
| // TypeTraits: Type Traits float Specialization | |
| template<> | |
| struct TypeTraits< float > | |
| { | |
| typedef float traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return ( std::numeric_limits< traits_type >::has_signaling_NaN ? std::numeric_limits< traits_type >::signaling_NaN() : std::numeric_limits< traits_type >::max() ); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| #ifdef OBJEXXFCL_TYPETRAITS_EXTRA_PRECISION | |
| static std::streamsize const precision = 9; // Precision | |
| #else | |
| static std::streamsize const precision = 8; // Precision | |
| #endif | |
| static Size const width = 15; // Field width | |
| static int const iwidth = 15; // Field width | |
| }; | |
| // TypeTraits: Type Traits double Specialization | |
| template<> | |
| struct TypeTraits< double > | |
| { | |
| typedef double traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return ( std::numeric_limits< traits_type >::has_signaling_NaN ? std::numeric_limits< traits_type >::signaling_NaN() : std::numeric_limits< traits_type >::max() ); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| #ifdef OBJEXXFCL_TYPETRAITS_EXTRA_PRECISION | |
| static std::streamsize const precision = 17; // Precision | |
| #else | |
| static std::streamsize const precision = 16; // Precision | |
| #endif | |
| static Size const width = 23; // Field width | |
| static int const iwidth = 23; // Field width | |
| }; | |
| // TypeTraits: Type Traits long double Specialization | |
| template<> | |
| struct TypeTraits< long double > | |
| { | |
| typedef long double traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return ( std::numeric_limits< traits_type >::has_signaling_NaN ? std::numeric_limits< traits_type >::signaling_NaN() : std::numeric_limits< traits_type >::max() ); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| #ifdef OBJEXXFCL_TYPETRAITS_EXTRA_PRECISION | |
| static std::streamsize const precision = 34; // Precision | |
| #else | |
| static std::streamsize const precision = 33; // Precision | |
| #endif | |
| static Size const width = 42; // Field width | |
| static int const iwidth = 42; // Field width | |
| }; | |
| // TypeTraits: Type Traits std::complex< float > Specialization | |
| template<> | |
| struct TypeTraits< std::complex< float > > | |
| { | |
| typedef float value_type; | |
| typedef std::complex< float > traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return traits_type( TypeTraits< value_type >::debug_value(), TypeTraits< value_type >::debug_value() ); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| #ifdef OBJEXXFCL_TYPETRAITS_EXTRA_PRECISION | |
| static std::streamsize const precision = 9; // Precision | |
| #else | |
| static std::streamsize const precision = 8; // Precision | |
| #endif | |
| static Size const width = 33; // Field width | |
| static int const iwidth = 33; // Field width | |
| }; | |
| // TypeTraits: Type Traits std::complex< double > Specialization | |
| template<> | |
| struct TypeTraits< std::complex< double > > | |
| { | |
| typedef double value_type; | |
| typedef std::complex< double > traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return traits_type( TypeTraits< value_type >::debug_value(), TypeTraits< value_type >::debug_value() ); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| #ifdef OBJEXXFCL_TYPETRAITS_EXTRA_PRECISION | |
| static std::streamsize const precision = 17; // Precision | |
| #else | |
| static std::streamsize const precision = 16; // Precision | |
| #endif | |
| static Size const width = 49; // Field width | |
| static int const iwidth = 49; // Field width | |
| }; | |
| // TypeTraits: Type Traits std::complex< long double > Specialization | |
| template<> | |
| struct TypeTraits< std::complex< long double > > | |
| { | |
| typedef long double value_type; | |
| typedef std::complex< long double > traits_type; | |
| typedef std::size_t Size; | |
| // Initial Value | |
| static | |
| traits_type | |
| initial_value() | |
| { | |
| return traits_type(); // Use default constructor | |
| } | |
| // Debug Value | |
| static | |
| traits_type | |
| debug_value() | |
| { | |
| return traits_type( TypeTraits< value_type >::debug_value(), TypeTraits< value_type >::debug_value() ); | |
| } | |
| // Initial Array Value | |
| static | |
| traits_type | |
| initial_array_value() | |
| { | |
| #ifdef OBJEXXFCL_ARRAY_INIT_DEBUG | |
| return debug_value(); | |
| #else | |
| return initial_value(); | |
| #endif | |
| } | |
| #ifdef OBJEXXFCL_TYPETRAITS_EXTRA_PRECISION | |
| static std::streamsize const precision = 34; // Precision | |
| #else | |
| static std::streamsize const precision = 33; // Precision | |
| #endif | |
| static Size const width = 83; // Field width | |
| static int const iwidth = 83; // Field width | |
| }; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_TypeTraits_hh_INCLUDED | |
| // ===== ObjexxFCL/ArrayS.hh ===== | |
| #ifndef ObjexxFCL_ArrayS_hh_INCLUDED | |
| #define ObjexxFCL_ArrayS_hh_INCLUDED | |
| // ArrayS: Slice Array Proxy Abstract Base Class Template | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <cstdlib> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <istream> | |
| #include <limits> | |
| #include <ostream> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Array; | |
| // ArrayS: Slice Array Proxy Abstract Base Class Template | |
| template< typename T > | |
| class ArrayS : public BArray | |
| { | |
| private: // Friend | |
| template< typename > friend class ArrayS; | |
| template< typename > friend class Array; | |
| public: // Types | |
| typedef ArrayS< T > Base; | |
| typedef TypeTraits< T > Traits; | |
| // STL style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| // C++ style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| protected: // Creation | |
| // Default Constructor | |
| ArrayS() : | |
| data_( nullptr ), | |
| data_beg_( nullptr ), | |
| data_end_( nullptr ), | |
| size_( 0u ), | |
| contiguous_( false ) | |
| {} | |
| // Copy Constructor | |
| ArrayS( ArrayS const & a ) : | |
| BArray( a ), | |
| data_( a.data_ ), | |
| data_beg_( a.data_beg_ ), | |
| data_end_( a.data_end_ ), | |
| size_( a.size_ ), | |
| contiguous_( a.contiguous_ ) | |
| {} | |
| // Data Constructor | |
| ArrayS( T const * data, size_type const size ) : | |
| data_( const_cast< T * >( data ) ), | |
| data_beg_( nullptr ), | |
| data_end_( nullptr ), | |
| size_( size ), | |
| contiguous_( false ) | |
| {} | |
| // Non-Const Data Constructor | |
| ArrayS( T * data, size_type const size ) : | |
| data_( data ), | |
| data_beg_( nullptr ), | |
| data_end_( nullptr ), | |
| size_( size ), | |
| contiguous_( false ) | |
| {} | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~ArrayS() = default; | |
| public: // Predicate | |
| // Active Array Empty? | |
| bool | |
| empty() const | |
| { | |
| return ( size_ == 0u ); | |
| } | |
| // Active Array Size Bounded? | |
| bool | |
| size_bounded() const | |
| { | |
| return true; | |
| } | |
| // Contiguous? | |
| bool | |
| contiguous() const | |
| { | |
| return contiguous_; | |
| } | |
| // Conformable? | |
| template< class A > | |
| bool | |
| conformable( A const & a ) const | |
| { | |
| if ( rank() != a.rank() ) return false; | |
| for ( int i = 1; i <= rank(); ++i ) if ( size( i ) != a.size( i ) ) return false; | |
| return true; | |
| } | |
| // Memory Can Overlap a Range? | |
| bool | |
| overlap( T const * const b, T const * const e ) const | |
| { | |
| if ( ( data_beg_ == nullptr ) || ( data_end_ == nullptr ) || ( b == nullptr ) || ( e == nullptr ) ) { // No active memory range(s) | |
| return false; | |
| } else if ( size_ == 0u ) { // No finite memory range | |
| return false; | |
| } else { // Bounded ranges | |
| assert( data_beg_ <= data_end_ ); | |
| assert( b <= e ); | |
| return ( ( data_beg_ >= b ? data_beg_ : b ) <= ( data_end_ <= e ? data_end_ : e ) ); | |
| } | |
| } | |
| // Memory Can Overlap an Array? | |
| template< template< typename > class A > | |
| bool | |
| overlap( A< T > const & a ) const | |
| { | |
| if ( data_ == nullptr ) { // No active memory range | |
| return false; | |
| } else { // Bounded ranges | |
| return overlap( a.data_beg(), a.data_end() ); | |
| } | |
| } | |
| public: // Inspector | |
| // Rank | |
| virtual | |
| int | |
| rank() const = 0; | |
| // Active Array Size | |
| size_type | |
| size() const | |
| { | |
| return size_; | |
| } | |
| // Active Array Size | |
| int | |
| isize() const | |
| { | |
| return static_cast< int >( size_ ); | |
| } | |
| // Lower Index of a Dimension | |
| int | |
| l( int const d ) const | |
| { | |
| assert( ( 1 <= d ) && ( d <= rank() ) ); | |
| #ifdef NDEBUG | |
| static_cast< void >( d ); // Suppress unused warning | |
| #endif | |
| return 1; | |
| } | |
| // Upper Index of a Dimension | |
| virtual | |
| int | |
| u( int const d ) const = 0; | |
| // Size of a Dimension | |
| virtual | |
| size_type | |
| size( int const d ) const = 0; | |
| // Size of a Dimension | |
| virtual | |
| int | |
| isize( int const d ) const = 0; | |
| // Array Data Pointer | |
| T const * | |
| data() const | |
| { | |
| return data_; | |
| } | |
| // Array Data Pointer | |
| T * | |
| data() | |
| { | |
| return data_; | |
| } | |
| // Array Data Begin Pointer | |
| T const * | |
| data_beg() const | |
| { | |
| return data_beg_; | |
| } | |
| // Array Data Begin Pointer | |
| T * | |
| data_beg() | |
| { | |
| return data_beg_; | |
| } | |
| // Array Data End Pointer | |
| T const * | |
| data_end() const | |
| { | |
| return data_end_; | |
| } | |
| // Array Data End Pointer | |
| T * | |
| data_end() | |
| { | |
| return data_end_; | |
| } | |
| protected: // Static Methods | |
| // Is Last Index in [1,u] Range? | |
| static | |
| bool | |
| in_range( int const u, int const i ) | |
| { | |
| assert( u > 0 ); | |
| return ( ( 1 <= i ) && ( i <= u ) ); | |
| } | |
| // Are Last Two Indexes in [1,u] Range? | |
| static | |
| bool | |
| in_range( int const u, int const i, int const j ) | |
| { | |
| assert( u > 0 ); | |
| return ( ( 1 <= i ) && ( i <= u ) && ( 1 <= j ) && ( j <= u ) ); | |
| } | |
| // Slice Constant for a Scalar Index | |
| static | |
| std::int64_t | |
| slice_k( IR const & range, int const i, std::int64_t const multiplier = 1 ) | |
| { | |
| assert( range.contains( i ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( i ) ); | |
| (void)range; // Suppress unused warning in release builds | |
| return i * multiplier; | |
| } | |
| // Slice Constant for a Scalar Index | |
| static | |
| std::int64_t | |
| slice_k( int const u, int const i, std::int64_t const multiplier = 1 ) | |
| { | |
| assert( ( 1 <= i ) && ( i <= u ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( i ) ); | |
| (void)u; // Suppress unused warning in release builds | |
| return i * multiplier; | |
| } | |
| protected: // Data | |
| T * data_; // Pointer to data array | |
| T * data_beg_; // Pointer to data begin | |
| T * data_end_; // Pointer to data end | |
| size_type const size_; // Size of visible array | |
| bool contiguous_; // Contiguous? | |
| }; // ArrayS | |
| // Conformable? | |
| template< typename T, class A > | |
| inline | |
| bool | |
| conformable( ArrayS< T > const & s, A const & a ) | |
| { | |
| return s.conformable( a ); | |
| } | |
| // Conformable? | |
| template< class A, typename T > | |
| inline | |
| bool | |
| conformable( A const & a, ArrayS< T > const & s ) | |
| { | |
| return s.conformable( a ); | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_ArrayS_hh_INCLUDED | |
| // ===== ObjexxFCL/CArrayA.fwd.hh ===== | |
| #ifndef ObjexxFCL_CArrayA_fwd_hh_INCLUDED | |
| #define ObjexxFCL_CArrayA_fwd_hh_INCLUDED | |
| // CArrayA Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class CArrayA; | |
| // Types | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_CArrayA_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/CArrayA.hh ===== | |
| #ifndef ObjexxFCL_CArrayA_hh_INCLUDED | |
| #define ObjexxFCL_CArrayA_hh_INCLUDED | |
| // CArrayA: Memory-Managed C Array Wrapper with Alignment Support | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <istream> | |
| #include <iterator> | |
| #include <new> | |
| #include <ostream> | |
| #include <type_traits> | |
| #include <utility> | |
| namespace ObjexxFCL { | |
| // CArrayA: Memory-Managed C Array Wrapper with Alignment Support | |
| template< typename T > | |
| class CArrayA | |
| { | |
| private: // Friend | |
| template< typename > friend class CArrayA; // Friendship across value types | |
| public: // Types | |
| typedef AlignedAllocator< T > Aligned; | |
| typedef TypeTraits< T > Traits; | |
| typedef typename std::conditional< std::is_scalar< T >::value, T const, T const & >::type Tc; | |
| typedef typename std::conditional< std::is_scalar< T >::value, typename std::remove_const< T >::type, T const & >::type Tr; | |
| // STL Style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| typedef T * iterator; | |
| typedef T const * const_iterator; | |
| typedef std::reverse_iterator< T * > reverse_iterator; | |
| typedef std::reverse_iterator< T const * > const_reverse_iterator; | |
| typedef std::size_t size_type; | |
| typedef std::ptrdiff_t difference_type; | |
| // C++ Style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| typedef T * Iterator; | |
| typedef T const * ConstIterator; | |
| typedef std::reverse_iterator< T * > ReverseIterator; | |
| typedef std::reverse_iterator< T const * > ConstReverseIterator; | |
| typedef std::size_t Size; | |
| typedef std::ptrdiff_t Difference; | |
| // Types to prevent compile failure when std::distance is in scope | |
| typedef void iterator_category; | |
| public: // Creation | |
| // Default Constructor | |
| CArrayA() : | |
| size_( 0u ), | |
| mem_( nullptr ), | |
| data_( nullptr ) | |
| {} | |
| // Copy Constructor | |
| CArrayA( CArrayA const & a ) : | |
| size_( a.size_ ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a.data_[ i ] ); | |
| } | |
| } | |
| // Move Constructor | |
| CArrayA( CArrayA && a ) noexcept : | |
| size_( a.size_ ), | |
| mem_( a.mem_ ), | |
| data_( a.data_ ) | |
| { | |
| a.size_ = 0u; | |
| a.mem_ = a.data_ = nullptr; | |
| } | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| CArrayA( CArrayA< U > const & a ) : | |
| size_( a.size_ ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a.data_[ i ] ); | |
| } | |
| } | |
| // Pointer + Size Constructor | |
| CArrayA( | |
| T const * const p, | |
| size_type const size | |
| ) : | |
| size_( size ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( p[ i ] ); | |
| } | |
| } | |
| // Pointer + Size Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| CArrayA( | |
| U const * const p, | |
| size_type const size | |
| ) : | |
| size_( size ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( p[ i ] ); | |
| } | |
| } | |
| // Iterator Range Constructor Template | |
| template< typename InputIterator > | |
| CArrayA( | |
| InputIterator const beg, | |
| InputIterator const end | |
| ) : | |
| size_( end - beg ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| if ( size_ > 0u ) { | |
| InputIterator k( beg ); | |
| for ( size_type i = 0; i < size_; ++i, ++k ) { | |
| new ( data_ + i ) T( *k ); | |
| } | |
| } | |
| } | |
| // Size Constructor: Built-in types are default, not zero, initialized for performance | |
| explicit | |
| CArrayA( size_type const size ) : | |
| size_( size ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T; | |
| } | |
| } | |
| // Size + Uniform Value Constructor | |
| CArrayA( | |
| size_type const size, | |
| Tc t | |
| ) : | |
| size_( size ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( t ); | |
| } | |
| } | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| CArrayA( std::initializer_list< U > const l ) : | |
| size_( l.size() ), | |
| mem_( Aligned::allocate( size_ ) ), | |
| data_( Aligned::data( mem_ ) ) | |
| { | |
| auto li( l.begin() ); | |
| for ( size_type i = 0; i < size_; ++i, ++li ) { | |
| new ( data_ + i ) T( *li ); | |
| } | |
| } | |
| // Destructor | |
| ~CArrayA() | |
| { | |
| destroy(); | |
| } | |
| public: // Conversion | |
| // Active? | |
| operator bool() const | |
| { | |
| return ( data_ != nullptr ); | |
| } | |
| // Data | |
| operator T const *() const | |
| { | |
| return data_; | |
| } | |
| // Data | |
| operator T *() | |
| { | |
| return data_; | |
| } | |
| public: // Assignment | |
| // Copy Assignment | |
| CArrayA & | |
| operator =( CArrayA const & a ) | |
| { | |
| if ( this != &a ) { | |
| if ( size_ != a.size_ ) { | |
| destroy(); | |
| size_ = a.size_; | |
| mem_ = Aligned::allocate( size_ ); | |
| data_ = Aligned::data( mem_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a.data_[ i ] ); | |
| } | |
| } else { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = a.data_[ i ]; | |
| } | |
| } | |
| } | |
| return *this; | |
| } | |
| // Move Assignment | |
| CArrayA & | |
| operator =( CArrayA && a ) noexcept | |
| { | |
| assert( this != &a ); | |
| destroy(); | |
| size_ = a.size_; | |
| mem_ = a.mem_; | |
| data_ = a.data_; | |
| a.size_ = 0u; | |
| a.mem_ = a.data_ = nullptr; | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArrayA & | |
| operator =( CArrayA< U > const & a ) | |
| { | |
| if ( size_ != a.size_ ) { | |
| destroy(); | |
| size_ = a.size_; | |
| mem_ = Aligned::allocate( size_ ); | |
| data_ = Aligned::data( mem_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a.data_[ i ] ); | |
| } | |
| } else { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( a.data_[ i ] ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Uniform Value Assignment | |
| CArrayA & | |
| operator =( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = t; | |
| } | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArrayA & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == size_ ); | |
| std::copy( l.begin(), l.end(), data_ ); | |
| return *this; | |
| } | |
| // Pointer + Size Assignment | |
| CArrayA & | |
| assign( | |
| T const * const p, | |
| size_type const size | |
| ) | |
| { | |
| if ( size_ != size ) { | |
| destroy(); | |
| size_ = size; | |
| mem_ = Aligned::allocate( size_ ); | |
| data_ = Aligned::data( mem_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( p[ i ] ); | |
| } | |
| } else { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = p[ i ]; | |
| } | |
| } | |
| return *this; | |
| } | |
| // Pointer + Size Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArrayA & | |
| assign( | |
| U const * const p, | |
| size_type const size | |
| ) | |
| { | |
| if ( size_ != size ) { | |
| destroy(); | |
| size_ = size; | |
| mem_ = Aligned::allocate( size_ ); | |
| data_ = Aligned::data( mem_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( p[ i ] ); | |
| } | |
| } else { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( p[ i ] ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Iterator Range Assignment Template | |
| template< typename InputIterator > | |
| CArrayA & | |
| assign( | |
| InputIterator const beg, | |
| InputIterator const end | |
| ) | |
| { | |
| size_type const size( end - beg ); | |
| if ( size_ != size ) { | |
| destroy(); | |
| size_ = size; | |
| mem_ = Aligned::allocate( size_ ); | |
| data_ = Aligned::data( mem_ ); | |
| if ( size_ > 0u ) { | |
| InputIterator k( beg ); | |
| for ( size_type i = 0; i < size_; ++i, ++k ) { | |
| new ( data_ + i ) T( *k ); | |
| } | |
| } | |
| } else { | |
| if ( size_ > 0u ) { | |
| InputIterator k( beg ); | |
| for ( size_type i = 0; i < size_; ++i, ++k ) { | |
| data_[ i ] = T( *k ); | |
| } | |
| } | |
| } | |
| return *this; | |
| } | |
| // Size + Value Assignment | |
| CArrayA & | |
| assign( | |
| size_type const size, | |
| Tc t | |
| ) | |
| { | |
| if ( size_ != size ) { // Set to new array with uniform values | |
| CArrayA( size, t ).swap( *this ); | |
| } else { // Set to uniform value | |
| (*this) = t; | |
| } | |
| return *this; | |
| } | |
| // += CArrayA | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArrayA & | |
| operator +=( CArrayA< U > const & a ) | |
| { | |
| assert( size_ == a.size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += T( a.data_[ i ] ); | |
| } | |
| return *this; | |
| } | |
| // -= CArrayA | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArrayA & | |
| operator -=( CArrayA< U > const & a ) | |
| { | |
| assert( size_ == a.size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= T( a.data_[ i ] ); | |
| } | |
| return *this; | |
| } | |
| // += Value | |
| CArrayA & | |
| operator +=( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += t; | |
| } | |
| return *this; | |
| } | |
| // -= Value | |
| CArrayA & | |
| operator -=( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= t; | |
| } | |
| return *this; | |
| } | |
| // *= Value | |
| CArrayA & | |
| operator *=( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= t; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| CArrayA & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= inv_u; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| CArrayA & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] /= u; | |
| } | |
| return *this; | |
| } | |
| public: // Predicate | |
| // Active? | |
| bool | |
| active() const | |
| { | |
| return ( data_ != nullptr ); | |
| } | |
| // Empty? | |
| bool | |
| empty() const | |
| { | |
| return ( size_ == 0u ); | |
| } | |
| public: // Inspector | |
| // Size | |
| size_type | |
| size() const | |
| { | |
| return size_; | |
| } | |
| // Lower Index | |
| size_type | |
| l() const | |
| { | |
| return 0u; | |
| } | |
| // Upper index | |
| size_type | |
| u() const | |
| { | |
| return size_ - 1u; // npos if size_ == 0 | |
| } | |
| // First Element | |
| Tr | |
| front() const | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ 0 ]; | |
| } | |
| // Last Element | |
| Tr | |
| back() const | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ size_ - 1 ]; | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| T length_sq( T( 0 ) ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| length_sq += data_[ i ] * data_[ i ]; | |
| } | |
| return std::sqrt( length_sq ); | |
| } | |
| // Length Squared | |
| T | |
| length_squared() const | |
| { | |
| T length_sq( T( 0 ) ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| length_sq += data_[ i ] * data_[ i ]; | |
| } | |
| return length_sq; | |
| } | |
| public: // Modifier | |
| // First Element | |
| T & | |
| front() | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ 0 ]; | |
| } | |
| // Last Element | |
| T & | |
| back() | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ size_ - 1 ]; | |
| } | |
| // Resize: Values not Preserved | |
| // Built-in values are uninitialized if size changes | |
| CArrayA & | |
| size( size_type const size ) | |
| { | |
| if ( size_ != size ) { // Set to new array | |
| CArrayA( size ).swap( *this ); | |
| } | |
| return *this; | |
| } | |
| // Resize to Size With Fill Value: Values Preserved | |
| CArrayA & | |
| resize( | |
| size_type const size, | |
| Tc fill = T() | |
| ) | |
| { | |
| if ( size_ < size ) { | |
| CArrayA a( size, fill ); // New array: Elements set to fill fill | |
| for ( size_type i = 0; i < size_; ++i ) { // Copy current values | |
| a.data_[ i ] = data_[ i ]; | |
| } | |
| swap( a ); // Swap in new array | |
| } else if ( size_ > size ) { | |
| CArrayA a( size ); // New array | |
| for ( size_type i = 0; i < size; ++i ) { // Copy current values within new range | |
| a.data_[ i ] = data_[ i ]; | |
| } | |
| swap( a ); // Swap in new array | |
| } | |
| return *this; | |
| } | |
| // Swap | |
| void | |
| swap( CArrayA & a ) | |
| { | |
| std::swap( size_, a.size_ ); | |
| std::swap( mem_, a.mem_ ); | |
| std::swap( data_, a.data_ ); | |
| } | |
| // Clear | |
| CArrayA & | |
| clear() | |
| { | |
| destroy(); | |
| size_ = 0u; | |
| mem_ = data_ = nullptr; | |
| return *this; | |
| } | |
| // Normalize to Unit Length | |
| CArrayA & | |
| normalize() | |
| { | |
| T const length_( length() ); | |
| assert( length_ > T( 0 ) ); | |
| operator /=( length_ ); | |
| return *this; | |
| } | |
| public: // Subscript | |
| // CArrayA[ i ] const: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value && std::is_const< T >::value >::type > | |
| Tr | |
| operator []( I const i ) const | |
| { | |
| assert( i < size_ ); | |
| return data_[ i ]; | |
| } | |
| // CArrayA[ i ] const: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value && std::is_const< T >::value >::type, typename = void > | |
| Tr | |
| operator []( I const i ) const | |
| { | |
| assert( ( i >= 0 ) && ( static_cast< size_type >( i ) < size_ ) ); | |
| return data_[ i ]; | |
| } | |
| // CArrayA[ i ]: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value >::type > | |
| T & | |
| operator []( I const i ) | |
| { | |
| assert( i < size_ ); | |
| return data_[ i ]; | |
| } | |
| // CArrayA[ i ]: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value >::type, typename = void > | |
| T & | |
| operator []( I const i ) | |
| { | |
| assert( ( i >= 0 ) && ( static_cast< size_type >( i ) < size_ ) ); | |
| return data_[ i ]; | |
| } | |
| // CArrayA( i ) const: 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value && std::is_const< T >::value >::type > | |
| Tr | |
| operator ()( I const i ) const | |
| { | |
| assert( ( i > 0u ) && ( i <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| // CArrayA( i ) const: 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value && std::is_const< T >::value >::type, typename = void > | |
| Tr | |
| operator ()( I const i ) const | |
| { | |
| assert( ( i > 0 ) && ( static_cast< size_type >( i ) <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| // CArrayA( i ): 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value >::type > | |
| T & | |
| operator ()( I const i ) | |
| { | |
| assert( ( i > 0u ) && ( i <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| // CArrayA( i ): 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value >::type, typename = void > | |
| T & | |
| operator ()( I const i ) | |
| { | |
| assert( ( i > 0 ) && ( static_cast< size_type >( i ) <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| public: // Iterator | |
| // Begin Iterator | |
| const_iterator | |
| begin() const | |
| { | |
| return data_; | |
| } | |
| // Begin Iterator | |
| iterator | |
| begin() | |
| { | |
| return data_; | |
| } | |
| // End Iterator | |
| const_iterator | |
| end() const | |
| { | |
| return ( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // End Iterator | |
| iterator | |
| end() | |
| { | |
| return ( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse Begin Iterator | |
| const_reverse_iterator | |
| rbegin() const | |
| { | |
| return const_reverse_iterator( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse Begin Iterator | |
| reverse_iterator | |
| rbegin() | |
| { | |
| return reverse_iterator( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse End Iterator | |
| const_reverse_iterator | |
| rend() const | |
| { | |
| return const_reverse_iterator( data_ ); | |
| } | |
| // Reverse End Iterator | |
| reverse_iterator | |
| rend() | |
| { | |
| return reverse_iterator( data_ ); | |
| } | |
| public: // Array Accessor | |
| // C Array const Accessor | |
| T const * | |
| operator ()() const | |
| { | |
| return data_; | |
| } | |
| // C Array Non-const Accessor | |
| T * | |
| operator ()() | |
| { | |
| return data_; | |
| } | |
| private: // Methods | |
| // Destruct Elements and Delete Array Memory (Doesn't Nullify Pointers) | |
| void | |
| destroy() | |
| { | |
| size_type i( size_ ); | |
| while ( i ) data_[ --i ].~T(); | |
| ::operator delete( mem_ ); | |
| } | |
| private: // Data | |
| size_type size_; // Number of array elements | |
| void * mem_; // Pointer to raw memory | |
| T * data_; // Pointer to data | |
| }; // CArrayA | |
| // Functions | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( CArrayA< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| mag_sq += a[ i ] * a[ i ]; | |
| } | |
| return std::sqrt( mag_sq ); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( CArrayA< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| mag_sq += a[ i ] * a[ i ]; | |
| } | |
| return mag_sq; | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| T const distance_i( a[ i ] - b[ i ] ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| T const distance_i( a[ i ] - b[ i ] ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T sum( T( 0 ) ); | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| sum += a[ i ] * b[ i ]; | |
| } | |
| return sum; | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot_product( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T sum( T( 0 ) ); | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| sum += a[ i ] * b[ i ]; | |
| } | |
| return sum; | |
| } | |
| // Swap | |
| template< typename T > | |
| inline | |
| void | |
| swap( CArrayA< T > & a, CArrayA< T > & b ) | |
| { | |
| a.swap( b ); | |
| } | |
| // Comparison | |
| // Are Two CArrayAs Comparable? | |
| template< typename T > | |
| inline | |
| bool | |
| comparable( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| return ( a.size() == b.size() ); | |
| } | |
| // CArrayA == CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return true; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] == b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArrayA != CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| return !( a == b ); | |
| } | |
| // CArrayA < CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return false; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] < b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArrayA <= CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return true; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] <= b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArrayA >= CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return true; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] >= b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArrayA > CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return false; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] > b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArrayA == Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( a[ i ] != t ) return false; | |
| } | |
| return true; | |
| } | |
| // CArrayA != Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| return !( a == t ); | |
| } | |
| // CArrayA < Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] < t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // CArrayA <= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] <= t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // CArrayA >= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] >= t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // CArrayA > Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] > t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value == CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| return ( a == t ); | |
| } | |
| // Value != CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| return !( t == a ); | |
| } | |
| // Value < CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t < a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value <= CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t <= a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value >= CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t >= a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value > CArrayA | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| for ( typename CArrayA< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t > a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Generator | |
| // -CArrayA | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator -( CArrayA< T > const & a ) | |
| { | |
| CArrayA< T > r( a ); | |
| r *= T( -1 ); | |
| return r; | |
| } | |
| // CArrayA + CArrayA | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator +( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| CArrayA< T > r( a ); | |
| r += b; | |
| return r; | |
| } | |
| // CArrayA - CArrayA | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator -( CArrayA< T > const & a, CArrayA< T > const & b ) | |
| { | |
| CArrayA< T > r( a ); | |
| r -= b; | |
| return r; | |
| } | |
| // CArrayA + Value | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator +( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| CArrayA< T > r( a ); | |
| r += t; | |
| return r; | |
| } | |
| // Value + CArrayA | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator +( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| CArrayA< T > r( a ); | |
| r += t; | |
| return r; | |
| } | |
| // CArrayA - Value | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator -( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| CArrayA< T > r( a ); | |
| r -= t; | |
| return r; | |
| } | |
| // Value - CArrayA | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator -( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| CArrayA< T > r( -a ); | |
| r += t; | |
| return r; | |
| } | |
| // CArrayA * Value | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator *( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| CArrayA< T > r( a ); | |
| r *= t; | |
| return r; | |
| } | |
| // Value * CArrayA | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator *( typename CArrayA< T >::Tc t, CArrayA< T > const & a ) | |
| { | |
| CArrayA< T > r( a ); | |
| r *= t; | |
| return r; | |
| } | |
| // CArrayA / Value | |
| template< typename T > | |
| inline | |
| CArrayA< T > | |
| operator /( CArrayA< T > const & a, typename CArrayA< T >::Tc t ) | |
| { | |
| CArrayA< T > r( a ); | |
| r /= t; | |
| return r; | |
| } | |
| // Stream >> CArrayA | |
| template< typename T > | |
| inline | |
| std::istream & | |
| operator >>( std::istream & stream, CArrayA< T > & a ) | |
| { | |
| typedef typename CArrayA< T >::size_type size_type; | |
| if ( stream && ( ! a.emtpy() ) ) { | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| stream >> a[ i ]; | |
| if ( ! stream ) break; | |
| } | |
| } | |
| return stream; | |
| } | |
| // Stream << CArrayA | |
| template< typename T > | |
| inline | |
| std::ostream & | |
| operator <<( std::ostream & stream, CArrayA< T > const & a ) | |
| { | |
| using std::setw; | |
| typedef TypeTraits< T > Traits; | |
| typedef typename CArrayA< T >::size_type size_type; | |
| if ( stream && ( ! a.emtpy() ) ) { | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| size_type const e( a.size() - 1 ); | |
| int const w( Traits::iwidth ); | |
| for ( size_type i = 0; i < e; ++i ) { | |
| stream << setw( w ) << a[ i ] << ' '; | |
| } stream << setw( w ) << a[ e ]; | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| } | |
| return stream; | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_CArrayA_hh_INCLUDED | |
| // ===== ObjexxFCL/InitializerSentinel.hh ===== | |
| #ifndef ObjexxFCL_InitializerSentinel_hh_INCLUDED | |
| #define ObjexxFCL_InitializerSentinel_hh_INCLUDED | |
| // InitializerSentinel: Array Constructor Initializer Sentinel Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| namespace ObjexxFCL { | |
| namespace internal { | |
| // InitializerSentinel: Array Constructor Initializer Sentinel Class | |
| struct InitializerSentinel | |
| { | |
| }; // InitializerSentinel | |
| } // internal | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_InitializerSentinel_hh_INCLUDED | |
| // ===== ObjexxFCL/MArray.hh ===== | |
| #ifndef ObjexxFCL_MArray_hh_INCLUDED | |
| #define ObjexxFCL_MArray_hh_INCLUDED | |
| // MArray: Member Array Proxy Abstract Base Class Template | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cstddef> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <istream> | |
| #include <ostream> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| // MArray: Member Array Proxy Abstract Base Class Template | |
| template< class A, typename T > | |
| class MArray : public BArray | |
| { | |
| public: // Types | |
| typedef A ArrayType; | |
| typedef typename A::value_type Class; | |
| typedef T Class::* MPtr; | |
| typedef TypeTraits< T > Traits; | |
| // STL style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| // C++ style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| protected: // Creation | |
| // Copy Constructor | |
| MArray( MArray const & a ) : | |
| BArray( a ), | |
| array_( a.array_ ), | |
| pmem_( a.pmem_ ) | |
| {} | |
| // Constructor | |
| MArray( A & a, T Class::* pmem ) : | |
| array_( a ), | |
| pmem_( pmem ) | |
| {} | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~MArray() = default; | |
| // Copy Assignment | |
| MArray & | |
| operator =( MArray const & a ) = delete; | |
| public: // Predicate | |
| // Allocated | |
| bool | |
| allocated() const | |
| { | |
| return array_.allocated(); | |
| } | |
| // Active Array Empty? | |
| bool | |
| empty() const | |
| { | |
| return ( array_.size() == 0u ); | |
| } | |
| // Active Array Size Bounded? | |
| bool | |
| size_bounded() const | |
| { | |
| return array_.size_bounded(); | |
| } | |
| // Conformable? | |
| template< class Ar > | |
| bool | |
| conformable( Ar const & a ) const | |
| { | |
| return array_.conformable( a ); | |
| } | |
| public: // Inspector | |
| // Rank | |
| virtual | |
| int | |
| rank() const = 0; | |
| // Size | |
| size_type | |
| size() const | |
| { | |
| return array_.size(); | |
| } | |
| // Size | |
| int | |
| isize() const | |
| { | |
| return array_.isize(); | |
| } | |
| // IndexRange of a Dimension | |
| IR | |
| I( int const d ) const | |
| { | |
| return IR( 1, u( d ) ); | |
| } | |
| // Lower Index of a Dimension | |
| int | |
| l( int const d ) const | |
| { | |
| assert( ( 1 <= d ) && ( d <= rank() ) ); | |
| #ifdef NDEBUG | |
| static_cast< void >( d ); // Suppress unused warning | |
| #endif | |
| return 1; | |
| } | |
| // Upper Index of a Dimension | |
| int | |
| u( int const d ) const | |
| { | |
| return array_.isize( d ); | |
| } | |
| // Size of a Dimension | |
| size_type | |
| size( int const d ) const | |
| { | |
| return array_.size( d ); | |
| } | |
| // Size of a Dimension | |
| int | |
| isize( int const d ) const | |
| { | |
| return array_.isize( d ); | |
| } | |
| // Proxied Array | |
| A const & | |
| array() const | |
| { | |
| return array_; | |
| } | |
| // Proxied Array | |
| A & | |
| array() | |
| { | |
| return array_; | |
| } | |
| protected: // Methods | |
| // Array Index of an Index of Dimension | |
| int | |
| j( int const d, int const i ) const | |
| { | |
| return array_.l( d ) + i - 1; | |
| } | |
| // Array Index of Dimension 1 | |
| int | |
| j1( int const i ) const | |
| { | |
| return array_.l1() + i - 1; | |
| } | |
| protected: // Static Methods | |
| // Is Last Index in [1,u] Range? | |
| static | |
| bool | |
| in_range( int const u, int const i ) | |
| { | |
| assert( u > 0 ); | |
| return ( ( 1 <= i ) && ( i <= u ) ); | |
| } | |
| // Are Last Two Indexes in [1,u] Range? | |
| static | |
| bool | |
| in_range( int const u, int const i, int const j ) | |
| { | |
| assert( u > 0 ); | |
| return ( ( 1 <= i ) && ( i <= u ) && ( 1 <= j ) && ( j <= u ) ); | |
| } | |
| protected: // Data | |
| A & array_; // A | |
| T Class::* pmem_; // Pointer to member | |
| }; // MArray | |
| // Conformable? | |
| template< class A, typename T, class Ar > | |
| inline | |
| bool | |
| conformable( MArray< A, T > const & a, Ar const & b ) | |
| { | |
| return a.conformable( b ); | |
| } | |
| // Conformable? | |
| template< class A, typename T, class Ar > | |
| inline | |
| bool | |
| conformable( Ar const & a, MArray< A, T > const & b ) | |
| { | |
| return b.conformable( a ); | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_MArray_hh_INCLUDED | |
| // ===== ObjexxFCL/ProxySentinel.hh ===== | |
| #ifndef ObjexxFCL_ProxySentinel_hh_INCLUDED | |
| #define ObjexxFCL_ProxySentinel_hh_INCLUDED | |
| // ProxySentinel: Array Constructor Proxy Sentinel Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| namespace ObjexxFCL { | |
| namespace internal { | |
| // ProxySentinel: Array Constructor Proxy Sentinel Class | |
| struct ProxySentinel | |
| { | |
| }; // ProxySentinel | |
| } // internal | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_ProxySentinel_hh_INCLUDED | |
| // ===== ObjexxFCL/Vector2.fwd.hh ===== | |
| #ifndef ObjexxFCL_Vector2_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Vector2_fwd_hh_INCLUDED | |
| // Vector2 Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Vector2; | |
| // Types | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Vector2_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/Fmath.hh ===== | |
| #ifndef ObjexxFCL_Fmath_hh_INCLUDED | |
| #define ObjexxFCL_Fmath_hh_INCLUDED | |
| // Fortran Intrinsic-Compatible and General Math Functions | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cfloat> | |
| #include <cmath> | |
| #include <complex> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <cstdlib> | |
| #include <limits> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| typedef std::intmax_t SSize; | |
| // min ///// | |
| // min( short, short ) | |
| inline | |
| short int | |
| min( short int const a, short int const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( int, int ) | |
| inline | |
| int | |
| min( int const a, int const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( long, long ) | |
| inline | |
| long int | |
| min( long int const a, long int const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( unsigned short, unsigned short ) | |
| inline | |
| unsigned short int | |
| min( unsigned short int const a, unsigned short int const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( unsigned, unsigned ) | |
| inline | |
| unsigned int | |
| min( unsigned int const a, unsigned int const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( unsigned long, unsigned long ) | |
| inline | |
| unsigned long int | |
| min( unsigned long int const a, unsigned long int const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( float, float ) | |
| inline | |
| float | |
| min( float const a, float const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( double, double ) | |
| inline | |
| double | |
| min( double const a, double const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // min( long double, long double ) | |
| inline | |
| long double | |
| min( long double const a, long double const b ) | |
| { | |
| return ( a < b ? a : b ); | |
| } | |
| // Use std::min for 2 arguments not covered by the above overloads | |
| using std::min; | |
| // min( short, short, short ) | |
| inline | |
| short int | |
| min( short int const a, short int const b, short int const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( short, short, short, short, ... ) | |
| template< typename... Ts > | |
| inline | |
| short int | |
| min( short int const a, short int const b, short int const c, short int const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( int, int, int ) | |
| inline | |
| int | |
| min( int const a, int const b, int const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( int, int, int, int, ... ) | |
| template< typename... Ts > | |
| inline | |
| int | |
| min( int const a, int const b, int const c, int const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( long, long, long ) | |
| inline | |
| long int | |
| min( long int const a, long int const b, long int const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( long, long, long, long, ... ) | |
| template< typename... Ts > | |
| inline | |
| long int | |
| min( long int const a, long int const b, long int const c, long int const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( unsigned short, unsigned short, unsigned short ) | |
| inline | |
| unsigned short int | |
| min( unsigned short int const a, unsigned short int const b, unsigned short int const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( unsigned short, unsigned short, unsigned short, unsigned short, ... ) | |
| template< typename... Ts > | |
| inline | |
| unsigned short int | |
| min( unsigned short int const a, unsigned short int const b, unsigned short int const c, unsigned short int const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( unsigned, unsigned, unsigned ) | |
| inline | |
| unsigned int | |
| min( unsigned int const a, unsigned int const b, unsigned int const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( unsigned, unsigned, unsigned, unsigned, ... ) | |
| template< typename... Ts > | |
| inline | |
| unsigned int | |
| min( unsigned int const a, unsigned int const b, unsigned int const c, unsigned int const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( unsigned long, unsigned long, unsigned long ) | |
| inline | |
| unsigned long int | |
| min( unsigned long int const a, unsigned long int const b, unsigned long int const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( unsigned long, unsigned long, unsigned long, unsigned long, ... ) | |
| template< typename... Ts > | |
| inline | |
| unsigned long int | |
| min( unsigned long int const a, unsigned long int const b, unsigned long int const c, unsigned long int const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( float, float, float ) | |
| inline | |
| float | |
| min( float const a, float const b, float const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( float, float, float, float, ... ) | |
| template< typename... Ts > | |
| inline | |
| float | |
| min( float const a, float const b, float const c, float const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( double, double, double ) | |
| inline | |
| double | |
| min( double const a, double const b, double const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( double, double, double, double, ... ) | |
| template< typename... Ts > | |
| inline | |
| double | |
| min( double const a, double const b, double const c, double const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( long double, long double, long double ) | |
| inline | |
| long double | |
| min( long double const a, long double const b, long double const c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( long double, long double, long double, long double, ... ) | |
| template< typename... Ts > | |
| inline | |
| long double | |
| min( long double const a, long double const b, long double const c, long double const d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // min( a, b, c ) | |
| template< typename T > | |
| inline | |
| T const & | |
| min( T const & a, T const & b, T const & c ) | |
| { | |
| return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) ); | |
| } | |
| // min( a, b, c, d, ... ) | |
| template< typename T, typename... Ts > | |
| inline | |
| T const & | |
| min( T const & a, T const & b, T const & c, T const & d, Ts const &... o ) | |
| { | |
| return min( a < b ? a : b, c < d ? c : d, o... ); | |
| } | |
| // max ///// | |
| // max( short, short ) | |
| inline | |
| short int | |
| max( short int const a, short int const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( int, int ) | |
| inline | |
| int | |
| max( int const a, int const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( long, long ) | |
| inline | |
| long int | |
| max( long int const a, long int const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( unsigned short, unsigned short ) | |
| inline | |
| unsigned short int | |
| max( unsigned short int const a, unsigned short int const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( unsigned, unsigned ) | |
| inline | |
| unsigned int | |
| max( unsigned int const a, unsigned int const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( unsigned long, unsigned long ) | |
| inline | |
| unsigned long int | |
| max( unsigned long int const a, unsigned long int const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( float, float ) | |
| inline | |
| float | |
| max( float const a, float const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( double, double ) | |
| inline | |
| double | |
| max( double const a, double const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // max( long double, long double ) | |
| inline | |
| long double | |
| max( long double const a, long double const b ) | |
| { | |
| return ( a < b ? b : a ); | |
| } | |
| // Use std::max for 2 arguments not covered by the above overloads | |
| using std::max; | |
| // max( short, short, short ) | |
| inline | |
| short int | |
| max( short int const a, short int const b, short int const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( short, short, short, short, ... ) | |
| template< typename... Ts > | |
| inline | |
| short int | |
| max( short int const a, short int const b, short int const c, short int const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( int, int, int ) | |
| inline | |
| int | |
| max( int const a, int const b, int const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( int, int, int, int, ... ) | |
| template< typename... Ts > | |
| inline | |
| int | |
| max( int const a, int const b, int const c, int const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( long, long, long ) | |
| inline | |
| long int | |
| max( long int const a, long int const b, long int const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( long, long, long, long, ... ) | |
| template< typename... Ts > | |
| inline | |
| long int | |
| max( long int const a, long int const b, long int const c, long int const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( unsigned short, unsigned short, unsigned short ) | |
| inline | |
| unsigned short int | |
| max( unsigned short int const a, unsigned short int const b, unsigned short int const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( unsigned short, unsigned short, unsigned short, unsigned short, ... ) | |
| template< typename... Ts > | |
| inline | |
| unsigned short int | |
| max( unsigned short int const a, unsigned short int const b, unsigned short int const c, unsigned short int const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( unsigned, unsigned, unsigned ) | |
| inline | |
| unsigned int | |
| max( unsigned int const a, unsigned int const b, unsigned int const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( unsigned, unsigned, unsigned, unsigned, ... ) | |
| template< typename... Ts > | |
| inline | |
| unsigned int | |
| max( unsigned int const a, unsigned int const b, unsigned int const c, unsigned int const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( unsigned long, unsigned long, unsigned long ) | |
| inline | |
| unsigned long int | |
| max( unsigned long int const a, unsigned long int const b, unsigned long int const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( unsigned long, unsigned long, unsigned long, unsigned long, ... ) | |
| template< typename... Ts > | |
| inline | |
| unsigned long int | |
| max( unsigned long int const a, unsigned long int const b, unsigned long int const c, unsigned long int const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( float, float, float ) | |
| inline | |
| float | |
| max( float const a, float const b, float const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( float, float, float, float, ... ) | |
| template< typename... Ts > | |
| inline | |
| float | |
| max( float const a, float const b, float const c, float const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( double, double, double ) | |
| inline | |
| double | |
| max( double const a, double const b, double const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( double, double, double, double, ... ) | |
| template< typename... Ts > | |
| inline | |
| double | |
| max( double const a, double const b, double const c, double const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( long double, long double, long double ) | |
| inline | |
| long double | |
| max( long double const a, long double const b, long double const c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( long double, long double, long double, long double, ... ) | |
| template< typename... Ts > | |
| inline | |
| long double | |
| max( long double const a, long double const b, long double const c, long double const d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // max( a, b, c ) | |
| template< typename T > | |
| inline | |
| T const & | |
| max( T const & a, T const & b, T const & c ) | |
| { | |
| return ( a < b ? ( b < c ? c : b ) : ( a < c ? c : a ) ); | |
| } | |
| // max( a, b, c, d, ... ) | |
| template< typename T, typename... Ts > | |
| inline | |
| T const & | |
| max( T const & a, T const & b, T const & c, T const & d, Ts const &... o ) | |
| { | |
| return max( a < b ? b : a, c < d ? d : c, o... ); | |
| } | |
| // General ///// | |
| // abs( x ) == | x | | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| abs( T const & x ) | |
| { | |
| return ( x < T( 0 ) ? -x : x ); | |
| } | |
| // FLOOR( x ) | |
| template< typename T > | |
| inline | |
| int | |
| FLOOR( T const & x ) | |
| { | |
| return int( std::floor( x ) ); | |
| } | |
| // CEILING( x ) | |
| template< typename T > | |
| inline | |
| int | |
| CEILING( T const & x ) | |
| { | |
| return int( std::ceil( x ) ); | |
| } | |
| // signum( x ) | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| int | |
| signum( T const & x ) | |
| { | |
| return ( x > T( 0 ) ? +1 : ( x < T( 0 ) ? -1 : 0 ) ); | |
| } | |
| // sign( x ) | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| int | |
| sign( T const & x ) | |
| { | |
| return ( x >= T( 0 ) ? +1 : -1 ); | |
| } | |
| // Sign Transfer from Second Argument to First Argument | |
| template< typename X, typename Y, class = typename std::enable_if< std::is_arithmetic< X >::value && std::is_arithmetic< Y >::value, X >::type > | |
| inline | |
| X | |
| sign( X const & x, Y const & y ) | |
| { | |
| return ( y >= Y( 0 ) ? abs( x ) : -abs( x ) ); | |
| } | |
| // nint( x ): Nearest int | |
| template< typename T > | |
| inline | |
| int | |
| nint( T const & x ) | |
| { | |
| return static_cast< int >( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| // nsint( x ): Nearest short int | |
| template< typename T > | |
| inline | |
| short int | |
| nsint( T const & x ) | |
| { | |
| return static_cast< short int >( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| // nlint( x ): Nearest long int | |
| template< typename T > | |
| inline | |
| long int | |
| nlint( T const & x ) | |
| { | |
| return static_cast< long int >( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| // nlint( x ): Nearest long int | |
| template< typename T > | |
| inline | |
| int64_t | |
| nint64( T const & x ) | |
| { | |
| return static_cast< int64_t >( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| // Nearest function selector class for R non-integer or T integer | |
| template< typename R, typename T, bool > | |
| struct NearestSelector | |
| { | |
| static | |
| R | |
| nearest( T const & x ) | |
| { | |
| return R( x ); | |
| } | |
| }; | |
| // Nearest function selector class for R integer and T non-integer | |
| template< typename R, typename T > | |
| struct NearestSelector< R, T, true > | |
| { | |
| static | |
| R | |
| nearest( T const & x ) | |
| { | |
| return R( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| }; | |
| // nearest< R >( x ): Nearest R | |
| template< typename R, typename T > | |
| inline | |
| R | |
| nearest( T const & x ) | |
| { | |
| return NearestSelector< R, T, ( ( std::numeric_limits< R >::is_integer ) && ( ! std::numeric_limits< T >::is_integer ) ) >::nearest( x ); | |
| } | |
| // nearest_size( x ): Nearest std::size_t | |
| template< typename T > | |
| inline | |
| std::size_t | |
| nearest_size( T const & x ) | |
| { | |
| return std::size_t( x > T( 0 ) ? x + ( sign( x ) * T( 0.5 ) ) : 0 ); | |
| } | |
| // nearest_ssize( x ): Nearest SSize | |
| template< typename T > | |
| inline | |
| SSize | |
| nearest_ssize( T const & x ) | |
| { | |
| return SSize( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| // nearest_int( x ): Nearest int | |
| template< typename T > | |
| inline | |
| int | |
| nearest_int( T const & x ) | |
| { | |
| return static_cast< int >( x + ( sign( x ) * T( 0.5 ) ) ); | |
| } | |
| // Mod function selector class for non-integer types | |
| template< typename T, bool > | |
| struct ModSelector | |
| { | |
| static | |
| T | |
| mod( T const & x, T const & y ) | |
| { | |
| return ( y != T( 0 ) ? x - ( T( static_cast< SSize >( x / y ) ) * y ) : T( 0 ) ); | |
| } | |
| }; | |
| // Mod function selector class for integer types | |
| // When used with negative integer arguments this assumes integer division | |
| // rounds towards zero (de facto and future C++ standard) | |
| template< typename T > | |
| struct ModSelector< T, true > | |
| { | |
| static | |
| T | |
| mod( T const & x, T const & y ) | |
| { | |
| return ( y != T( 0 ) ? x - ( ( x / y ) * y ) : T( 0 ) ); | |
| } | |
| }; | |
| // x(mod y) computational modulo returning magnitude < | y | and sign of x | |
| // When used with negative integer arguments this assumes integer division | |
| // rounds towards zero (de facto and future C++ standard) | |
| template< typename T > | |
| inline | |
| T | |
| mod( T const & x, T const & y ) | |
| { | |
| return ModSelector< T, std::numeric_limits< T >::is_integer >::mod( x, y ); | |
| } | |
| // i(mod n) : float Arguments | |
| inline | |
| float | |
| mod( float const i, float const n ) | |
| { | |
| return ( n != 0.0f ? std::fmod( i, n ) : 0.0f ); | |
| } | |
| // i(mod n) : double Arguments | |
| inline | |
| double | |
| mod( double const i, double const n ) | |
| { | |
| return ( n != 0.0 ? std::fmod( i, n ) : 0.0 ); | |
| } | |
| // i(mod n) : long double Arguments | |
| inline | |
| long double | |
| mod( long double const & i, long double const & n ) | |
| { | |
| return ( n != 0.0l ? std::fmod( i, n ) : 0.0l ); | |
| } | |
| // Modulo function selector class for non-integer types | |
| template< typename T, bool > | |
| struct ModuloSelector | |
| { | |
| static | |
| T | |
| modulo( T const & x, T const & y ) | |
| { | |
| return ( y != T( 0 ) ? x - ( std::floor( x / y ) * y ) : x ); // Intel Fortran behavior if y==0 | |
| } | |
| }; | |
| // Modulo function selector class for integer types | |
| template< typename T > | |
| struct ModuloSelector< T, true > | |
| { | |
| static | |
| T | |
| modulo( T const & x, T const & y ) | |
| { | |
| return ( y != T( 0 ) ? x - ( T( std::floor( static_cast< long double >( x ) / y ) ) * y ) : x ); // Intel Fortran behavior if y==0 | |
| } | |
| }; | |
| // x(mod y) mathematical modulo returning magnitude < | y | and sign of y | |
| template< typename T > | |
| inline | |
| T | |
| modulo( T const & x, T const & y ) | |
| { | |
| return ModuloSelector< T, std::numeric_limits< T >::is_integer >::modulo( x, y ); | |
| } | |
| // Positive Difference | |
| template< typename T > | |
| inline | |
| T | |
| dim( T const & x, T const & y ) | |
| { | |
| return max( x - y, T( 0 ) ); | |
| } | |
| // Greatest Common Divisor | |
| template< typename T > | |
| inline | |
| T | |
| gcd( T const & m, T const & n ) | |
| { | |
| T lo( min( m, n ) ); | |
| T hi( max( m, n ) ); | |
| while ( lo > T( 0 ) ) { | |
| T const rem( mod( hi, lo ) ); | |
| hi = lo; | |
| lo = rem; | |
| } | |
| return hi; | |
| } | |
| // Complex ///// | |
| // Real Part | |
| template< typename T > | |
| inline | |
| T | |
| REAL( std::complex< T > const & c ) | |
| { | |
| return c.real(); | |
| } | |
| // Real Conversion | |
| template< typename T > | |
| inline | |
| T | |
| REAL( T const & x ) | |
| { | |
| return float( x ); | |
| } | |
| // Complex Maker | |
| template< typename R, typename I, class = typename std::enable_if< std::is_integral< R >::value && std::is_integral< I >::value >::type > | |
| inline | |
| std::complex< float > | |
| make_complex( R const & r, I const & i ) | |
| { | |
| return std::complex< float >( r, i ); | |
| } | |
| // Complex Maker | |
| template< typename R, typename I, class = typename std::enable_if< std::is_integral< R >::value && ( ! std::is_integral< I >::value ) >::type > | |
| inline | |
| std::complex< I > | |
| make_complex( R const & r, I const & i ) | |
| { | |
| return std::complex< I >( r, i ); | |
| } | |
| // Complex Maker | |
| template< typename R, typename I, class = typename std::enable_if< ( ! std::is_integral< R >::value ) && std::is_integral< I >::value >::type > | |
| inline | |
| std::complex< R > | |
| make_complex( R const & r, I const & i ) | |
| { | |
| return std::complex< R >( r, i ); | |
| } | |
| // Complex Maker | |
| template< typename R, typename I, class = typename std::enable_if< ( ! std::is_integral< R >::value ) && ( ! std::is_integral< I >::value ) && std::is_same< R, I >::value >::type, typename = void > | |
| inline | |
| std::complex< R > | |
| make_complex( R const & r, I const & i ) | |
| { | |
| return std::complex< R >( r, i ); | |
| } | |
| // Complex Maker | |
| template< typename R, typename I, class = typename std::enable_if< ( ! std::is_integral< R >::value ) && ( ! std::is_integral< I >::value ) && ( ! std::is_same< R, I >::value ) >::type > | |
| inline | |
| std::complex< double > | |
| make_complex( R const & r, I const & i ) | |
| { | |
| return std::complex< double >( r, i ); | |
| } | |
| // Trigonometric ///// | |
| // pi | |
| template< typename T > | |
| inline | |
| T | |
| pi() | |
| { | |
| static T const Pi( T( 4 ) * std::atan( T( 1 ) ) ); | |
| return Pi; | |
| } | |
| // pi/2 | |
| template< typename T > | |
| inline | |
| T | |
| pi_over_2() | |
| { | |
| static T const Pi__2( T( 2 ) * std::atan( T( 1 ) ) ); | |
| return Pi__2; | |
| } | |
| // pi/2 | |
| template< typename T > | |
| inline | |
| T | |
| pi__2() | |
| { | |
| static T const Pi__2( T( 2 ) * std::atan( T( 1 ) ) ); | |
| return Pi__2; | |
| } | |
| // Radians to Degrees | |
| template< typename T > | |
| inline | |
| T | |
| degrees( T const & r ) | |
| { | |
| static T const r2d( T( 180 ) / pi< T >() ); | |
| return r * r2d; | |
| } | |
| // Radians to Degrees | |
| template< typename T > | |
| inline | |
| T | |
| deg( T const & r ) | |
| { | |
| static T const r2d( T( 180 ) / pi< T >() ); | |
| return r * r2d; | |
| } | |
| // Degrees to Radians | |
| template< typename T > | |
| inline | |
| T | |
| radians( T const & d ) | |
| { | |
| static T const d2r( pi< T >() / T( 180 ) ); | |
| return d * d2r; | |
| } | |
| // Degrees to Radians | |
| template< typename T > | |
| inline | |
| T | |
| rad( T const & d ) | |
| { | |
| static T const d2r( pi< T >() / T( 180 ) ); | |
| return d * d2r; | |
| } | |
| // Cotangent | |
| template< typename T > | |
| inline | |
| T | |
| cot( T const & r ) | |
| { | |
| if ( r == T( 0 ) ) { | |
| return std::numeric_limits< T >::infinity(); | |
| } else { | |
| return std::tan( pi_over_2< T >() - r ); | |
| } | |
| } | |
| // Arccotangent | |
| template< typename T > | |
| inline | |
| T | |
| acot( T const & x ) | |
| { | |
| return pi_over_2< T >() - std::atan( x ); | |
| } | |
| // Tangent of Angle in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| tand( T const & d ) | |
| { | |
| return std::tan( radians( d ) ); | |
| } | |
| // Cotangent of Angle in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| cotd( T const & d ) | |
| { | |
| return cot( radians( d ) ); | |
| } | |
| // Arcsine in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| asind( T const & x ) | |
| { | |
| return degrees( std::asin( x ) ); | |
| } | |
| // Arccosine in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| acosd( T const & x ) | |
| { | |
| return degrees( std::acos( x ) ); | |
| } | |
| // Arctangent in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| atand( T const & x ) | |
| { | |
| return degrees( std::atan( x ) ); | |
| } | |
| // Arccotangent in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| acotd( T const & x ) | |
| { | |
| return degrees( acot( x ) ); | |
| } | |
| // Two-Argument Arctangent in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| atan2d( T const & y, T const & x ) | |
| { | |
| return degrees( std::atan2( y, x ) ); | |
| } | |
| // Error Function ///// | |
| // Two-Argument Arctangent in Degrees | |
| template< typename T > | |
| inline | |
| T | |
| erfcx( T const & x ) | |
| { | |
| return T( std::exp( x * x ) * std::erfc( x ) ); | |
| } | |
| // Power and Roots ///// | |
| // square( x ) == x^2 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| square( T const x ) | |
| { | |
| return x * x; | |
| } | |
| // cube( x ) == x^3 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| cube( T const x ) | |
| { | |
| return x * x * x; | |
| } | |
| // quad( x ) == x^4 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| quad( T const x ) | |
| { | |
| T const t( x * x ); | |
| return t * t; | |
| } | |
| // pow_2( x ) == x^2 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_2( T const x ) | |
| { | |
| return x * x; | |
| } | |
| // pow_3( x ) == x^3 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_3( T const x ) | |
| { | |
| return x * x * x; | |
| } | |
| // pow_4( x ) == x^4 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_4( T const x ) | |
| { | |
| T const t( x * x ); | |
| return t * t; | |
| } | |
| // pow_5( x ) == x^5 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_5( T const x ) | |
| { | |
| T const t( x * x ); | |
| return t * t * x; | |
| } | |
| // pow_6( x ) == x^6 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_6( T const x ) | |
| { | |
| T const t( x * x * x ); | |
| return t * t; | |
| } | |
| // pow_7( x ) == x^7 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_7( T const x ) | |
| { | |
| T const t( x * x * x ); | |
| return t * t * x; | |
| } | |
| // pow_8( x ) == x^8 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_8( T const x ) | |
| { | |
| T t( x * x ); | |
| t *= t; | |
| return t * t; | |
| } | |
| // pow_9( x ) == x^9 | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_9( T const x ) | |
| { | |
| T const t( x * x * x ); | |
| return t * t * t; | |
| } | |
| // root_4( x ) == x^(1/4) | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| root_4( T const x ) | |
| { | |
| return T( std::sqrt( std::sqrt( x ) ) ); | |
| } | |
| // root_8( x ) == x^(1/8) | |
| template< typename T, class = typename std::enable_if< std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| root_8( T const x ) | |
| { | |
| return T( std::sqrt( std::sqrt( std::sqrt( x ) ) ) ); | |
| } | |
| // square( x ) == x^2 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| square( T const & x ) | |
| { | |
| return x * x; | |
| } | |
| // cube( x ) == x^3 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| cube( T const & x ) | |
| { | |
| return x * x * x; | |
| } | |
| // quad( x ) == x^4 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| quad( T const & x ) | |
| { | |
| T const t( x * x ); | |
| return t * t; | |
| } | |
| // pow_2( x ) == x^2 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_2( T const & x ) | |
| { | |
| return x * x; | |
| } | |
| // pow_3( x ) == x^3 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_3( T const & x ) | |
| { | |
| return x * x * x; | |
| } | |
| // pow_4( x ) == x^4 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_4( T const & x ) | |
| { | |
| T const t( x * x ); | |
| return t * t; | |
| } | |
| // pow_5( x ) == x^5 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_5( T const & x ) | |
| { | |
| T const t( x * x ); | |
| return t * t * x; | |
| } | |
| // pow_6( x ) == x^6 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_6( T const & x ) | |
| { | |
| T const t( x * x * x ); | |
| return t * t; | |
| } | |
| // pow_7( x ) == x^7 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_7( T const & x ) | |
| { | |
| T const t( x * x * x ); | |
| return t * t * x; | |
| } | |
| // pow_8( x ) == x^8 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_8( T const & x ) | |
| { | |
| T t( x * x ); | |
| t *= t; | |
| return t * t; | |
| } | |
| // pow_9( x ) == x^9 | |
| template< typename T, class = typename std::enable_if< ! std::is_arithmetic< T >::value >::type > | |
| inline | |
| T | |
| pow_9( T const & x ) | |
| { | |
| T const t( x * x * x ); | |
| return t * t * t; | |
| } | |
| // Tolerant Comparisons ///// | |
| // x == y Within Specified Relative or Absolute Tolerances? | |
| template< typename T > | |
| inline | |
| bool | |
| eq_tol( T const & x, T const & y, T const & r_tol, T const & a_tol = T( 0 ) ) | |
| { | |
| using std::abs; // Can use std::abs or user-defined abs | |
| assert( r_tol >= T( 0 ) ); | |
| assert( a_tol >= T( 0 ) ); | |
| return ( abs( x - y ) <= max( r_tol * max( abs( x ), abs( y ) ), a_tol ) ); | |
| } | |
| // x < y Within Specified Relative or Absolute Tolerances? | |
| template< typename T > | |
| inline | |
| bool | |
| lt_tol( T const & x, T const & y, T const & r_tol, T const & a_tol = T( 0 ) ) | |
| { | |
| using std::abs; // Can use std::abs or user-defined abs | |
| assert( r_tol >= T( 0 ) ); | |
| assert( a_tol >= T( 0 ) ); | |
| return ( x < y + max( r_tol * max( abs( x ), abs( y ) ), a_tol ) ); | |
| } | |
| // x <= y Within Specified Relative or Absolute Tolerances? | |
| template< typename T > | |
| inline | |
| bool | |
| le_tol( T const & x, T const & y, T const & r_tol, T const & a_tol = T( 0 ) ) | |
| { | |
| using std::abs; // Can use std::abs or user-defined abs | |
| assert( r_tol >= T( 0 ) ); | |
| assert( a_tol >= T( 0 ) ); | |
| return ( x <= y + max( r_tol * max( abs( x ), abs( y ) ), a_tol ) ); | |
| } | |
| // x >= y Within Specified Relative or Absolute Tolerances? | |
| template< typename T > | |
| inline | |
| bool | |
| ge_tol( T const & x, T const & y, T const & r_tol, T const & a_tol = T( 0 ) ) | |
| { | |
| using std::abs; // Can use std::abs or user-defined abs | |
| assert( r_tol >= T( 0 ) ); | |
| assert( a_tol >= T( 0 ) ); | |
| return ( x >= y - max( r_tol * max( abs( x ), abs( y ) ), a_tol ) ); | |
| } | |
| // x > y Within Specified Relative or Absolute Tolerances? | |
| template< typename T > | |
| inline | |
| bool | |
| gt_tol( T const & x, T const & y, T const & r_tol, T const & a_tol = T( 0 ) ) | |
| { | |
| using std::abs; // Can use std::abs or user-defined abs | |
| assert( r_tol >= T( 0 ) ); | |
| assert( a_tol >= T( 0 ) ); | |
| return ( x > y - max( r_tol * max( abs( x ), abs( y ) ), a_tol ) ); | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Fmath_hh_INCLUDED | |
| // ===== ObjexxFCL/Vector2.hh ===== | |
| #ifndef ObjexxFCL_Vector2_hh_INCLUDED | |
| #define ObjexxFCL_Vector2_hh_INCLUDED | |
| // Vector2: Fast 2-Element Vector | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <cstdlib> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <iostream> | |
| #include <sstream> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| // Vector2: Fast 2-Element Vector | |
| // . Heap-free and loop-free for speed | |
| // . Provides direct element access via .x style lookup | |
| // . Use std::array< T, 2 > instead in array/vectorization context | |
| template< typename T > | |
| class Vector2 | |
| { | |
| private: // Friends | |
| template< typename > friend class Vector2; | |
| public: // Types | |
| typedef TypeTraits< T > Traits; | |
| typedef typename std::conditional< std::is_scalar< T >::value, T const, T const & >::type Tc; | |
| typedef typename std::conditional< std::is_scalar< T >::value, typename std::remove_const< T >::type, T const & >::type Tr; | |
| // STL Style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| typedef std::size_t size_type; | |
| typedef std::ptrdiff_t difference_type; | |
| // C++ Style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| typedef std::size_t Size; | |
| typedef std::ptrdiff_t Difference; | |
| public: // Creation | |
| // Default Constructor | |
| Vector2() | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| : | |
| x( Traits::initial_array_value() ), | |
| y( Traits::initial_array_value() ) | |
| #endif | |
| {} | |
| // Copy Constructor | |
| Vector2( Vector2 const & v ) : | |
| x( v.x ), | |
| y( v.y ) | |
| {} | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Vector2( Vector2< U > const & v ) : | |
| x( v.x ), | |
| y( v.y ) | |
| {} | |
| // Uniform Value Constructor | |
| explicit | |
| Vector2( Tc t ) : | |
| x( t ), | |
| y( t ) | |
| {} | |
| // Value Constructor | |
| Vector2( | |
| Tc x_, | |
| Tc y_ | |
| ) : | |
| x( x_ ), | |
| y( y_ ) | |
| {} | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Vector2( std::initializer_list< U > const l ) : | |
| x( *l.begin() ), | |
| y( *( l.begin() + 1 ) ) | |
| { | |
| assert( l.size() == 2 ); | |
| } | |
| // Array Constructor Template | |
| template< typename A, class = typename std::enable_if< std::is_constructible< T, typename A::value_type >::value >::type > | |
| Vector2( A const & a ) : | |
| x( a[ 0 ] ), | |
| y( a[ 1 ] ) | |
| { | |
| assert( a.size() == 2 ); | |
| } | |
| // Default Vector Named Constructor | |
| static | |
| Vector2 | |
| default_vector() | |
| { | |
| return Vector2( T() ); | |
| } | |
| // Zero Vector Named Constructor | |
| static | |
| Vector2 | |
| zero_vector() | |
| { | |
| return Vector2( T( 0 ) ); | |
| } | |
| // x Vector of Specified Length Named Constructor | |
| static | |
| Vector2 | |
| x_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector2( tar_length, T( 0 ) ); | |
| } | |
| // y Vector of Specified Length Named Constructor | |
| static | |
| Vector2 | |
| y_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector2( T( 0 ), tar_length ); | |
| } | |
| // Uniform Vector of Specified Length Named Constructor | |
| static | |
| Vector2 | |
| uniform_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector2( tar_length / std::sqrt( T( 2 ) ) ); | |
| } | |
| // Destructor | |
| ~Vector2() | |
| {} | |
| public: // Assignment | |
| // Copy Assignment | |
| Vector2 & | |
| operator =( Vector2 const & v ) | |
| { | |
| if ( this != &v ) { | |
| x = v.x; | |
| y = v.y; | |
| } | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator =( Vector2< U > const & v ) | |
| { | |
| x = v.x; | |
| y = v.y; | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 2 ); | |
| auto i( l.begin() ); | |
| x = *i; | |
| y = *(++i); | |
| return *this; | |
| } | |
| // Array Assignment Template | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector2 & | |
| operator =( A const & a ) | |
| { | |
| assert( a.size() == 2 ); | |
| x = a[ 0 ]; | |
| y = a[ 1 ]; | |
| return *this; | |
| } | |
| // += Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator +=( Vector2< U > const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| return *this; | |
| } | |
| // -= Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator -=( Vector2< U > const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| return *this; | |
| } | |
| // *= Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator *=( Vector2< U > const & v ) | |
| { | |
| x *= v.x; | |
| y *= v.y; | |
| return *this; | |
| } | |
| // /= Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator /=( Vector2< U > const & v ) | |
| { | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| x /= v.x; | |
| y /= v.y; | |
| return *this; | |
| } | |
| // += Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator +=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 2 ); | |
| auto i( l.begin() ); | |
| x += *i; | |
| y += *(++i); | |
| return *this; | |
| } | |
| // -= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator -=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 2 ); | |
| auto i( l.begin() ); | |
| x -= *i; | |
| y -= *(++i); | |
| return *this; | |
| } | |
| // *= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator *=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 2 ); | |
| auto i( l.begin() ); | |
| x *= *i; | |
| y *= *(++i); | |
| return *this; | |
| } | |
| // /= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| operator /=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 2 ); | |
| auto i( l.begin() ); | |
| assert( *i != T( 0 ) ); | |
| assert( *(i+1) != T( 0 ) ); | |
| x /= *i; | |
| y /= *(++i); | |
| return *this; | |
| } | |
| // += Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector2 & | |
| operator +=( A const & a ) | |
| { | |
| assert( a.size() == 2 ); | |
| x += a[ 0 ]; | |
| y += a[ 1 ]; | |
| return *this; | |
| } | |
| // -= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector2 & | |
| operator -=( A const & a ) | |
| { | |
| assert( a.size() == 2 ); | |
| x -= a[ 0 ]; | |
| y -= a[ 1 ]; | |
| return *this; | |
| } | |
| // *= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector2 & | |
| operator *=( A const & a ) | |
| { | |
| assert( a.size() == 2 ); | |
| x *= a[ 0 ]; | |
| y *= a[ 1 ]; | |
| return *this; | |
| } | |
| // /= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector2 & | |
| operator /=( A const & a ) | |
| { | |
| assert( a.size() == 2 ); | |
| assert( a[ 0 ] != T( 0 ) ); | |
| assert( a[ 1 ] != T( 0 ) ); | |
| x /= a[ 0 ]; | |
| y /= a[ 1 ]; | |
| return *this; | |
| } | |
| // = Value | |
| Vector2 & | |
| operator =( Tc t ) | |
| { | |
| x = y = t; | |
| return *this; | |
| } | |
| // += Value | |
| Vector2 & | |
| operator +=( Tc t ) | |
| { | |
| x += t; | |
| y += t; | |
| return *this; | |
| } | |
| // -= Value | |
| Vector2 & | |
| operator -=( Tc t ) | |
| { | |
| x -= t; | |
| y -= t; | |
| return *this; | |
| } | |
| // *= Value | |
| Vector2 & | |
| operator *=( Tc t ) | |
| { | |
| x *= t; | |
| y *= t; | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| Vector2 & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| x *= inv_u; | |
| y *= inv_u; | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void, typename = void > | |
| Vector2 & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| x /= u; | |
| y /= u; | |
| return *this; | |
| } | |
| // Value Assignment | |
| Vector2 & | |
| assign( | |
| Tc x_, | |
| Tc y_ | |
| ) | |
| { | |
| x = x_; | |
| y = y_; | |
| return *this; | |
| } | |
| public: // Assignment: Scaled | |
| // Assign Value * Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| scaled_assign( Tc t, Vector2< U > const & v ) | |
| { | |
| x = t * v.x; | |
| y = t * v.y; | |
| return *this; | |
| } | |
| // Add Value * Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| scaled_add( Tc t, Vector2< U > const & v ) | |
| { | |
| x += t * v.x; | |
| y += t * v.y; | |
| return *this; | |
| } | |
| // Subtract Value * Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| scaled_sub( Tc t, Vector2< U > const & v ) | |
| { | |
| x -= t * v.x; | |
| y -= t * v.y; | |
| return *this; | |
| } | |
| // Multiply by Value * Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| scaled_mul( Tc t, Vector2< U > const & v ) | |
| { | |
| x *= t * v.x; | |
| y *= t * v.y; | |
| return *this; | |
| } | |
| // Divide by Value * Vector2 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector2 & | |
| scaled_div( Tc t, Vector2< U > const & v ) | |
| { | |
| assert( t != T( 0 ) ); | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| x /= t * v.x; | |
| y /= t * v.y; | |
| return *this; | |
| } | |
| public: // Subscript | |
| // Vector2[ i ] const: 0-Based Index | |
| Tr | |
| operator []( size_type const i ) const | |
| { | |
| assert( i <= 1 ); | |
| return ( i == 0 ? x : y ); | |
| } | |
| // Vector2[ i ]: 0-Based Index | |
| T & | |
| operator []( size_type const i ) | |
| { | |
| assert( i <= 1 ); | |
| return ( i == 0 ? x : y ); | |
| } | |
| // Vector2( i ) const: 1-Based Index | |
| Tr | |
| operator ()( size_type const i ) const | |
| { | |
| assert( ( 1 <= i ) && ( i <= 2 ) ); | |
| return ( i == 1 ? x : y ); | |
| } | |
| // Vector2( i ): 1-Based Index | |
| T & | |
| operator ()( size_type const i ) | |
| { | |
| assert( ( 1 <= i ) && ( i <= 2 ) ); | |
| return ( i == 1 ? x : y ); | |
| } | |
| public: // Properties: Predicates | |
| // Is Zero Vector? | |
| bool | |
| is_zero() const | |
| { | |
| static T const ZERO( 0 ); | |
| return ( x == ZERO ) && ( y == ZERO ); | |
| } | |
| // Is Unit Vector? | |
| bool | |
| is_unit() const | |
| { | |
| return ( length_squared() == T( 1 ) ); | |
| } | |
| public: // Properties: General | |
| // Size | |
| Size | |
| size() const | |
| { | |
| return 2u; | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) ); | |
| } | |
| // Length Squared | |
| T | |
| length_squared() const | |
| { | |
| return ( x * x ) + ( y * y ); | |
| } | |
| // Magnitude | |
| T | |
| magnitude() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) ); | |
| } | |
| // Magnitude | |
| T | |
| mag() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) ); | |
| } | |
| // Magnitude Squared | |
| T | |
| magnitude_squared() const | |
| { | |
| return ( x * x ) + ( y * y ); | |
| } | |
| // Magnitude Squared | |
| T | |
| mag_squared() const | |
| { | |
| return ( x * x ) + ( y * y ); | |
| } | |
| // L1 Norm | |
| T | |
| norm_L1() const | |
| { | |
| return std::abs( x ) + std::abs( y ); | |
| } | |
| // L2 Norm | |
| T | |
| norm_L2() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) ); | |
| } | |
| // L-infinity Norm | |
| T | |
| norm_Linf() const | |
| { | |
| return std::max( std::abs( x ), std::abs( y ) ); | |
| } | |
| // Distance to a Vector2 | |
| T | |
| distance( Vector2 const & v ) const | |
| { | |
| return std::sqrt( square( x - v.x ) + square( y - v.y ) ); | |
| } | |
| // Distance Squared to a Vector2 | |
| T | |
| distance_squared( Vector2 const & v ) const | |
| { | |
| return square( x - v.x ) + square( y - v.y ); | |
| } | |
| // Dot Product with a Vector2 | |
| T | |
| dot( Vector2 const & v ) const | |
| { | |
| return ( x * v.x ) + ( y * v.y ); | |
| } | |
| // Dot Product with an Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| T | |
| dot( A const & a ) const | |
| { | |
| assert( a.size() == 2 ); | |
| return ( x * a[ 0 ] ) + ( y * a[ 1 ] ); | |
| } | |
| // Cross Product with a Vector2 | |
| T | |
| cross( Vector2 const & v ) const | |
| { | |
| return ( x * v.y ) - ( y * v.x ); | |
| } | |
| // Cross Product with an Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| T | |
| cross( A const & a ) const | |
| { | |
| assert( a.size() == 2 ); | |
| return ( x * a[ 1 ] ) - ( y * a[ 0 ] ); | |
| } | |
| // Alias for Element 1 | |
| Tr | |
| x1() const | |
| { | |
| return x; | |
| } | |
| // Alias for Element 1 | |
| T & | |
| x1() | |
| { | |
| return x; | |
| } | |
| // Alias for Element 2 | |
| Tr | |
| x2() const | |
| { | |
| return y; | |
| } | |
| // Alias for Element 2 | |
| T & | |
| x2() | |
| { | |
| return y; | |
| } | |
| public: // Modifiers | |
| // Zero | |
| Vector2 & | |
| zero() | |
| { | |
| x = y = T( 0 ); | |
| return *this; | |
| } | |
| // Negate | |
| Vector2 & | |
| negate() | |
| { | |
| x = -x; | |
| y = -y; | |
| return *this; | |
| } | |
| // Normalize to a Length | |
| Vector2 & | |
| normalize( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| assert( cur_length != T ( 0 ) ); | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| return *this; | |
| } | |
| // Normalize to a Length: Zero Vector2 if Length is Zero | |
| Vector2 & | |
| normalize_zero( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| } else { // Set zero vector | |
| x = y = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: Uniform Vector2 if Length is Zero | |
| Vector2 & | |
| normalize_uniform( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| } else { // Set uniform vector | |
| operator =( uniform_vector( tar_length ) ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: x Vector2 if Length is Zero | |
| Vector2 & | |
| normalize_x( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| } else { // Set x vector | |
| x = tar_length; | |
| y = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: y Vector2 if Length is Zero | |
| Vector2 & | |
| normalize_y( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| } else { // Set y vector | |
| y = tar_length; | |
| x = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Minimum Coordinates with a Vector2 | |
| Vector2 & | |
| min( Vector2 const & v ) | |
| { | |
| x = ( x <= v.x ? x : v.x ); | |
| y = ( y <= v.y ? y : v.y ); | |
| return *this; | |
| } | |
| // Maximum Coordinates with a Vector2 | |
| Vector2 & | |
| max( Vector2 const & v ) | |
| { | |
| x = ( x >= v.x ? x : v.x ); | |
| y = ( y >= v.y ? y : v.y ); | |
| return *this; | |
| } | |
| // Add a Vector2 | |
| Vector2 & | |
| add( Vector2 const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| return *this; | |
| } | |
| // Sum a Vector2 | |
| Vector2 & | |
| sum( Vector2 const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| return *this; | |
| } | |
| // Subtract a Vector2 | |
| Vector2 & | |
| sub( Vector2 const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| return *this; | |
| } | |
| // Subtract a Vector2 | |
| Vector2 & | |
| subtract( Vector2 const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| return *this; | |
| } | |
| // Project Normal to a Vector2 | |
| Vector2 & | |
| project_normal( Vector2 const & v ) | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| x -= c * v.x; | |
| y -= c * v.y; | |
| return *this; | |
| } | |
| // Project onto a Vector2 | |
| Vector2 & | |
| project_parallel( Vector2 const & v ) | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| x = c * v.x; | |
| y = c * v.y; | |
| return *this; | |
| } | |
| public: // Generators | |
| // -Vector2 (Negated) | |
| Vector2 | |
| operator -() const | |
| { | |
| return Vector2( -x, -y ); | |
| } | |
| // Negated | |
| Vector2 | |
| negated() const | |
| { | |
| return Vector2( -x, -y ); | |
| } | |
| // Normalized to a Length | |
| Vector2 | |
| normalized( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| assert( cur_length != T ( 0 ) ); | |
| T const dilation( tar_length / cur_length ); | |
| return Vector2( | |
| x * dilation, | |
| y * dilation | |
| ); | |
| } | |
| // Normalized to a Length: Zero Vector2 if Length is Zero | |
| Vector2 | |
| normalized_zero( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector2( | |
| x * dilation, | |
| y * dilation | |
| ); | |
| } else { // Return zero vector | |
| return Vector2( T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: Uniform Vector2 if Length is Zero | |
| Vector2 | |
| normalized_uniform( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector2( | |
| x * dilation, | |
| y * dilation | |
| ); | |
| } else { // Return uniform vector | |
| return uniform_vector( tar_length ); | |
| } | |
| } | |
| // Normalized to a Length: x Vector2 if Length is Zero | |
| Vector2 | |
| normalized_x( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector2( | |
| x * dilation, | |
| y * dilation | |
| ); | |
| } else { // Return x vector | |
| return Vector2( tar_length, T( 0 ), T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: y Vector2 if Length is Zero | |
| Vector2 | |
| normalized_y( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector2( | |
| x * dilation, | |
| y * dilation | |
| ); | |
| } else { // Return y vector | |
| return Vector2( T( 0 ), tar_length, T( 0 ) ); | |
| } | |
| } | |
| // Projected Normal to a Vector2 | |
| Vector2 | |
| projected_normal( Vector2 const & v ) const | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| return Vector2( x - ( c * v.x ), y - ( c * v.y ) ); | |
| } | |
| // Projected onto a Vector2 | |
| Vector2 | |
| projected_parallel( Vector2 const & v ) const | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| return Vector2( c * v.x, c * v.y ); | |
| } | |
| public: // Static Methods | |
| // Square of a value | |
| static | |
| T | |
| square( Tc t ) | |
| { | |
| return t * t; | |
| } | |
| // Value Clipped to [-1,1] | |
| static | |
| T | |
| sin_cos_range( Tc t ) | |
| { | |
| return std::min( std::max( t, T( -1 ) ), T( 1 ) ); | |
| } | |
| // Add 2*Pi to a Negative Value | |
| static | |
| T | |
| bump_up_angle( Tc t ) | |
| { | |
| static T const Two_Pi( T( 2 ) * std::acos( -1.0 ) ); | |
| return ( t >= T( 0 ) ? t : Two_Pi + t ); | |
| } | |
| public: // Data | |
| T x, y; // Elements | |
| }; // Vector2 | |
| // Length | |
| template< typename T > | |
| inline | |
| T | |
| length( Vector2< T > const & v ) | |
| { | |
| return v.length(); | |
| } | |
| // Length Squared | |
| template< typename T > | |
| inline | |
| T | |
| length_squared( Vector2< T > const & v ) | |
| { | |
| return v.length_squared(); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( Vector2< T > const & v ) | |
| { | |
| return v.magnitude(); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| mag( Vector2< T > const & v ) | |
| { | |
| return v.mag(); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( Vector2< T > const & v ) | |
| { | |
| return v.magnitude_squared(); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| mag_squared( Vector2< T > const & v ) | |
| { | |
| return v.mag_squared(); | |
| } | |
| // Vector2 == Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x == b.x ) && ( a.y == b.y ); | |
| } | |
| // Vector2 != Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x != b.x ) || ( a.y != b.y ); | |
| } | |
| // Vector2 < Vector2: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( | |
| ( a.x < b.x ? true : | |
| ( b.x < a.x ? false : // a.x == b.x | |
| ( a.y < b.y ) ) ) | |
| ); | |
| } | |
| // Vector2 <= Vector2: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( | |
| ( a.x < b.x ? true : | |
| ( b.x < a.x ? false : // a.x == b.x | |
| ( a.y <= b.y ) ) ) | |
| ); | |
| } | |
| // Vector2 >= Vector2: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( | |
| ( a.x > b.x ? true : | |
| ( b.x > a.x ? false : // a.x == b.x | |
| ( a.y >= b.y ) ) ) | |
| ); | |
| } | |
| // Vector2 > Vector2: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( | |
| ( a.x > b.x ? true : | |
| ( b.x > a.x ? false : // a.x == b.x | |
| ( a.y > b.y ) ) ) | |
| ); | |
| } | |
| // Vector2 < Vector2: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| lt( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x < b.x ) && ( a.y < b.y ); | |
| } | |
| // Vector2 <= Vector2: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| le( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x <= b.x ) && ( a.y <= b.y ); | |
| } | |
| // Vector2 >= Vector2: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| ge( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x >= b.x ) && ( a.y >= b.y ); | |
| } | |
| // Vector2 > Vector2: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| gt( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x > b.x ) && ( a.y > b.y ); | |
| } | |
| // Vector2 == Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return ( v.x == t ) && ( v.y == t ); | |
| } | |
| // Vector2 != Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return ( v.x != t ) || ( v.y != t ); | |
| } | |
| // Vector2 < Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return ( v.x < t ) && ( v.y < t ); | |
| } | |
| // Vector2 <= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return ( v.x <= t ) && ( v.y <= t ); | |
| } | |
| // Vector2 >= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return ( v.x >= t ) && ( v.y >= t ); | |
| } | |
| // Vector2 > Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return ( v.x > t ) && ( v.y > t ); | |
| } | |
| // Value == Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return ( t == v.x ) && ( t == v.y ); | |
| } | |
| // Value != Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return ( t != v.x ) || ( t != v.y ); | |
| } | |
| // Value < Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return ( t < v.x ) && ( t < v.y ); | |
| } | |
| // Value <= Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return ( t <= v.x ) && ( t <= v.y ); | |
| } | |
| // Value >= Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return ( t >= v.x ) && ( t >= v.y ); | |
| } | |
| // Value > Vector2 | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return ( t > v.x ) && ( t > v.y ); | |
| } | |
| // Equal Length? | |
| template< typename T > | |
| inline | |
| bool | |
| equal_length( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.length_squared() == b.length_squared() ); | |
| } | |
| // Not Equal Length? | |
| template< typename T > | |
| inline | |
| bool | |
| not_equal_length( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.length_squared() != b.length_squared() ); | |
| } | |
| // Vector2 + Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator +( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( a.x + b.x, a.y + b.y ); | |
| } | |
| // Vector2 + Value | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator +( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return Vector2< T >( v.x + t, v.y + t ); | |
| } | |
| // Value + Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator +( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return Vector2< T >( t + v.x, t + v.y ); | |
| } | |
| // Vector2 - Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator -( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( a.x - b.x, a.y - b.y ); | |
| } | |
| // Vector2 - Value | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator -( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return Vector2< T >( v.x - t, v.y - t ); | |
| } | |
| // Value - Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator -( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return Vector2< T >( t - v.x, t - v.y ); | |
| } | |
| // Vector2 * Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator *( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( a.x * b.x, a.y * b.y ); | |
| } | |
| // Vector2 * Value | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator *( Vector2< T > const & v, typename Vector2< T >::Tc t ) | |
| { | |
| return Vector2< T >( v.x * t, v.y * t ); | |
| } | |
| // Value * Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator *( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| return Vector2< T >( t * v.x, t * v.y ); | |
| } | |
| // Vector2 / Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator /( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( b.x != T( 0 ) ); | |
| assert( b.y != T( 0 ) ); | |
| return Vector2< T >( a.x / b.x, a.y / b.y ); | |
| } | |
| // Vector2 / Value | |
| template< typename T, typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| inline | |
| Vector2< T > | |
| operator /( Vector2< T > const & v, U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U ( 1 ) / u ); | |
| return Vector2< T >( v.x * inv_u, v.y * inv_u ); | |
| } | |
| // Vector2 / Value | |
| template< typename T, typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| inline | |
| Vector2< T > | |
| operator /( Vector2< T > const & v, U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| return Vector2< T >( v.x / u, v.y / u ); | |
| } | |
| // Value / Vector2 | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| operator /( typename Vector2< T >::Tc t, Vector2< T > const & v ) | |
| { | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| return Vector2< T >( t / v.x, t / v.y ); | |
| } | |
| // Minimum of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| min( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( | |
| ( a.x <= b.x ? a.x : b.x ), | |
| ( a.y <= b.y ? a.y : b.y ) | |
| ); | |
| } | |
| // Minimum of Three Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| min( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return Vector2< T >( | |
| ObjexxFCL::min( a.x, b.x, c.x ), | |
| ObjexxFCL::min( a.y, b.y, c.y ) | |
| ); | |
| } | |
| // Minimum of Four Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| min( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c, Vector2< T > const & d ) | |
| { | |
| return Vector2< T >( | |
| ObjexxFCL::min( a.x, b.x, c.x, d.x ), | |
| ObjexxFCL::min( a.y, b.y, c.y, d.y ) | |
| ); | |
| } | |
| // Maximum of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| max( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( | |
| ( a.x >= b.x ? a.x : b.x ), | |
| ( a.y >= b.y ? a.y : b.y ) | |
| ); | |
| } | |
| // Maximum of Three Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| max( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return Vector2< T >( | |
| ObjexxFCL::max( a.x, b.x, c.x ), | |
| ObjexxFCL::max( a.y, b.y, c.y ) | |
| ); | |
| } | |
| // Maximum of Four Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| max( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c, Vector2< T > const & d ) | |
| { | |
| return Vector2< T >( | |
| ObjexxFCL::max( a.x, b.x, c.x, d.x ), | |
| ObjexxFCL::max( a.y, b.y, c.y, d.y ) | |
| ); | |
| } | |
| // Sum of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| sum( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( a.x + b.x, a.y + b.y ); | |
| } | |
| // Sum of Three Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| sum( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return Vector2< T >( a.x + b.x + c.x, a.y + b.y + c.y ); | |
| } | |
| // Sum of Four Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| sum( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c, Vector2< T > const & d ) | |
| { | |
| return Vector2< T >( a.x + b.x + c.x + d.x, a.y + b.y + c.y + d.y ); | |
| } | |
| // Subtract of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| sub( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( a.x - b.x, a.y - b.y ); | |
| } | |
| // Subtract of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| subtract( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( a.x - b.x, a.y - b.y ); | |
| } | |
| // Midpoint of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| mid( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( | |
| T( 0.5 * ( a.x + b.x ) ), | |
| T( 0.5 * ( a.y + b.y ) ) | |
| ); | |
| } | |
| // Center of Two Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| cen( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >( | |
| T( 0.5 * ( a.x + b.x ) ), | |
| T( 0.5 * ( a.y + b.y ) ) | |
| ); | |
| } | |
| // Center of Three Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| cen( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| static long double const third( 1.0 / 3.0 ); | |
| return Vector2< T >( | |
| T( third * ( a.x + b.x + c.x ) ), | |
| T( third * ( a.y + b.y + c.y ) ) | |
| ); | |
| } | |
| // Center of Four Vector2s | |
| template< typename T > | |
| inline | |
| Vector2< T > | |
| cen( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c, Vector2< T > const & d ) | |
| { | |
| return Vector2< T >( | |
| T( 0.25 * ( a.x + b.x + c.x + d.x ) ), | |
| T( 0.25 * ( a.y + b.y + c.y + d.y ) ) | |
| ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return std::sqrt( Vector2< T >::square( a.x - b.x ) + Vector2< T >::square( a.y - b.y ) ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return Vector2< T >::square( a.x - b.x ) + Vector2< T >::square( a.y - b.y ); | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x * b.x ) + ( a.y * b.y ); | |
| } | |
| // Cross Product | |
| template< typename T > | |
| inline | |
| T | |
| cross( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| return ( a.x * b.y ) - ( a.y * b.x ); | |
| } | |
| // Angle Between Two Vector2s (in Radians on [0,pi]) | |
| template< typename T > | |
| inline | |
| T | |
| angle( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| T const axb( std::abs( a.cross( b ) ) ); | |
| T const adb( a.dot( b ) ); | |
| return ( ( axb != T( 0 ) ) || ( adb != T( 0 ) ) ? Vector2< T >::bump_up_angle( std::atan2( axb, adb ) ) : T( 0 ) ); // More accurate than dot-based for angles near 0 and Pi | |
| } | |
| // Angle abc Formed by Three Vector2s (in Radians on [0,pi]) | |
| template< typename T > | |
| inline | |
| T | |
| angle( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return angle( a - b, c - b ); | |
| } | |
| // Cosine of Angle Between Two Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| cos( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? Vector2< T >::sin_cos_range( a.dot( b ) / mag ) : T( 1 ) ); | |
| } | |
| // Cosine of Angle abc Formed by Three Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| cos( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return cos( a - b, c - b ); | |
| } | |
| // Sine of Angle Between Two Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| sin( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? std::abs( Vector2< T >::sin_cos_range( a.cross( b ) / mag ) ) : T( 0 ) ); | |
| } | |
| // Sine of Angle abc Formed by Three Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| sin( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return sin( a - b, c - b ); | |
| } | |
| // Directed Angle Between Two Vector2s (in Radians on [0,2*pi]) | |
| template< typename T > | |
| inline | |
| T | |
| dir_angle( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| T const axb( a.cross( b ) ); | |
| T const adb( a.dot( b ) ); | |
| return ( ( axb != T( 0 ) ) || ( adb != T( 0 ) ) ? Vector2< T >::bump_up_angle( std::atan2( axb, adb ) ) : T( 0 ) ); | |
| } | |
| // Directed Angle abc Formed by Three Vector2s (in Radians on [0,2*pi]) | |
| template< typename T > | |
| inline | |
| T | |
| dir_angle( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return dir_angle( a - b, c - b ); | |
| } | |
| // Cosine of Directed Angle Between Two Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| dir_cos( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? Vector2< T >::sin_cos_range( a.dot( b ) / mag ) : T( 1 ) ); | |
| } | |
| // Cosine of Directed Angle abc Formed by Three Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| dir_cos( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return dir_cos( a - b, c - b ); | |
| } | |
| // Sine of Directed Angle Between Two Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| dir_sin( Vector2< T > const & a, Vector2< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? Vector2< T >::sin_cos_range( a.cross( b ) / mag ) : T( 0 ) ); | |
| } | |
| // Sine of Directed Angle abc Formed by Three Vector2s | |
| template< typename T > | |
| inline | |
| T | |
| dir_sin( Vector2< T > const & a, Vector2< T > const & b, Vector2< T > const & c ) | |
| { | |
| return dir_sin( a - b, c - b ); | |
| } | |
| // Stream << Vector2 output operator | |
| template< typename T > | |
| std::ostream & | |
| operator <<( std::ostream & stream, Vector2< T > const & v ) | |
| { | |
| // Types | |
| typedef TypeTraits< T > Traits; | |
| // Save current stream state and set persistent state | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| // Output Vector2 | |
| std::size_t const w( Traits::width ); | |
| stream << std::setw( w ) << v.x << ' ' << std::setw( w ) << v.y; | |
| // Restore previous stream state | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| return stream; | |
| } | |
| // Stream >> Vector2 input operator | |
| // Supports whitespace-separated values with optional commas between values as long as whitespace is also present | |
| // String or char values containing whitespace or commas or enclosed in quotes are not supported | |
| // Vector can optionally be enclosed in parentheses () or square brackets [] | |
| template< typename T > | |
| std::istream & | |
| operator >>( std::istream & stream, Vector2< T > & v ) | |
| { | |
| bool parens( false ); // Opening ( present? | |
| bool brackets( false ); // Opening [ present? | |
| { // x | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "(" ) { // Skip opening ( | |
| stream >> input_string; | |
| parens = true; | |
| } else if ( input_string[ 0 ] == '(' ) { // Skip opening ( | |
| input_string.erase( 0, 1 ); | |
| brackets = true; | |
| } else if ( input_string == "[" ) { // Skip opening [ | |
| stream >> input_string; | |
| brackets = true; | |
| } else if ( input_string[ 0 ] == '[' ) { // Skip opening [ | |
| input_string.erase( 0, 1 ); | |
| brackets = true; | |
| } | |
| std::string::size_type const input_size( input_string.size() ); | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.x; | |
| } | |
| { // y | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "," ) { // Skip , | |
| stream >> input_string; | |
| } else if ( input_string[ 0 ] == ',' ) { // Skip leading , | |
| input_string.erase( 0, 1 ); | |
| } | |
| std::string::size_type input_size( input_string.size() ); | |
| if ( parens || brackets ) { // Remove closing ) or ] | |
| if ( input_size > 0 ) { | |
| if ( parens ) { | |
| if ( input_string[ input_size - 1 ] == ')' ) { // Remove closing ) | |
| input_string.erase( input_size - 1 ); | |
| --input_size; | |
| } | |
| } else if ( brackets ) { | |
| if ( input_string[ input_size - 1 ] == ']' ) { // Remove closing ] | |
| input_string.erase( input_size - 1 ); | |
| --input_size; | |
| } | |
| } | |
| } | |
| } | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.y; | |
| } | |
| // Remove closing ) or ] if opening ( or [ present | |
| if ( parens || brackets ) { // Remove closing ) or ] | |
| while ( ( stream.peek() == ' ' ) || ( stream.peek() == '\t' ) ) { | |
| stream.ignore(); | |
| } | |
| if ( parens ) { // Remove closing ) if present | |
| if ( stream.peek() == ')' ) stream.ignore(); | |
| } else if ( brackets ) { // Remove closing ] if present | |
| if ( stream.peek() == ']' ) stream.ignore(); | |
| } | |
| } | |
| return stream; | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Vector2_hh_INCLUDED | |
| // ===== ObjexxFCL/Vector3.fwd.hh ===== | |
| #ifndef ObjexxFCL_Vector3_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Vector3_fwd_hh_INCLUDED | |
| // Vector3 Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Vector3; | |
| // Types | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Vector3_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/Vector3.hh ===== | |
| #ifndef ObjexxFCL_Vector3_hh_INCLUDED | |
| #define ObjexxFCL_Vector3_hh_INCLUDED | |
| // Vector3: Fast 3-Element Vector | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <cstdlib> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <iostream> | |
| #include <sstream> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| // Vector3: Fast 3-Element Vector | |
| // . Heap-free and loop-free for speed | |
| // . Provides direct element access via .x style lookup | |
| // . Use std::array< T, 3 > instead in array/vectorization context | |
| template< typename T > | |
| class Vector3 | |
| { | |
| private: // Friends | |
| template< typename > friend class Vector3; | |
| public: // Types | |
| typedef TypeTraits< T > Traits; | |
| typedef typename std::conditional< std::is_scalar< T >::value, T const, T const & >::type Tc; | |
| typedef typename std::conditional< std::is_scalar< T >::value, typename std::remove_const< T >::type, T const & >::type Tr; | |
| // STL Style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| typedef std::size_t size_type; | |
| typedef std::ptrdiff_t difference_type; | |
| // C++ Style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| typedef std::size_t Size; | |
| typedef std::ptrdiff_t Difference; | |
| public: // Creation | |
| // Default Constructor | |
| Vector3() | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| : | |
| x( Traits::initial_array_value() ), | |
| y( Traits::initial_array_value() ), | |
| z( Traits::initial_array_value() ) | |
| #endif | |
| {} | |
| // Copy Constructor | |
| Vector3( Vector3 const & v ) : | |
| x( v.x ), | |
| y( v.y ), | |
| z( v.z ) | |
| {} | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Vector3( Vector3< U > const & v ) : | |
| x( v.x ), | |
| y( v.y ), | |
| z( v.z ) | |
| {} | |
| // Uniform Value Constructor | |
| explicit | |
| Vector3( Tc t ) : | |
| x( t ), | |
| y( t ), | |
| z( t ) | |
| {} | |
| // Value Constructor | |
| Vector3( | |
| Tc x_, | |
| Tc y_, | |
| Tc z_ | |
| ) : | |
| x( x_ ), | |
| y( y_ ), | |
| z( z_ ) | |
| {} | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Vector3( std::initializer_list< U > const l ) : | |
| x( *l.begin() ), | |
| y( *( l.begin() + 1 ) ), | |
| z( *( l.begin() + 2 ) ) | |
| { | |
| assert( l.size() == 3 ); | |
| } | |
| // Array Constructor Template | |
| template< typename A, class = typename std::enable_if< std::is_constructible< T, typename A::value_type >::value >::type > | |
| Vector3( A const & a ) : | |
| x( a[ 0 ] ), | |
| y( a[ 1 ] ), | |
| z( a[ 2 ] ) | |
| { | |
| assert( a.size() == 3 ); | |
| } | |
| // Default Vector Named Constructor | |
| static | |
| Vector3 | |
| default_vector() | |
| { | |
| return Vector3( T() ); | |
| } | |
| // Zero Vector Named Constructor | |
| static | |
| Vector3 | |
| zero_vector() | |
| { | |
| return Vector3( T( 0 ) ); | |
| } | |
| // x Vector of Specified Length Named Constructor | |
| static | |
| Vector3 | |
| x_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector3( tar_length, T( 0 ), T( 0 ) ); | |
| } | |
| // y Vector of Specified Length Named Constructor | |
| static | |
| Vector3 | |
| y_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector3( T( 0 ), tar_length, T( 0 ) ); | |
| } | |
| // z Vector of Specified Length Named Constructor | |
| static | |
| Vector3 | |
| z_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector3( T( 0 ), T( 0 ), tar_length ); | |
| } | |
| // Uniform Vector of Specified Length Named Constructor | |
| static | |
| Vector3 | |
| uniform_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector3( tar_length / std::sqrt( T( 3 ) ) ); | |
| } | |
| // Destructor | |
| ~Vector3() | |
| {} | |
| public: // Assignment | |
| // Copy Assignment | |
| Vector3 & | |
| operator =( Vector3 const & v ) | |
| { | |
| if ( this != &v ) { | |
| x = v.x; | |
| y = v.y; | |
| z = v.z; | |
| } | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator =( Vector3< U > const & v ) | |
| { | |
| x = v.x; | |
| y = v.y; | |
| z = v.z; | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 3 ); | |
| auto i( l.begin() ); | |
| x = *i; | |
| y = *(++i); | |
| z = *(++i); | |
| return *this; | |
| } | |
| // Array Assignment Template | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector3 & | |
| operator =( A const & a ) | |
| { | |
| assert( a.size() == 3 ); | |
| x = a[ 0 ]; | |
| y = a[ 1 ]; | |
| z = a[ 2 ]; | |
| return *this; | |
| } | |
| // += Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator +=( Vector3< U > const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| z += v.z; | |
| return *this; | |
| } | |
| // -= Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator -=( Vector3< U > const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| z -= v.z; | |
| return *this; | |
| } | |
| // *= Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator *=( Vector3< U > const & v ) | |
| { | |
| x *= v.x; | |
| y *= v.y; | |
| z *= v.z; | |
| return *this; | |
| } | |
| // /= Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator /=( Vector3< U > const & v ) | |
| { | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| assert( v.z != T( 0 ) ); | |
| x /= v.x; | |
| y /= v.y; | |
| z /= v.z; | |
| return *this; | |
| } | |
| // += Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator +=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 3 ); | |
| auto i( l.begin() ); | |
| x += *i; | |
| y += *(++i); | |
| z += *(++i); | |
| return *this; | |
| } | |
| // -= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator -=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 3 ); | |
| auto i( l.begin() ); | |
| x -= *i; | |
| y -= *(++i); | |
| z -= *(++i); | |
| return *this; | |
| } | |
| // *= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator *=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 3 ); | |
| auto i( l.begin() ); | |
| x *= *i; | |
| y *= *(++i); | |
| z *= *(++i); | |
| return *this; | |
| } | |
| // /= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| operator /=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 3 ); | |
| auto i( l.begin() ); | |
| assert( *i != T( 0 ) ); | |
| assert( *(i+1) != T( 0 ) ); | |
| assert( *(i+2) != T( 0 ) ); | |
| x /= *i; | |
| y /= *(++i); | |
| z /= *(++i); | |
| return *this; | |
| } | |
| // += Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector3 & | |
| operator +=( A const & a ) | |
| { | |
| assert( a.size() == 3 ); | |
| x += a[ 0 ]; | |
| y += a[ 1 ]; | |
| z += a[ 2 ]; | |
| return *this; | |
| } | |
| // -= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector3 & | |
| operator -=( A const & a ) | |
| { | |
| assert( a.size() == 3 ); | |
| x -= a[ 0 ]; | |
| y -= a[ 1 ]; | |
| z -= a[ 2 ]; | |
| return *this; | |
| } | |
| // *= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector3 & | |
| operator *=( A const & a ) | |
| { | |
| assert( a.size() == 3 ); | |
| x *= a[ 0 ]; | |
| y *= a[ 1 ]; | |
| z *= a[ 2 ]; | |
| return *this; | |
| } | |
| // /= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector3 & | |
| operator /=( A const & a ) | |
| { | |
| assert( a.size() == 3 ); | |
| assert( a[ 0 ] != T( 0 ) ); | |
| assert( a[ 1 ] != T( 0 ) ); | |
| assert( a[ 2 ] != T( 0 ) ); | |
| x /= a[ 0 ]; | |
| y /= a[ 1 ]; | |
| z /= a[ 2 ]; | |
| return *this; | |
| } | |
| // = Value | |
| Vector3 & | |
| operator =( Tc t ) | |
| { | |
| x = y = z = t; | |
| return *this; | |
| } | |
| // += Value | |
| Vector3 & | |
| operator +=( Tc t ) | |
| { | |
| x += t; | |
| y += t; | |
| z += t; | |
| return *this; | |
| } | |
| // -= Value | |
| Vector3 & | |
| operator -=( Tc t ) | |
| { | |
| x -= t; | |
| y -= t; | |
| z -= t; | |
| return *this; | |
| } | |
| // *= Value | |
| Vector3 & | |
| operator *=( Tc t ) | |
| { | |
| x *= t; | |
| y *= t; | |
| z *= t; | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| Vector3 & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| x *= inv_u; | |
| y *= inv_u; | |
| z *= inv_u; | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void, typename = void > | |
| Vector3 & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| x /= u; | |
| y /= u; | |
| z /= u; | |
| return *this; | |
| } | |
| // Value Assignment | |
| Vector3 & | |
| assign( | |
| Tc x_, | |
| Tc y_, | |
| Tc z_ | |
| ) | |
| { | |
| x = x_; | |
| y = y_; | |
| z = z_; | |
| return *this; | |
| } | |
| public: // Assignment: Scaled | |
| // Assign Value * Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| scaled_assign( Tc t, Vector3< U > const & v ) | |
| { | |
| x = t * v.x; | |
| y = t * v.y; | |
| z = t * v.z; | |
| return *this; | |
| } | |
| // Add Value * Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| scaled_add( Tc t, Vector3< U > const & v ) | |
| { | |
| x += t * v.x; | |
| y += t * v.y; | |
| z += t * v.z; | |
| return *this; | |
| } | |
| // Subtract Value * Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| scaled_sub( Tc t, Vector3< U > const & v ) | |
| { | |
| x -= t * v.x; | |
| y -= t * v.y; | |
| z -= t * v.z; | |
| return *this; | |
| } | |
| // Multiply by Value * Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| scaled_mul( Tc t, Vector3< U > const & v ) | |
| { | |
| x *= t * v.x; | |
| y *= t * v.y; | |
| z *= t * v.z; | |
| return *this; | |
| } | |
| // Divide by Value * Vector3 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector3 & | |
| scaled_div( Tc t, Vector3< U > const & v ) | |
| { | |
| assert( t != T( 0 ) ); | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| assert( v.z != T( 0 ) ); | |
| x /= t * v.x; | |
| y /= t * v.y; | |
| z /= t * v.z; | |
| return *this; | |
| } | |
| public: // Subscript | |
| // Vector3[ i ] const: 0-Based Index | |
| Tr | |
| operator []( size_type const i ) const | |
| { | |
| assert( i <= 2 ); | |
| return ( i == 0 ? x : ( i == 1 ? y : z ) ); | |
| } | |
| // Vector3[ i ]: 0-Based Index | |
| T & | |
| operator []( size_type const i ) | |
| { | |
| assert( i <= 2 ); | |
| return ( i == 0 ? x : ( i == 1 ? y : z ) ); | |
| } | |
| // Vector3( i ) const: 1-Based Index | |
| Tr | |
| operator ()( size_type const i ) const | |
| { | |
| assert( ( 1 <= i ) && ( i <= 3 ) ); | |
| return ( i == 1 ? x : ( i == 2 ? y : z ) ); | |
| } | |
| // Vector3( i ): 1-Based Index | |
| T & | |
| operator ()( size_type const i ) | |
| { | |
| assert( ( 1 <= i ) && ( i <= 3 ) ); | |
| return ( i == 1 ? x : ( i == 2 ? y : z ) ); | |
| } | |
| public: // Properties: Predicates | |
| // Is Zero Vector? | |
| bool | |
| is_zero() const | |
| { | |
| static T const ZERO( 0 ); | |
| return ( x == ZERO ) && ( y == ZERO ) && ( z == ZERO ); | |
| } | |
| // Is Unit Vector? | |
| bool | |
| is_unit() const | |
| { | |
| return ( length_squared() == T( 1 ) ); | |
| } | |
| public: // Properties: General | |
| // Size | |
| Size | |
| size() const | |
| { | |
| return 3u; | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); | |
| } | |
| // Length Squared | |
| T | |
| length_squared() const | |
| { | |
| return ( x * x ) + ( y * y ) + ( z * z ); | |
| } | |
| // Magnitude | |
| T | |
| magnitude() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); | |
| } | |
| // Magnitude | |
| T | |
| mag() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); | |
| } | |
| // Magnitude Squared | |
| T | |
| magnitude_squared() const | |
| { | |
| return ( x * x ) + ( y * y ) + ( z * z ); | |
| } | |
| // Magnitude Squared | |
| T | |
| mag_squared() const | |
| { | |
| return ( x * x ) + ( y * y ) + ( z * z ); | |
| } | |
| // L1 Norm | |
| T | |
| norm_L1() const | |
| { | |
| return std::abs( x ) + std::abs( y ) + std::abs( z ); | |
| } | |
| // L2 Norm | |
| T | |
| norm_L2() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); | |
| } | |
| // L-infinity Norm | |
| T | |
| norm_Linf() const | |
| { | |
| return ObjexxFCL::max( std::abs( x ), std::abs( y ), std::abs( z ) ); | |
| } | |
| // Distance to a Vector3 | |
| T | |
| distance( Vector3 const & v ) const | |
| { | |
| return std::sqrt( square( x - v.x ) + square( y - v.y ) + square( z - v.z ) ); | |
| } | |
| // Distance Squared to a Vector3 | |
| T | |
| distance_squared( Vector3 const & v ) const | |
| { | |
| return square( x - v.x ) + square( y - v.y ) + square( z - v.z ); | |
| } | |
| // Dot Product with a Vector3 | |
| T | |
| dot( Vector3 const & v ) const | |
| { | |
| return ( x * v.x ) + ( y * v.y ) + ( z * v.z ); | |
| } | |
| // Dot Product with an Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| T | |
| dot( A const & a ) const | |
| { | |
| assert( a.size() == 3 ); | |
| return ( x * a[ 0 ] ) + ( y * a[ 1 ] ) + ( z * a[ 2 ] ); | |
| } | |
| // Cross Product with a Vector3 | |
| Vector3 | |
| cross( Vector3 const & v ) const | |
| { | |
| return Vector3( | |
| ( y * v.z ) - ( z * v.y ), | |
| ( z * v.x ) - ( x * v.z ), | |
| ( x * v.y ) - ( y * v.x ) | |
| ); | |
| } | |
| // Cross Product with an Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector3 | |
| cross( A const & a ) const | |
| { | |
| assert( a.size() == 3 ); | |
| return Vector3( | |
| ( y * a[ 2 ] ) - ( z * a[ 1 ] ), | |
| ( z * a[ 0 ] ) - ( x * a[ 2 ] ), | |
| ( x * a[ 1 ] ) - ( y * a[ 0 ] ) | |
| ); | |
| } | |
| // Alias for Element 1 | |
| Tr | |
| x1() const | |
| { | |
| return x; | |
| } | |
| // Alias for Element 1 | |
| T & | |
| x1() | |
| { | |
| return x; | |
| } | |
| // Alias for Element 2 | |
| Tr | |
| x2() const | |
| { | |
| return y; | |
| } | |
| // Alias for Element 2 | |
| T & | |
| x2() | |
| { | |
| return y; | |
| } | |
| // Alias for Element 3 | |
| Tr | |
| x3() const | |
| { | |
| return z; | |
| } | |
| // Alias for Element 3 | |
| T & | |
| x3() | |
| { | |
| return z; | |
| } | |
| public: // Modifiers | |
| // Zero | |
| Vector3 & | |
| zero() | |
| { | |
| x = y = z = T( 0 ); | |
| return *this; | |
| } | |
| // Negate | |
| Vector3 & | |
| negate() | |
| { | |
| x = -x; | |
| y = -y; | |
| z = -z; | |
| return *this; | |
| } | |
| // Normalize to a Length | |
| Vector3 & | |
| normalize( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| assert( cur_length != T ( 0 ) ); | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| return *this; | |
| } | |
| // Normalize to a Length: Zero Vector3 if Length is Zero | |
| Vector3 & | |
| normalize_zero( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| } else { // Set zero vector | |
| x = y = z = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: Uniform Vector3 if Length is Zero | |
| Vector3 & | |
| normalize_uniform( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| } else { // Set uniform vector | |
| operator =( uniform_vector( tar_length ) ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: x Vector3 if Length is Zero | |
| Vector3 & | |
| normalize_x( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| } else { // Set x vector | |
| x = tar_length; | |
| y = z = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: y Vector3 if Length is Zero | |
| Vector3 & | |
| normalize_y( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| } else { // Set y vector | |
| y = tar_length; | |
| x = z = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: z Vector3 if Length is Zero | |
| Vector3 & | |
| normalize_z( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| } else { // Set z vector | |
| z = tar_length; | |
| x = y = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Minimum Coordinates with a Vector3 | |
| Vector3 & | |
| min( Vector3 const & v ) | |
| { | |
| x = ( x <= v.x ? x : v.x ); | |
| y = ( y <= v.y ? y : v.y ); | |
| z = ( z <= v.z ? z : v.z ); | |
| return *this; | |
| } | |
| // Maximum Coordinates with a Vector3 | |
| Vector3 & | |
| max( Vector3 const & v ) | |
| { | |
| x = ( x >= v.x ? x : v.x ); | |
| y = ( y >= v.y ? y : v.y ); | |
| z = ( z >= v.z ? z : v.z ); | |
| return *this; | |
| } | |
| // Add a Vector3 | |
| Vector3 & | |
| add( Vector3 const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| z += v.z; | |
| return *this; | |
| } | |
| // Sum a Vector3 | |
| Vector3 & | |
| sum( Vector3 const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| z += v.z; | |
| return *this; | |
| } | |
| // Subtract a Vector3 | |
| Vector3 & | |
| sub( Vector3 const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| z -= v.z; | |
| return *this; | |
| } | |
| // Subtract a Vector3 | |
| Vector3 & | |
| subtract( Vector3 const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| z -= v.z; | |
| return *this; | |
| } | |
| // Project Normal to a Vector3 | |
| Vector3 & | |
| project_normal( Vector3 const & v ) | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| x -= c * v.x; | |
| y -= c * v.y; | |
| z -= c * v.z; | |
| return *this; | |
| } | |
| // Project onto a Vector3 | |
| Vector3 & | |
| project_parallel( Vector3 const & v ) | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| x = c * v.x; | |
| y = c * v.y; | |
| z = c * v.z; | |
| return *this; | |
| } | |
| public: // Generators | |
| // -Vector3 (Negated) | |
| Vector3 | |
| operator -() const | |
| { | |
| return Vector3( -x, -y, -z ); | |
| } | |
| // Negated | |
| Vector3 | |
| negated() const | |
| { | |
| return Vector3( -x, -y, -z ); | |
| } | |
| // Normalized to a Length | |
| Vector3 | |
| normalized( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| assert( cur_length != T ( 0 ) ); | |
| T const dilation( tar_length / cur_length ); | |
| return Vector3( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation | |
| ); | |
| } | |
| // Normalized to a Length: Zero Vector3 if Length is Zero | |
| Vector3 | |
| normalized_zero( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector3( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation | |
| ); | |
| } else { // Return zero vector | |
| return Vector3( T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: Uniform Vector3 if Length is Zero | |
| Vector3 | |
| normalized_uniform( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector3( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation | |
| ); | |
| } else { // Return uniform vector | |
| return uniform_vector( tar_length ); | |
| } | |
| } | |
| // Normalized to a Length: x Vector3 if Length is Zero | |
| Vector3 | |
| normalized_x( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector3( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation | |
| ); | |
| } else { // Return x vector | |
| return Vector3( tar_length, T( 0 ), T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: y Vector3 if Length is Zero | |
| Vector3 | |
| normalized_y( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector3( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation | |
| ); | |
| } else { // Return y vector | |
| return Vector3( T( 0 ), tar_length, T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: z Vector3 if Length is Zero | |
| Vector3 | |
| normalized_z( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector3( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation | |
| ); | |
| } else { // Return z vector | |
| return Vector3( tar_length, T( 0 ), T( 0 ), tar_length ); | |
| } | |
| } | |
| // Projected Normal to a Vector3 | |
| Vector3 | |
| projected_normal( Vector3 const & v ) const | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| return Vector3( x - ( c * v.x ), y - ( c * v.y ), z - ( c * v.z ) ); | |
| } | |
| // Projected onto a Vector3 | |
| Vector3 | |
| projected_parallel( Vector3 const & v ) const | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| return Vector3( c * v.x, c * v.y, c * v.z ); | |
| } | |
| public: // Static Methods | |
| // Square of a value | |
| static | |
| T | |
| square( Tc t ) | |
| { | |
| return t * t; | |
| } | |
| // Value Clipped to [-1,1] | |
| static | |
| T | |
| sin_cos_range( Tc t ) | |
| { | |
| return std::min( std::max( t, T( -1 ) ), T( 1 ) ); | |
| } | |
| // Add 2*Pi to a Negative Value | |
| static | |
| T | |
| bump_up_angle( Tc t ) | |
| { | |
| static T const Two_Pi( T( 2 ) * std::acos( -1.0 ) ); | |
| return ( t >= T( 0 ) ? t : Two_Pi + t ); | |
| } | |
| public: // Data | |
| T x, y, z; // Elements | |
| }; // Vector3 | |
| // Length | |
| template< typename T > | |
| inline | |
| T | |
| length( Vector3< T > const & v ) | |
| { | |
| return v.length(); | |
| } | |
| // Length Squared | |
| template< typename T > | |
| inline | |
| T | |
| length_squared( Vector3< T > const & v ) | |
| { | |
| return v.length_squared(); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( Vector3< T > const & v ) | |
| { | |
| return v.magnitude(); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| mag( Vector3< T > const & v ) | |
| { | |
| return v.mag(); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( Vector3< T > const & v ) | |
| { | |
| return v.magnitude_squared(); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| mag_squared( Vector3< T > const & v ) | |
| { | |
| return v.mag_squared(); | |
| } | |
| // Vector3 == Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ); | |
| } | |
| // Vector3 != Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ); | |
| } | |
| // Vector3 < Vector3: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( | |
| ( a.x < b.x ? true : | |
| ( b.x < a.x ? false : // a.x == b.x | |
| ( a.y < b.y ? true : | |
| ( b.y < a.y ? false : // a.y == b.y | |
| ( a.z < b.z ) ) ) ) ) | |
| ); | |
| } | |
| // Vector3 <= Vector3: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( | |
| ( a.x < b.x ? true : | |
| ( b.x < a.x ? false : // a.x == b.x | |
| ( a.y < b.y ? true : | |
| ( b.y < a.y ? false : // a.y == b.y | |
| ( a.z <= b.z ) ) ) ) ) | |
| ); | |
| } | |
| // Vector3 >= Vector3: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( | |
| ( a.x > b.x ? true : | |
| ( b.x > a.x ? false : // a.x == b.x | |
| ( a.y > b.y ? true : | |
| ( b.y > a.y ? false : // a.y == b.y | |
| ( a.z >= b.z ) ) ) ) ) | |
| ); | |
| } | |
| // Vector3 > Vector3: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( | |
| ( a.x > b.x ? true : | |
| ( b.x > a.x ? false : // a.x == b.x | |
| ( a.y > b.y ? true : | |
| ( b.y > a.y ? false : // a.y == b.y | |
| ( a.z > b.z ) ) ) ) ) | |
| ); | |
| } | |
| // Vector3 < Vector3: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| lt( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x < b.x ) && ( a.y < b.y ) && ( a.z < b.z ); | |
| } | |
| // Vector3 <= Vector3: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| le( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x <= b.x ) && ( a.y <= b.y ) && ( a.z <= b.z ); | |
| } | |
| // Vector3 >= Vector3: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| ge( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x >= b.x ) && ( a.y >= b.y ) && ( a.z >= b.z ); | |
| } | |
| // Vector3 > Vector3: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| gt( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x > b.x ) && ( a.y > b.y ) && ( a.z > b.z ); | |
| } | |
| // Vector3 == Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return ( v.x == t ) && ( v.y == t ) && ( v.z == t ); | |
| } | |
| // Vector3 != Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return ( v.x != t ) || ( v.y != t ) || ( v.z != t ); | |
| } | |
| // Vector3 < Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return ( v.x < t ) && ( v.y < t ) && ( v.z < t ); | |
| } | |
| // Vector3 <= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return ( v.x <= t ) && ( v.y <= t ) && ( v.z <= t ); | |
| } | |
| // Vector3 >= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return ( v.x >= t ) && ( v.y >= t ) && ( v.z >= t ); | |
| } | |
| // Vector3 > Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return ( v.x > t ) && ( v.y > t ) && ( v.z > t ); | |
| } | |
| // Value == Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return ( t == v.x ) && ( t == v.y ) && ( t == v.z ); | |
| } | |
| // Value != Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return ( t != v.x ) || ( t != v.y ) || ( t != v.z ); | |
| } | |
| // Value < Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return ( t < v.x ) && ( t < v.y ) && ( t < v.z ); | |
| } | |
| // Value <= Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return ( t <= v.x ) && ( t <= v.y ) && ( t <= v.z ); | |
| } | |
| // Value >= Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return ( t >= v.x ) && ( t >= v.y ) && ( t >= v.z ); | |
| } | |
| // Value > Vector3 | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return ( t > v.x ) && ( t > v.y ) && ( t > v.z ); | |
| } | |
| // Equal Length? | |
| template< typename T > | |
| inline | |
| bool | |
| equal_length( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.length_squared() == b.length_squared() ); | |
| } | |
| // Not Equal Length? | |
| template< typename T > | |
| inline | |
| bool | |
| not_equal_length( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.length_squared() != b.length_squared() ); | |
| } | |
| // Vector3 + Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator +( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( a.x + b.x, a.y + b.y, a.z + b.z ); | |
| } | |
| // Vector3 + Value | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator +( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return Vector3< T >( v.x + t, v.y + t, v.z + t ); | |
| } | |
| // Value + Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator +( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return Vector3< T >( t + v.x, t + v.y, t + v.z ); | |
| } | |
| // Vector3 - Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator -( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( a.x - b.x, a.y - b.y, a.z - b.z ); | |
| } | |
| // Vector3 - Value | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator -( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return Vector3< T >( v.x - t, v.y - t, v.z - t ); | |
| } | |
| // Value - Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator -( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return Vector3< T >( t - v.x, t - v.y, t - v.z ); | |
| } | |
| // Vector3 * Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator *( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( a.x * b.x, a.y * b.y, a.z * b.z ); | |
| } | |
| // Vector3 * Value | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator *( Vector3< T > const & v, typename Vector3< T >::Tc t ) | |
| { | |
| return Vector3< T >( v.x * t, v.y * t, v.z * t ); | |
| } | |
| // Value * Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator *( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| return Vector3< T >( t * v.x, t * v.y, t * v.z ); | |
| } | |
| // Vector3 / Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator /( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( b.x != T( 0 ) ); | |
| assert( b.y != T( 0 ) ); | |
| assert( b.z != T( 0 ) ); | |
| return Vector3< T >( a.x / b.x, a.y / b.y, a.z / b.z ); | |
| } | |
| // Vector3 / Value | |
| template< typename T, typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| inline | |
| Vector3< T > | |
| operator /( Vector3< T > const & v, U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U ( 1 ) / u ); | |
| return Vector3< T >( v.x * inv_u, v.y * inv_u, v.z * inv_u ); | |
| } | |
| // Vector3 / Value | |
| template< typename T, typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| inline | |
| Vector3< T > | |
| operator /( Vector3< T > const & v, U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| return Vector3< T >( v.x / u, v.y / u, v.z / u ); | |
| } | |
| // Value / Vector3 | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| operator /( typename Vector3< T >::Tc t, Vector3< T > const & v ) | |
| { | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| assert( v.z != T( 0 ) ); | |
| return Vector3< T >( t / v.x, t / v.y, t / v.z ); | |
| } | |
| // Minimum of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| min( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( | |
| ( a.x <= b.x ? a.x : b.x ), | |
| ( a.y <= b.y ? a.y : b.y ), | |
| ( a.z <= b.z ? a.z : b.z ) | |
| ); | |
| } | |
| // Minimum of Three Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| min( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| return Vector3< T >( | |
| ObjexxFCL::min( a.x, b.x, c.x ), | |
| ObjexxFCL::min( a.y, b.y, c.y ), | |
| ObjexxFCL::min( a.z, b.z, c.z ) | |
| ); | |
| } | |
| // Minimum of Four Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| min( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c, Vector3< T > const & d ) | |
| { | |
| return Vector3< T >( | |
| ObjexxFCL::min( a.x, b.x, c.x, d.x ), | |
| ObjexxFCL::min( a.y, b.y, c.y, d.y ), | |
| ObjexxFCL::min( a.z, b.z, c.z, d.z ) | |
| ); | |
| } | |
| // Maximum of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| max( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( | |
| ( a.x >= b.x ? a.x : b.x ), | |
| ( a.y >= b.y ? a.y : b.y ), | |
| ( a.z >= b.z ? a.z : b.z ) | |
| ); | |
| } | |
| // Maximum of Three Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| max( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| return Vector3< T >( | |
| ObjexxFCL::max( a.x, b.x, c.x ), | |
| ObjexxFCL::max( a.y, b.y, c.y ), | |
| ObjexxFCL::max( a.z, b.z, c.z ) | |
| ); | |
| } | |
| // Maximum of Four Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| max( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c, Vector3< T > const & d ) | |
| { | |
| return Vector3< T >( | |
| ObjexxFCL::max( a.x, b.x, c.x, d.x ), | |
| ObjexxFCL::max( a.y, b.y, c.y, d.y ), | |
| ObjexxFCL::max( a.z, b.z, c.z, d.z ) | |
| ); | |
| } | |
| // Sum of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| sum( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( a.x + b.x, a.y + b.y, a.z + b.z ); | |
| } | |
| // Sum of Three Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| sum( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| return Vector3< T >( a.x + b.x + c.x, a.y + b.y + c.y, a.z + b.z + c.z ); | |
| } | |
| // Sum of Four Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| sum( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c, Vector3< T > const & d ) | |
| { | |
| return Vector3< T >( a.x + b.x + c.x + d.x, a.y + b.y + c.y + d.y, a.z + b.z + c.z + d.z ); | |
| } | |
| // Subtract of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| sub( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( a.x - b.x, a.y - b.y, a.z - b.z ); | |
| } | |
| // Subtract of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| subtract( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( a.x - b.x, a.y - b.y, a.z - b.z ); | |
| } | |
| // Midpoint of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| mid( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( | |
| T( 0.5 * ( a.x + b.x ) ), | |
| T( 0.5 * ( a.y + b.y ) ), | |
| T( 0.5 * ( a.z + b.z ) ) | |
| ); | |
| } | |
| // Center of Two Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| cen( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( | |
| T( 0.5 * ( a.x + b.x ) ), | |
| T( 0.5 * ( a.y + b.y ) ), | |
| T( 0.5 * ( a.z + b.z ) ) | |
| ); | |
| } | |
| // Center of Three Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| cen( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| static long double const third( 1.0 / 3.0 ); | |
| return Vector3< T >( | |
| T( third * ( a.x + b.x + c.x ) ), | |
| T( third * ( a.y + b.y + c.y ) ), | |
| T( third * ( a.z + b.z + c.z ) ) | |
| ); | |
| } | |
| // Center of Four Vector3s | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| cen( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c, Vector3< T > const & d ) | |
| { | |
| return Vector3< T >( | |
| T( 0.25 * ( a.x + b.x + c.x + d.x ) ), | |
| T( 0.25 * ( a.y + b.y + c.y + d.y ) ), | |
| T( 0.25 * ( a.z + b.z + c.z + d.z ) ) | |
| ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return std::sqrt( Vector3< T >::square( a.x - b.x ) + Vector3< T >::square( a.y - b.y ) + Vector3< T >::square( a.z - b.z ) ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >::square( a.x - b.x ) + Vector3< T >::square( a.y - b.y ) + Vector3< T >::square( a.z - b.z ); | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return ( a.x * b.x ) + ( a.y * b.y ) + ( a.z * b.z ); | |
| } | |
| // Cross Product | |
| template< typename T > | |
| inline | |
| Vector3< T > | |
| cross( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| return Vector3< T >( | |
| ( a.y * b.z ) - ( a.z * b.y ), | |
| ( a.z * b.x ) - ( a.x * b.z ), | |
| ( a.x * b.y ) - ( a.y * b.x ) | |
| ); | |
| } | |
| // Angle Between Two Vector3s (in Radians on [0,pi]) | |
| template< typename T > | |
| inline | |
| T | |
| angle( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| T const axb( a.cross( b ).magnitude() ); | |
| T const adb( a.dot( b ) ); | |
| return ( ( axb != T( 0 ) ) || ( adb != T( 0 ) ) ? Vector3< T >::bump_up_angle( std::atan2( axb, adb ) ) : T( 0 ) ); // More accurate than dot-based for angles near 0 and Pi | |
| } | |
| // Angle abc Formed by Three Vector3s (in Radians on [0,pi]) | |
| template< typename T > | |
| inline | |
| T | |
| angle( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| return angle( a - b, c - b ); | |
| } | |
| // Cosine of Angle Between Two Vector3s | |
| template< typename T > | |
| inline | |
| T | |
| cos( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? Vector3< T >::sin_cos_range( a.dot( b ) / mag ) : T( 1 ) ); | |
| } | |
| // Cosine of Angle abc Formed by Three Vector3s | |
| template< typename T > | |
| inline | |
| T | |
| cos( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| return cos( a - b, c - b ); | |
| } | |
| // Sine of Angle Between Two Vector3s | |
| template< typename T > | |
| inline | |
| T | |
| sin( Vector3< T > const & a, Vector3< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? std::abs( Vector3< T >::sin_cos_range( a.cross( b ).magnitude() / mag ) ) : T( 0 ) ); | |
| } | |
| // Sine of Angle abc Formed by Three Vector3s | |
| template< typename T > | |
| inline | |
| T | |
| sin( Vector3< T > const & a, Vector3< T > const & b, Vector3< T > const & c ) | |
| { | |
| return sin( a - b, c - b ); | |
| } | |
| // Stream << Vector3 output operator | |
| template< typename T > | |
| std::ostream & | |
| operator <<( std::ostream & stream, Vector3< T > const & v ) | |
| { | |
| // Types | |
| typedef TypeTraits< T > Traits; | |
| // Save current stream state and set persistent state | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| // Output Vector3 | |
| std::size_t const w( Traits::width ); | |
| stream << std::setw( w ) << v.x << ' ' << std::setw( w ) << v.y << ' ' << std::setw( w ) << v.z; | |
| // Restore previous stream state | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| return stream; | |
| } | |
| // Stream >> Vector3 input operator | |
| // Supports whitespace-separated values with optional commas between values as long as whitespace is also present | |
| // String or char values containing whitespace or commas or enclosed in quotes are not supported | |
| // Vector can optionally be enclosed in parentheses () or square brackets [] | |
| template< typename T > | |
| std::istream & | |
| operator >>( std::istream & stream, Vector3< T > & v ) | |
| { | |
| bool parens( false ); // Opening ( present? | |
| bool brackets( false ); // Opening [ present? | |
| { // x | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "(" ) { // Skip opening ( | |
| stream >> input_string; | |
| parens = true; | |
| } else if ( input_string[ 0 ] == '(' ) { // Skip opening ( | |
| input_string.erase( 0, 1 ); | |
| brackets = true; | |
| } else if ( input_string == "[" ) { // Skip opening [ | |
| stream >> input_string; | |
| brackets = true; | |
| } else if ( input_string[ 0 ] == '[' ) { // Skip opening [ | |
| input_string.erase( 0, 1 ); | |
| brackets = true; | |
| } | |
| std::string::size_type const input_size( input_string.size() ); | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.x; | |
| } | |
| { // y | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "," ) { // Skip , | |
| stream >> input_string; | |
| } else if ( input_string[ 0 ] == ',' ) { // Skip leading , | |
| input_string.erase( 0, 1 ); | |
| } | |
| std::string::size_type const input_size( input_string.size() ); | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.y; | |
| } | |
| { // z | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "," ) { // Skip , | |
| stream >> input_string; | |
| } else if ( input_string[ 0 ] == ',' ) { // Skip leading , | |
| input_string.erase( 0, 1 ); | |
| } | |
| std::string::size_type input_size( input_string.size() ); | |
| if ( parens || brackets ) { // Remove closing ) or ] | |
| if ( input_size > 0 ) { | |
| if ( parens ) { | |
| if ( input_string[ input_size - 1 ] == ')' ) { // Remove closing ) | |
| input_string.erase( input_size - 1 ); | |
| --input_size; | |
| } | |
| } else if ( brackets ) { | |
| if ( input_string[ input_size - 1 ] == ']' ) { // Remove closing ] | |
| input_string.erase( input_size - 1 ); | |
| --input_size; | |
| } | |
| } | |
| } | |
| } | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.z; | |
| } | |
| // Remove closing ) or ] if opening ( or [ present | |
| if ( parens || brackets ) { // Remove closing ) or ] | |
| while ( ( stream.peek() == ' ' ) || ( stream.peek() == '\t' ) ) { | |
| stream.ignore(); | |
| } | |
| if ( parens ) { // Remove closing ) if present | |
| if ( stream.peek() == ')' ) stream.ignore(); | |
| } else if ( brackets ) { // Remove closing ] if present | |
| if ( stream.peek() == ']' ) stream.ignore(); | |
| } | |
| } | |
| return stream; | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Vector3_hh_INCLUDED | |
| // ===== ObjexxFCL/Vector4.fwd.hh ===== | |
| #ifndef ObjexxFCL_Vector4_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Vector4_fwd_hh_INCLUDED | |
| // Vector3 Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Vector4; | |
| // Types | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Vector3_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/Vector4.hh ===== | |
| #ifndef ObjexxFCL_Vector4_hh_INCLUDED | |
| #define ObjexxFCL_Vector4_hh_INCLUDED | |
| // Vector4: Fast 4-Element Vector | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <cstdlib> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <iostream> | |
| #include <sstream> | |
| #include <type_traits> | |
| namespace ObjexxFCL { | |
| // Vector4: Fast 4-Element Vector | |
| // . Heap-free and loop-free for speed | |
| // . Provides direct element access via .x style lookup | |
| // . Use std::array< T, 4 > instead in array/vectorization context | |
| template< typename T > | |
| class Vector4 | |
| { | |
| private: // Friends | |
| template< typename > friend class Vector4; | |
| public: // Types | |
| typedef TypeTraits< T > Traits; | |
| typedef typename std::conditional< std::is_scalar< T >::value, T const, T const & >::type Tc; | |
| typedef typename std::conditional< std::is_scalar< T >::value, typename std::remove_const< T >::type, T const & >::type Tr; | |
| // STL Style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| typedef std::size_t size_type; | |
| typedef std::ptrdiff_t difference_type; | |
| // C++ Style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| typedef std::size_t Size; | |
| typedef std::ptrdiff_t Difference; | |
| public: // Creation | |
| // Default Constructor | |
| Vector4() | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| : | |
| x( Traits::initial_array_value() ), | |
| y( Traits::initial_array_value() ), | |
| z( Traits::initial_array_value() ), | |
| w( Traits::initial_array_value() ) | |
| #endif | |
| {} | |
| // Copy Constructor | |
| Vector4( Vector4 const & v ) : | |
| x( v.x ), | |
| y( v.y ), | |
| z( v.z ), | |
| w( v.w ) | |
| {} | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Vector4( Vector4< U > const & v ) : | |
| x( v.x ), | |
| y( v.y ), | |
| z( v.z ), | |
| w( v.w ) | |
| {} | |
| // Uniform Value Constructor | |
| explicit | |
| Vector4( Tc t ) : | |
| x( t ), | |
| y( t ), | |
| z( t ), | |
| w( t ) | |
| {} | |
| // Value Constructor | |
| Vector4( | |
| Tc x_, | |
| Tc y_, | |
| Tc z_, | |
| Tc w_ | |
| ) : | |
| x( x_ ), | |
| y( y_ ), | |
| z( z_ ), | |
| w( w_ ) | |
| {} | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Vector4( std::initializer_list< U > const l ) : | |
| x( *l.begin() ), | |
| y( *( l.begin() + 1 ) ), | |
| z( *( l.begin() + 2 ) ), | |
| w( *( l.begin() + 3 ) ) | |
| { | |
| assert( l.size() == 4 ); | |
| } | |
| // Array Constructor Template | |
| template< typename A, class = typename std::enable_if< std::is_constructible< T, typename A::value_type >::value >::type > | |
| Vector4( A const & a ) : | |
| x( a[ 0 ] ), | |
| y( a[ 1 ] ), | |
| z( a[ 2 ] ), | |
| w( a[ 3 ] ) | |
| { | |
| assert( a.size() == 4 ); | |
| } | |
| // Default Vector Named Constructor | |
| static | |
| Vector4 | |
| default_vector() | |
| { | |
| return Vector4( T() ); | |
| } | |
| // Zero Vector Named Constructor | |
| static | |
| Vector4 | |
| zero_vector() | |
| { | |
| return Vector4( T( 0 ) ); | |
| } | |
| // x Vector of Specified Length Named Constructor | |
| static | |
| Vector4 | |
| x_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector4( tar_length, T( 0 ), T( 0 ), T( 0 ) ); | |
| } | |
| // y Vector of Specified Length Named Constructor | |
| static | |
| Vector4 | |
| y_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector4( T( 0 ), tar_length, T( 0 ), T( 0 ) ); | |
| } | |
| // z Vector of Specified Length Named Constructor | |
| static | |
| Vector4 | |
| z_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector4( T( 0 ), T( 0 ), tar_length, T( 0 ) ); | |
| } | |
| // W Vector of Specified Length Named Constructor | |
| static | |
| Vector4 | |
| W_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector4( T( 0 ), T( 0 ), T( 0 ), tar_length, T( 0 ) ); | |
| } | |
| // Uniform Vector of Specified Length Named Constructor | |
| static | |
| Vector4 | |
| uniform_vector( Tc tar_length = T( 1 ) ) | |
| { | |
| return Vector4( tar_length / T( 2 ) ); | |
| } | |
| // Destructor | |
| ~Vector4() | |
| {} | |
| public: // Assignment | |
| // Copy Assignment | |
| Vector4 & | |
| operator =( Vector4 const & v ) | |
| { | |
| if ( this != &v ) { | |
| x = v.x; | |
| y = v.y; | |
| z = v.z; | |
| w = v.w; | |
| } | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator =( Vector4< U > const & v ) | |
| { | |
| x = v.x; | |
| y = v.y; | |
| z = v.z; | |
| w = v.w; | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 4 ); | |
| auto i( l.begin() ); | |
| x = *i; | |
| y = *(++i); | |
| z = *(++i); | |
| w = *(++i); | |
| return *this; | |
| } | |
| // Array Assignment Template | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector4 & | |
| operator =( A const & a ) | |
| { | |
| assert( a.size() == 4 ); | |
| x = a[ 0 ]; | |
| y = a[ 1 ]; | |
| z = a[ 2 ]; | |
| w = a[ 3 ]; | |
| return *this; | |
| } | |
| // += Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator +=( Vector4< U > const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| z += v.z; | |
| w += v.w; | |
| return *this; | |
| } | |
| // -= Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator -=( Vector4< U > const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| z -= v.z; | |
| w -= v.w; | |
| return *this; | |
| } | |
| // *= Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator *=( Vector4< U > const & v ) | |
| { | |
| x *= v.x; | |
| y *= v.y; | |
| z *= v.z; | |
| w *= v.w; | |
| return *this; | |
| } | |
| // /= Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator /=( Vector4< U > const & v ) | |
| { | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| assert( v.z != T( 0 ) ); | |
| assert( v.w != T( 0 ) ); | |
| x /= v.x; | |
| y /= v.y; | |
| z /= v.z; | |
| w /= v.w; | |
| return *this; | |
| } | |
| // += Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator +=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 4 ); | |
| auto i( l.begin() ); | |
| x += *i; | |
| y += *(++i); | |
| z += *(++i); | |
| w += *(++i); | |
| return *this; | |
| } | |
| // -= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator -=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 4 ); | |
| auto i( l.begin() ); | |
| x -= *i; | |
| y -= *(++i); | |
| z -= *(++i); | |
| w -= *(++i); | |
| return *this; | |
| } | |
| // *= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator *=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 4 ); | |
| auto i( l.begin() ); | |
| x *= *i; | |
| y *= *(++i); | |
| z *= *(++i); | |
| w *= *(++i); | |
| return *this; | |
| } | |
| // /= Initializer List | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| operator /=( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == 4 ); | |
| auto i( l.begin() ); | |
| assert( *i != T( 0 ) ); | |
| assert( *(i+1) != T( 0 ) ); | |
| assert( *(i+2) != T( 0 ) ); | |
| assert( *(i+3) != T( 0 ) ); | |
| x /= *i; | |
| y /= *(++i); | |
| z /= *(++i); | |
| w /= *(++i); | |
| return *this; | |
| } | |
| // += Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector4 & | |
| operator +=( A const & a ) | |
| { | |
| assert( a.size() == 4 ); | |
| x += a[ 0 ]; | |
| y += a[ 1 ]; | |
| z += a[ 2 ]; | |
| w += a[ 3 ]; | |
| return *this; | |
| } | |
| // -= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector4 & | |
| operator -=( A const & a ) | |
| { | |
| assert( a.size() == 4 ); | |
| x -= a[ 0 ]; | |
| y -= a[ 1 ]; | |
| z -= a[ 2 ]; | |
| w -= a[ 3 ]; | |
| return *this; | |
| } | |
| // *= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector4 & | |
| operator *=( A const & a ) | |
| { | |
| assert( a.size() == 4 ); | |
| x *= a[ 0 ]; | |
| y *= a[ 1 ]; | |
| z *= a[ 2 ]; | |
| w *= a[ 3 ]; | |
| return *this; | |
| } | |
| // /= Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| Vector4 & | |
| operator /=( A const & a ) | |
| { | |
| assert( a.size() == 4 ); | |
| assert( a[ 0 ] != T( 0 ) ); | |
| assert( a[ 1 ] != T( 0 ) ); | |
| assert( a[ 2 ] != T( 0 ) ); | |
| assert( a[ 3 ] != T( 0 ) ); | |
| x /= a[ 0 ]; | |
| y /= a[ 1 ]; | |
| z /= a[ 2 ]; | |
| w /= a[ 3 ]; | |
| return *this; | |
| } | |
| // = Value | |
| Vector4 & | |
| operator =( Tc t ) | |
| { | |
| x = y = z = w = t; | |
| return *this; | |
| } | |
| // += Value | |
| Vector4 & | |
| operator +=( Tc t ) | |
| { | |
| x += t; | |
| y += t; | |
| z += t; | |
| w += t; | |
| return *this; | |
| } | |
| // -= Value | |
| Vector4 & | |
| operator -=( Tc t ) | |
| { | |
| x -= t; | |
| y -= t; | |
| z -= t; | |
| w -= t; | |
| return *this; | |
| } | |
| // *= Value | |
| Vector4 & | |
| operator *=( Tc t ) | |
| { | |
| x *= t; | |
| y *= t; | |
| z *= t; | |
| w *= t; | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| Vector4 & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| x *= inv_u; | |
| y *= inv_u; | |
| z *= inv_u; | |
| w *= inv_u; | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void, typename = void > | |
| Vector4 & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| x /= u; | |
| y /= u; | |
| z /= u; | |
| w /= u; | |
| return *this; | |
| } | |
| // Value Assignment | |
| Vector4 & | |
| assign( | |
| Tc x_, | |
| Tc y_, | |
| Tc z_, | |
| Tc w_ | |
| ) | |
| { | |
| x = x_; | |
| y = y_; | |
| z = z_; | |
| w = w_; | |
| return *this; | |
| } | |
| public: // Assignment: Scaled | |
| // Assign Value * Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| scaled_assign( Tc t, Vector4< U > const & v ) | |
| { | |
| x = t * v.x; | |
| y = t * v.y; | |
| z = t * v.z; | |
| w = t * v.w; | |
| return *this; | |
| } | |
| // Add Value * Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| scaled_add( Tc t, Vector4< U > const & v ) | |
| { | |
| x += t * v.x; | |
| y += t * v.y; | |
| z += t * v.z; | |
| w += t * v.w; | |
| return *this; | |
| } | |
| // Subtract Value * Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| scaled_sub( Tc t, Vector4< U > const & v ) | |
| { | |
| x -= t * v.x; | |
| y -= t * v.y; | |
| z -= t * v.z; | |
| w -= t * v.w; | |
| return *this; | |
| } | |
| // Multiply by Value * Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| scaled_mul( Tc t, Vector4< U > const & v ) | |
| { | |
| x *= t * v.x; | |
| y *= t * v.y; | |
| z *= t * v.z; | |
| w *= t * v.w; | |
| return *this; | |
| } | |
| // Divide by Value * Vector4 | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Vector4 & | |
| scaled_div( Tc t, Vector4< U > const & v ) | |
| { | |
| assert( t != T( 0 ) ); | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| assert( v.z != T( 0 ) ); | |
| assert( v.w != T( 0 ) ); | |
| x /= t * v.x; | |
| y /= t * v.y; | |
| z /= t * v.z; | |
| w /= t * v.w; | |
| return *this; | |
| } | |
| public: // Subscript | |
| // Vector4[ i ] const: 0-Based Index | |
| Tr | |
| operator []( size_type const i ) const | |
| { | |
| assert( i <= 3 ); | |
| return ( i < 2 ? ( i == 0 ? x : y ) : ( i == 2 ? z : w ) ); | |
| } | |
| // Vector4[ i ]: 0-Based Index | |
| T & | |
| operator []( size_type const i ) | |
| { | |
| assert( i <= 3 ); | |
| return ( i < 2 ? ( i == 0 ? x : y ) : ( i == 2 ? z : w ) ); | |
| } | |
| // Vector4( i ) const: 1-Based Index | |
| Tr | |
| operator ()( size_type const i ) const | |
| { | |
| assert( ( 1 <= i ) && ( i <= 4 ) ); | |
| return ( i <= 2 ? ( i == 1 ? x : y ) : ( i == 3 ? z : w ) ); | |
| } | |
| // Vector4( i ): 1-Based Index | |
| T & | |
| operator ()( size_type const i ) | |
| { | |
| assert( ( 1 <= i ) && ( i <= 4 ) ); | |
| return ( i <= 2 ? ( i == 1 ? x : y ) : ( i == 3 ? z : w ) ); | |
| } | |
| public: // Properties: Predicates | |
| // Is Zero Vector? | |
| bool | |
| is_zero() const | |
| { | |
| static T const ZERO( 0 ); | |
| return ( x == ZERO ) && ( y == ZERO ) && ( z == ZERO ) && ( w == ZERO ); | |
| } | |
| // Is Unit Vector? | |
| bool | |
| is_unit() const | |
| { | |
| return ( length_squared() == T( 1 ) ); | |
| } | |
| public: // Properties: General | |
| // Size | |
| Size | |
| size() const | |
| { | |
| return 4u; | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ) ); | |
| } | |
| // Length Squared | |
| T | |
| length_squared() const | |
| { | |
| return ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ); | |
| } | |
| // Magnitude | |
| T | |
| magnitude() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ) ); | |
| } | |
| // Magnitude | |
| T | |
| mag() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ) ); | |
| } | |
| // Magnitude Squared | |
| T | |
| magnitude_squared() const | |
| { | |
| return ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ); | |
| } | |
| // Magnitude Squared | |
| T | |
| mag_squared() const | |
| { | |
| return ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ); | |
| } | |
| // L1 Norm | |
| T | |
| norm_L1() const | |
| { | |
| return std::abs( x ) + std::abs( y ) + std::abs( z ) + std::abs( w ); | |
| } | |
| // L2 Norm | |
| T | |
| norm_L2() const | |
| { | |
| return std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ) ); | |
| } | |
| // L-infinity Norm | |
| T | |
| norm_Linf() const | |
| { | |
| return ObjexxFCL::max( std::abs( x ), std::abs( y ), std::abs( z ), std::abs( w ) ); | |
| } | |
| // Distance to a Vector4 | |
| T | |
| distance( Vector4 const & v ) const | |
| { | |
| return std::sqrt( square( x - v.x ) + square( y - v.y ) + square( z - v.z ) + square( w - v.w ) ); | |
| } | |
| // Distance Squared to a Vector4 | |
| T | |
| distance_squared( Vector4 const & v ) const | |
| { | |
| return square( x - v.x ) + square( y - v.y ) + square( z - v.z ) + square( w - v.w ); | |
| } | |
| // Dot Product with a Vector4 | |
| T | |
| dot( Vector4 const & v ) const | |
| { | |
| return ( x * v.x ) + ( y * v.y ) + ( z * v.z ) + ( w * v.w ); | |
| } | |
| // Dot Product with an Array | |
| template< typename A, class = typename std::enable_if< std::is_assignable< T&, typename A::value_type >::value >::type > | |
| T | |
| dot( A const & a ) const | |
| { | |
| assert( a.size() == 4 ); | |
| return ( x * a[ 0 ] ) + ( y * a[ 1 ] ) + ( z * a[ 2 ] ) + ( w * a[ 3 ] ); | |
| } | |
| // Alias for Element 1 | |
| Tr | |
| x1() const | |
| { | |
| return x; | |
| } | |
| // Alias for Element 1 | |
| T & | |
| x1() | |
| { | |
| return x; | |
| } | |
| // Alias for Element 2 | |
| Tr | |
| x2() const | |
| { | |
| return y; | |
| } | |
| // Alias for Element 2 | |
| T & | |
| x2() | |
| { | |
| return y; | |
| } | |
| // Alias for Element 3 | |
| Tr | |
| x3() const | |
| { | |
| return z; | |
| } | |
| // Alias for Element 3 | |
| T & | |
| x3() | |
| { | |
| return z; | |
| } | |
| // Alias for Element 4 | |
| Tr | |
| x4() const | |
| { | |
| return w; | |
| } | |
| // Alias for Element 4 | |
| T & | |
| x4() | |
| { | |
| return w; | |
| } | |
| public: // Modifiers | |
| // Zero | |
| Vector4 & | |
| zero() | |
| { | |
| x = y = z = w = T( 0 ); | |
| return *this; | |
| } | |
| // Negate | |
| Vector4 & | |
| negate() | |
| { | |
| x = -x; | |
| y = -y; | |
| z = -z; | |
| w = -w; | |
| return *this; | |
| } | |
| // Normalize to a Length | |
| Vector4 & | |
| normalize( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| assert( cur_length != T ( 0 ) ); | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| return *this; | |
| } | |
| // Normalize to a Length: Zero Vector4 if Length is Zero | |
| Vector4 & | |
| normalize_zero( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| } else { // Set zero vector | |
| x = y = z = w = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: Uniform Vector4 if Length is Zero | |
| Vector4 & | |
| normalize_uniform( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| } else { // Set uniform vector | |
| operator =( uniform_vector( tar_length ) ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: x Vector4 if Length is Zero | |
| Vector4 & | |
| normalize_x( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| } else { // Set x vector | |
| x = tar_length; | |
| y = z = w = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: y Vector4 if Length is Zero | |
| Vector4 & | |
| normalize_y( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| } else { // Set y vector | |
| y = tar_length; | |
| x = z = w = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: z Vector4 if Length is Zero | |
| Vector4 & | |
| normalize_z( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| } else { // Set z vector | |
| z = tar_length; | |
| x = y = w = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Normalize to a Length: w Vector4 if Length is Zero | |
| Vector4 & | |
| normalize_w( Tc tar_length = T( 1 ) ) | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| x *= dilation; | |
| y *= dilation; | |
| z *= dilation; | |
| w *= dilation; | |
| } else { // Set z vector | |
| w = tar_length; | |
| x = y = z = T( 0 ); | |
| } | |
| return *this; | |
| } | |
| // Minimum Coordinates with a Vector4 | |
| Vector4 & | |
| min( Vector4 const & v ) | |
| { | |
| x = ( x <= v.x ? x : v.x ); | |
| y = ( y <= v.y ? y : v.y ); | |
| z = ( z <= v.z ? z : v.z ); | |
| w = ( w <= v.w ? w : v.w ); | |
| return *this; | |
| } | |
| // Maximum Coordinates with a Vector4 | |
| Vector4 & | |
| max( Vector4 const & v ) | |
| { | |
| x = ( x >= v.x ? x : v.x ); | |
| y = ( y >= v.y ? y : v.y ); | |
| z = ( z >= v.z ? z : v.z ); | |
| w = ( w >= v.w ? w : v.w ); | |
| return *this; | |
| } | |
| // Add a Vector4 | |
| Vector4 & | |
| add( Vector4 const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| z += v.z; | |
| w += v.w; | |
| return *this; | |
| } | |
| // Sum a Vector4 | |
| Vector4 & | |
| sum( Vector4 const & v ) | |
| { | |
| x += v.x; | |
| y += v.y; | |
| z += v.z; | |
| w += v.w; | |
| return *this; | |
| } | |
| // Subtract a Vector4 | |
| Vector4 & | |
| sub( Vector4 const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| z -= v.z; | |
| w -= v.w; | |
| return *this; | |
| } | |
| // Subtract a Vector4 | |
| Vector4 & | |
| subtract( Vector4 const & v ) | |
| { | |
| x -= v.x; | |
| y -= v.y; | |
| z -= v.z; | |
| w -= v.w; | |
| return *this; | |
| } | |
| // Project Normal to a Vector4 | |
| Vector4 & | |
| project_normal( Vector4 const & v ) | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| x -= c * v.x; | |
| y -= c * v.y; | |
| z -= c * v.z; | |
| w -= c * v.w; | |
| return *this; | |
| } | |
| // Project onto a Vector4 | |
| Vector4 & | |
| project_parallel( Vector4 const & v ) | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| x = c * v.x; | |
| y = c * v.y; | |
| z = c * v.z; | |
| w = c * v.w; | |
| return *this; | |
| } | |
| public: // Generators | |
| // -Vector4 (Negated) | |
| Vector4 | |
| operator -() const | |
| { | |
| return Vector4( -x, -y, -z, -w ); | |
| } | |
| // Negated | |
| Vector4 | |
| negated() const | |
| { | |
| return Vector4( -x, -y, -z, -w ); | |
| } | |
| // Normalized to a Length | |
| Vector4 | |
| normalized( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| assert( cur_length != T ( 0 ) ); | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } | |
| // Normalized to a Length: Zero Vector4 if Length is Zero | |
| Vector4 | |
| normalized_zero( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } else { // Return zero vector | |
| return Vector4( T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: Uniform Vector4 if Length is Zero | |
| Vector4 | |
| normalized_uniform( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } else { // Return uniform vector | |
| return uniform_vector( tar_length ); | |
| } | |
| } | |
| // Normalized to a Length: x Vector4 if Length is Zero | |
| Vector4 | |
| normalized_x( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } else { // Return x vector | |
| return Vector4( tar_length, T( 0 ), T( 0 ), T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: y Vector4 if Length is Zero | |
| Vector4 | |
| normalized_y( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } else { // Return y vector | |
| return Vector4( T( 0 ), tar_length, T( 0 ), T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: z Vector4 if Length is Zero | |
| Vector4 | |
| normalized_z( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } else { // Return z vector | |
| return Vector4( tar_length, T( 0 ), T( 0 ), tar_length, T( 0 ) ); | |
| } | |
| } | |
| // Normalized to a Length: w Vector4 if Length is Zero | |
| Vector4 | |
| normalized_w( Tc tar_length = T( 1 ) ) const | |
| { | |
| T const cur_length( length() ); | |
| if ( cur_length > T( 0 ) ) { | |
| T const dilation( tar_length / cur_length ); | |
| return Vector4( | |
| x * dilation, | |
| y * dilation, | |
| z * dilation, | |
| w * dilation | |
| ); | |
| } else { // Return z vector | |
| return Vector4( tar_length, T( 0 ), T( 0 ), T( 0 ), tar_length ); | |
| } | |
| } | |
| // Projected Normal to a Vector4 | |
| Vector4 | |
| projected_normal( Vector4 const & v ) const | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| return Vector4( x - ( c * v.x ), y - ( c * v.y ), z - ( c * v.z ), w - ( c * v.w ) ); | |
| } | |
| // Projected onto a Vector4 | |
| Vector4 | |
| projected_parallel( Vector4 const & v ) const | |
| { | |
| assert( v.length_squared() != T( 0 ) ); | |
| T const c( dot( v ) / v.length_squared() ); | |
| return Vector4( c * v.x, c * v.y, c * v.z, c * v.w ); | |
| } | |
| public: // Static Methods | |
| // Square of a value | |
| static | |
| T | |
| square( Tc t ) | |
| { | |
| return t * t; | |
| } | |
| // Value Clipped to [-1,1] | |
| static | |
| T | |
| sin_cos_range( Tc t ) | |
| { | |
| return std::min( std::max( t, T( -1 ) ), T( 1 ) ); | |
| } | |
| // Add 2*Pi to a Negative Value | |
| static | |
| T | |
| bump_up_angle( Tc t ) | |
| { | |
| static T const Two_Pi( T( 2 ) * std::acos( -1.0 ) ); | |
| return ( t >= T( 0 ) ? t : Two_Pi + t ); | |
| } | |
| public: // Data | |
| T x, y, z, w; // Elements | |
| }; // Vector4 | |
| // Length | |
| template< typename T > | |
| inline | |
| T | |
| length( Vector4< T > const & v ) | |
| { | |
| return v.length(); | |
| } | |
| // Length Squared | |
| template< typename T > | |
| inline | |
| T | |
| length_squared( Vector4< T > const & v ) | |
| { | |
| return v.length_squared(); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( Vector4< T > const & v ) | |
| { | |
| return v.magnitude(); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| mag( Vector4< T > const & v ) | |
| { | |
| return v.mag(); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( Vector4< T > const & v ) | |
| { | |
| return v.magnitude_squared(); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| mag_squared( Vector4< T > const & v ) | |
| { | |
| return v.mag_squared(); | |
| } | |
| // Vector4 == Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ); | |
| } | |
| // Vector4 != Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) || ( a.w != b.w ); | |
| } | |
| // Vector4 < Vector4: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( | |
| ( a.x < b.x ? true : | |
| ( b.x < a.x ? false : // a.x == b.x | |
| ( a.y < b.y ? true : | |
| ( b.y < a.y ? false : // a.y == b.y | |
| ( a.z < b.z ? true : | |
| ( b.z < a.z ? false : // a.z == b.z | |
| ( a.w < b.w ) ) ) ) ) ) ) | |
| ); | |
| } | |
| // Vector4 <= Vector4: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( | |
| ( a.x < b.x ? true : | |
| ( b.x < a.x ? false : // a.x == b.x | |
| ( a.y < b.y ? true : | |
| ( b.y < a.y ? false : // a.y == b.y | |
| ( a.z < b.z ? true : | |
| ( b.z < a.z ? false : // a.z == b.z | |
| ( a.w <= b.w ) ) ) ) ) ) ) | |
| ); | |
| } | |
| // Vector4 >= Vector4: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( | |
| ( a.x > b.x ? true : | |
| ( b.x > a.x ? false : // a.x == b.x | |
| ( a.y > b.y ? true : | |
| ( b.y > a.y ? false : // a.y == b.y | |
| ( a.z > b.z ? true : | |
| ( b.z > a.z ? false : // a.z == b.z | |
| ( a.w >= b.w ) ) ) ) ) ) ) | |
| ); | |
| } | |
| // Vector4 > Vector4: Lexicographic | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( | |
| ( a.x > b.x ? true : | |
| ( b.x > a.x ? false : // a.x == b.x | |
| ( a.y > b.y ? true : | |
| ( b.y > a.y ? false : // a.y == b.y | |
| ( a.z > b.z ? true : | |
| ( b.z > a.z ? false : // a.z == b.z | |
| ( a.w > b.w ) ) ) ) ) ) ) | |
| ); | |
| } | |
| // Vector4 < Vector4: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| lt( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x < b.x ) && ( a.y < b.y ) && ( a.z < b.z ) && ( a.w < b.w ); | |
| } | |
| // Vector4 <= Vector4: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| le( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x <= b.x ) && ( a.y <= b.y ) && ( a.z <= b.z ) && ( a.w <= b.w ); | |
| } | |
| // Vector4 >= Vector4: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| ge( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x >= b.x ) && ( a.y >= b.y ) && ( a.z >= b.z ) && ( a.w >= b.w ); | |
| } | |
| // Vector4 > Vector4: Element-wise | |
| template< typename T > | |
| inline | |
| bool | |
| gt( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x > b.x ) && ( a.y > b.y ) && ( a.z > b.z ) && ( a.w > b.w ); | |
| } | |
| // Vector4 == Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return ( v.x == t ) && ( v.y == t ) && ( v.z == t ) && ( v.w == t ); | |
| } | |
| // Vector4 != Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return ( v.x != t ) || ( v.y != t ) || ( v.z != t ) || ( v.w != t ); | |
| } | |
| // Vector4 < Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return ( v.x < t ) && ( v.y < t ) && ( v.z < t ) && ( v.w < t ); | |
| } | |
| // Vector4 <= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return ( v.x <= t ) && ( v.y <= t ) && ( v.z <= t ) && ( v.w <= t ); | |
| } | |
| // Vector4 >= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return ( v.x >= t ) && ( v.y >= t ) && ( v.z >= t ) && ( v.w >= t ); | |
| } | |
| // Vector4 > Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return ( v.x > t ) && ( v.y > t ) && ( v.z > t ) && ( v.w > t ); | |
| } | |
| // Value == Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return ( t == v.x ) && ( t == v.y ) && ( t == v.z ) && ( t == v.w ); | |
| } | |
| // Value != Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return ( t != v.x ) || ( t != v.y ) || ( t != v.z ) || ( t != v.w ); | |
| } | |
| // Value < Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return ( t < v.x ) && ( t < v.y ) && ( t < v.z ) && ( t < v.w ); | |
| } | |
| // Value <= Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return ( t <= v.x ) && ( t <= v.y ) && ( t <= v.z ) && ( t <= v.w ); | |
| } | |
| // Value >= Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return ( t >= v.x ) && ( t >= v.y ) && ( t >= v.z ) && ( t >= v.w ); | |
| } | |
| // Value > Vector4 | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return ( t > v.x ) && ( t > v.y ) && ( t > v.z ) && ( t > v.w ); | |
| } | |
| // Equal Length? | |
| template< typename T > | |
| inline | |
| bool | |
| equal_length( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.length_squared() == b.length_squared() ); | |
| } | |
| // Not Equal Length? | |
| template< typename T > | |
| inline | |
| bool | |
| not_equal_length( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.length_squared() != b.length_squared() ); | |
| } | |
| // Vector4 + Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator +( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w ); | |
| } | |
| // Vector4 + Value | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator +( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return Vector4< T >( v.x + t, v.y + t, v.z + t, v.w + t ); | |
| } | |
| // Value + Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator +( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return Vector4< T >( t + v.x, t + v.y, t + v.z, t + v.w ); | |
| } | |
| // Vector4 - Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator -( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w ); | |
| } | |
| // Vector4 - Value | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator -( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return Vector4< T >( v.x - t, v.y - t, v.z - t, v.w - t ); | |
| } | |
| // Value - Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator -( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return Vector4< T >( t - v.x, t - v.y, t - v.z, t - v.w ); | |
| } | |
| // Vector4 * Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator *( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w ); | |
| } | |
| // Vector4 * Value | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator *( Vector4< T > const & v, typename Vector4< T >::Tc t ) | |
| { | |
| return Vector4< T >( v.x * t, v.y * t, v.z * t, v.w * t ); | |
| } | |
| // Value * Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator *( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| return Vector4< T >( t * v.x, t * v.y, t * v.z, t * v.w ); | |
| } | |
| // Vector4 / Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator /( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( b.x != T( 0 ) ); | |
| assert( b.y != T( 0 ) ); | |
| assert( b.z != T( 0 ) ); | |
| assert( b.w != T( 0 ) ); | |
| return Vector4< T >( a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w ); | |
| } | |
| // Vector4 / Value | |
| template< typename T, typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| inline | |
| Vector4< T > | |
| operator /( Vector4< T > const & v, U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U ( 1 ) / u ); | |
| return Vector4< T >( v.x * inv_u, v.y * inv_u, v.z * inv_u, v.w * inv_u ); | |
| } | |
| // Vector4 / Value | |
| template< typename T, typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| inline | |
| Vector4< T > | |
| operator /( Vector4< T > const & v, U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| return Vector4< T >( v.x / u, v.y / u, v.z / u, v.w / u ); | |
| } | |
| // Value / Vector4 | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| operator /( typename Vector4< T >::Tc t, Vector4< T > const & v ) | |
| { | |
| assert( v.x != T( 0 ) ); | |
| assert( v.y != T( 0 ) ); | |
| assert( v.z != T( 0 ) ); | |
| assert( v.w != T( 0 ) ); | |
| return Vector4< T >( t / v.x, t / v.y, t / v.z, t / v.w ); | |
| } | |
| // Minimum of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| min( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( | |
| ( a.x <= b.x ? a.x : b.x ), | |
| ( a.y <= b.y ? a.y : b.y ), | |
| ( a.z <= b.z ? a.z : b.z ), | |
| ( a.w <= b.w ? a.w : b.w ) | |
| ); | |
| } | |
| // Minimum of Three Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| min( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| return Vector4< T >( | |
| ObjexxFCL::min( a.x, b.x, c.x ), | |
| ObjexxFCL::min( a.y, b.y, c.y ), | |
| ObjexxFCL::min( a.z, b.z, c.z ), | |
| ObjexxFCL::min( a.w, b.w, c.w ) | |
| ); | |
| } | |
| // Minimum of Four Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| min( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c, Vector4< T > const & d ) | |
| { | |
| return Vector4< T >( | |
| ObjexxFCL::min( a.x, b.x, c.x, d.x ), | |
| ObjexxFCL::min( a.y, b.y, c.y, d.y ), | |
| ObjexxFCL::min( a.z, b.z, c.z, d.z ), | |
| ObjexxFCL::min( a.w, b.w, c.w, d.w ) | |
| ); | |
| } | |
| // Maximum of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| max( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( | |
| ( a.x >= b.x ? a.x : b.x ), | |
| ( a.y >= b.y ? a.y : b.y ), | |
| ( a.z >= b.z ? a.z : b.z ), | |
| ( a.w >= b.w ? a.w : b.w ) | |
| ); | |
| } | |
| // Maximum of Three Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| max( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| return Vector4< T >( | |
| ObjexxFCL::max( a.x, b.x, c.x ), | |
| ObjexxFCL::max( a.y, b.y, c.y ), | |
| ObjexxFCL::max( a.z, b.z, c.z ), | |
| ObjexxFCL::max( a.w, b.w, c.w ) | |
| ); | |
| } | |
| // Maximum of Four Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| max( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c, Vector4< T > const & d ) | |
| { | |
| return Vector4< T >( | |
| ObjexxFCL::max( a.x, b.x, c.x, d.x ), | |
| ObjexxFCL::max( a.y, b.y, c.y, d.y ), | |
| ObjexxFCL::max( a.z, b.z, c.z, d.z ), | |
| ObjexxFCL::max( a.w, b.w, c.w, d.w ) | |
| ); | |
| } | |
| // Sum of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| sum( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w ); | |
| } | |
| // Sum of Three Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| sum( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| return Vector4< T >( a.x + b.x + c.x, a.y + b.y + c.y, a.z + b.z + c.z, a.w + b.w + c.w ); | |
| } | |
| // Sum of Four Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| sum( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c, Vector4< T > const & d ) | |
| { | |
| return Vector4< T >( a.x + b.x + c.x + d.x, a.y + b.y + c.y + d.y, a.z + b.z + c.z + d.z, a.w + b.w + c.w + d.w ); | |
| } | |
| // Subtract of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| sub( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w ); | |
| } | |
| // Subtract of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| subtract( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w ); | |
| } | |
| // Midpoint of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| mid( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( | |
| T( 0.5 * ( a.x + b.x ) ), | |
| T( 0.5 * ( a.y + b.y ) ), | |
| T( 0.5 * ( a.z + b.z ) ), | |
| T( 0.5 * ( a.w + b.w ) ) | |
| ); | |
| } | |
| // Center of Two Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| cen( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >( | |
| T( 0.5 * ( a.x + b.x ) ), | |
| T( 0.5 * ( a.y + b.y ) ), | |
| T( 0.5 * ( a.z + b.z ) ), | |
| T( 0.5 * ( a.w + b.w ) ) | |
| ); | |
| } | |
| // Center of Three Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| cen( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| static long double const third( 1.0 / 3.0 ); | |
| return Vector4< T >( | |
| T( third * ( a.x + b.x + c.x ) ), | |
| T( third * ( a.y + b.y + c.y ) ), | |
| T( third * ( a.z + b.z + c.z ) ), | |
| T( third * ( a.w + b.w + c.w ) ) | |
| ); | |
| } | |
| // Center of Four Vector4s | |
| template< typename T > | |
| inline | |
| Vector4< T > | |
| cen( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c, Vector4< T > const & d ) | |
| { | |
| return Vector4< T >( | |
| T( 0.25 * ( a.x + b.x + c.x + d.x ) ), | |
| T( 0.25 * ( a.y + b.y + c.y + d.y ) ), | |
| T( 0.25 * ( a.z + b.z + c.z + d.z ) ), | |
| T( 0.25 * ( a.w + b.w + c.w + d.w ) ) | |
| ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return std::sqrt( Vector4< T >::square( a.x - b.x ) + Vector4< T >::square( a.y - b.y ) + Vector4< T >::square( a.z - b.z ) + Vector4< T >::square( a.w - b.w ) ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return Vector4< T >::square( a.x - b.x ) + Vector4< T >::square( a.y - b.y ) + Vector4< T >::square( a.z - b.z ) + Vector4< T >::square( a.w - b.w ); | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return ( a.x * b.x ) + ( a.y * b.y ) + ( a.z * b.z ) + ( a.w * b.w ); | |
| } | |
| // Angle Between Two Vector4s (in Radians on [0,pi]) | |
| template< typename T > | |
| inline | |
| T | |
| angle( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? std::acos( Vector4< T >::sin_cos_range( a.dot( b ) / mag ) ) : T( 0 ) ); | |
| } | |
| // Angle abc Formed by Three Vector4s (in Radians on [0,pi]) | |
| template< typename T > | |
| inline | |
| T | |
| angle( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| return angle( a - b, c - b ); | |
| } | |
| // Cosine of Angle Between Two Vector4s | |
| template< typename T > | |
| inline | |
| T | |
| cos( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| T const mag( std::sqrt( a.length_squared() * b.length_squared() ) ); | |
| return ( mag > T( 0 ) ? Vector4< T >::sin_cos_range( a.dot( b ) / mag ) : T( 1 ) ); | |
| } | |
| // Cosine of Angle abc Formed by Three Vector4s | |
| template< typename T > | |
| inline | |
| T | |
| cos( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| return cos( a - b, c - b ); | |
| } | |
| // Sine of Angle Between Two Vector4s | |
| template< typename T > | |
| inline | |
| T | |
| sin( Vector4< T > const & a, Vector4< T > const & b ) | |
| { | |
| return std::sin( angle( a, b ) ); | |
| } | |
| // Sine of Angle abc Formed by Three Vector4s | |
| template< typename T > | |
| inline | |
| T | |
| sin( Vector4< T > const & a, Vector4< T > const & b, Vector4< T > const & c ) | |
| { | |
| return sin( a - b, c - b ); | |
| } | |
| // Stream << Vector4 output operator | |
| template< typename T > | |
| std::ostream & | |
| operator <<( std::ostream & stream, Vector4< T > const & v ) | |
| { | |
| // Types | |
| typedef TypeTraits< T > Traits; | |
| // Save current stream state and set persistent state | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| // Output Vector4 | |
| std::size_t const w( Traits::width ); | |
| stream << std::setw( w ) << v.x << ' ' << std::setw( w ) << v.y << ' ' << std::setw( w ) << v.z << ' ' << std::setw( w ) << v.w; | |
| // Restore previous stream state | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| return stream; | |
| } | |
| // Stream >> Vector4 input operator | |
| // Supports whitespace-separated values with optional commas between values as long as whitespace is also present | |
| // String or char values containing whitespace or commas or enclosed in quotes are not supported | |
| // Vector can optionally be enclosed in parentheses () or square brackets [] | |
| template< typename T > | |
| std::istream & | |
| operator >>( std::istream & stream, Vector4< T > & v ) | |
| { | |
| bool parens( false ); // Opening ( present? | |
| bool brackets( false ); // Opening [ present? | |
| { // x | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "(" ) { // Skip opening ( | |
| stream >> input_string; | |
| parens = true; | |
| } else if ( input_string[ 0 ] == '(' ) { // Skip opening ( | |
| input_string.erase( 0, 1 ); | |
| brackets = true; | |
| } else if ( input_string == "[" ) { // Skip opening [ | |
| stream >> input_string; | |
| brackets = true; | |
| } else if ( input_string[ 0 ] == '[' ) { // Skip opening [ | |
| input_string.erase( 0, 1 ); | |
| brackets = true; | |
| } | |
| std::string::size_type const input_size( input_string.size() ); | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.x; | |
| } | |
| { // y | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "," ) { // Skip , | |
| stream >> input_string; | |
| } else if ( input_string[ 0 ] == ',' ) { // Skip leading , | |
| input_string.erase( 0, 1 ); | |
| } | |
| std::string::size_type const input_size( input_string.size() ); | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.y; | |
| } | |
| { // z | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "," ) { // Skip , | |
| stream >> input_string; | |
| } else if ( input_string[ 0 ] == ',' ) { // Skip leading , | |
| input_string.erase( 0, 1 ); | |
| } | |
| std::string::size_type const input_size( input_string.size() ); | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.z; | |
| } | |
| { // w | |
| std::string input_string; | |
| stream >> input_string; | |
| if ( input_string == "," ) { // Skip , | |
| stream >> input_string; | |
| } else if ( input_string[ 0 ] == ',' ) { // Skip leading , | |
| input_string.erase( 0, 1 ); | |
| } | |
| std::string::size_type input_size( input_string.size() ); | |
| if ( parens || brackets ) { // Remove closing ) or ] | |
| if ( input_size > 0 ) { | |
| if ( parens ) { | |
| if ( input_string[ input_size - 1 ] == ')' ) { // Remove closing ) | |
| input_string.erase( input_size - 1 ); | |
| --input_size; | |
| } | |
| } else if ( brackets ) { | |
| if ( input_string[ input_size - 1 ] == ']' ) { // Remove closing ] | |
| input_string.erase( input_size - 1 ); | |
| --input_size; | |
| } | |
| } | |
| } | |
| } | |
| if ( ( input_size > 0 ) && ( input_string[ input_size - 1 ] == ',' ) ) { | |
| input_string.erase( input_size - 1 ); // Remove trailing , | |
| } | |
| std::istringstream num_stream( input_string ); | |
| num_stream >> v.w; | |
| } | |
| // Remove closing ) or ] if opening ( or [ present | |
| if ( parens || brackets ) { // Remove closing ) or ] | |
| while ( ( stream.peek() == ' ' ) || ( stream.peek() == '\t' ) ) { | |
| stream.ignore(); | |
| } | |
| if ( parens ) { // Remove closing ) if present | |
| if ( stream.peek() == ')' ) stream.ignore(); | |
| } else if ( brackets ) { // Remove closing ] if present | |
| if ( stream.peek() == ']' ) stream.ignore(); | |
| } | |
| } | |
| return stream; | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Vector4_hh_INCLUDED | |
| // ===== ObjexxFCL/Array.hh ===== | |
| #ifndef ObjexxFCL_Array_hh_INCLUDED | |
| #define ObjexxFCL_Array_hh_INCLUDED | |
| // Array: Array Abstract Base Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <algorithm> | |
| #include <array> | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <cstdlib> | |
| #include <cstring> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <istream> | |
| #include <iterator> | |
| #include <limits> | |
| #include <memory> | |
| #include <new> | |
| #include <ostream> | |
| #include <type_traits> | |
| #include <typeinfo> | |
| #include <utility> | |
| #include <vector> | |
| namespace ObjexxFCL { | |
| // Array: Array Abstract Base Class | |
| // | |
| // Note: | |
| // Can hold numeric or non-numeric values: Numeric operations on non-numeric values won't compile | |
| // Any meaningful array index ranges can be specified as in Fortran | |
| // Zero-sized arrays are supported but have no valid indices | |
| // Argument/proxy arrays can have unbounded/unknown size | |
| // For efficiency constructors without initializer function or value do not initialize the array | |
| // For efficiency bounds checking is only active via asserts in debug builds | |
| template< typename T > | |
| class Array : public BArray | |
| { | |
| private: // Friend | |
| template< typename > friend class Array; | |
| protected: // Types | |
| typedef internal::InitializerSentinel InitializerSentinel; | |
| typedef internal::ProxySentinel ProxySentinel; | |
| public: // Types | |
| typedef Array< T > Base; | |
| typedef AlignedAllocator< T > Aligned; | |
| typedef TypeTraits< T > Traits; | |
| // STL style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| typedef T * iterator; | |
| typedef T const * const_iterator; | |
| typedef std::reverse_iterator< T * > reverse_iterator; | |
| typedef std::reverse_iterator< T const * > const_reverse_iterator; | |
| // C++ style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| typedef T * Iterator; | |
| typedef T const * ConstIterator; | |
| typedef std::reverse_iterator< T * > ReverseIterator; | |
| typedef std::reverse_iterator< T const * > ConstReverseIterator; | |
| protected: // Creation | |
| // Default Constructor | |
| Array() : | |
| owner_( true ), | |
| capacity_( 0u ), | |
| size_( 0u ), | |
| mem_( nullptr ), | |
| data_( nullptr ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| // Copy Constructor | |
| Array( Array const & a ) : | |
| BArray( a ), | |
| owner_( true ), | |
| capacity_( size_of( a.size_ ) ), | |
| size_( capacity_ ), | |
| mem_( a.data_ != nullptr ? Aligned::allocate_zero( capacity_ ) : nullptr ), | |
| data_( a.data_ != nullptr ? Aligned::data( mem_ ) : nullptr ), | |
| shift_( a.shift_ ), | |
| sdata_( data_ - shift_ ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a.data_[ i ] ); | |
| } | |
| } | |
| // Move Constructor | |
| Array( Array && a ) noexcept : | |
| BArray( std::move( a ) ), | |
| owner_( a.owner_ ), | |
| capacity_( a.capacity_ ), | |
| size_( a.size_ ), | |
| mem_( a.mem_ ), | |
| data_( a.data_ ), | |
| shift_( a.shift_ ), | |
| sdata_( a.sdata_ ) | |
| { | |
| a.capacity_ = a.size_ = 0u; | |
| a.mem_ = a.data_ = a.sdata_ = nullptr; | |
| a.shift_ = 0; | |
| } | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array( Array< U > const & a ) : | |
| owner_( true ), | |
| capacity_( size_of( a.size() ) ), | |
| size_( capacity_ ), | |
| mem_( a.data_ != nullptr ? Aligned::allocate_zero( capacity_ ) : nullptr ), | |
| data_( a.data_ != nullptr ? Aligned::data( mem_ ) : nullptr ), | |
| shift_( a.shift_ ), | |
| sdata_( data_ - shift_ ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a.data_[ i ] ); | |
| } | |
| } | |
| // Slice Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array( ArrayS< U > const & a ) : | |
| owner_( true ), | |
| capacity_( size_of( a.size() ) ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| // MArray Constructor Template | |
| template< class A, typename M > | |
| explicit | |
| Array( MArray< A, M > const & a ) : | |
| owner_( true ), | |
| capacity_( size_of( a.size() ) ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| // Size Constructor | |
| explicit | |
| Array( size_type const size ) : | |
| owner_( true ), | |
| capacity_( size_of( size ) ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| T const fill( Traits::initial_array_value() ); | |
| #endif | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| new ( data_ + i ) T( fill ); | |
| #else | |
| new ( data_ + i ) T; | |
| #endif | |
| } | |
| } | |
| // Size + InitializerSentinel Constructor | |
| Array( size_type const size, InitializerSentinel ) : | |
| owner_( true ), | |
| capacity_( size_of( size ) ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array( std::initializer_list< U > const l ) : | |
| owner_( true ), | |
| capacity_( l.size() ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| auto il( l.begin() ); | |
| for ( size_type i = 0; i < size_; ++i, ++il ) { | |
| new ( data_ + i ) T( *il ); | |
| } | |
| } | |
| // std::array Constructor Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array( std::array< U, s > const & a ) : | |
| owner_( true ), | |
| capacity_( s ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| auto ia( a.begin() ); | |
| for ( size_type i = 0; i < size_; ++i, ++ia ) { | |
| new ( data_ + i ) T( *ia ); | |
| } | |
| } | |
| // std::vector Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array( std::vector< U > const & v ) : | |
| owner_( true ), | |
| capacity_( v.size() ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| auto iv( v.begin() ); | |
| for ( size_type i = 0; i < size_; ++i, ++iv ) { | |
| new ( data_ + i ) T( *iv ); | |
| } | |
| } | |
| // Vector2 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array( Vector2< U > const & v ) : | |
| owner_( true ), | |
| capacity_( 2u ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| new ( &data_[ 0 ] ) T( v.x ); | |
| new ( &data_[ 1 ] ) T( v.y ); | |
| } | |
| // Vector3 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array( Vector3< U > const & v ) : | |
| owner_( true ), | |
| capacity_( 3u ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| new ( &data_[ 0 ] ) T( v.x ); | |
| new ( &data_[ 1 ] ) T( v.y ); | |
| new ( &data_[ 2 ] ) T( v.z ); | |
| } | |
| // Vector4 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array( Vector4< U > const & v ) : | |
| owner_( true ), | |
| capacity_( 4u ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| new ( &data_[ 0 ] ) T( v.x ); | |
| new ( &data_[ 1 ] ) T( v.y ); | |
| new ( &data_[ 2 ] ) T( v.z ); | |
| new ( &data_[ 3 ] ) T( v.w ); | |
| } | |
| // Iterator Range Constructor Template | |
| template< class Iterator, typename = decltype( *std::declval< Iterator & >(), void(), ++std::declval< Iterator & >(), void() ) > | |
| Array( Iterator const beg, Iterator const end ) : | |
| owner_( true ), | |
| capacity_( end - beg ), | |
| size_( capacity_ ), | |
| mem_( Aligned::allocate_zero( capacity_ ) ), | |
| data_( Aligned::data( mem_ ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| size_type i( 0u ); | |
| for ( Iterator ii = beg; ii != end; ++ii, ++i ) { | |
| new ( data_ + i ) T( *ii ); | |
| } | |
| } | |
| // Default Proxy Constructor | |
| Array( ProxySentinel ) : | |
| owner_( false ), | |
| capacity_( 0u ), | |
| size_( 0u ), | |
| mem_( nullptr ), | |
| data_( nullptr ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| // Array Proxy Constructor | |
| Array( Array const & a, ProxySentinel ) : | |
| owner_( false ), | |
| capacity_( a.capacity_ ), | |
| size_( a.size_ ), | |
| mem_( nullptr ), | |
| data_( a.data_ ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| // Slice Proxy Constructor | |
| Array( ArrayS< T > const & a, ProxySentinel ) : | |
| owner_( false ), | |
| capacity_( a.size() ), | |
| size_( a.size() ), | |
| mem_( nullptr ), | |
| data_( a.data_beg_ ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| { | |
| assert( a.contiguous() ); | |
| } | |
| // Value Proxy Constructor | |
| Array( T const & t, ProxySentinel ) : | |
| owner_( false ), | |
| capacity_( npos ), // Unknown | |
| size_( npos ), // Unbounded | |
| mem_( nullptr ), | |
| data_( const_cast< T * >( &t ) ), | |
| shift_( 0 ), | |
| sdata_( nullptr ) | |
| {} | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~Array() | |
| { | |
| if ( owner_ ) destroy(); | |
| } | |
| protected: // Assignment: Array | |
| // Copy Assignment | |
| void | |
| operator =( Array const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size_ ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| c[ i ] = a[ i ]; | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = a[ i ]; | |
| } | |
| } | |
| } | |
| // Move Assignment | |
| void | |
| operator =( Array && a ) noexcept | |
| { | |
| assert( this != &a ); | |
| assert( owner_ == a.owner_ ); | |
| if ( owner_ ) destroy(); | |
| capacity_ = a.capacity_; | |
| size_ = a.size_; | |
| mem_ = a.mem_; | |
| data_ = a.data_; | |
| shift_ = a.shift_; | |
| sdata_ = a.sdata_; | |
| a.capacity_ = a.size_ = 0u; | |
| a.mem_ = a.data_ = a.sdata_ = nullptr; | |
| a.shift_ = 0; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( Array< U > const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = a[ i ]; | |
| } | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( size_ == l.size() ); | |
| std::copy( l.begin(), l.end(), data_ ); | |
| } | |
| // std::array Assignment Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( std::array< U, s > const & a ) | |
| { | |
| assert( size_ == s ); | |
| std::copy( a.begin(), a.end(), data_ ); | |
| } | |
| // std::vector Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( std::vector< U > const & v ) | |
| { | |
| assert( size_ == v.size() ); | |
| std::copy( v.begin(), v.end(), data_ ); | |
| } | |
| // Vector2 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( Vector2< U > const & v ) | |
| { | |
| assert( size_ == 2u ); | |
| operator []( 0 ) = v.x; | |
| operator []( 1 ) = v.y; | |
| } | |
| // Vector3 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( Vector3< U > const & v ) | |
| { | |
| assert( size_ == 3u ); | |
| operator []( 0 ) = v.x; | |
| operator []( 1 ) = v.y; | |
| operator []( 2 ) = v.z; | |
| } | |
| // Vector4 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator =( Vector4< U > const & v ) | |
| { | |
| assert( size_ == 4u ); | |
| operator []( 0 ) = v.x; | |
| operator []( 1 ) = v.y; | |
| operator []( 2 ) = v.z; | |
| operator []( 3 ) = v.w; | |
| } | |
| // += Array | |
| void | |
| operator +=( Array const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size() ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| c[ i ] = a[ i ]; | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += a[ i ]; | |
| } | |
| } | |
| } | |
| // -= Array | |
| void | |
| operator -=( Array const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size() ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| c[ i ] = a[ i ]; | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= a[ i ]; | |
| } | |
| } | |
| } | |
| // += Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator +=( Array< U > const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += a[ i ]; | |
| } | |
| } | |
| // -= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator -=( Array< U > const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= a[ i ]; | |
| } | |
| } | |
| // *= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator *=( Array< U > const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= a[ i ]; | |
| } | |
| } | |
| // += std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator +=( std::array< U, s > const & a ) | |
| { | |
| assert( size_ == s ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += a[ i ]; | |
| } | |
| } | |
| // -= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator -=( std::array< U, s > const & a ) | |
| { | |
| assert( size_ == s ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= a[ i ]; | |
| } | |
| } | |
| // += std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator +=( std::vector< U > const & v ) | |
| { | |
| assert( size_ == v.size() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += v[ i ]; | |
| } | |
| } | |
| // -= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| void | |
| operator -=( std::vector< U > const & v ) | |
| { | |
| assert( size_ == v.size() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= v[ i ]; | |
| } | |
| } | |
| public: // Assignment: Value | |
| // = Value | |
| Array & | |
| operator =( T const & t ) | |
| { | |
| assert( size_bounded() ); | |
| if ( data_ ) std::fill_n( data_, size_, t ); | |
| return *this; | |
| } | |
| // += Value | |
| Array & | |
| operator +=( T const & t ) | |
| { | |
| assert( size_bounded() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += t; | |
| } | |
| return *this; | |
| } | |
| // -= Value | |
| Array & | |
| operator -=( T const & t ) | |
| { | |
| assert( size_bounded() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= t; | |
| } | |
| return *this; | |
| } | |
| // *= Value | |
| Array & | |
| operator *=( T const & t ) | |
| { | |
| assert( size_bounded() ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= t; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| Array & | |
| operator /=( U const & u ) | |
| { | |
| assert( size_bounded() ); | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= inv_u; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| Array & | |
| operator /=( U const & u ) | |
| { | |
| assert( size_bounded() ); | |
| assert( u != U( 0 ) ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] /= u; | |
| } | |
| return *this; | |
| } | |
| public: // Subscript | |
| // array[ i ] const: Linear Subscript | |
| T const & | |
| operator []( size_type const i ) const | |
| { | |
| assert( ( i < size_ ) || ( size_ == npos ) ); | |
| return data_[ i ]; | |
| } | |
| // array[ i ]: Linear Subscript | |
| T & | |
| operator []( size_type const i ) | |
| { | |
| assert( ( i < size_ ) || ( size_ == npos ) ); | |
| return data_[ i ]; | |
| } | |
| public: // Predicate | |
| // Owner? | |
| bool | |
| owner() const | |
| { | |
| return owner_; | |
| } | |
| // Proxy? | |
| bool | |
| proxy() const | |
| { | |
| return ! owner_; | |
| } | |
| // Active? | |
| bool | |
| active() const | |
| { | |
| return ( data_ != nullptr ); | |
| } | |
| // Allocated | |
| bool | |
| allocated() const | |
| { | |
| return ( data_ != nullptr ); | |
| } | |
| // Active Array Empty? | |
| bool | |
| empty() const | |
| { | |
| return ( size_ == 0u ); | |
| } | |
| // Active Array Size Bounded? | |
| bool | |
| size_bounded() const | |
| { | |
| return ( size_ != npos ); | |
| } | |
| // Memory Can Overlap a Range? | |
| bool | |
| overlap( T const * const b, T const * const e ) const | |
| { | |
| if ( ( data_ == nullptr ) || ( b == nullptr ) || ( e == nullptr ) ) { // No active memory range(s) | |
| return false; | |
| } else if ( size_ == 0u ) { // No finite memory range | |
| return false; | |
| } else if ( size_ == npos ) { // No memory upper bound | |
| return ( e >= data_ ); | |
| } else { // Bounded ranges | |
| assert( b <= e ); | |
| T const * const de( data_ + size_ - 1 ); // Data end pointer | |
| return ( ( data_ >= b ? data_ : b ) <= ( de <= e ? de : e ) ); | |
| } | |
| } | |
| // Memory Can Overlap an Array? | |
| template< template< typename > class A > | |
| bool | |
| overlap( A< T > const & a ) const | |
| { | |
| if ( data_ == nullptr ) { // No active memory range | |
| return false; | |
| } else { // Bounded ranges | |
| return overlap( a.data_beg(), a.data_end() ); | |
| } | |
| } | |
| public: // Inspector | |
| // Rank | |
| virtual | |
| int | |
| rank() const = 0; | |
| // Data Size | |
| size_type | |
| capacity() const | |
| { | |
| return capacity_; | |
| } | |
| // Active Array Size | |
| size_type | |
| size() const | |
| { | |
| return size_; | |
| } | |
| // Active Array Size | |
| int | |
| isize() const | |
| { | |
| assert( size_ != npos ); | |
| return static_cast< int >( size_ ); | |
| } | |
| // IndexRange of a Dimension | |
| virtual | |
| IR const & | |
| I( int const d ) const = 0; | |
| // Lower Index of a Dimension | |
| virtual | |
| int | |
| l( int const d ) const = 0; | |
| // Upper Index of a Dimension | |
| virtual | |
| int | |
| u( int const d ) const = 0; | |
| // Size of a Dimension | |
| virtual | |
| size_type | |
| size( int const d ) const = 0; | |
| // Size of a Dimension | |
| virtual | |
| int | |
| isize( int const d ) const = 0; | |
| // Begin Iterator | |
| const_iterator | |
| begin() const | |
| { | |
| return data_; | |
| } | |
| // Begin Iterator | |
| iterator | |
| begin() | |
| { | |
| return data_; | |
| } | |
| // End Iterator | |
| const_iterator | |
| end() const | |
| { | |
| return ( ( data_ != nullptr ) && ( size_ != npos ) ? data_ + size_ : nullptr ); | |
| } | |
| // End Iterator | |
| iterator | |
| end() | |
| { | |
| return ( ( data_ != nullptr ) && ( size_ != npos ) ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse Begin Iterator | |
| const_reverse_iterator | |
| rbegin() const | |
| { | |
| return const_reverse_iterator( ( data_ != nullptr ) && ( size_ != npos ) ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse Begin Iterator | |
| reverse_iterator | |
| rbegin() | |
| { | |
| return reverse_iterator( ( data_ != nullptr ) && ( size_ != npos ) ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse End Iterator | |
| const_reverse_iterator | |
| rend() const | |
| { | |
| return const_reverse_iterator( data_ ); | |
| } | |
| // Reverse End Iterator | |
| reverse_iterator | |
| rend() | |
| { | |
| return reverse_iterator( data_ ); | |
| } | |
| // Data Pointer | |
| T const * | |
| data() const | |
| { | |
| return data_; | |
| } | |
| // Data Pointer | |
| T * | |
| data() | |
| { | |
| return data_; | |
| } | |
| // Data Begin Pointer | |
| T const * | |
| data_beg() const | |
| { | |
| return data_; | |
| } | |
| // Data Begin Pointer | |
| T * | |
| data_beg() | |
| { | |
| return data_; | |
| } | |
| // Data End Pointer | |
| T const * | |
| data_end() const | |
| { | |
| return ( ( data_ != nullptr ) && ( size_ > 0u ) && ( size_ != npos ) ? data_ + size_ - 1 : nullptr ); | |
| } | |
| // Data End Pointer | |
| T * | |
| data_end() | |
| { | |
| return ( ( data_ != nullptr ) && ( size_ > 0u ) && ( size_ != npos ) ? data_ + size_ - 1 : nullptr ); | |
| } | |
| public: // Modifier | |
| // Clear | |
| virtual | |
| Array & | |
| clear() | |
| { | |
| if ( owner_ ) destroy(); | |
| capacity_ = size_ = 0u; | |
| mem_ = data_ = sdata_ = nullptr; | |
| shift_ = 0; | |
| return *this; | |
| } | |
| public: // Comparison: Predicate | |
| // Array == Value | |
| friend | |
| bool | |
| eq( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return true; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( ! ( a[ i ] == t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value == Array | |
| friend | |
| bool | |
| eq( T const & t, Array const & a ) | |
| { | |
| return eq( a, t ); | |
| } | |
| public: // Comparison: Predicate: Any | |
| // Any Array == Value | |
| friend | |
| bool | |
| any_eq( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return false; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] == t ) return true; | |
| } | |
| return false; | |
| } | |
| // Any Value == Array | |
| friend | |
| bool | |
| any_eq( T const & t, Array const & a ) | |
| { | |
| return any_eq( a, t ); | |
| } | |
| // Any Array != Value | |
| friend | |
| bool | |
| any_ne( Array const & a, T const & t ) | |
| { | |
| return ! eq( a, t ); | |
| } | |
| // Any Value != Array | |
| friend | |
| bool | |
| any_ne( T const & t, Array const & a ) | |
| { | |
| return ! eq( a, t ); | |
| } | |
| // Any Array < Value | |
| friend | |
| bool | |
| any_lt( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return false; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] < t ) return true; | |
| } | |
| return false; | |
| } | |
| // Any Value < Array | |
| friend | |
| bool | |
| any_lt( T const & t, Array const & a ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return false; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( t < a[ i ] ) return true; | |
| } | |
| return false; | |
| } | |
| // Any Array <= Value | |
| friend | |
| bool | |
| any_le( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return false; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] <= t ) return true; | |
| } | |
| return false; | |
| } | |
| // Any Value <= Array | |
| friend | |
| bool | |
| any_le( T const & t, Array const & a ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return false; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( t <= a[ i ] ) return true; | |
| } | |
| return false; | |
| } | |
| // Any Array > Value | |
| friend | |
| bool | |
| any_gt( Array const & a, T const & t ) | |
| { | |
| return any_lt( t, a ); | |
| } | |
| // Any Value > Array | |
| friend | |
| bool | |
| any_gt( T const & t, Array const & a ) | |
| { | |
| return any_lt( a, t ); | |
| } | |
| // Any Array >= Value | |
| friend | |
| bool | |
| any_ge( Array const & a, T const & t ) | |
| { | |
| return any_le( t, a ); | |
| } | |
| // Any Value >= Array | |
| friend | |
| bool | |
| any_ge( T const & t, Array const & a ) | |
| { | |
| return any_le( a, t ); | |
| } | |
| public: // Comparison: Predicate: All | |
| // All Array != Value | |
| friend | |
| bool | |
| all_ne( Array const & a, T const & t ) | |
| { | |
| return ! any_eq( a, t ); | |
| } | |
| // All Value != Array | |
| friend | |
| bool | |
| all_ne( T const & t, Array const & a ) | |
| { | |
| return ! any_eq( a, t ); | |
| } | |
| // All Array <= Value | |
| friend | |
| bool | |
| all_le( Array const & a, T const & t ) | |
| { | |
| return le( a, t ); | |
| } | |
| // All Value <= Array | |
| friend | |
| bool | |
| all_le( T const & t, Array const & a ) | |
| { | |
| return le( t, a ); | |
| } | |
| // All Value > Array | |
| friend | |
| bool | |
| all_gt( T const & t, Array const & a ) | |
| { | |
| return gt( t, a ); | |
| } | |
| // All Value >= Array | |
| friend | |
| bool | |
| all_ge( T const & t, Array const & a ) | |
| { | |
| return ge( t, a ); | |
| } | |
| public: // Comparison: Count | |
| // Count Array == Value | |
| friend | |
| size_type | |
| count_eq( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return 0; | |
| size_type n( 0u ); | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] == t ) ++n; | |
| } | |
| return n; | |
| } | |
| // Count Value == Array | |
| friend | |
| size_type | |
| count_eq( T const & t, Array const & a ) | |
| { | |
| return count_eq( a, t ); | |
| } | |
| // Count Array != Value | |
| friend | |
| size_type | |
| count_ne( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return 0; | |
| size_type n( 0u ); | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] != t ) ++n; | |
| } | |
| return n; | |
| } | |
| // Count Value != Array | |
| friend | |
| size_type | |
| count_ne( T const & t, Array const & a ) | |
| { | |
| return count_ne( a, t ); | |
| } | |
| // Count Array < Value | |
| friend | |
| size_type | |
| count_lt( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return 0; | |
| size_type n( 0u ); | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] < t ) ++n; | |
| } | |
| return n; | |
| } | |
| // Count Value < Array | |
| friend | |
| size_type | |
| count_lt( T const & t, Array const & a ) | |
| { | |
| return count_gt( a, t ); | |
| } | |
| // Count Array <= Value | |
| friend | |
| size_type | |
| count_le( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return 0; | |
| size_type n( 0u ); | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] <= t ) ++n; | |
| } | |
| return n; | |
| } | |
| // Count Value <= Array | |
| friend | |
| size_type | |
| count_le( T const & t, Array const & a ) | |
| { | |
| return count_ge( a, t ); | |
| } | |
| // Count Array > Value | |
| friend | |
| size_type | |
| count_gt( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return 0; | |
| size_type n( 0u ); | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] > t ) ++n; | |
| } | |
| return n; | |
| } | |
| // Count Value > Array | |
| friend | |
| size_type | |
| count_gt( T const & t, Array const & a ) | |
| { | |
| return count_lt( a, t ); | |
| } | |
| // Count Array >= Value | |
| friend | |
| size_type | |
| count_ge( Array const & a, T const & t ) | |
| { | |
| assert( a.size_bounded() ); | |
| if ( a.empty() ) return 0; | |
| size_type n( 0u ); | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( a[ i ] >= t ) ++n; | |
| } | |
| return n; | |
| } | |
| // Count Value >= Array | |
| friend | |
| size_type | |
| count_ge( T const & t, Array const & a ) | |
| { | |
| return count_le( a, t ); | |
| } | |
| protected: // Comparison: Predicate | |
| // Array == Array | |
| friend | |
| bool | |
| eq( Array const & a, Array const & b ) | |
| { | |
| assert( a.size_bounded() ); | |
| assert( a.size_ == b.size_ ); | |
| if ( ( &a == &b ) || a.empty() ) return true; | |
| for ( size_type i = 0, e = a.size_; i < e; ++i ) { | |
| if ( ! ( a[ i ] == b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| protected: // Comparison: Elemental | |
| // Array == Array | |
| friend | |
| void | |
| eq_elemental( Array const & a, Array const & b, Array< bool > & r ) | |
| { | |
| assert( a.size() == b.size() ); | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] == b[ i ] ); | |
| } | |
| } | |
| // Array != Array | |
| friend | |
| void | |
| ne_elemental( Array const & a, Array const & b, Array< bool > & r ) | |
| { | |
| assert( a.size() == b.size() ); | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] != b[ i ] ); | |
| } | |
| } | |
| // Array < Array | |
| friend | |
| void | |
| lt_elemental( Array const & a, Array const & b, Array< bool > & r ) | |
| { | |
| assert( a.size() == b.size() ); | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] < b[ i ] ); | |
| } | |
| } | |
| // Array <= Array | |
| friend | |
| void | |
| le_elemental( Array const & a, Array const & b, Array< bool > & r ) | |
| { | |
| assert( a.size() == b.size() ); | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] <= b[ i ] ); | |
| } | |
| } | |
| // Array > Array | |
| friend | |
| void | |
| gt_elemental( Array const & a, Array const & b, Array< bool > & r ) | |
| { | |
| assert( a.size() == b.size() ); | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] > b[ i ] ); | |
| } | |
| } | |
| // Array >= Array | |
| friend | |
| void | |
| ge_elemental( Array const & a, Array const & b, Array< bool > & r ) | |
| { | |
| assert( a.size() == b.size() ); | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] >= b[ i ] ); | |
| } | |
| } | |
| // Array == Value | |
| friend | |
| void | |
| eq_elemental( Array const & a, T const & t, Array< bool > & r ) | |
| { | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] == t ); | |
| } | |
| } | |
| // Array != Value | |
| friend | |
| void | |
| ne_elemental( Array const & a, T const & t, Array< bool > & r ) | |
| { | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] != t ); | |
| } | |
| } | |
| // Array < Value | |
| friend | |
| void | |
| lt_elemental( Array const & a, T const & t, Array< bool > & r ) | |
| { | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] < t ); | |
| } | |
| } | |
| // Array <= Value | |
| friend | |
| void | |
| le_elemental( Array const & a, T const & t, Array< bool > & r ) | |
| { | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] <= t ); | |
| } | |
| } | |
| // Array > Value | |
| friend | |
| void | |
| gt_elemental( Array const & a, T const & t, Array< bool > & r ) | |
| { | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] > t ); | |
| } | |
| } | |
| // Array >= Value | |
| friend | |
| void | |
| ge_elemental( Array const & a, T const & t, Array< bool > & r ) | |
| { | |
| assert( a.size() == r.size() ); | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| r[ i ] = ( a[ i ] >= t ); | |
| } | |
| } | |
| // Value == Array | |
| friend | |
| void | |
| eq_elemental( T const & t, Array const & b, Array< bool > & r ) | |
| { | |
| assert( b.size() == r.size() ); | |
| for ( size_type i = 0, e = b.size(); i < e; ++i ) { | |
| r[ i ] = ( t == b[ i ] ); | |
| } | |
| } | |
| // Value != Array | |
| friend | |
| void | |
| ne_elemental( T const & t, Array const & b, Array< bool > & r ) | |
| { | |
| assert( b.size() == r.size() ); | |
| for ( size_type i = 0, e = b.size(); i < e; ++i ) { | |
| r[ i ] = ( t != b[ i ] ); | |
| } | |
| } | |
| // Value < Array | |
| friend | |
| void | |
| lt_elemental( T const & t, Array const & b, Array< bool > & r ) | |
| { | |
| assert( b.size() == r.size() ); | |
| for ( size_type i = 0, e = b.size(); i < e; ++i ) { | |
| r[ i ] = ( t < b[ i ] ); | |
| } | |
| } | |
| // Value <= Array | |
| friend | |
| void | |
| le_elemental( T const & t, Array const & b, Array< bool > & r ) | |
| { | |
| assert( b.size() == r.size() ); | |
| for ( size_type i = 0, e = b.size(); i < e; ++i ) { | |
| r[ i ] = ( t <= b[ i ] ); | |
| } | |
| } | |
| // Value > Array | |
| friend | |
| void | |
| gt_elemental( T const & t, Array const & b, Array< bool > & r ) | |
| { | |
| assert( b.size() == r.size() ); | |
| for ( size_type i = 0, e = b.size(); i < e; ++i ) { | |
| r[ i ] = ( t > b[ i ] ); | |
| } | |
| } | |
| // Value >= Array | |
| friend | |
| void | |
| ge_elemental( T const & t, Array const & b, Array< bool > & r ) | |
| { | |
| assert( b.size() == r.size() ); | |
| for ( size_type i = 0, e = b.size(); i < e; ++i ) { | |
| r[ i ] = ( t >= b[ i ] ); | |
| } | |
| } | |
| protected: // Methods | |
| // Shift Setup | |
| void | |
| shift_set( difference_type const shift ) | |
| { | |
| shift_ = shift; | |
| sdata_ = data_ - shift_; | |
| } | |
| // Shift Setup Without Setting Shifted Data Pointer | |
| void | |
| shift_only_set( difference_type const shift ) | |
| { | |
| shift_ = shift; | |
| } | |
| // Active Array Size Setup | |
| void | |
| size_set( size_type const size ) | |
| { | |
| assert( size <= capacity_ ); | |
| size_ = size; | |
| } | |
| // Resize a Real Array: Return Whether Reallocation Happened | |
| bool | |
| resize( size_type const size ) | |
| { | |
| assert( owner_ ); | |
| assert( size != npos ); | |
| if ( ( data_ == nullptr ) || ( capacity_ < size ) || ( ( capacity_ == size_ ) && ( size != size_ ) ) ) { | |
| destroy(); | |
| capacity_ = size_ = size; | |
| mem_ = Aligned::allocate_zero( capacity_ ); | |
| data_ = Aligned::data( mem_ ); | |
| sdata_ = data_ - shift_; | |
| return true; // Reallocated: Elements not constructed | |
| } else { | |
| size_type i( size_ ); | |
| while ( i > size ) { // Destruct removed elements | |
| data_[ --i ].~T(); | |
| } | |
| size_ = size; | |
| sdata_ = data_ - shift_; | |
| return false; // Not reallocated | |
| } | |
| } | |
| // Reserve Capacity in a Real Array | |
| void | |
| reserve_capacity( size_type const n ) | |
| { | |
| assert( owner_ ); | |
| assert( n <= max_size ); | |
| if ( capacity_ < n ) { | |
| void * new_mem = Aligned::allocate_zero( n ); | |
| T * new_data = Aligned::data( new_mem ); | |
| if ( size_ > 0u ) uninitialized_move_or_copy( data_, data_ + size_, new_data ); | |
| destroy(); | |
| capacity_ = n; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| } | |
| } | |
| // Shrink Capacity to Size in a Real Array | |
| void | |
| shrink_capacity() | |
| { | |
| assert( owner_ ); | |
| if ( capacity_ > size_ ) { | |
| void * new_mem = Aligned::allocate_zero( size_ ); | |
| T * new_data = Aligned::data( new_mem ); | |
| if ( size_ > 0u ) uninitialized_move_or_copy( data_, data_ + size_, new_data ); | |
| destroy(); | |
| capacity_ = size_; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| } | |
| } | |
| // Append Value by Copy in a Real Array | |
| void | |
| do_push_back_copy( T const & t ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - 1 ); | |
| size_type const new_size( size_ + 1 ); | |
| assert( new_size <= max_size ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| new ( &new_data[ size_ ] ) T( t ); | |
| if ( size_ > 0u ) uninitialized_move_or_copy( data_, data_ + size_, new_data ); | |
| destroy(); | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| } else { | |
| new ( &data_[ size_ ] ) T( t ); | |
| } | |
| size_ = new_size; | |
| } | |
| // Append Value by Move in a Real Array | |
| void | |
| do_push_back_move( T && t ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - 1 ); | |
| size_type const new_size( size_ + 1 ); | |
| assert( new_size <= max_size ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| new ( &new_data[ size_ ] ) T( std::move( t ) ); | |
| if ( size_ > 0u ) uninitialized_move_or_copy( data_, data_ + size_, new_data ); | |
| destroy(); | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| } else { | |
| new ( &data_[ size_ ] ) T( std::move( t ) ); | |
| } | |
| size_ = new_size; | |
| } | |
| // Append Value by Move in a Real Array | |
| void | |
| do_pop_back() | |
| { | |
| if ( size_ > 0u ) { | |
| --size_; | |
| data_[ size_ ].~T(); | |
| } | |
| } | |
| // Insert Value by Copy in a Real Array | |
| iterator | |
| do_insert_copy( const_iterator pos, T const & t ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - 1 ); | |
| assert( data_ <= pos ); | |
| assert( pos <= end() ); | |
| size_type const new_size( size_ + 1 ); | |
| assert( new_size <= max_size ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| iterator const new_pos( new_data + ( pos - data_ ) ); | |
| new ( &*new_pos ) T( t ); | |
| if ( data_ < pos ) uninitialized_move_or_copy( data_, old_pos, new_data ); | |
| if ( pos < old_end ) uninitialized_move_or_copy( old_pos, old_end, new_pos + 1 ); | |
| destroy(); | |
| size_ = new_size; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| return new_pos; | |
| } else { | |
| if ( pos == old_end ) { | |
| new ( &*old_end ) T( t ); | |
| } else { | |
| T const tt( t ); | |
| uninitialized_move_or_copy( old_end - 1, old_end, old_end ); | |
| if ( size_ > 1u ) move_or_copy_backward( old_pos, old_end - 1, old_end ); | |
| *old_pos = tt; | |
| } | |
| size_ = new_size; | |
| return old_pos; | |
| } | |
| } | |
| // Insert Value by Move in a Real Array | |
| iterator | |
| do_insert_move( const_iterator pos, T && t ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - 1 ); | |
| assert( data_ <= pos ); | |
| assert( pos <= end() ); | |
| size_type const new_size( size_ + 1 ); | |
| assert( new_size <= max_size ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| iterator const new_pos( new_data + ( pos - data_ ) ); | |
| new ( &*new_pos ) T( std::move( t ) ); | |
| if ( data_ < pos ) uninitialized_move_or_copy( data_, old_pos, new_data ); | |
| if ( pos < old_end ) uninitialized_move_or_copy( old_pos, old_end, new_pos + 1 ); | |
| destroy(); | |
| size_ = new_size; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| return new_pos; | |
| } else { | |
| if ( pos == old_end ) { | |
| new ( &*old_end ) T( std::move( t ) ); | |
| } else { | |
| uninitialized_move_or_copy( old_end - 1, old_end, old_end ); | |
| if ( size_ > 1u ) move_or_copy_backward( old_pos, old_end - 1, old_end ); | |
| *old_pos = std::move( t ); | |
| } | |
| size_ = new_size; | |
| return old_pos; | |
| } | |
| } | |
| // Insert Multiples of a Value by Copy in a Real Array | |
| iterator | |
| do_insert_n( const_iterator pos, size_type n, T const & t ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - n ); | |
| assert( data_ <= pos ); | |
| assert( pos <= end() ); | |
| size_type const new_size( size_ + n ); | |
| assert( new_size <= max_size ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| iterator const new_pos( new_data + ( pos - data_ ) ); | |
| std::uninitialized_fill_n( new_pos, n, t ); | |
| if ( data_ < pos ) uninitialized_move_or_copy( data_, old_pos, new_data ); | |
| if ( pos < old_end ) uninitialized_move_or_copy( old_pos, old_end, new_pos + n ); | |
| destroy(); | |
| size_ = new_size; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| return new_pos; | |
| } else { | |
| if ( pos == old_end ) { | |
| std::uninitialized_fill_n( old_end, n, t ); | |
| } else { | |
| T const tt( t ); | |
| iterator const k( old_pos + n < old_end ? old_end - n : old_pos ); | |
| uninitialized_move_or_copy( k, old_end, k + n ); | |
| move_or_copy_backward( old_pos, k, old_end ); | |
| size_type const ni( std::min( n, static_cast< size_type >( old_end - old_pos ) ) ); | |
| std::fill_n( old_pos, ni, tt ); | |
| if ( ni < n ) std::uninitialized_fill_n( old_end, n - ni, tt ); | |
| } | |
| size_ = new_size; | |
| return old_pos; | |
| } | |
| } | |
| // Insert Iterator Range in a Real Array | |
| template< typename Iterator, class = typename std::enable_if< | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::input_iterator_tag >::value || | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::forward_iterator_tag >::value || | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::bidirectional_iterator_tag >::value || | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::random_access_iterator_tag >::value | |
| >::type > | |
| iterator | |
| do_insert_iterator( const_iterator pos, Iterator first, Iterator last ) // Like std containers first and last may not be iterators to this Array | |
| { | |
| assert( owner_ ); | |
| size_type const n( std::distance( first, last ) ); | |
| assert( size_ < npos - n ); | |
| assert( data_ <= pos ); | |
| assert( pos <= end() ); | |
| size_type const new_size( size_ + n ); | |
| assert( new_size <= max_size ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| iterator const new_pos( new_data + ( pos - data_ ) ); | |
| std::copy( first, last, new_pos ); | |
| if ( data_ < pos ) uninitialized_move_or_copy( data_, old_pos, new_data ); | |
| if ( pos < old_end ) uninitialized_move_or_copy( old_pos, old_end, new_pos + n ); | |
| destroy(); | |
| size_ = new_size; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| return new_pos; | |
| } else { | |
| if ( pos == old_end ) { | |
| std::uninitialized_copy( first, last, old_pos ); | |
| } else { | |
| iterator const k( old_pos + n < old_end ? old_end - n : old_pos ); | |
| uninitialized_move_or_copy( k, old_end, k + n ); | |
| move_or_copy_backward( old_pos, k, old_end ); | |
| size_type const ni( std::min( n, static_cast< size_type >( old_end - old_pos ) ) ); | |
| std::copy( first, first + ni, old_pos ); | |
| if ( ni < n ) std::uninitialized_copy( first + ni, last, old_pos + ni ); | |
| } | |
| size_ = new_size; | |
| return old_pos; | |
| } | |
| } | |
| // Insert Initializer List in a Real Array | |
| iterator | |
| do_insert_initializer_list( const_iterator pos, std::initializer_list< T > il ) | |
| { | |
| assert( owner_ ); | |
| size_type const n( il.size() ); | |
| assert( size_ < npos - n ); | |
| assert( data_ <= pos ); | |
| assert( pos <= end() ); | |
| size_type const new_size( size_ + n ); | |
| assert( new_size <= max_size ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| iterator const new_pos( new_data + ( pos - data_ ) ); | |
| std::copy( il.begin(), il.end(), new_pos ); | |
| if ( data_ < pos ) uninitialized_move_or_copy( data_, old_pos, new_data ); | |
| if ( pos < old_end ) uninitialized_move_or_copy( old_pos, old_end, new_pos + n ); | |
| destroy(); | |
| size_ = new_size; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| return new_pos; | |
| } else { | |
| if ( pos == old_end ) { | |
| std::uninitialized_copy( il.begin(), il.end(), old_pos ); | |
| } else { | |
| iterator const k( old_pos + n < old_end ? old_end - n : old_pos ); | |
| uninitialized_move_or_copy( k, old_end, k + n ); | |
| move_or_copy_backward( old_pos, k, old_end ); | |
| size_type const ni( std::min( n, static_cast< size_type >( old_end - old_pos ) ) ); | |
| std::copy( il.begin(), il.begin() + ni, old_pos ); | |
| if ( ni < n ) std::uninitialized_copy( il.begin() + ni, il.end(), old_pos + ni ); | |
| } | |
| size_ = new_size; | |
| return old_pos; | |
| } | |
| } | |
| // Insert Value Constructed in Place in a Real Array | |
| template< typename... Args > | |
| iterator | |
| do_emplace( const_iterator pos, Args &&... args ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - 1 ); | |
| assert( data_ <= pos ); | |
| assert( pos <= end() ); | |
| size_type const new_size( size_ + 1 ); | |
| assert( new_size <= max_size ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| iterator const new_pos( new_data + ( pos - data_ ) ); | |
| new ( &*new_pos ) T( std::forward< Args >( args )... ); | |
| if ( data_ < pos ) uninitialized_move_or_copy( data_, old_pos, new_data ); | |
| if ( pos < old_end ) uninitialized_move_or_copy( old_pos, old_end, new_pos + 1 ); | |
| destroy(); | |
| size_ = new_size; | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| return new_pos; | |
| } else { | |
| if ( pos == old_end ) { | |
| new ( &*pos ) T( std::forward< Args >( args )... ); | |
| } else { | |
| new ( &data_[ size_ ] ) T( data_[ size_ - 1 ] ); | |
| move_or_copy_backward( old_pos, old_end - 1, old_end ); | |
| *pos = T( std::forward< Args >( args )... ); | |
| } | |
| size_ = new_size; | |
| return old_pos; | |
| } | |
| } | |
| // Append Value Constructed in Place in a Real Array | |
| template< typename... Args > | |
| void | |
| do_emplace_back( Args &&... args ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ < npos - 1 ); | |
| size_type const new_size( size_ + 1 ); | |
| assert( new_size <= max_size ); | |
| if ( capacity_ < new_size ) { | |
| capacity_ = std::min( std::max( capacity_ << 1, new_size ), max_size ); | |
| void * const new_mem = Aligned::allocate_zero( capacity_ ); | |
| T * const new_data = Aligned::data( new_mem ); | |
| new ( &new_data[ size_ ] ) T( std::forward< Args >( args )... ); | |
| if ( size_ > 0u ) uninitialized_move_or_copy( data_, data_ + size_, new_data ); | |
| destroy(); | |
| mem_ = new_mem; | |
| data_ = new_data; | |
| sdata_ = data_ - shift_; | |
| } else { | |
| new ( &data_[ size_ ] ) T( std::forward< Args >( args )... ); | |
| } | |
| size_ = new_size; | |
| } | |
| // Erase Iterator in a Real Array | |
| iterator | |
| do_erase( const_iterator pos ) | |
| { | |
| assert( owner_ ); | |
| assert( data_ <= pos ); | |
| assert( pos < end() ); | |
| iterator const old_pos( data_ + ( pos - data_ ) ); | |
| iterator const old_end( end() ); | |
| move_or_copy( old_pos + 1, old_end, old_pos ); | |
| old_end->~T(); | |
| --size_; | |
| return old_pos; | |
| } | |
| // Erase Iterator Range in a Real Array | |
| iterator | |
| do_erase_iterator( const_iterator first, const_iterator last ) | |
| { | |
| assert( owner_ ); | |
| assert( ( data_ <= first ) || ( first == last ) ); | |
| assert( ( first <= last ) || ( first == last ) ); | |
| assert( ( last <= end() ) || ( first == last ) ); | |
| size_type const n( std::distance( first, last ) ); | |
| iterator const start( data_ + ( first - data_ ) ); | |
| if ( n > 0u ) { | |
| iterator const stop( data_ + ( last - data_ ) ); | |
| iterator const old_end( end() ); | |
| move_or_copy( stop, old_end, start ); | |
| for ( auto i = stop; i != old_end; ++i ) i->~T(); | |
| size_ -= n; | |
| } | |
| return start; | |
| } | |
| // Swap | |
| void | |
| swapB( Array & v ) | |
| { | |
| assert( owner_ ); | |
| assert( v.owner_ ); | |
| std::swap( capacity_, v.capacity_ ); | |
| std::swap( size_, v.size_ ); | |
| std::swap( mem_, v.mem_ ); | |
| std::swap( data_, v.data_ ); | |
| std::swap( shift_, v.shift_ ); | |
| std::swap( sdata_, v.sdata_ ); | |
| } | |
| // Initialize by Uniform Value | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| void | |
| initialize( U const & u ) | |
| { | |
| assert( owner_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( u ); | |
| } | |
| } | |
| // Initialize by Array | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| void | |
| initialize( Array< U > const & a ) | |
| { | |
| assert( owner_ ); | |
| assert( size_ == a.size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T( a[ i ] ); | |
| } | |
| } | |
| // Initialize an Element | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| void | |
| initialize( size_type const i, U const & u ) | |
| { | |
| assert( owner_ ); | |
| new ( data_ + i ) T( u ); | |
| } | |
| // Uniform Assignment | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| void | |
| assign( U const & u ) | |
| { | |
| assert( owner_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( u ); | |
| } | |
| } | |
| // Element Assignment | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| void | |
| assign( size_type const i, U const & u ) | |
| { | |
| data_[ i ] = T( u ); | |
| } | |
| // Assign Array | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| void | |
| assign( Array< U > const & a ) | |
| { | |
| assert( size_bounded() ); | |
| assert( size_ == a.size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( a[ i ] ); | |
| } | |
| } | |
| // Switch to Size Construction | |
| void | |
| reconstruct_by_size( size_type const size ) | |
| { | |
| assert( owner_ ); | |
| destroy(); | |
| capacity_ = size_ = size; | |
| assert( size_bounded() ); | |
| mem_ = Aligned::allocate_zero( capacity_ ); | |
| data_ = Aligned::data( mem_ ); | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| T const fill( Traits::initial_array_value() ); | |
| #endif | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| new ( data_ + i ) T( fill ); | |
| #else | |
| new ( data_ + i ) T; | |
| #endif | |
| } | |
| } | |
| // Conformable Move | |
| void | |
| conformable_move( Array & a ) | |
| { | |
| assert( this != &a ); | |
| assert( owner_ == a.owner_ ); | |
| destroy(); | |
| capacity_ = a.capacity_; | |
| mem_ = a.mem_; | |
| data_ = a.data_; | |
| sdata_ = data_ - shift_; | |
| a.capacity_ = a.size_ = 0u; | |
| a.mem_ = a.data_ = a.sdata_ = nullptr; | |
| a.shift_ = 0; | |
| } | |
| protected: // Static Methods | |
| // Array Size Product of Specified Bounded Dimensional Sizes | |
| static | |
| size_type | |
| size_of( size_type const s1 ) | |
| { | |
| assert( s1 != npos ); | |
| return s1; | |
| } | |
| // Array Size Product of Specified Bounded Dimensional Sizes | |
| static | |
| size_type | |
| size_of( size_type const s1, size_type const s2 ) | |
| { | |
| assert( s1 != npos ); | |
| assert( s2 != npos ); | |
| assert( ( s2 == 0 ) || ( s1 <= max_size / s2 ) ); | |
| return s1 * s2; | |
| } | |
| // Array Size Product of Specified Bounded Dimensional Sizes | |
| static | |
| size_type | |
| size_of( size_type const s1, size_type const s2, size_type const s3 ) | |
| { | |
| return size_of( size_of( s1, s2 ), s3 ); | |
| } | |
| // Array Size Product of Specified Bounded Dimensional Sizes | |
| static | |
| size_type | |
| size_of( size_type const s1, size_type const s2, size_type const s3, size_type const s4 ) | |
| { | |
| return size_of( size_of( s1, s2 ), size_of( s3, s4 ) ); | |
| } | |
| // Array Size Product of Specified Bounded Dimensional Sizes | |
| static | |
| size_type | |
| size_of( size_type const s1, size_type const s2, size_type const s3, size_type const s4, size_type const s5 ) | |
| { | |
| return size_of( size_of( size_of( s1, s2 ), size_of( s3, s4 ) ), s5 ); | |
| } | |
| // Array Size Product of Specified Bounded Dimensional Sizes | |
| static | |
| size_type | |
| size_of( size_type const s1, size_type const s2, size_type const s3, size_type const s4, size_type const s5, size_type const s6 ) | |
| { | |
| return size_of( size_of( size_of( s1, s2 ), size_of( s3, s4 ) ), size_of( s5, s6 ) ); | |
| } | |
| // Array Size Product of Specified Bounded IndexRanges | |
| static | |
| size_type | |
| size_of( IR const & I1 ) | |
| { | |
| return size_of( I1.size() ); | |
| } | |
| // Array Size Product of Specified Bounded IndexRanges | |
| static | |
| size_type | |
| size_of( IR const & I1, IR const & I2 ) | |
| { | |
| return size_of( I1.size(), I2.size() ); | |
| } | |
| // Array Size Product of Specified Bounded IndexRanges | |
| static | |
| size_type | |
| size_of( IR const & I1, IR const & I2, IR const & I3 ) | |
| { | |
| return size_of( I1.size(), I2.size(), I3.size() ); | |
| } | |
| // Array Size Product of Specified Bounded IndexRanges | |
| static | |
| size_type | |
| size_of( IR const & I1, IR const & I2, IR const & I3, IR const & I4 ) | |
| { | |
| return size_of( I1.size(), I2.size(), I3.size(), I4.size() ); | |
| } | |
| // Array Size Product of Specified Bounded IndexRanges | |
| static | |
| size_type | |
| size_of( IR const & I1, IR const & I2, IR const & I3, IR const & I4, IR const & I5 ) | |
| { | |
| return size_of( I1.size(), I2.size(), I3.size(), I4.size(), I5.size() ); | |
| } | |
| // Array Size Product of Specified Bounded IndexRanges | |
| static | |
| size_type | |
| size_of( IR const & I1, IR const & I2, IR const & I3, IR const & I4, IR const & I5, IR const & I6 ) | |
| { | |
| return size_of( I1.size(), I2.size(), I3.size(), I4.size(), I5.size(), I6.size() ); | |
| } | |
| // Slice Constant for a Scalar Index | |
| static | |
| std::int64_t | |
| slice_k( IR const & range, int const i, std::int64_t const multiplier = 1 ) | |
| { | |
| assert( range.contains( i ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( i ) ); | |
| (void)range; // Suppress unused warning in release builds | |
| return i * multiplier; | |
| } | |
| // Slice Constant for a Scalar Index | |
| static | |
| std::int64_t | |
| slice_k( IR const & range, int const i, size_type const multiplier ) | |
| { | |
| assert( range.contains( i ) ); | |
| assert( multiplier <= size_type( std::numeric_limits< std::int64_t >::max() / std::abs( i ) ) ); | |
| (void)range; // Suppress unused warning in release builds | |
| return i * multiplier; | |
| } | |
| // Slice Constant for a Scalar Index | |
| static | |
| std::int64_t | |
| slice_k( int const u, int const i, std::int64_t const multiplier = 1 ) | |
| { | |
| assert( ( 1 <= i ) && ( i <= u ) ); | |
| assert( multiplier <= std::numeric_limits< std::int64_t >::max() / std::abs( i ) ); | |
| (void)u; // Suppress unused warning in release builds | |
| return i * multiplier; | |
| } | |
| // Slice Constant for a Scalar Index | |
| static | |
| std::int64_t | |
| slice_k( int const u, int const i, size_type const multiplier ) | |
| { | |
| assert( ( 1 <= i ) && ( i <= u ) ); | |
| assert( multiplier <= size_type( std::numeric_limits< std::int64_t >::max() / std::abs( i ) ) ); | |
| (void)u; // Suppress unused warning in release builds | |
| return i * multiplier; | |
| } | |
| // Move if Movable: Movable Overload | |
| template< typename U, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| static | |
| U && | |
| move_if( U & u ) | |
| { | |
| return std::move( u ); | |
| } | |
| // Move if Movable: Non-Movable Overload | |
| template< typename U, class = typename std::enable_if< ! std::is_move_assignable< U >::value >::type, typename = void > | |
| static | |
| U & | |
| move_if( U & u ) | |
| { | |
| return u; | |
| } | |
| // Move or Copy: Move Overload | |
| template< typename InputIterator, typename OutputIterator, typename U = T, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| static | |
| OutputIterator | |
| move_or_copy( InputIterator beg, InputIterator end, OutputIterator out ) | |
| { | |
| return std::move( beg, end, out ); | |
| } | |
| // Move or Copy: Copy Overload | |
| template< typename InputIterator, typename OutputIterator, typename U = T, class = typename std::enable_if< ! std::is_move_assignable< U >::value >::type, typename = void > | |
| static | |
| OutputIterator | |
| move_or_copy( InputIterator beg, InputIterator end, OutputIterator out ) | |
| { | |
| return std::copy( beg, end, out ); | |
| } | |
| // Move or Copy Backward: Move Overload | |
| template< typename InputIterator, typename OutputIterator, typename U = T, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| static | |
| OutputIterator | |
| move_or_copy_backward( InputIterator beg, InputIterator end, OutputIterator out ) | |
| { | |
| return std::move_backward( beg, end, out ); | |
| } | |
| // Move or Copy Backward: Copy Overload | |
| template< typename InputIterator, typename OutputIterator, typename U = T, class = typename std::enable_if< ! std::is_move_assignable< U >::value >::type, typename = void > | |
| static | |
| OutputIterator | |
| move_or_copy_backward( InputIterator beg, InputIterator end, OutputIterator out ) | |
| { | |
| return std::copy_backward( beg, end, out ); | |
| } | |
| // Move or Copy: Move Overload | |
| template< typename InputIterator, typename OutputIterator, typename U = T, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| static | |
| OutputIterator | |
| uninitialized_move_or_copy( InputIterator beg, InputIterator end, OutputIterator out ) | |
| { | |
| return std::uninitialized_copy( std::make_move_iterator( beg ), std::make_move_iterator( end ), out ); | |
| } | |
| // Move or Copy: Copy Overload | |
| template< typename InputIterator, typename OutputIterator, typename U = T, class = typename std::enable_if< ! std::is_move_assignable< U >::value >::type, typename = void > | |
| static | |
| OutputIterator | |
| uninitialized_move_or_copy( InputIterator beg, InputIterator end, OutputIterator out ) | |
| { | |
| return std::uninitialized_copy( beg, end, out ); | |
| } | |
| private: // Methods | |
| // Destruct Elements and Delete Array Memory (Doesn't Nullify Pointers) | |
| void | |
| destroy() | |
| { | |
| if ( data_ != nullptr ) { | |
| size_type i( size_ ); | |
| while ( i ) { | |
| data_[ --i ].~T(); | |
| } | |
| } | |
| ::operator delete( mem_ ); | |
| } | |
| protected: // Data | |
| bool const owner_; // Owner of data array? | |
| size_type capacity_; // Size of data array | |
| size_type size_; // Size of active array | |
| void * mem_; // Pointer to raw memory | |
| T * data_; // Pointer to data array | |
| difference_type shift_; // Array shift | |
| T * sdata_; // Shifted pointer to data array | |
| }; // Array | |
| // Stream >> Array | |
| template< typename T > | |
| inline | |
| std::istream & | |
| operator >>( std::istream & stream, Array< T > & a ) | |
| { | |
| if ( stream && ( a.size() > 0u ) ) { | |
| for ( BArray::size_type i = 0, e = a.size(); i < e; ++i ) { | |
| stream >> a[ i ]; | |
| if ( ! stream ) break; | |
| } | |
| } | |
| return stream; | |
| } | |
| // Stream << Array | |
| template< typename T > | |
| inline | |
| std::ostream & | |
| operator <<( std::ostream & stream, Array< T > const & a ) | |
| { | |
| typedef TypeTraits< T > Traits; | |
| if ( stream && ( a.size() > 0u ) ) { | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| int const w( Traits::iwidth ); | |
| for ( BArray::size_type i = 0, e = a.size() - 1; i < e; ++i ) { | |
| stream << std::setw( w ) << a[ i ] << ' '; | |
| if ( ! stream ) break; | |
| } if ( stream ) stream << std::setw( w ) << a[ a.size() - 1 ]; | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| } | |
| return stream; | |
| } | |
| namespace fmt { | |
| // List-Directed Format: Array | |
| template< typename T > | |
| inline | |
| std::string | |
| LD( Array< T > const & a ) | |
| { | |
| std::string s; | |
| std::size_t const n( a.size() ); | |
| if ( n > 0u ) { | |
| s.reserve( n * TypeTraits< T >::width ); | |
| for ( std::size_t i = 0; i < n; ++i ) { | |
| s.append( fmt::LD( a[ i ] ) ); | |
| } | |
| } | |
| return s; | |
| } | |
| } // fmt | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array_hh_INCLUDED | |
| // ===== ObjexxFCL/Array1S.fwd.hh ===== | |
| #ifndef ObjexxFCL_Array1S_fwd_hh_INCLUDED | |
| #define ObjexxFCL_Array1S_fwd_hh_INCLUDED | |
| // Array1S Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Array1S; | |
| // Types | |
| typedef Array1S< bool > Array1S_bool; | |
| typedef Array1S< int > Array1S_int; | |
| typedef Array1S< std::string > Array1S_string; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array1S_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/ArrayRS.fwd.hh ===== | |
| #ifndef ObjexxFCL_ArrayRS_fwd_hh_INCLUDED | |
| #define ObjexxFCL_ArrayRS_fwd_hh_INCLUDED | |
| // ArrayRS Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename, int > class ArrayRS; | |
| // Types | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_ArrayRS_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/ArrayRS.hh ===== | |
| #ifndef ObjexxFCL_ArrayRS_hh_INCLUDED | |
| #define ObjexxFCL_ArrayRS_hh_INCLUDED | |
| // ArrayRS: Rank Slice Array Proxy Abstract Base Class Template | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| namespace ObjexxFCL { | |
| // ArrayRS: Rank Slice Array Proxy Abstract Base Class Template | |
| template< typename T, int Rank > | |
| class ArrayRS : public ArrayS< T > | |
| { | |
| private: // Types | |
| typedef ArrayS< T > Super; | |
| private: // Friend | |
| template< typename, int > friend class ArrayRS; | |
| public: // Types | |
| typedef typename Super::Base Base; | |
| typedef typename Super::Traits Traits; | |
| typedef typename Super::IR IR; | |
| typedef typename Super::IS IS; | |
| typedef typename Super::DS DS; | |
| // STL Style | |
| typedef typename Super::value_type value_type; | |
| typedef typename Super::reference reference; | |
| typedef typename Super::const_reference const_reference; | |
| typedef typename Super::pointer pointer; | |
| typedef typename Super::const_pointer const_pointer; | |
| typedef typename Super::size_type size_type; | |
| typedef typename Super::difference_type difference_type; | |
| // C++ Style | |
| typedef typename Super::Value Value; | |
| typedef typename Super::Reference Reference; | |
| typedef typename Super::ConstReference ConstReference; | |
| typedef typename Super::Pointer Pointer; | |
| typedef typename Super::ConstPointer ConstPointer; | |
| typedef typename Super::Size Size; | |
| typedef typename Super::Difference Difference; | |
| using Super::isize; | |
| using Super::overlap; | |
| using Super::size; | |
| protected: // Types | |
| using Super::in_range; | |
| using Super::slice_k; | |
| using Super::contiguous_; | |
| using Super::data_; | |
| using Super::data_beg_; | |
| using Super::data_end_; | |
| using Super::size_; | |
| protected: // Creation | |
| // Default Constructor | |
| ArrayRS() | |
| {} | |
| // Copy Constructor | |
| ArrayRS( ArrayRS const & a ) : | |
| Super( a ) | |
| {} | |
| // Data Constructor | |
| ArrayRS( T const * data, size_type const size ) : | |
| Super( data, size ) | |
| {} | |
| // Non-Const Data Constructor | |
| ArrayRS( T * data, size_type const size ) : | |
| Super( data, size ) | |
| {} | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~ArrayRS() = default; | |
| public: // Predicate | |
| // Conformable? | |
| template< template< typename > class A, typename U > | |
| bool | |
| conformable( A< U > const & a ) const | |
| { | |
| if ( Rank != a.rank() ) return false; | |
| for ( int i = 1; i <= Rank; ++i ) if ( size( i ) != a.size( i ) ) return false; | |
| return true; | |
| } | |
| public: // Inspector | |
| // Rank | |
| int | |
| rank() const | |
| { | |
| return Rank; | |
| } | |
| }; // ArrayRS | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_ArrayRS_hh_INCLUDED | |
| // ===== ObjexxFCL/CArray.fwd.hh ===== | |
| #ifndef ObjexxFCL_CArray_fwd_hh_INCLUDED | |
| #define ObjexxFCL_CArray_fwd_hh_INCLUDED | |
| // CArray Forward Declarations | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // C++ Headers | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <string> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class CArray; | |
| // Types | |
| typedef CArray< bool > CArray_bool; | |
| typedef CArray< short int > CArray_short; | |
| typedef CArray< int > CArray_int; | |
| typedef CArray< std::size_t > CArray_size; | |
| typedef CArray< double > CArray_double; | |
| typedef CArray< signed char > CArray_schar; | |
| typedef CArray< std::string > CArray_string; | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_CArray_fwd_hh_INCLUDED | |
| // ===== ObjexxFCL/CArray.hh ===== | |
| #ifndef ObjexxFCL_CArray_hh_INCLUDED | |
| #define ObjexxFCL_CArray_hh_INCLUDED | |
| // CArray: Memory-Managed C Array Wrapper | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <algorithm> | |
| #include <cassert> | |
| #include <cmath> | |
| #include <cstddef> | |
| #include <initializer_list> | |
| #include <iomanip> | |
| #include <istream> | |
| #include <iterator> | |
| #include <ostream> | |
| #include <type_traits> | |
| #include <utility> | |
| namespace ObjexxFCL { | |
| // CArray: Memory-Managed C Array Wrapper | |
| template< typename T > | |
| class CArray | |
| { | |
| private: // Friend | |
| template< typename > friend class CArray; // Friendship across value types | |
| public: // Types | |
| typedef TypeTraits< T > Traits; | |
| typedef typename std::conditional< std::is_scalar< T >::value, T const, T const & >::type Tc; | |
| typedef typename std::conditional< std::is_scalar< T >::value, typename std::remove_const< T >::type, T const & >::type Tr; | |
| // STL Style | |
| typedef T value_type; | |
| typedef T & reference; | |
| typedef T const & const_reference; | |
| typedef T * pointer; | |
| typedef T const * const_pointer; | |
| typedef T * iterator; | |
| typedef T const * const_iterator; | |
| typedef std::reverse_iterator< T * > reverse_iterator; | |
| typedef std::reverse_iterator< T const * > const_reverse_iterator; | |
| typedef std::size_t size_type; | |
| typedef std::ptrdiff_t difference_type; | |
| // C++ Style | |
| typedef T Value; | |
| typedef T & Reference; | |
| typedef T const & ConstReference; | |
| typedef T * Pointer; | |
| typedef T const * ConstPointer; | |
| typedef T * Iterator; | |
| typedef T const * ConstIterator; | |
| typedef std::reverse_iterator< T * > ReverseIterator; | |
| typedef std::reverse_iterator< T const * > ConstReverseIterator; | |
| typedef std::size_t Size; | |
| typedef std::ptrdiff_t Difference; | |
| // Types to prevent compile failure when std::distance is in scope | |
| typedef void iterator_category; | |
| public: // Creation | |
| // Default Constructor | |
| CArray() : | |
| size_( 0u ), | |
| data_( nullptr ) | |
| {} | |
| // Copy Constructor | |
| CArray( CArray const & a ) : | |
| size_( a.size_ ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = a.data_[ i ]; | |
| } | |
| } | |
| // Move Constructor | |
| CArray( CArray && a ) noexcept : | |
| size_( a.size_ ), | |
| data_( a.data_ ) | |
| { | |
| a.size_ = 0u; | |
| a.data_ = nullptr; | |
| } | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| CArray( CArray< U > const & a ) : | |
| size_( a.size_ ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( a.data_[ i ] ); | |
| } | |
| } | |
| // Pointer + Size Constructor | |
| CArray( | |
| T const * const p, | |
| size_type const size | |
| ) : | |
| size_( size ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = p[ i ]; | |
| } | |
| } | |
| // Pointer + Size Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| CArray( | |
| U const * const p, | |
| size_type const size | |
| ) : | |
| size_( size ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( p[ i ] ); | |
| } | |
| } | |
| // Iterator Range Constructor Template | |
| template< typename InputIterator > | |
| CArray( | |
| InputIterator const beg, | |
| InputIterator const end | |
| ) : | |
| size_( end - beg ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| if ( size_ > 0u ) { | |
| InputIterator k( beg ); | |
| for ( size_type i = 0; i < size_; ++i, ++k ) { | |
| data_[ i ] = T( *k ); | |
| } | |
| } | |
| } | |
| // Size Constructor: Built-in types are default, not zero, initialized for performance | |
| explicit | |
| CArray( size_type const size ) : | |
| size_( size ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| {} | |
| // Size + Uniform Value Constructor | |
| CArray( | |
| size_type const size, | |
| Tc t | |
| ) : | |
| size_( size ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = t; | |
| } | |
| } | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| CArray( std::initializer_list< U > const l ) : | |
| size_( l.size() ), | |
| data_( size_ > 0u ? new T[ size_ ] : nullptr ) | |
| { | |
| std::copy( l.begin(), l.end(), data_ ); | |
| } | |
| // Destructor | |
| ~CArray() | |
| { | |
| delete[] data_; | |
| } | |
| public: // Conversion | |
| // Active? | |
| operator bool() const | |
| { | |
| return ( data_ != nullptr ); | |
| } | |
| // Data | |
| operator T const *() const | |
| { | |
| return data_; | |
| } | |
| // Data | |
| operator T *() | |
| { | |
| return data_; | |
| } | |
| public: // Assignment | |
| // Copy Assignment | |
| CArray & | |
| operator =( CArray const & a ) | |
| { | |
| if ( this != &a ) { | |
| if ( size_ != a.size_ ) { | |
| size_ = a.size_; | |
| delete[] data_; data_ = ( size_ > 0u ? new T[ size_ ] : nullptr ); | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = a.data_[ i ]; | |
| } | |
| } | |
| return *this; | |
| } | |
| // Move Assignment | |
| CArray & | |
| operator =( CArray && a ) noexcept | |
| { | |
| assert( this != &a ); | |
| size_ = a.size_; | |
| delete[] data_; data_ = a.data_; | |
| a.size_ = 0u; | |
| a.data_ = nullptr; | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArray & | |
| operator =( CArray< U > const & a ) | |
| { | |
| if ( size_ != a.size_ ) { | |
| size_ = a.size_; | |
| delete[] data_; data_ = ( size_ > 0u ? new T[ size_ ] : nullptr ); | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( a.data_[ i ] ); | |
| } | |
| return *this; | |
| } | |
| // Uniform Value Assignment | |
| CArray & | |
| operator =( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = t; | |
| } | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArray & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( l.size() == size_ ); | |
| std::copy( l.begin(), l.end(), data_ ); | |
| return *this; | |
| } | |
| // Pointer + Size Assignment | |
| CArray & | |
| assign( | |
| T const * const p, | |
| size_type const size | |
| ) | |
| { | |
| if ( size_ != size ) { | |
| size_ = size; | |
| delete[] data_; data_ = ( size_ > 0u ? new T[ size_ ] : nullptr ); | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = p[ i ]; | |
| } | |
| return *this; | |
| } | |
| // Pointer + Size Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArray & | |
| assign( | |
| U const * const p, | |
| size_type const size | |
| ) | |
| { | |
| if ( size_ != size ) { | |
| size_ = size; | |
| delete[] data_; data_ = ( size_ > 0u ? new T[ size_ ] : nullptr ); | |
| } | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] = T( p[ i ] ); | |
| } | |
| return *this; | |
| } | |
| // Iterator Range Assignment Template | |
| template< typename InputIterator > | |
| CArray & | |
| assign( | |
| InputIterator const beg, | |
| InputIterator const end | |
| ) | |
| { | |
| size_type const size( end - beg ); | |
| if ( size_ != size ) { | |
| size_ = size; | |
| delete[] data_; data_ = ( size_ > 0u ? new T[ size_ ] : nullptr ); | |
| } | |
| if ( size_ > 0u ) { | |
| InputIterator k( beg ); | |
| for ( size_type i = 0; i < size_; ++i, ++k ) { | |
| data_[ i ] = T( *k ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Size + Value Assignment | |
| CArray & | |
| assign( | |
| size_type const size, | |
| Tc t | |
| ) | |
| { | |
| if ( size_ != size ) { // Set to new array with uniform values | |
| CArray( size, t ).swap( *this ); | |
| } else { // Set to uniform value | |
| (*this) = t; | |
| } | |
| return *this; | |
| } | |
| // += CArray | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArray & | |
| operator +=( CArray< U > const & a ) | |
| { | |
| assert( size_ == a.size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += T( a.data_[ i ] ); | |
| } | |
| return *this; | |
| } | |
| // -= CArray | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| CArray & | |
| operator -=( CArray< U > const & a ) | |
| { | |
| assert( size_ == a.size_ ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= T( a.data_[ i ] ); | |
| } | |
| return *this; | |
| } | |
| // += Value | |
| CArray & | |
| operator +=( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] += t; | |
| } | |
| return *this; | |
| } | |
| // -= Value | |
| CArray & | |
| operator -=( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] -= t; | |
| } | |
| return *this; | |
| } | |
| // *= Value | |
| CArray & | |
| operator *=( Tc t ) | |
| { | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= t; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| CArray & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] *= inv_u; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| CArray & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| data_[ i ] /= u; | |
| } | |
| return *this; | |
| } | |
| public: // Predicate | |
| // Active? | |
| bool | |
| active() const | |
| { | |
| return ( data_ != nullptr ); | |
| } | |
| // Empty? | |
| bool | |
| empty() const | |
| { | |
| return ( size_ == 0u ); | |
| } | |
| public: // Inspector | |
| // Size | |
| size_type | |
| size() const | |
| { | |
| return size_; | |
| } | |
| // Lower Index | |
| size_type | |
| l() const | |
| { | |
| return 0u; | |
| } | |
| // Upper index | |
| size_type | |
| u() const | |
| { | |
| return size_ - 1u; // npos if size_ == 0 | |
| } | |
| // First Element | |
| Tr | |
| front() const | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ 0 ]; | |
| } | |
| // Last Element | |
| Tr | |
| back() const | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ size_ - 1 ]; | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| T length_sq( T( 0 ) ); | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| length_sq += data_[ i ] * data_[ i ]; | |
| } | |
| return std::sqrt( length_sq ); | |
| } | |
| public: // Modifier | |
| // First Element | |
| T & | |
| front() | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ 0 ]; | |
| } | |
| // Last Element | |
| T & | |
| back() | |
| { | |
| assert( size_ > 0u ); | |
| return data_[ size_ - 1 ]; | |
| } | |
| // Resize: Values not Preserved | |
| // Built-in values are uninitialized if size changes | |
| CArray & | |
| size( size_type const size ) | |
| { | |
| if ( size_ != size ) { // Set to new array | |
| CArray( size ).swap( *this ); | |
| } | |
| return *this; | |
| } | |
| // Resize to Size With Fill Value: Values Preserved | |
| CArray & | |
| resize( | |
| size_type const size, | |
| Tc fill = T() | |
| ) | |
| { | |
| if ( size_ < size ) { | |
| CArray a( size, fill ); // New array: Elements set to fill fill | |
| for ( size_type i = 0; i < size_; ++i ) { // Copy current values | |
| a.data_[ i ] = data_[ i ]; | |
| } | |
| swap( a ); // Swap in new array | |
| } else if ( size_ > size ) { | |
| CArray a( size ); // New array | |
| for ( size_type i = 0; i < size; ++i ) { // Copy current values within new range | |
| a.data_[ i ] = data_[ i ]; | |
| } | |
| swap( a ); // Swap in new array | |
| } | |
| return *this; | |
| } | |
| // Swap | |
| void | |
| swap( CArray & a ) | |
| { | |
| std::swap( size_, a.size_ ); | |
| std::swap( data_, a.data_ ); | |
| } | |
| // Clear | |
| CArray & | |
| clear() | |
| { | |
| size_ = 0u; | |
| delete[] data_; data_ = nullptr; | |
| return *this; | |
| } | |
| // Normalize to Unit Length | |
| CArray & | |
| normalize() | |
| { | |
| T const length_( length() ); | |
| assert( length_ > T( 0 ) ); | |
| operator /=( length_ ); | |
| return *this; | |
| } | |
| public: // Subscript | |
| // CArray[ i ] const: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value && std::is_const< T >::value >::type > | |
| Tr | |
| operator []( I const i ) const | |
| { | |
| assert( i < size_ ); | |
| return data_[ i ]; | |
| } | |
| // CArray[ i ] const: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value && std::is_const< T >::value >::type, typename = void > | |
| Tr | |
| operator []( I const i ) const | |
| { | |
| assert( ( i >= 0 ) && ( static_cast< size_type >( i ) < size_ ) ); | |
| return data_[ i ]; | |
| } | |
| // CArray[ i ]: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value >::type > | |
| T & | |
| operator []( I const i ) | |
| { | |
| assert( i < size_ ); | |
| return data_[ i ]; | |
| } | |
| // CArray[ i ]: 0-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value >::type, typename = void > | |
| T & | |
| operator []( I const i ) | |
| { | |
| assert( ( i >= 0 ) && ( static_cast< size_type >( i ) < size_ ) ); | |
| return data_[ i ]; | |
| } | |
| // CArray( i ) const: 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value && std::is_const< T >::value >::type > | |
| Tr | |
| operator ()( I const i ) const | |
| { | |
| assert( ( i > 0u ) && ( i <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| // CArray( i ) const: 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value && std::is_const< T >::value >::type, typename = void > | |
| Tr | |
| operator ()( I const i ) const | |
| { | |
| assert( ( i > 0 ) && ( static_cast< size_type >( i ) <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| // CArray( i ): 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_unsigned< I >::value >::type > | |
| T & | |
| operator ()( I const i ) | |
| { | |
| assert( ( i > 0u ) && ( i <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| // CArray( i ): 1-Based Indexing | |
| template< typename I, class = typename std::enable_if< std::is_integral< I >::value && std::is_signed< I >::value >::type, typename = void > | |
| T & | |
| operator ()( I const i ) | |
| { | |
| assert( ( i > 0 ) && ( static_cast< size_type >( i ) <= size_ ) ); | |
| return data_[ i - 1 ]; | |
| } | |
| public: // Iterator | |
| // Begin Iterator | |
| const_iterator | |
| begin() const | |
| { | |
| return data_; | |
| } | |
| // Begin Iterator | |
| iterator | |
| begin() | |
| { | |
| return data_; | |
| } | |
| // End Iterator | |
| const_iterator | |
| end() const | |
| { | |
| return ( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // End Iterator | |
| iterator | |
| end() | |
| { | |
| return ( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse Begin Iterator | |
| const_reverse_iterator | |
| rbegin() const | |
| { | |
| return const_reverse_iterator( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse Begin Iterator | |
| reverse_iterator | |
| rbegin() | |
| { | |
| return reverse_iterator( data_ != nullptr ? data_ + size_ : nullptr ); | |
| } | |
| // Reverse End Iterator | |
| const_reverse_iterator | |
| rend() const | |
| { | |
| return const_reverse_iterator( data_ ); | |
| } | |
| // Reverse End Iterator | |
| reverse_iterator | |
| rend() | |
| { | |
| return reverse_iterator( data_ ); | |
| } | |
| public: // Array Accessor | |
| // C Array const Accessor | |
| T const * | |
| operator ()() const | |
| { | |
| return data_; | |
| } | |
| // C Array Non-const Accessor | |
| T * | |
| operator ()() | |
| { | |
| return data_; | |
| } | |
| private: // Data | |
| size_type size_; // Number of array elements | |
| T * data_; // C array | |
| }; // CArray | |
| // Functions | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( CArray< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| mag_sq += a[ i ] * a[ i ]; | |
| } | |
| return std::sqrt( mag_sq ); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( CArray< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| mag_sq += a[ i ] * a[ i ]; | |
| } | |
| return mag_sq; | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| T const distance_i( a[ i ] - b[ i ] ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| T const distance_i( a[ i ] - b[ i ] ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T sum( T( 0 ) ); | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| sum += a[ i ] * b[ i ]; | |
| } | |
| return sum; | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot_product( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T sum( T( 0 ) ); | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| sum += a[ i ] * b[ i ]; | |
| } | |
| return sum; | |
| } | |
| // Swap | |
| template< typename T > | |
| inline | |
| void | |
| swap( CArray< T > & a, CArray< T > & b ) | |
| { | |
| a.swap( b ); | |
| } | |
| // Comparison | |
| // Are Two CArrays Comparable? | |
| template< typename T > | |
| inline | |
| bool | |
| comparable( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| return ( a.size() == b.size() ); | |
| } | |
| // CArray == CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return true; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] == b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArray != CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| return !( a == b ); | |
| } | |
| // CArray < CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return false; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] < b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArray <= CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return true; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] <= b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArray >= CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return true; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] >= b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArray > CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| if ( &a == &b ) { // Same objects | |
| return false; | |
| } else if ( a.size() != b.size() ) { // Sizes differ | |
| return false; | |
| } else { // Compare values | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] > b[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| } | |
| // CArray == Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( a[ i ] != t ) return false; | |
| } | |
| return true; | |
| } | |
| // CArray != Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| return !( a == t ); | |
| } | |
| // CArray < Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] < t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // CArray <= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] <= t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // CArray >= Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] >= t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // CArray > Value | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( a[ i ] > t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value == CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator ==( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| return ( a == t ); | |
| } | |
| // Value != CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator !=( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| return !( t == a ); | |
| } | |
| // Value < CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator <( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t < a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value <= CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator <=( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t <= a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value >= CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator >=( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t >= a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Value > CArray | |
| template< typename T > | |
| inline | |
| bool | |
| operator >( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| for ( typename CArray< T >::size_type i = 0, ie = a.size(); i < ie; ++i ) { | |
| if ( !( t > a[ i ] ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Generator | |
| // -CArray | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator -( CArray< T > const & a ) | |
| { | |
| CArray< T > r( a ); | |
| r *= T( -1 ); | |
| return r; | |
| } | |
| // CArray + CArray | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator +( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| CArray< T > r( a ); | |
| r += b; | |
| return r; | |
| } | |
| // CArray - CArray | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator -( CArray< T > const & a, CArray< T > const & b ) | |
| { | |
| CArray< T > r( a ); | |
| r -= b; | |
| return r; | |
| } | |
| // CArray + Value | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator +( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| CArray< T > r( a ); | |
| r += t; | |
| return r; | |
| } | |
| // Value + CArray | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator +( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| CArray< T > r( a ); | |
| r += t; | |
| return r; | |
| } | |
| // CArray - Value | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator -( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| CArray< T > r( a ); | |
| r -= t; | |
| return r; | |
| } | |
| // Value - CArray | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator -( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| CArray< T > r( -a ); | |
| r += t; | |
| return r; | |
| } | |
| // CArray * Value | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator *( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| CArray< T > r( a ); | |
| r *= t; | |
| return r; | |
| } | |
| // Value * CArray | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator *( typename CArray< T >::Tc t, CArray< T > const & a ) | |
| { | |
| CArray< T > r( a ); | |
| r *= t; | |
| return r; | |
| } | |
| // CArray / Value | |
| template< typename T > | |
| inline | |
| CArray< T > | |
| operator /( CArray< T > const & a, typename CArray< T >::Tc t ) | |
| { | |
| CArray< T > r( a ); | |
| r /= t; | |
| return r; | |
| } | |
| // Stream >> CArray | |
| template< typename T > | |
| inline | |
| std::istream & | |
| operator >>( std::istream & stream, CArray< T > & a ) | |
| { | |
| typedef typename CArray< T >::size_type size_type; | |
| if ( stream && ( ! a.emtpy() ) ) { | |
| for ( size_type i = 0, e = a.size(); i < e; ++i ) { | |
| stream >> a[ i ]; | |
| if ( ! stream ) break; | |
| } | |
| } | |
| return stream; | |
| } | |
| // Stream << CArray | |
| template< typename T > | |
| inline | |
| std::ostream & | |
| operator <<( std::ostream & stream, CArray< T > const & a ) | |
| { | |
| using std::setw; | |
| typedef TypeTraits< T > Traits; | |
| typedef typename CArray< T >::size_type size_type; | |
| if ( stream && ( ! a.emtpy() ) ) { | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| size_type const e( a.size() - 1 ); | |
| int const w( Traits::iwidth ); | |
| for ( size_type i = 0; i < e; ++i ) { | |
| stream << setw( w ) << a[ i ] << ' '; | |
| } stream << setw( w ) << a[ e ]; | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| } | |
| return stream; | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_CArray_hh_INCLUDED | |
| // ===== ObjexxFCL/Array1S.hh ===== | |
| #ifndef ObjexxFCL_Array1S_hh_INCLUDED | |
| #define ObjexxFCL_Array1S_hh_INCLUDED | |
| // Array1S: 1D Slice Array Proxy | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <array> | |
| #include <vector> | |
| namespace ObjexxFCL { | |
| // Array1S: 1D Slice Array Proxy | |
| template< typename T > | |
| class Array1S : public ArrayRS< T, 1 > | |
| { | |
| private: // Types | |
| typedef ArrayRS< T, 1 > Super; | |
| private: // Friend | |
| template< typename > friend class Array1S; | |
| public: // Types | |
| typedef typename Super::Base Base; | |
| typedef typename Super::Traits Traits; | |
| typedef typename Super::IR IR; | |
| typedef typename Super::IS IS; | |
| typedef typename Super::DS DS; | |
| // STL Style | |
| typedef typename Super::value_type value_type; | |
| typedef typename Super::reference reference; | |
| typedef typename Super::const_reference const_reference; | |
| typedef typename Super::pointer pointer; | |
| typedef typename Super::const_pointer const_pointer; | |
| typedef typename Super::size_type size_type; | |
| typedef typename Super::difference_type difference_type; | |
| // C++ Style | |
| typedef typename Super::Value Value; | |
| typedef typename Super::Reference Reference; | |
| typedef typename Super::ConstReference ConstReference; | |
| typedef typename Super::Pointer Pointer; | |
| typedef typename Super::ConstPointer ConstPointer; | |
| typedef typename Super::Size Size; | |
| typedef typename Super::Difference Difference; | |
| using Super::isize; | |
| using Super::overlap; | |
| using Super::size; | |
| protected: // Types | |
| using Super::in_range; | |
| using Super::slice_k; | |
| using Super::contiguous_; | |
| using Super::data_; | |
| using Super::data_beg_; | |
| using Super::data_end_; | |
| using Super::size_; | |
| public: // Creation | |
| // Default Constructor | |
| Array1S() : | |
| m_( 1 ), | |
| k_( 0 ), | |
| u_( 0 ) | |
| {} | |
| // Copy Constructor | |
| Array1S( Array1S const & a ) : | |
| Super( a ), | |
| m_( a.m_ ), | |
| k_( a.k_ ), | |
| u_( a.u_ ) | |
| { | |
| data_set(); | |
| } | |
| // Data Constructor | |
| Array1S( T const * data, std::int64_t const k, DS const & d ) : | |
| Super( data, d.z() ), | |
| m_( d.m() ), | |
| k_( k + d.k() ), | |
| u_( d.u() ) | |
| { | |
| contiguous_ = computed_contiguous(); | |
| data_set(); | |
| } | |
| // Non-Const Data Constructor | |
| Array1S( T * data, std::int64_t const k, DS const & d ) : | |
| Super( data, d.z() ), | |
| m_( d.m() ), | |
| k_( k + d.k() ), | |
| u_( d.u() ) | |
| { | |
| contiguous_ = computed_contiguous(); | |
| data_set(); | |
| } | |
| // Array Constructor | |
| template< template< typename > class A > | |
| Array1S( A< T > const & a ) : | |
| Super( a.data(), a.size() ), | |
| m_( 1 ), | |
| k_( -m_ ), | |
| u_( a.isize() ) | |
| { | |
| contiguous_ = true; | |
| data_set(); | |
| } | |
| // Destructor | |
| virtual | |
| ~Array1S() = default; | |
| public: // Assignment: Array | |
| // Copy Assignment | |
| Array1S & | |
| operator =( Array1S const & a ) | |
| { | |
| if ( this != &a ) { | |
| assert( conformable( a ) ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArray< T > c( size_ ); | |
| for ( int i = 1; i <= u_; ++i ) { | |
| c( i ) = a( i ); | |
| } | |
| for ( int i = 1; i <= u_; ++i ) { | |
| operator ()( i ) = c( i ); | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1; i <= u_; ++i ) { | |
| operator ()( i ) = a( i ); | |
| } | |
| } | |
| } | |
| return *this; | |
| } | |
| // += Array Template | |
| template< template< typename > class A > | |
| Array1S & | |
| operator +=( A< T > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArray< T > c( size_ ); | |
| for ( int i = 1, j = a.l(); i <= u_; ++i, ++j ) { | |
| c( i ) = a( j ); | |
| } | |
| for ( int i = 1; i <= u_; ++i ) { | |
| operator ()( i ) += c( i ); | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1, j = a.l(); i <= u_; ++i, ++j ) { | |
| operator ()( i ) += a( j ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // *= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1S & | |
| operator *=( std::array< U, s > const & a ) | |
| { | |
| assert( size_ == s ); | |
| auto r( a.begin() ); | |
| for ( int i = 1; i <= u_; ++i, ++r ) { | |
| operator ()( i ) *= *r; | |
| } | |
| return *this; | |
| } | |
| // += std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1S & | |
| operator +=( std::array< U, s > const & a ) | |
| { | |
| assert( size_ == s ); | |
| auto r( a.begin() ); | |
| for ( int i = 1; i <= u_; ++i, ++r ) { | |
| operator ()( i ) += *r; | |
| } | |
| return *this; | |
| } | |
| public: // Assignment: Value | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1S & | |
| operator =( std::array< U, s > const & a ) | |
| { | |
| assert( size_ == s ); | |
| auto r( a.begin() ); | |
| for ( int i = 1; i <= u_; ++i, ++r ) { | |
| operator ()( i ) = *r; | |
| } | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1S & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( size_ == l.size() ); | |
| auto r( l.begin() ); | |
| for ( int i = 1; i <= u_; ++i, ++r ) { | |
| operator ()( i ) = *r; | |
| } | |
| return *this; | |
| } | |
| // = Value | |
| Array1S &operator=(T const &t) { | |
| for (int i = 1; i <= u_; ++i) { | |
| operator()(i) = t; | |
| } | |
| return *this; | |
| } | |
| // *= Value | |
| Array1S & | |
| operator *=( T const & t ) | |
| { | |
| for ( int i = 1; i <= u_; ++i ) { | |
| operator ()( i ) *= t; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type > | |
| Array1S & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| U const inv_u( U( 1 ) / u ); | |
| for ( int i = 1; i <= u_; ++i ) { | |
| operator ()( i ) *= inv_u; | |
| } | |
| return *this; | |
| } | |
| // /= Value | |
| template< typename U, class = typename std::enable_if< ! std::is_floating_point< U >::value && std::is_assignable< T&, U >::value >::type, typename = void > | |
| Array1S & | |
| operator /=( U const & u ) | |
| { | |
| assert( u != U( 0 ) ); | |
| for ( int i = 1; i <= u_; ++i ) { | |
| operator ()( i ) /= u; | |
| } | |
| return *this; | |
| } | |
| public: // Subscript | |
| // array( i ) const | |
| T const & | |
| operator ()( int const i ) const | |
| { | |
| assert( contains( i ) ); | |
| return data_[ k_ + ( m_ * i ) ]; | |
| } | |
| // array( i ) | |
| T & | |
| operator ()( int const i ) | |
| { | |
| assert( contains( i ) ); | |
| return data_[ k_ + ( m_ * i ) ]; | |
| } | |
| // Linear Index | |
| size_type | |
| index( int const i ) const | |
| { | |
| return k_ + ( m_ * i ); | |
| } | |
| // array[ i ] const: 0-Based Subscript | |
| T const & | |
| operator []( size_type const i ) const | |
| { | |
| assert( i < std::numeric_limits< size_type >::max() ); | |
| assert( contains( static_cast< int >( i + 1 ) ) ); | |
| return data_[ k_ + ( m_ * ( i + 1 ) ) ]; | |
| } | |
| // array[ i ]: 0-Based Subscript | |
| T & | |
| operator []( size_type const i ) | |
| { | |
| assert( i < std::numeric_limits< int >::max() ); | |
| assert( contains( static_cast< int >( i + 1 ) ) ); | |
| return data_[ k_ + ( m_ * ( i + 1 ) ) ]; | |
| } | |
| public: // Slice Proxy Generators | |
| // array( s ) const | |
| Array1S | |
| operator ()( IS const & s ) const | |
| { | |
| DS const d( u_, s, m_ ); | |
| return Array1S( data_, k_, d ); | |
| } | |
| // array( s ) | |
| Array1S | |
| operator ()( IS const & s ) | |
| { | |
| DS const d( u_, s, m_ ); | |
| return Array1S( data_, k_, d ); | |
| } | |
| // array( {s} ) const | |
| template< typename U, class = typename std::enable_if< std::is_constructible< int, U >::value >::type > | |
| Array1S | |
| operator ()( std::initializer_list< U > const l ) const | |
| { | |
| IS const s( l ); | |
| DS const d( u_, s, m_ ); | |
| return Array1S( data_, k_, d ); | |
| } | |
| // array( {s} ) | |
| template< typename U, class = typename std::enable_if< std::is_constructible< int, U >::value >::type > | |
| Array1S | |
| operator ()( std::initializer_list< U > const l ) | |
| { | |
| IS const s( l ); | |
| DS const d( u_, s, m_ ); | |
| return Array1S( data_, k_, d ); | |
| } | |
| public: // Predicate | |
| // Contains Indexed Element? | |
| bool | |
| contains( int const i ) const | |
| { | |
| return in_range( u_, i ); | |
| } | |
| // Conformable? | |
| template< typename U > | |
| bool | |
| conformable( Array1S< U > const & a ) const | |
| { | |
| return ( u_ == a.u_ ); | |
| } | |
| // Conformable? | |
| template< class A > | |
| bool | |
| conformable( A const & a ) const | |
| { | |
| return ( ( a.rank() == 1 ) && ( size_ == a.size() ) ); | |
| } | |
| // Equal Dimensions? | |
| template< typename U > | |
| bool | |
| equal_dimensions( Array1S< U > const & a ) const | |
| { | |
| return conformable( a ); | |
| } | |
| // Equal Dimensions? | |
| template< class A > | |
| bool | |
| equal_dimensions( A const & a ) const | |
| { | |
| return conformable( a ); | |
| } | |
| public: // Inspector | |
| // IndexRange of a Dimension | |
| IR | |
| I( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return I1(); | |
| default: | |
| assert( false ); | |
| return I1(); | |
| } | |
| } | |
| // Upper Index of a Dimension | |
| int | |
| u( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return u_; | |
| default: | |
| assert( false ); | |
| return u_; | |
| } | |
| } | |
| // Size of a Dimension | |
| size_type | |
| size( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return u_; | |
| default: | |
| assert( false ); | |
| return u_; | |
| } | |
| } | |
| // Size of a Dimension | |
| int | |
| isize( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return u_; | |
| default: | |
| assert( false ); | |
| return u_; | |
| } | |
| } | |
| // IndexRange | |
| IR | |
| I() const | |
| { | |
| return IR( 1, u_ ); | |
| } | |
| // Lower Index | |
| int | |
| l() const | |
| { | |
| return 1; | |
| } | |
| // Upper Index | |
| int | |
| u() const | |
| { | |
| return u_; | |
| } | |
| // IndexRange of Dimension 1 | |
| IR | |
| I1() const | |
| { | |
| return IR( 1, u_ ); | |
| } | |
| // Lower Index of Dimension 1 | |
| int | |
| l1() const | |
| { | |
| return 1; | |
| } | |
| // Upper Index of Dimension 1 | |
| int | |
| u1() const | |
| { | |
| return u_; | |
| } | |
| // Size of Dimension 1 | |
| size_type | |
| size1() const | |
| { | |
| return u_; | |
| } | |
| // Size of Dimension 1 | |
| int | |
| isize1() const | |
| { | |
| return u_; | |
| } | |
| // Shift for Proxy | |
| std::ptrdiff_t | |
| shift() const | |
| { | |
| return 1; | |
| } | |
| public: | |
| // Slice == Value | |
| friend | |
| bool | |
| eq( Array1S const & a, T const & t ) | |
| { | |
| if ( a.empty() ) return true; | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| if ( ! ( a( i ) == t ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Any Slice != Value | |
| friend | |
| bool | |
| any_ne( Array1S const & a, T const & t ) | |
| { | |
| return ! eq( a, t ); | |
| } | |
| // Any Slice < Value | |
| friend | |
| bool | |
| any_lt( Array1S const & a, T const & t ) | |
| { | |
| if ( a.empty() ) return false; | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| if ( a( i ) < t ) return true; | |
| } | |
| return false; | |
| } | |
| // Any Slice > Value | |
| friend | |
| bool | |
| any_gt( Array1S const & a, T const & t ) | |
| { | |
| return any_lt( t, a ); | |
| } | |
| // Any Value < Slice | |
| friend | |
| bool | |
| any_lt( T const & t, Array1S const & a ) | |
| { | |
| if ( a.empty() ) return false; | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| if ( t < a( i ) ) return true; | |
| } | |
| return false; | |
| } | |
| private: // Methods | |
| // Contiguous? | |
| bool | |
| computed_contiguous() const | |
| { | |
| return m_ == 1; | |
| } | |
| // Memory Range Set | |
| void | |
| data_set() | |
| { | |
| if ( size_ > 0u ) { // Non-empty slice | |
| data_beg_ = data_end_ = data_ + k_; | |
| data_beg_ += m_ * ( m_ >= 0 ? 1 : u_ ); | |
| data_end_ += m_ * ( m_ <= 0 ? 1 : u_ ); | |
| } else { | |
| data_ = data_beg_ = data_end_ = nullptr; | |
| } | |
| } | |
| private: // Data | |
| std::int64_t const m_; // Multiplier | |
| std::int64_t const k_; // Constant | |
| int const u_; // Upper index | |
| }; // Array1S | |
| // Conformable? | |
| template< typename U, typename V > | |
| inline | |
| bool | |
| conformable( Array1S< U > const & a, Array1S< V > const & b ) | |
| { | |
| return a.conformable( b ); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( Array1S< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| T const mag_i( a( i ) ); | |
| mag_sq += mag_i * mag_i; | |
| } | |
| return std::sqrt( mag_sq ); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( Array1S< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| T const mag_i( a( i ) ); | |
| mag_sq += mag_i * mag_i; | |
| } | |
| return mag_sq; | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| T const distance_i( a( i ) - b( i ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1S< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( a.size() == 2u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector2< T > const & a, Array1S< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1S< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( a.size() == 3u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector3< T > const & a, Array1S< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1S< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( a.size() == 4u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector4< T > const & a, Array1S< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| T const distance_i( a( i ) - b( i ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1S< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( a.size() == 2u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector2< T > const & a, Array1S< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1S< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( a.size() == 3u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector3< T > const & a, Array1S< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1S< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( a.size() == 4u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector4< T > const & a, Array1S< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product of Boolean Arrays | |
| inline | |
| bool | |
| dot( Array1S< bool > const & a, Array1S< bool > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| bool result( false ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| if ( a( i ) && b( i ) ) { | |
| result = true; | |
| break; | |
| } | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector2 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1S< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( a.size() == 2u ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector2 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector2< T > const & a, Array1S< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product with Vector3 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1S< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( a.size() == 3u ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector3 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector3< T > const & a, Array1S< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product with Vector4 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1S< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( a.size() == 4u ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector4 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector4< T > const & a, Array1S< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product (Fortran Intrinsic Name) | |
| template< typename T > | |
| inline | |
| T | |
| dot_product( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Dot Product of Boolean Arrays (Fortran Intrinsic Name) | |
| inline | |
| bool | |
| dot_product( Array1S< bool > const & a, Array1S< bool > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Cross Product of 2-Tuples | |
| template< typename T > | |
| inline | |
| T | |
| cross2( Vector2< T > const & a, Array1S< T > const & b ) | |
| { | |
| return cross2( b, a ); | |
| } | |
| // Stream >> Array1S | |
| template< typename T > | |
| inline | |
| std::istream & | |
| operator >>( std::istream & stream, Array1S< T > & a ) | |
| { | |
| if ( stream && ( a.size() > 0u ) ) { | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| stream >> a( i ); | |
| if ( ! stream ) break; | |
| } | |
| } | |
| return stream; | |
| } | |
| // Stream << Array1S | |
| template< typename T > | |
| inline | |
| std::ostream & | |
| operator <<( std::ostream & stream, Array1S< T > const & a ) | |
| { | |
| typedef TypeTraits< T > Traits; | |
| if ( stream && ( a.size() > 0u ) ) { | |
| std::ios_base::fmtflags const old_flags( stream.flags() ); | |
| std::streamsize const old_precision( stream.precision( Traits::precision ) ); | |
| stream << std::right << std::showpoint << std::uppercase; | |
| int const w( Traits::iwidth ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| stream << std::setw( w ) << a( i ) << ' '; | |
| if ( ! stream ) break; | |
| } | |
| stream.precision( old_precision ); | |
| stream.flags( old_flags ); | |
| } | |
| return stream; | |
| } | |
| namespace fmt { | |
| // List-Directed Format: Array1S | |
| template< typename T > | |
| inline | |
| std::string | |
| LD( Array1S< T > const & a ) | |
| { | |
| std::string s; | |
| std::size_t const n( a.size() ); | |
| if ( n > 0u ) { | |
| s.reserve( n * TypeTraits< T >::width ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| s.append( fmt::LD( a( i ) ) ); | |
| } | |
| } | |
| return s; | |
| } | |
| } // fmt | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array1S_hh_INCLUDED | |
| // ===== ObjexxFCL/MArrayR.hh ===== | |
| #ifndef ObjexxFCL_MArrayR_hh_INCLUDED | |
| #define ObjexxFCL_MArrayR_hh_INCLUDED | |
| // MArrayR: Rank Member Array Proxy Abstract Base Class Template | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| namespace ObjexxFCL { | |
| // MArrayR: Rank Member Array Proxy Abstract Base Class Template | |
| template< class A, typename T, int Rank > | |
| class MArrayR : public MArray< A, T > | |
| { | |
| private: // Types | |
| typedef MArray< A, T > Super; | |
| private: // Friend | |
| template< typename, typename, int > friend class MArrayR; | |
| public: // Types | |
| typedef typename Super::ArrayType ArrayType; | |
| typedef typename Super::Class Class; | |
| typedef typename Super::MPtr MPtr; | |
| typedef typename Super::Traits Traits; | |
| typedef typename Super::IR IR; | |
| // STL Style | |
| typedef typename Super::value_type value_type; | |
| typedef typename Super::reference reference; | |
| typedef typename Super::const_reference const_reference; | |
| typedef typename Super::pointer pointer; | |
| typedef typename Super::const_pointer const_pointer; | |
| typedef typename Super::size_type size_type; | |
| typedef typename Super::difference_type difference_type; | |
| // C++ Style | |
| typedef typename Super::Value Value; | |
| typedef typename Super::Reference Reference; | |
| typedef typename Super::ConstReference ConstReference; | |
| typedef typename Super::Pointer Pointer; | |
| typedef typename Super::ConstPointer ConstPointer; | |
| typedef typename Super::Size Size; | |
| typedef typename Super::Difference Difference; | |
| using Super::isize; | |
| using Super::l; | |
| using Super::u; | |
| using Super::size; | |
| protected: // Types | |
| using Super::in_range; | |
| using Super::array_; | |
| using Super::pmem_; | |
| protected: // Creation | |
| // Copy Constructor | |
| MArrayR( MArrayR const & a ) : | |
| Super( a ) | |
| { | |
| assert( a.rank() == Rank ); | |
| } | |
| // Constructor | |
| MArrayR( A & a, T Class::* pmem ) : | |
| Super( a, pmem ) | |
| {} | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~MArrayR() = default; | |
| // Copy Assignment | |
| MArrayR & | |
| operator =( MArrayR const & a ) = delete; | |
| public: // Inspector | |
| // Rank | |
| int | |
| rank() const | |
| { | |
| return Rank; | |
| } | |
| }; // MArrayR | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_MArrayR_hh_INCLUDED | |
| // ===== ObjexxFCL/MArray1.hh ===== | |
| #ifndef ObjexxFCL_MArray1_hh_INCLUDED | |
| #define ObjexxFCL_MArray1_hh_INCLUDED | |
| // MArray1: 1D Member Array Proxy | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <array> | |
| #include <cmath> | |
| #include <vector> | |
| namespace ObjexxFCL { | |
| // MArray1: 1D Member Array Proxy | |
| template< class A, typename T > | |
| class MArray1 : public MArrayR< A, T, 1 > | |
| { | |
| private: // Types | |
| typedef MArrayR< A, T, 1 > Super; | |
| private: // Friend | |
| template< typename, typename > friend class MArray1; | |
| public: // Types | |
| typedef typename Super::ArrayType ArrayType; | |
| typedef typename Super::Class Class; | |
| typedef typename Super::MPtr MPtr; | |
| typedef typename Super::Traits Traits; | |
| typedef typename Super::IR IR; | |
| // STL Style | |
| typedef typename Super::value_type value_type; | |
| typedef typename Super::reference reference; | |
| typedef typename Super::const_reference const_reference; | |
| typedef typename Super::pointer pointer; | |
| typedef typename Super::const_pointer const_pointer; | |
| typedef typename Super::size_type size_type; | |
| typedef typename Super::difference_type difference_type; | |
| // C++ Style | |
| typedef typename Super::Value Value; | |
| typedef typename Super::Reference Reference; | |
| typedef typename Super::ConstReference ConstReference; | |
| typedef typename Super::Pointer Pointer; | |
| typedef typename Super::ConstPointer ConstPointer; | |
| typedef typename Super::Size Size; | |
| typedef typename Super::Difference Difference; | |
| using Super::isize; | |
| using Super::l; | |
| using Super::u; | |
| using Super::size; | |
| protected: // Types | |
| using Super::in_range; | |
| using Super::j1; | |
| using Super::array_; | |
| using Super::pmem_; | |
| public: // Creation | |
| // Copy Constructor | |
| MArray1( MArray1 const & a ) : | |
| Super( a ) | |
| {} | |
| // Constructor | |
| MArray1( A & a, T Class::* pmem ) : | |
| Super( a, pmem ) | |
| {} | |
| // Destructor | |
| virtual | |
| ~MArray1() = default; | |
| public: // Assignment: Array | |
| // Copy Assignment | |
| MArray1 & | |
| operator =( MArray1 const & a ) | |
| { | |
| if ( this != &a ) { | |
| assert( conformable( a ) ); | |
| for ( int i = 1, e = u(); i <= e; ++i ) { | |
| operator ()( i ) = a( i ); // Not overlap-safe | |
| } | |
| } | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename Aa, typename Ta > | |
| MArray1 & | |
| operator =( MArray1< Aa, Ta > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| for ( int i = 1, e = u(); i <= e; ++i ) { | |
| operator ()( i ) = a( i ); // Not overlap-safe | |
| } | |
| return *this; | |
| } | |
| // Array Assignment Template | |
| template< template< typename > class Ar, typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( Ar< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| for ( int i = 1, j = a.l(), e = u(); i <= e; ++i, ++j ) { | |
| operator ()( i ) = a( j ); // Not overlap-safe | |
| } | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| assert( size() == l.size() ); | |
| auto r( l.begin() ); | |
| for ( int i = 1, e = u(); i <= e; ++i, ++r ) { | |
| operator ()( i ) = *r; | |
| } | |
| return *this; | |
| } | |
| // std::array Assignment Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( std::array< U, s > const & a ) | |
| { | |
| assert( size() == s ); | |
| auto r( a.begin() ); | |
| for ( int i = 1, e = u(); i <= e; ++i, ++r ) { | |
| operator ()( i ) = *r; | |
| } | |
| return *this; | |
| } | |
| // std::vector Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( std::vector< U > const & v ) | |
| { | |
| assert( size() == v.size() ); | |
| auto r( v.begin() ); | |
| for ( int i = 1, e = u(); i <= e; ++i, ++r ) { | |
| operator ()( i ) = *r; | |
| } | |
| return *this; | |
| } | |
| // Vector2 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( Vector2< U > const & v ) | |
| { | |
| assert( size() == 2u ); | |
| operator ()( 1 ) = v.x; | |
| operator ()( 2 ) = v.y; | |
| return *this; | |
| } | |
| // Vector3 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( Vector3< U > const & v ) | |
| { | |
| assert( size() == 3u ); | |
| operator ()( 1 ) = v.x; | |
| operator ()( 2 ) = v.y; | |
| operator ()( 3 ) = v.z; | |
| return *this; | |
| } | |
| // Vector4 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( Vector4< U > const & v ) | |
| { | |
| assert( size() == 4u ); | |
| operator ()( 1 ) = v.x; | |
| operator ()( 2 ) = v.y; | |
| operator ()( 3 ) = v.z; | |
| operator ()( 3 ) = v.w; | |
| return *this; | |
| } | |
| public: // Assignment: Value | |
| // = Value | |
| MArray1 & | |
| operator =( T const & t ) | |
| { | |
| for ( int i = 1, e = u(); i <= e; ++i ) { | |
| operator ()( i ) = t; | |
| } | |
| return *this; | |
| } | |
| // = Value Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| MArray1 & | |
| operator =( U const & t ) | |
| { | |
| for ( int i = 1, e = u(); i <= e; ++i ) { | |
| operator ()( i ) = t; | |
| } | |
| return *this; | |
| } | |
| public: // Subscript | |
| // array( i ) const | |
| T const & | |
| operator ()( int const i ) const | |
| { | |
| assert( contains( i ) ); | |
| return array_( j1( i ) ).*pmem_; | |
| } | |
| // array( i ) | |
| T & | |
| operator ()( int const i ) | |
| { | |
| assert( contains( i ) ); | |
| return array_( j1( i ) ).*pmem_; | |
| } | |
| // array[ i ] const: 0-Based Subscript | |
| T const & | |
| operator []( size_type const i ) const | |
| { | |
| assert( i < std::numeric_limits< int >::max() ); | |
| assert( contains( static_cast< int >( i + 1 ) ) ); | |
| return array_( j1( static_cast< int >( i + 1 ) ) ).*pmem_; | |
| } | |
| // array[ i ]: 0-Based Subscript | |
| T & | |
| operator []( size_type const i ) | |
| { | |
| assert( i < std::numeric_limits< int >::max() ); | |
| assert( contains( static_cast< int >( i + 1 ) ) ); | |
| return array_( j1( static_cast< int >( i + 1 ) ) ).*pmem_; | |
| } | |
| public: // Predicate | |
| // Contains Indexed Element? | |
| bool | |
| contains( int const i ) const | |
| { | |
| return in_range( u(), i ); | |
| } | |
| // Conformable? | |
| template< typename Aa, typename Ta > | |
| bool | |
| conformable( MArray1< Aa, Ta > const & a ) const | |
| { | |
| return ( size() == a.size() ); | |
| } | |
| // Conformable? | |
| template< class Ar > | |
| bool | |
| conformable( Ar const & a ) const | |
| { | |
| return ( ( a.rank() == 1 ) && ( size() == a.size() ) ); | |
| } | |
| // Equal Dimensions? | |
| template< typename Aa, typename Ta > | |
| bool | |
| equal_dimensions( MArray1< Aa, Ta > const & a ) const | |
| { | |
| return conformable( a ); | |
| } | |
| // Equal Dimensions? | |
| template< class Ar > | |
| bool | |
| equal_dimensions( Ar const & a ) const | |
| { | |
| return conformable( a ); | |
| } | |
| public: // Inspector | |
| // IndexRange | |
| IR | |
| I() const | |
| { | |
| return IR( 1, u() ); | |
| } | |
| // Lower Index | |
| int | |
| l() const | |
| { | |
| return 1; | |
| } | |
| // Upper Index | |
| int | |
| u() const | |
| { | |
| return array_.isize1(); | |
| } | |
| // IndexRange of Dimension 1 | |
| IR | |
| I1() const | |
| { | |
| return IR( 1, u1() ); | |
| } | |
| // Lower Index of Dimension 1 | |
| int | |
| l1() const | |
| { | |
| return 1; | |
| } | |
| // Upper Index of Dimension 1 | |
| int | |
| u1() const | |
| { | |
| return array_.isize1(); | |
| } | |
| // Size of Dimension 1 | |
| size_type | |
| size1() const | |
| { | |
| return array_.size1(); | |
| } | |
| // Size of Dimension 1 | |
| int | |
| isize1() const | |
| { | |
| return array_.isize1(); | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| T length_sq( T( 0 ) ); | |
| for ( int i = 1, e = u(); i <= e; ++i ) { | |
| T const length_i( operator ()( i ) ); | |
| length_sq += length_i * length_i; | |
| } | |
| return std::sqrt( length_sq ); | |
| } | |
| public: // Modifier | |
| // Normalize to Unit Length | |
| MArray1 & | |
| normalize() | |
| { | |
| T const length_( length() ); | |
| assert( length_ > T( 0 ) ); | |
| operator /=( length_ ); | |
| return *this; | |
| } | |
| }; // MArray1 | |
| namespace fmt { | |
| // List-Directed Format: MArray1 | |
| template< class A, typename T > | |
| inline | |
| std::string | |
| LD( MArray1< A, T > const & a ) | |
| { | |
| std::string s; | |
| std::size_t const n( a.size() ); | |
| if ( n > 0u ) { | |
| s.reserve( n * TypeTraits< T >::width ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| s.append( fmt::LD( a( i ) ) ); | |
| } | |
| } | |
| return s; | |
| } | |
| } // fmt | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_MArray1_hh_INCLUDED | |
| // ===== ObjexxFCL/Array1.hh ===== | |
| #ifndef ObjexxFCL_Array1_hh_INCLUDED | |
| #define ObjexxFCL_Array1_hh_INCLUDED | |
| // Array1: 1D Array Abstract Base Class | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <cmath> | |
| namespace ObjexxFCL { | |
| // Forward | |
| template< typename > class Array1D; | |
| template< typename > class Array1A; | |
| // Array1: 1D Array Abstract Base Class | |
| template< typename T > | |
| class Array1 : public Array< T > | |
| { | |
| private: // Types | |
| typedef Array< T > Super; | |
| private: // Friend | |
| template< typename > friend class Array1; | |
| template< typename > friend class Array1D; | |
| template< typename > friend class Array1A; | |
| protected: // Types | |
| typedef internal::InitializerSentinel InitializerSentinel; | |
| typedef internal::ProxySentinel ProxySentinel; | |
| public: // Types | |
| typedef typename Super::Base Base; | |
| typedef typename Super::IR IR; | |
| typedef typename Super::IS IS; | |
| typedef typename Super::DS DS; | |
| // STL Style | |
| typedef typename Super::value_type value_type; | |
| typedef typename Super::reference reference; | |
| typedef typename Super::const_reference const_reference; | |
| typedef typename Super::pointer pointer; | |
| typedef typename Super::const_pointer const_pointer; | |
| typedef typename Super::iterator iterator; | |
| typedef typename Super::const_iterator const_iterator; | |
| typedef typename Super::reverse_iterator reverse_iterator; | |
| typedef typename Super::const_reverse_iterator const_reverse_iterator; | |
| typedef typename Super::size_type size_type; | |
| typedef typename Super::difference_type difference_type; | |
| // C++ Style | |
| typedef typename Super::Value Value; | |
| typedef typename Super::Reference Reference; | |
| typedef typename Super::ConstReference ConstReference; | |
| typedef typename Super::Pointer Pointer; | |
| typedef typename Super::ConstPointer ConstPointer; | |
| typedef typename Super::Iterator Iterator; | |
| typedef typename Super::ConstIterator ConstIterator; | |
| typedef typename Super::ReverseIterator ReverseIterator; | |
| typedef typename Super::ConstReverseIterator ConstReverseIterator; | |
| typedef typename Super::Size Size; | |
| typedef typename Super::Difference Difference; | |
| typedef void iterator_category; // Prevent compile failure when std::distance is in scope | |
| using Super::isize; | |
| using Super::npos; | |
| using Super::overlap; | |
| using Super::size; | |
| protected: // Types | |
| using Super::shift_set; | |
| using Super::size_of; | |
| using Super::slice_k; | |
| using Super::swapB; | |
| using Super::capacity_; | |
| using Super::data_; | |
| using Super::sdata_; | |
| using Super::shift_; | |
| using Super::size_; | |
| protected: // Creation | |
| // Default Constructor | |
| Array1() = default; | |
| // Copy Constructor | |
| Array1( Array1 const & a ) : | |
| Super( a ), | |
| I_( a.I_ ) | |
| {} | |
| // Move Constructor | |
| Array1( Array1 && a ) noexcept : | |
| Super( std::move( a ) ), | |
| I_( a.I_ ) | |
| { | |
| a.clear_move(); | |
| } | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array1( Array1< U > const & a ) : | |
| Super( a ), | |
| I_( a.I_ ) | |
| {} | |
| // Slice Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array1( Array1S< U > const & a ) : | |
| Super( a ), | |
| I_( a.u() ) | |
| {} | |
| // MArray Constructor Template | |
| template< class A, typename M > | |
| explicit | |
| Array1( MArray1< A, M > const & a ) : | |
| Super( a ), | |
| I_( a.u() ) | |
| {} | |
| // IndexRange Constructor | |
| explicit | |
| Array1( IR const & I ) : | |
| Super( size_of( I ) ), | |
| I_( I ) | |
| {} | |
| // IndexRange + InitializerSentinel Constructor | |
| Array1( IR const & I, InitializerSentinel initialized ) : | |
| Super( size_of( I ), initialized ), | |
| I_( I ) | |
| {} | |
| // Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( std::initializer_list< U > const l ) : | |
| Super( l ), | |
| I_( static_cast< int >( l.size() ) ) | |
| {} | |
| // Index Range + Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( IR const & I, std::initializer_list< U > const l ) : | |
| Super( l ), | |
| I_( I ) | |
| { | |
| assert( size_of( I ) == l.size() ); | |
| } | |
| // std::array Constructor Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( std::array< U, s > const & a ) : | |
| Super( a ), | |
| I_( static_cast< int >( s ) ) | |
| {} | |
| // std::vector Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( std::vector< U > const & v ) : | |
| Super( v ), | |
| I_( static_cast< int >( v.size() ) ) | |
| {} | |
| // Vector2 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( Vector2< U > const & v ) : | |
| Super( v ), | |
| I_( 2 ) | |
| {} | |
| // Vector3 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( Vector3< U > const & v ) : | |
| Super( v ), | |
| I_( 3 ) | |
| {} | |
| // Vector4 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1( Vector4< U > const & v ) : | |
| Super( v ), | |
| I_( 4 ) | |
| {} | |
| // Iterator Range Constructor Template | |
| template< class Iterator, typename = decltype( *std::declval< Iterator & >(), void(), ++std::declval< Iterator & >(), void() ) > | |
| Array1( Iterator const beg, Iterator const end ) : | |
| Super( beg, end ), | |
| I_( static_cast< int >( size_ ) ) | |
| {} | |
| // Default Proxy Constructor | |
| Array1( ProxySentinel proxy ) : | |
| Super( proxy ) | |
| {} | |
| // Copy Proxy Constructor | |
| Array1( Array1 const & a, ProxySentinel proxy ) : | |
| Super( a, proxy ), | |
| I_( a.I_ ) | |
| {} | |
| // Slice Proxy Constructor | |
| Array1( Array1S< T > const & a, ProxySentinel proxy ) : | |
| Super( a, proxy ), | |
| I_( a.u() ) | |
| {} | |
| // Base Proxy Constructor | |
| Array1( Base const & a, ProxySentinel proxy ) : | |
| Super( a, proxy ), | |
| I_( a.isize() ) | |
| {} | |
| // Value Proxy Constructor | |
| Array1( T const & t, ProxySentinel proxy ) : | |
| Super( t, proxy ), | |
| I_( _ ) | |
| {} | |
| // Copy + IndexRange Proxy Constructor | |
| Array1( Array1 const & a, IR const & I, ProxySentinel proxy ) : | |
| Super( a, proxy ), | |
| I_( I ) | |
| {} | |
| // Slice + IndexRange Proxy Constructor | |
| Array1( Array1S< T > const & a, IR const & I, ProxySentinel proxy ) : | |
| Super( a, proxy ), | |
| I_( I ) | |
| {} | |
| // Base + IndexRange Proxy Constructor | |
| Array1( Base const & a, IR const & I, ProxySentinel proxy ) : | |
| Super( a, proxy ), | |
| I_( I ) | |
| {} | |
| // Value + IndexRange Proxy Constructor | |
| Array1( T const & t, IR const & I, ProxySentinel proxy ) : | |
| Super( t, proxy ), | |
| I_( I ) | |
| {} | |
| public: // Creation | |
| // Destructor | |
| virtual | |
| ~Array1() = default; | |
| public: // Assignment: Array | |
| // Copy Assignment | |
| Array1 & | |
| operator =( Array1 const & a ) | |
| { | |
| if ( this != &a ) { | |
| if ( ( conformable( a ) ) || ( ! dimension_assign( a.I_ ) ) ) { | |
| Super::operator =( a ); | |
| } else { | |
| Super::initialize( a ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Copy Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( Array1< U > const & a ) | |
| { | |
| if ( ( conformable( a ) ) || ( ! dimension_assign( a.I_ ) ) ) { | |
| Super::operator =( a ); | |
| } else { | |
| Super::initialize( a ); | |
| } | |
| return *this; | |
| } | |
| // Slice Assignment | |
| Array1 & | |
| operator =( Array1S< T > const & a ) | |
| { | |
| size_type l( 0u ); | |
| if ( ( conformable( a ) ) || ( ! dimension_assign( a.I() ) ) ) { | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( a.size() ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| c[ l ] = a( i ); | |
| } | |
| for ( size_type i = 0; i < c.size(); ++i ) { | |
| data_[ i ] = c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] = a( i ); | |
| } | |
| } | |
| } else { | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| new ( data_ + l ) T( a( i ) ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Slice Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( Array1S< U > const & a ) | |
| { | |
| size_type l( 0u ); | |
| if ( ( conformable( a ) ) || ( ! dimension_assign( a.I() ) ) ) { | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] = a( i ); | |
| } | |
| } else { | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| new ( data_ + l ) T( a( i ) ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| Super::operator =( l ); | |
| return *this; | |
| } | |
| // std::array Assignment Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( std::array< U, s > const & a ) | |
| { | |
| Super::operator =( a ); | |
| return *this; | |
| } | |
| // std::vector Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( std::vector< U > const & v ) | |
| { | |
| Super::operator =( v ); | |
| return *this; | |
| } | |
| // Vector2 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( Vector2< U > const & v ) | |
| { | |
| Super::operator =( v ); | |
| return *this; | |
| } | |
| // Vector3 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( Vector3< U > const & v ) | |
| { | |
| Super::operator =( v ); | |
| return *this; | |
| } | |
| // Vector4 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator =( Vector4< U > const & v ) | |
| { | |
| Super::operator =( v ); | |
| return *this; | |
| } | |
| // += Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( Array1< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| Super::operator +=( a ); | |
| return *this; | |
| } | |
| // -= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( Array1< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| Super::operator -=( a ); | |
| return *this; | |
| } | |
| // *= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( Array1< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| Super::operator *=( a ); | |
| return *this; | |
| } | |
| // /= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( Array1< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| Super::operator /=( a ); | |
| return *this; | |
| } | |
| // += Slice | |
| Array1 & | |
| operator +=( Array1S< T > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( a.size() ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| c[ l ] = a( i ); | |
| } | |
| for ( size_type i = 0; i < c.size(); ++i ) { | |
| data_[ i ] += c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] += a( i ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // -= Slice | |
| Array1 & | |
| operator -=( Array1S< T > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( a.size() ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| c[ l ] = a( i ); | |
| } | |
| for ( size_type i = 0; i < c.size(); ++i ) { | |
| data_[ i ] -= c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] -= a( i ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // *= Slice | |
| Array1 & | |
| operator *=( Array1S< T > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( a.size() ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| c[ l ] = a( i ); | |
| } | |
| for ( size_type i = 0; i < c.size(); ++i ) { | |
| data_[ i ] *= c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] *= a( i ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // /= Slice | |
| Array1 & | |
| operator /=( Array1S< T > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| if ( overlap( a ) ) { // Overlap-safe | |
| CArrayA< T > c( a.size() ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| assert( a( i ) != T( 0 ) ); | |
| c[ l ] = a( i ); | |
| } | |
| for ( size_type i = 0; i < c.size(); ++i ) { | |
| data_[ i ] /= c[ i ]; | |
| } | |
| } else { // Not overlap-safe | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| assert( a( i ) != T( 0 ) ); | |
| data_[ l ] /= a( i ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // += Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( Array1S< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] += a( i ); | |
| } | |
| return *this; | |
| } | |
| // -= Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( Array1S< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] -= a( i ); | |
| } | |
| return *this; | |
| } | |
| // *= Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( Array1S< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| data_[ l ] *= a( i ); | |
| } | |
| return *this; | |
| } | |
| // /= Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( Array1S< U > const & a ) | |
| { | |
| assert( conformable( a ) ); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| assert( a( i ) != T( 0 ) ); | |
| data_[ l ] /= a( i ); | |
| } | |
| return *this; | |
| } | |
| // += Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( std::initializer_list< U > const l ) | |
| { | |
| Super::operator +=( l ); | |
| return *this; | |
| } | |
| // -= Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( std::initializer_list< U > const l ) | |
| { | |
| Super::operator -=( l ); | |
| return *this; | |
| } | |
| // *= Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( std::initializer_list< U > const l ) | |
| { | |
| Super::operator *=( l ); | |
| return *this; | |
| } | |
| // /= Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( std::initializer_list< U > const l ) | |
| { | |
| Super::operator /=( l ); | |
| return *this; | |
| } | |
| // += std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( std::array< U, s > const & a ) | |
| { | |
| Super::operator +=( a ); | |
| return *this; | |
| } | |
| // -= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( std::array< U, s > const & a ) | |
| { | |
| Super::operator -=( a ); | |
| return *this; | |
| } | |
| // *= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( std::array< U, s > const & a ) | |
| { | |
| Super::operator *=( a ); | |
| return *this; | |
| } | |
| // /= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( std::array< U, s > const & a ) | |
| { | |
| Super::operator /=( a ); | |
| return *this; | |
| } | |
| // += std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( std::vector< U > const & v ) | |
| { | |
| Super::operator +=( v ); | |
| return *this; | |
| } | |
| // -= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( std::vector< U > const & v ) | |
| { | |
| Super::operator -=( v ); | |
| return *this; | |
| } | |
| // *= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( std::vector< U > const & v ) | |
| { | |
| Super::operator *=( v ); | |
| return *this; | |
| } | |
| // /= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( std::vector< U > const & v ) | |
| { | |
| Super::operator /=( v ); | |
| return *this; | |
| } | |
| // += Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( Vector2< U > const & v ) | |
| { | |
| Super::operator +=( v ); | |
| return *this; | |
| } | |
| // -= Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( Vector2< U > const & v ) | |
| { | |
| Super::operator -=( v ); | |
| return *this; | |
| } | |
| // *= Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( Vector2< U > const & v ) | |
| { | |
| Super::operator *=( v ); | |
| return *this; | |
| } | |
| // /= Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( Vector2< U > const & v ) | |
| { | |
| Super::operator /=( v ); | |
| return *this; | |
| } | |
| // += Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( Vector3< U > const & v ) | |
| { | |
| Super::operator +=( v ); | |
| return *this; | |
| } | |
| // -= Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( Vector3< U > const & v ) | |
| { | |
| Super::operator -=( v ); | |
| return *this; | |
| } | |
| // *= Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( Vector3< U > const & v ) | |
| { | |
| Super::operator *=( v ); | |
| return *this; | |
| } | |
| // /= Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( Vector3< U > const & v ) | |
| { | |
| Super::operator /=( v ); | |
| return *this; | |
| } | |
| // += Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator +=( Vector4< U > const & v ) | |
| { | |
| Super::operator +=( v ); | |
| return *this; | |
| } | |
| // -= Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator -=( Vector4< U > const & v ) | |
| { | |
| Super::operator -=( v ); | |
| return *this; | |
| } | |
| // *= Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator *=( Vector4< U > const & v ) | |
| { | |
| Super::operator *=( v ); | |
| return *this; | |
| } | |
| // /= Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1 & | |
| operator /=( Vector4< U > const & v ) | |
| { | |
| Super::operator /=( v ); | |
| return *this; | |
| } | |
| public: // Assignment: Value | |
| // = Value | |
| Array1 & | |
| operator =( T const & t ) | |
| { | |
| Super::operator =( t ); | |
| return *this; | |
| } | |
| // += Value | |
| Array1 & | |
| operator +=( T const & t ) | |
| { | |
| Super::operator +=( t ); | |
| return *this; | |
| } | |
| // -= Value | |
| Array1 & | |
| operator -=( T const & t ) | |
| { | |
| Super::operator -=( t ); | |
| return *this; | |
| } | |
| // *= Value | |
| Array1 & | |
| operator *=( T const & t ) | |
| { | |
| Super::operator *=( t ); | |
| return *this; | |
| } | |
| // /= Value | |
| Array1 & | |
| operator /=( T const & t ) | |
| { | |
| Super::operator /=( t ); | |
| return *this; | |
| } | |
| public: // Subscript | |
| // array( i ) const | |
| T const & | |
| operator ()( int const i ) const | |
| { | |
| assert( contains( i ) ); | |
| return sdata_[ i ]; | |
| } | |
| // array( i ) | |
| T & | |
| operator ()( int const i ) | |
| { | |
| assert( contains( i ) ); | |
| return sdata_[ i ]; | |
| } | |
| // Linear Index | |
| size_type | |
| index( int const i ) const | |
| { | |
| return i - shift_; | |
| } | |
| public: // Slice Proxy Generators | |
| // array( s ) const | |
| Array1S< T > | |
| operator ()( IS const & s ) const | |
| { | |
| DS const d( I_, s ); | |
| return Array1S< T >( data_, -shift_, d ); | |
| } | |
| // array( s ) | |
| Array1S< T > | |
| operator ()( IS const & s ) | |
| { | |
| DS const d( I_, s ); | |
| return Array1S< T >( data_, -shift_, d ); | |
| } | |
| #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) // VC++2013 bug work-around | |
| // array( {s} ) const | |
| Array1S< T > | |
| operator ()( std::initializer_list< int > const l ) const | |
| { | |
| IS const s( l ); | |
| DS const d( I_, s ); | |
| return Array1S< T >( data_, -shift_, d ); | |
| } | |
| // array( {s} ) | |
| Array1S< T > | |
| operator ()( std::initializer_list< int > const l ) | |
| { | |
| IS const s( l ); | |
| DS const d( I_, s ); | |
| return Array1S< T >( data_, -shift_, d ); | |
| } | |
| #else | |
| // array( {s} ) const | |
| template< typename U, class = typename std::enable_if< std::is_constructible< int, U >::value >::type > | |
| Array1S< T > | |
| operator ()( std::initializer_list< U > const l ) const | |
| { | |
| IS const s( l ); | |
| DS const d( I_, s ); | |
| return Array1S< T >( data_, -shift_, d ); | |
| } | |
| // array( {s} ) | |
| template< typename U, class = typename std::enable_if< std::is_constructible< int, U >::value >::type > | |
| Array1S< T > | |
| operator ()( std::initializer_list< U > const l ) | |
| { | |
| IS const s( l ); | |
| DS const d( I_, s ); | |
| return Array1S< T >( data_, -shift_, d ); | |
| } | |
| #endif | |
| public: // Predicate | |
| // Contains Indexed Element? | |
| bool | |
| contains( int const i ) const | |
| { | |
| return I_.contains( i ); | |
| } | |
| // Conformable? | |
| template< typename U > | |
| bool | |
| conformable( Array1< U > const & a ) const | |
| { | |
| return ( size_ == a.size() ); | |
| } | |
| // Conformable? | |
| template< typename U > | |
| bool | |
| conformable( Array1S< U > const & a ) const | |
| { | |
| return ( size_ == a.size() ); | |
| } | |
| // Equal Dimensions? | |
| template< typename U > | |
| bool | |
| equal_dimensions( Array1< U > const & a ) const | |
| { | |
| return ( I_ == a.I_ ); | |
| } | |
| // Equal Dimensions? | |
| template< typename U > | |
| bool | |
| equal_dimensions( Array1S< U > const & a ) const | |
| { | |
| return ( ( l() == 1 ) && ( u() == a.u() ) ); | |
| } | |
| public: // Inspector | |
| // Rank | |
| int | |
| rank() const | |
| { | |
| return 1; | |
| } | |
| // IndexRange of a Dimension | |
| IR const & | |
| I( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return I_; | |
| default: | |
| assert( false ); | |
| return I_; | |
| } | |
| } | |
| // Lower Index of a Dimension | |
| int | |
| l( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return l1(); | |
| default: | |
| assert( false ); | |
| return l1(); | |
| } | |
| } | |
| // Upper Index of a Dimension | |
| int | |
| u( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return u1(); | |
| default: | |
| assert( false ); | |
| return u1(); | |
| } | |
| } | |
| // Size of a Dimension | |
| size_type | |
| size( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return size1(); | |
| default: | |
| assert( false ); | |
| return size1(); | |
| } | |
| } | |
| // Size of a Dimension | |
| int | |
| isize( int const d ) const | |
| { | |
| switch ( d ) { | |
| case 1: | |
| return isize1(); | |
| default: | |
| assert( false ); | |
| return isize1(); | |
| } | |
| } | |
| // IndexRange | |
| IR const & | |
| I() const | |
| { | |
| return I_; | |
| } | |
| // Lower Index | |
| int | |
| l() const | |
| { | |
| return I_.l(); | |
| } | |
| // Upper Index | |
| int | |
| u() const | |
| { | |
| return I_.u(); | |
| } | |
| // IndexRange of Dimension 1 | |
| IR const & | |
| I1() const | |
| { | |
| return I_; | |
| } | |
| // Lower Index of Dimension 1 | |
| int | |
| l1() const | |
| { | |
| return I_.l(); | |
| } | |
| // Upper Index of Dimension 1 | |
| int | |
| u1() const | |
| { | |
| return I_.u(); | |
| } | |
| // Size of Dimension 1 | |
| size_type | |
| size1() const | |
| { | |
| return I_.size(); | |
| } | |
| // Size of Dimension 1 | |
| int | |
| isize1() const | |
| { | |
| return I_.isize(); | |
| } | |
| // Length | |
| T | |
| length() const | |
| { | |
| T length_sq( T( 0 ) ); | |
| for ( int i = l(), e = u(); i <= e; ++i ) { | |
| T const length_i( sdata_[ i ] ); | |
| length_sq += length_i * length_i; | |
| } | |
| return std::sqrt( length_sq ); | |
| } | |
| public: // Modifier | |
| // Clear | |
| Array1 & | |
| clear() | |
| { | |
| Super::clear(); | |
| I_.clear(); | |
| shift_set( 1 ); | |
| return *this; | |
| } | |
| // Normalize to Unit Length | |
| Array1 & | |
| normalize() | |
| { | |
| T const length_( length() ); | |
| assert( length_ > T( 0 ) ); | |
| operator /=( length_ ); | |
| return *this; | |
| } | |
| public: // MArray Generators | |
| // Template Helpers | |
| template< typename U > class Wrapper {}; | |
| typedef typename std::conditional< std::is_class< T >::value, T, Wrapper< T > >::type ClassT; | |
| // MArray Generator | |
| template< typename M > | |
| MArray1< Array1 const, M > | |
| ma( M ClassT::* pmem ) const | |
| { | |
| return MArray1< Array1 const, M >( *this, pmem ); | |
| } | |
| // MArray Generator | |
| template< typename M > | |
| MArray1< Array1, M > | |
| ma( M ClassT::* pmem ) | |
| { | |
| return MArray1< Array1, M >( *this, pmem ); | |
| } | |
| public: // Comparison: Predicate | |
| // Array1 == Array1 | |
| friend | |
| bool | |
| eq( Array1 const & a, Array1 const & b ) | |
| { | |
| assert( a.size_bounded() ); | |
| assert( a.conformable( b ) ); | |
| return eq( static_cast< Super const & >( a ), static_cast< Super const & >( b ) ); | |
| } | |
| public: // Comparison: Predicate: Any | |
| // Array1 == Array1 | |
| friend | |
| bool | |
| any_eq( Array1 const & a, Array1 const & b ) | |
| { | |
| assert( a.size_bounded() ); | |
| assert( a.conformable( b ) ); | |
| return any_eq( static_cast< Super const & >( a ), static_cast< Super const & >( b ) ); | |
| } | |
| public: // Comparison: Predicate: Slice | |
| // Array1 == Array1S | |
| friend | |
| bool | |
| eq( Array1 const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size_bounded() ); | |
| assert( a.conformable( b ) ); | |
| if ( a.empty() ) return true; | |
| size_type l( 0u ); | |
| for ( int i = 1, e = b.u(); i <= e; ++i, ++l ) { | |
| if ( ! ( a[ l ] == b( i ) ) ) return false; | |
| } | |
| return true; | |
| } | |
| // Array1S == Array1 | |
| friend | |
| bool | |
| eq( Array1S< T > const & a, Array1 const & b ) | |
| { | |
| return eq( b, a ); | |
| } | |
| protected: // Functions | |
| // Dimension by IndexRange | |
| virtual | |
| bool | |
| dimension_assign( IR const & I ) = 0; | |
| // Clear on Move | |
| void | |
| clear_move() | |
| { | |
| I_.clear(); | |
| shift_set( 1 ); | |
| } | |
| // Swap | |
| void | |
| swap1( Array1 & v ) | |
| { | |
| swapB( v ); | |
| I_.swap( v.I_ ); | |
| } | |
| protected: // Data | |
| IR I_; // Index range | |
| }; // Array1 | |
| // Conformable? | |
| template< typename U, typename V > | |
| inline | |
| bool | |
| conformable( Array1< U > const & a, Array1< V > const & b ) | |
| { | |
| return a.conformable( b ); | |
| } | |
| // Conformable? | |
| template< typename U, typename V > | |
| inline | |
| bool | |
| conformable( Array1< U > const & a, Array1S< V > const & b ) | |
| { | |
| return a.conformable( b ); | |
| } | |
| // Conformable? | |
| template< typename U, typename V > | |
| inline | |
| bool | |
| conformable( Array1S< U > const & a, Array1< V > const & b ) | |
| { | |
| return b.conformable( a ); | |
| } | |
| // Equal Dimensions? | |
| template< typename U, typename V > | |
| inline | |
| bool | |
| equal_dimensions( Array1< U > const & a, Array1< V > const & b ) | |
| { | |
| return a.equal_dimensions( b ); | |
| } | |
| // Magnitude | |
| template< typename T > | |
| inline | |
| T | |
| magnitude( Array1< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( int i = a.l(), e = a.u(); i <= e; ++i ) { | |
| T const mag_i( a( i ) ); | |
| mag_sq += mag_i * mag_i; | |
| } | |
| return std::sqrt( mag_sq ); | |
| } | |
| // Magnitude Squared | |
| template< typename T > | |
| inline | |
| T | |
| magnitude_squared( Array1< T > const & a ) | |
| { | |
| T mag_sq( T( 0 ) ); | |
| for ( int i = a.l(), e = a.u(); i <= e; ++i ) { | |
| T const mag_i( a( i ) ); | |
| mag_sq += mag_i * mag_i; | |
| } | |
| return mag_sq; | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( a.size() == 2u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector2< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( a.size() == 3u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector3< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Array1< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( a.size() == 4u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return std::sqrt( distance_sq ); | |
| } | |
| // Distance | |
| template< typename T > | |
| inline | |
| T | |
| distance( Vector4< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( a.size() == 2u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector2< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( a.size() == 3u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector3< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Array1< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( a.size() == 4u ); | |
| T distance_sq( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| T const distance_i( a( i ) - b( j ) ); | |
| distance_sq += distance_i * distance_i; | |
| } | |
| return distance_sq; | |
| } | |
| // Distance Squared | |
| template< typename T > | |
| inline | |
| T | |
| distance_squared( Vector4< T > const & a, Array1< T > const & b ) | |
| { | |
| return distance_squared( b, a ); | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T result( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| result += a( i ) * b( j ); | |
| } | |
| return result; | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| T result( T( 0 ) ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| result += a( i ) * b( j ); | |
| } | |
| return result; | |
| } | |
| // Dot Product | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product of Boolean Arrays | |
| inline | |
| bool | |
| dot( Array1< bool > const & a, Array1< bool > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| bool result( false ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| if ( a( i ) && b( j ) ) { | |
| result = true; | |
| break; | |
| } | |
| } | |
| return result; | |
| } | |
| // Dot Product of Boolean Arrays | |
| inline | |
| bool | |
| dot( Array1< bool > const & a, Array1S< bool > const & b ) | |
| { | |
| assert( a.size() == b.size() ); | |
| bool result( false ); | |
| for ( int i = a.l(), j = b.l(), e = a.u(); i <= e; ++i, ++j ) { | |
| if ( a( i ) && b( j ) ) { | |
| result = true; | |
| break; | |
| } | |
| } | |
| return result; | |
| } | |
| // Dot Product of Boolean Arrays | |
| inline | |
| bool | |
| dot( Array1S< bool > const & a, Array1< bool > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product with Vector2 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1< T > const & a, Vector2< T > const & b ) | |
| { | |
| assert( a.size() == 2u ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector2 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector2< T > const & a, Array1< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product with Vector3 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1< T > const & a, Vector3< T > const & b ) | |
| { | |
| assert( a.size() == 3u ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector3 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector3< T > const & a, Array1< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product with Vector4 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Array1< T > const & a, Vector4< T > const & b ) | |
| { | |
| assert( a.size() == 4u ); | |
| T result( T( 0 ) ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i ) { | |
| result += a( i ) * b( i ); | |
| } | |
| return result; | |
| } | |
| // Dot Product with Vector4 | |
| template< typename T > | |
| inline | |
| T | |
| dot( Vector4< T > const & a, Array1< T > const & b ) | |
| { | |
| return dot( b, a ); | |
| } | |
| // Dot Product (Fortran Intrinsic Name) | |
| template< typename T > | |
| inline | |
| T | |
| dot_product( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Dot Product (Fortran Intrinsic Name) | |
| template< typename T > | |
| inline | |
| T | |
| dot_product( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Dot Product (Fortran Intrinsic Name) | |
| template< typename T > | |
| inline | |
| T | |
| dot_product( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Dot Product of Boolean Arrays (Fortran Intrinsic Name) | |
| inline | |
| bool | |
| dot_product( Array1< bool > const & a, Array1< bool > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Dot Product of Boolean Arrays (Fortran Intrinsic Name) | |
| inline | |
| bool | |
| dot_product( Array1< bool > const & a, Array1S< bool > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Dot Product of Boolean Arrays (Fortran Intrinsic Name) | |
| inline | |
| bool | |
| dot_product( Array1S< bool > const & a, Array1< bool > const & b ) | |
| { | |
| return dot( a, b ); | |
| } | |
| // Cross Product of 2-Tuples | |
| template< typename T > | |
| inline | |
| T | |
| cross2( Vector2< T > const & a, Array1< T > const & b ) | |
| { | |
| return cross2( b, a ); | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array1_hh_INCLUDED | |
| // ===== ObjexxFCL/Array1D.hh ===== | |
| #ifndef ObjexxFCL_Array1D_hh_INCLUDED | |
| #define ObjexxFCL_Array1D_hh_INCLUDED | |
| // Array1D: 1D Array | |
| // | |
| // Project: Objexx Fortran-C++ Library (ObjexxFCL) | |
| // | |
| // Version: 4.2.0 | |
| // | |
| // Language: C++ | |
| // | |
| // Copyright (c) 2000-2017 Objexx Engineering, Inc. All Rights Reserved. | |
| // Use of this source code or any derivative of it is restricted by license. | |
| // Licensing is available from Objexx Engineering, Inc.: http://objexx.com | |
| // ObjexxFCL Headers | |
| // C++ Headers | |
| #include <functional> | |
| namespace ObjexxFCL { | |
| // Array1D: 1D Array | |
| template< typename T > | |
| class Array1D : public Array1< T > | |
| { | |
| private: // Types | |
| typedef Array1< T > Super; | |
| typedef internal::InitializerSentinel InitializerSentinel; | |
| private: // Friend | |
| template< typename > friend class Array1D; | |
| friend class Array1A< T >; | |
| public: // Types | |
| typedef typename Super::Base Base; | |
| typedef typename Super::Traits Traits; | |
| typedef typename Super::IR IR; | |
| // STL Style | |
| typedef typename Super::value_type value_type; | |
| typedef typename Super::reference reference; | |
| typedef typename Super::const_reference const_reference; | |
| typedef typename Super::pointer pointer; | |
| typedef typename Super::const_pointer const_pointer; | |
| typedef typename Super::iterator iterator; | |
| typedef typename Super::const_iterator const_iterator; | |
| typedef typename Super::reverse_iterator reverse_iterator; | |
| typedef typename Super::const_reverse_iterator const_reverse_iterator; | |
| typedef typename Super::size_type size_type; | |
| typedef typename Super::difference_type difference_type; | |
| // C++ Style | |
| typedef typename Super::Value Value; | |
| typedef typename Super::Reference Reference; | |
| typedef typename Super::ConstReference ConstReference; | |
| typedef typename Super::Pointer Pointer; | |
| typedef typename Super::ConstPointer ConstPointer; | |
| typedef typename Super::Iterator Iterator; | |
| typedef typename Super::ConstIterator ConstIterator; | |
| typedef typename Super::ReverseIterator ReverseIterator; | |
| typedef typename Super::ConstReverseIterator ConstReverseIterator; | |
| typedef typename Super::Size Size; | |
| typedef typename Super::Difference Difference; | |
| typedef std::function< void( Array1D< T > & ) > InitializerFunction; | |
| using Super::conformable; | |
| using Super::contains; | |
| using Super::index; | |
| using Super::isize1; | |
| using Super::l; | |
| using Super::operator (); | |
| using Super::operator []; | |
| using Super::size1; | |
| using Super::u; | |
| protected: // Types | |
| using Super::assign; | |
| using Super::clear_move; | |
| using Super::initialize; | |
| using Super::move_if; | |
| using Super::move_or_copy; | |
| using Super::move_or_copy_backward; | |
| using Super::resize; | |
| using Super::shift_set; | |
| using Super::shift_only_set; | |
| using Super::size_of; | |
| using Super::swap1; | |
| using Super::capacity_; | |
| using Super::data_; | |
| using Super::I_; | |
| using Super::sdata_; | |
| using Super::shift_; | |
| using Super::size_; | |
| public: // Creation | |
| // Default Constructor | |
| Array1D() | |
| { | |
| shift_ = 1; // For std::vector-like API | |
| } | |
| // Copy Constructor | |
| Array1D( Array1D const & a ) : | |
| Super( a ) | |
| {} | |
| // Move Constructor | |
| Array1D( Array1D && a ) noexcept : | |
| Super( std::move( a ) ) | |
| { | |
| } | |
| // Copy Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array1D( Array1D< U > const & a ) : | |
| Super( a ) | |
| {} | |
| // Super Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array1D( Array1< U > const & a ) : | |
| Super( a ) | |
| {} | |
| // Slice Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array1D( Array1S< U > const & a ) : | |
| Super( a ) | |
| { | |
| setup_real(); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| initialize( l, a( i ) ); | |
| } | |
| } | |
| // MArray Constructor Template | |
| template< class A, typename M > | |
| explicit | |
| Array1D( MArray1< A, M > const & a ) : | |
| Super( a ) | |
| { | |
| setup_real(); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| initialize( l, a( i ) ); | |
| } | |
| } | |
| // IndexRange Constructor | |
| explicit | |
| Array1D( IR const & I ) : | |
| Super( I ) | |
| { | |
| setup_real(); | |
| } | |
| // IndexRange + Initializer Value Constructor | |
| Array1D( IR const & I, T const & t ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| setup_real(); | |
| initialize( t ); | |
| } | |
| // IndexRange + Initializer Function Constructor | |
| Array1D( IR const & I, InitializerFunction const & fxn ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| setup_real(); | |
| initialize( fxn ); | |
| } | |
| // IndexRange + Initializer List Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( IR const & I, std::initializer_list< U > const l ) : | |
| Super( I, l ) | |
| { | |
| setup_real(); | |
| } | |
| // IndexRange + Super Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( IR const & I, Array1< U > const & a ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| assert( conformable( a ) ); | |
| setup_real(); | |
| initialize( a ); | |
| } | |
| // IndexRange + Slice Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( IR const & I, Array1S< U > const & a ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| assert( conformable( a ) ); | |
| setup_real(); | |
| size_type l( 0u ); | |
| for ( int i = 1, e = a.u(); i <= e; ++i, ++l ) { | |
| initialize( l, a( i ) ); | |
| } | |
| } | |
| // Super + IndexRange Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( Array1< U > const & a, IR const & I ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| assert( conformable( a ) ); | |
| setup_real(); | |
| initialize( a ); | |
| } | |
| // IndexRange + Base Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( IR const & I, Array< U > const & a ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| assert( size_ == a.size() ); | |
| setup_real(); | |
| initialize( a ); | |
| } | |
| // Base + IndexRange Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( Array< U > const & a, IR const & I ) : | |
| Super( I, InitializerSentinel{} ) | |
| { | |
| assert( size_ == a.size() ); | |
| setup_real(); | |
| initialize( a ); | |
| } | |
| // Initializer List Index Range Constructor Template | |
| template< typename U, class = typename std::enable_if< ! std::is_constructible< T, U >::value >::type > | |
| explicit | |
| Array1D( std::initializer_list< U > const l ) : | |
| Super( IR( l ) ) | |
| { | |
| assert( l.size() == 2 ); | |
| setup_real(); | |
| } | |
| // Initializer List of Values Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value && ! ( std::is_same< U, int >::value || std::is_same< U, Index >::value ) >::type, typename = void > | |
| Array1D( std::initializer_list< U > const l ) : | |
| Super( l ) | |
| { | |
| setup_real(); | |
| } | |
| // Initializer List of Values or Index Range Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value && ( std::is_same< U, int >::value || std::is_same< U, Index >::value ) >::type, typename = void, typename = void > | |
| Array1D( std::initializer_list< U > const l ) : | |
| Super( l ) | |
| { // Note: 2 item lists of index-like elements treated as index range: Others treated as values: See ObjexxFCL.Users.Array.html | |
| #ifdef OBJEXXFCL_DISALLOW_AMBIGUOUS_INITIALIZER_LIST_CONSTRUCTORS | |
| assert( l.size() != 2 ); // Avoid ambiguity with IndexRange {l,u} usage | |
| #endif | |
| if ( l.size() == 2 ) { // Treat as an IndexRange | |
| I_ = l; | |
| Base::reconstruct_by_size( size_of( I_ ) ); | |
| } | |
| setup_real(); | |
| } | |
| // Initializer List Index Range + Initializer Value Constructor Template | |
| template< typename U > | |
| Array1D( std::initializer_list< U > const l, T const & t ) : | |
| Super( IR( l ), InitializerSentinel{} ) | |
| { | |
| assert( l.size() == 2 ); | |
| setup_real(); | |
| initialize( t ); | |
| } | |
| // Initializer List Index Range + Initializer Function Constructor Template | |
| template< typename U > | |
| Array1D( std::initializer_list< U > const l, InitializerFunction const & fxn ) : | |
| Super( IR( l ), InitializerSentinel{} ) | |
| { | |
| assert( l.size() == 2 ); | |
| setup_real(); | |
| initialize( fxn ); | |
| } | |
| // Initializer List Index Range + Super Constructor Template | |
| template< typename U, typename V, class = typename std::enable_if< std::is_constructible< T, V >::value >::type > | |
| Array1D( std::initializer_list< U > const l, Array1< V > const & a ) : | |
| Super( IR( l ), InitializerSentinel{} ) | |
| { | |
| assert( l.size() == 2 ); | |
| assert( conformable( a ) ); | |
| setup_real(); | |
| initialize( a ); | |
| } | |
| // Initializer List Index Range + Base Constructor Template | |
| template< typename U, typename V, class = typename std::enable_if< std::is_constructible< T, V >::value >::type > | |
| Array1D( std::initializer_list< U > const l, Array< V > const & a ) : | |
| Super( IR( l ), InitializerSentinel{} ) | |
| { | |
| assert( l.size() == 2 ); | |
| assert( size_ == a.size() ); | |
| setup_real(); | |
| initialize( a ); | |
| } | |
| // std::array Constructor Template | |
| template< typename U, Size s > | |
| Array1D( std::array< U, s > const & a ) : | |
| Super( a ) | |
| { | |
| setup_real(); | |
| } | |
| // std::vector Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( std::vector< U > const & v ) : | |
| Super( v ) | |
| { | |
| setup_real(); | |
| } | |
| // Vector2 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( Vector2< U > const & v ) : | |
| Super( v ) | |
| { | |
| setup_real(); | |
| } | |
| // Vector3 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( Vector3< U > const & v ) : | |
| Super( v ) | |
| { | |
| setup_real(); | |
| } | |
| // Vector4 Constructor Template | |
| template< typename U, class = typename std::enable_if< std::is_constructible< T, U >::value >::type > | |
| Array1D( Vector4< U > const & v ) : | |
| Super( v ) | |
| { | |
| setup_real(); | |
| } | |
| // Iterator Range Constructor Template | |
| template< class Iterator, typename = decltype( *std::declval< Iterator & >(), void(), ++std::declval< Iterator & >(), void() ) > | |
| Array1D( Iterator const beg, Iterator const end ) : | |
| Super( beg, end ) | |
| { | |
| setup_real(); | |
| } | |
| // Array Range Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| range( Array1< U > const & a ) | |
| { | |
| return Array1D( a.I() ); | |
| } | |
| // Array Range + Initializer Value Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| range( Array1< U > const & a, T const & t ) | |
| { | |
| return Array1D( a.I(), t ); | |
| } | |
| // Array Shape Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| shape( Array1< U > const & a ) | |
| { | |
| return Array1D( a.isize() ); | |
| } | |
| // Array Shape + Initializer Value Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| shape( Array1< U > const & a, T const & t ) | |
| { | |
| return Array1D( a.isize(), t ); | |
| } | |
| // Slice Shape Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| shape( Array1S< U > const & a ) | |
| { | |
| return Array1D( a.isize() ); | |
| } | |
| // Slice Shape + Initializer Value Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| shape( Array1S< U > const & a, T const & t ) | |
| { | |
| return Array1D( a.isize(), t ); | |
| } | |
| // One-Based Copy Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| one_based( Array1< U > const & a ) | |
| { | |
| return Array1D( a.isize(), a ); | |
| } | |
| // One-Based Slice Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| one_based( Array1S< U > const & a ) | |
| { | |
| return Array1D( a.isize(), a ); | |
| } | |
| // Initializer List One-Based Named Constructor Template | |
| template< typename U > | |
| static | |
| Array1D | |
| one_based( std::initializer_list< U > const l ) | |
| { | |
| return Array1D( static_cast< int >( l.size() ), l ); | |
| } | |
| // Destructor | |
| virtual | |
| ~Array1D() = default; | |
| private: // Creation | |
| // IndexRange Raw Constructor | |
| explicit | |
| Array1D( IR const & I, InitializerSentinel initialized ) : | |
| Super( I, initialized ) | |
| { | |
| setup_real(); | |
| } | |
| public: // Assignment: Array | |
| // Copy Assignment | |
| Array1D & | |
| operator =( Array1D const & a ) | |
| { | |
| if ( this != &a ) { | |
| if ( ( conformable( a ) ) || ( ! size_real( a.I_ ) ) ) { | |
| Base::operator =( a ); | |
| } else { | |
| Base::initialize( a ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Move Assignment | |
| Array1D & | |
| operator =( Array1D && a ) noexcept | |
| { | |
| if ( conformable( a ) ) { | |
| Base::conformable_move( a ); | |
| } else { | |
| Base::operator =( std::move( a ) ); | |
| I_ = a.I_; | |
| } | |
| a.clear_move(); | |
| return *this; | |
| } | |
| // Super Assignment | |
| Array1D & | |
| operator =( Super const & a ) | |
| { | |
| if ( this != &a ) { | |
| if ( ( conformable( a ) ) || ( ! size_real( a.I_ ) ) ) { | |
| Base::operator =( a ); | |
| } else { | |
| Base::initialize( a ); | |
| } | |
| } | |
| return *this; | |
| } | |
| // Super Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( Array1< U > const & a ) | |
| { | |
| if ( ( conformable( a ) ) || ( ! size_real( a.I_ ) ) ) { | |
| Base::operator =( a ); | |
| } else { | |
| Base::initialize( a ); | |
| } | |
| return *this; | |
| } | |
| // Slice Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( Array1S< U > const & a ) | |
| { | |
| Super::operator =( a ); | |
| return *this; | |
| } | |
| // Initializer List Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( std::initializer_list< U > const l ) | |
| { | |
| Base::operator =( l ); | |
| return *this; | |
| } | |
| // std::array Assignment Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( std::array< U, s > const & a ) | |
| { | |
| Base::operator =( a ); | |
| return *this; | |
| } | |
| // std::vector Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( std::vector< U > const & v ) | |
| { | |
| Base::operator =( v ); | |
| return *this; | |
| } | |
| // Vector2 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( Vector2< U > const & v ) | |
| { | |
| Base::operator =( v ); | |
| return *this; | |
| } | |
| // Vector3 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( Vector3< U > const & v ) | |
| { | |
| Base::operator =( v ); | |
| return *this; | |
| } | |
| // Vector4 Assignment Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator =( Vector4< U > const & v ) | |
| { | |
| Base::operator =( v ); | |
| return *this; | |
| } | |
| // += Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( Array1< U > const & a ) | |
| { | |
| Super::operator +=( a ); | |
| return *this; | |
| } | |
| // -= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( Array1< U > const & a ) | |
| { | |
| Super::operator -=( a ); | |
| return *this; | |
| } | |
| // *= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( Array1< U > const & a ) | |
| { | |
| Super::operator *=( a ); | |
| return *this; | |
| } | |
| // /= Array Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( Array1< U > const & a ) | |
| { | |
| Super::operator /=( a ); | |
| return *this; | |
| } | |
| // += Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( Array1S< U > const & a ) | |
| { | |
| Super::operator +=( a ); | |
| return *this; | |
| } | |
| // -= Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( Array1S< U > const & a ) | |
| { | |
| Super::operator -=( a ); | |
| return *this; | |
| } | |
| // *= Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( Array1S< U > const & a ) | |
| { | |
| Super::operator *=( a ); | |
| return *this; | |
| } | |
| // /= Slice Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( Array1S< U > const & a ) | |
| { | |
| Super::operator /=( a ); | |
| return *this; | |
| } | |
| // += Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( std::initializer_list< U > const l ) | |
| { | |
| Base::operator +=( l ); | |
| return *this; | |
| } | |
| // -= Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( std::initializer_list< U > const l ) | |
| { | |
| Base::operator -=( l ); | |
| return *this; | |
| } | |
| // *= Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( std::initializer_list< U > const l ) | |
| { | |
| Base::operator *=( l ); | |
| return *this; | |
| } | |
| // /= Initializer List Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( std::initializer_list< U > const l ) | |
| { | |
| Base::operator /=( l ); | |
| return *this; | |
| } | |
| // += std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( std::array< U, s > const & a ) | |
| { | |
| Base::operator +=( a ); | |
| return *this; | |
| } | |
| // -= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( std::array< U, s > const & a ) | |
| { | |
| Base::operator -=( a ); | |
| return *this; | |
| } | |
| // *= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( std::array< U, s > const & a ) | |
| { | |
| Base::operator *=( a ); | |
| return *this; | |
| } | |
| // /= std::array Template | |
| template< typename U, Size s, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( std::array< U, s > const & a ) | |
| { | |
| Base::operator /=( a ); | |
| return *this; | |
| } | |
| // += std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( std::vector< U > const & v ) | |
| { | |
| Base::operator +=( v ); | |
| return *this; | |
| } | |
| // -= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( std::vector< U > const & v ) | |
| { | |
| Base::operator -=( v ); | |
| return *this; | |
| } | |
| // *= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( std::vector< U > const & v ) | |
| { | |
| Base::operator *=( v ); | |
| return *this; | |
| } | |
| // /= std::vector Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( std::vector< U > const & v ) | |
| { | |
| Base::operator /=( v ); | |
| return *this; | |
| } | |
| // += Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( Vector2< U > const & v ) | |
| { | |
| Base::operator +=( v ); | |
| return *this; | |
| } | |
| // -= Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( Vector2< U > const & v ) | |
| { | |
| Base::operator -=( v ); | |
| return *this; | |
| } | |
| // *= Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( Vector2< U > const & v ) | |
| { | |
| Base::operator *=( v ); | |
| return *this; | |
| } | |
| // /= Vector2 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( Vector2< U > const & v ) | |
| { | |
| Base::operator /=( v ); | |
| return *this; | |
| } | |
| // += Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( Vector3< U > const & v ) | |
| { | |
| Base::operator +=( v ); | |
| return *this; | |
| } | |
| // -= Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( Vector3< U > const & v ) | |
| { | |
| Base::operator -=( v ); | |
| return *this; | |
| } | |
| // *= Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( Vector3< U > const & v ) | |
| { | |
| Base::operator *=( v ); | |
| return *this; | |
| } | |
| // /= Vector3 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( Vector3< U > const & v ) | |
| { | |
| Base::operator /=( v ); | |
| return *this; | |
| } | |
| // += Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator +=( Vector4< U > const & v ) | |
| { | |
| Base::operator +=( v ); | |
| return *this; | |
| } | |
| // -= Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator -=( Vector4< U > const & v ) | |
| { | |
| Base::operator -=( v ); | |
| return *this; | |
| } | |
| // *= Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator *=( Vector4< U > const & v ) | |
| { | |
| Base::operator *=( v ); | |
| return *this; | |
| } | |
| // /= Vector4 Template | |
| template< typename U, class = typename std::enable_if< std::is_assignable< T&, U >::value >::type > | |
| Array1D & | |
| operator /=( Vector4< U > const & v ) | |
| { | |
| Base::operator /=( v ); | |
| return *this; | |
| } | |
| public: // Assignment: Value | |
| // = Value | |
| Array1D & | |
| operator =( T const & t ) | |
| { | |
| Base::operator =( t ); | |
| return *this; | |
| } | |
| // += Value | |
| Array1D & | |
| operator +=( T const & t ) | |
| { | |
| Base::operator +=( t ); | |
| return *this; | |
| } | |
| // -= Value | |
| Array1D & | |
| operator -=( T const & t ) | |
| { | |
| Base::operator -=( t ); | |
| return *this; | |
| } | |
| // *= Value | |
| Array1D & | |
| operator *=( T const & t ) | |
| { | |
| Base::operator *=( t ); | |
| return *this; | |
| } | |
| // /= Value | |
| Array1D & | |
| operator /=( T const & t ) | |
| { | |
| Base::operator /=( t ); | |
| return *this; | |
| } | |
| public: // Modifier | |
| // Clear | |
| Array1D & | |
| clear() | |
| { | |
| Super::clear(); | |
| return *this; | |
| } | |
| // Dimension by IndexRange | |
| Array1D & | |
| allocate( IR const & I ) | |
| { | |
| dimension_real( I ); | |
| return *this; | |
| } | |
| // Dimension by Array Template | |
| template< typename U > | |
| Array1D & | |
| allocate( Array1< U > const & a ) | |
| { | |
| dimension_real( a.I_ ); | |
| return *this; | |
| } | |
| // Deallocate | |
| Array1D & | |
| deallocate() | |
| { | |
| Super::clear(); | |
| return *this; | |
| } | |
| // Dimension by IndexRange | |
| Array1D & | |
| dimension( IR const & I ) | |
| { | |
| dimension_real( I ); | |
| return *this; | |
| } | |
| // Dimension by IndexRange + Initializer Value | |
| Array1D & | |
| dimension( IR const & I, T const & t ) | |
| { | |
| dimension_real( I, t ); | |
| return *this; | |
| } | |
| // Dimension by IndexRange + Initializer Function | |
| Array1D & | |
| dimension( IR const & I, InitializerFunction const & fxn ) | |
| { | |
| dimension_real( I, fxn ); | |
| return *this; | |
| } | |
| // Dimension by Array Template | |
| template< typename U > | |
| Array1D & | |
| dimension( Array1< U > const & a ) | |
| { | |
| dimension_real( a.I_ ); | |
| return *this; | |
| } | |
| // Dimension by Array + Initializer Value Template | |
| template< typename U > | |
| Array1D & | |
| dimension( Array1< U > const & a, T const & t ) | |
| { | |
| dimension_real( a.I_, t ); | |
| return *this; | |
| } | |
| // Dimension by Array + Initializer Function Template | |
| template< typename U > | |
| Array1D & | |
| dimension( Array1< U > const & a, InitializerFunction const & fxn ) | |
| { | |
| dimension_real( a.I_, fxn ); | |
| return *this; | |
| } | |
| // Data-Preserving Redimension by IndexRange | |
| Array1D & | |
| redimension( IR const & I ) | |
| { | |
| if ( size_ == 0u ) { // No data | |
| return dimension( I ); | |
| } else if ( I.size() <= capacity_ ) { // Use existing capacity | |
| size_type const new_size( I.size() ); | |
| if ( new_size > size_ ) { // Initialize new tail elements | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| T const fill( Traits::initial_array_value() ); | |
| #endif | |
| for ( size_type i = size_; i < new_size; ++i ) { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| new ( data_ + i ) T( fill ); | |
| #else | |
| new ( data_ + i ) T; | |
| #endif | |
| } | |
| } | |
| std::ptrdiff_t const off( I_.l() - I.l() ); | |
| if ( off > 0 ) { // Move elements up | |
| size_type const offu( off ); | |
| size_type const stop( offu < new_size ? std::min( size_, new_size - offu ) : 0u ); | |
| move_or_copy_backward( data_, data_ + stop, data_ + stop + off ); | |
| } else if ( off < 0 ) { // Move elements down | |
| size_type const offu( -off ); | |
| size_type const stop( offu < size_ ? std::min( size_, new_size + offu ) : 0u ); | |
| if ( offu < stop ) move_or_copy( data_ + offu, data_ + stop, data_ ); | |
| } | |
| if ( new_size < size_ ) { // Destruct removed tail elements | |
| for ( size_type i = new_size; i < size_; ++i ) { | |
| data_[ i ].~T(); | |
| } | |
| } | |
| I_ = I; | |
| shift_set( I_.l() ); | |
| size_ = new_size; | |
| return *this; | |
| } else { // Allocate new space | |
| Array1D o( I, InitializerSentinel{} ); | |
| auto const l_( l() ); | |
| auto const I_l_( I.l() ); | |
| auto const l_max_( std::max( l_, I_l_ ) ); | |
| auto const u_( u() ); | |
| auto const I_u_( I.u() ); | |
| auto const u_min_( std::min( u_, I_u_ ) ); | |
| if ( I_l_ < l_ ) { // Initialize new lower elements | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| T const fill( Traits::initial_array_value() ); | |
| #endif | |
| for ( int i = I_l_, e = std::min( l_ - 1, I_u_ ); i <= e; ++i ) { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| new ( &o( i ) ) T( fill ); | |
| #else | |
| new ( &o( i ) ) T; | |
| #endif | |
| } | |
| } | |
| if ( l_max_ <= u_min_ ) { // Ranges overlap | |
| for ( int i = l_max_; i <= u_min_; ++i ) { | |
| new ( &o( i ) ) T( move_if( operator ()( i ) ) ); | |
| } | |
| } | |
| if ( u_ < I_u_ ) { // Initialize new upper elements | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| T const fill( Traits::initial_array_value() ); | |
| #endif | |
| for ( int i = std::max( u_ + 1, I_l_ ); i <= I_u_; ++i ) { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| new ( &o( i ) ) T( fill ); | |
| #else | |
| new ( &o( i ) ) T; | |
| #endif | |
| } | |
| } | |
| swap1( o ); | |
| return *this; | |
| } | |
| } | |
| // Data-Preserving Redimension by IndexRange + Fill Value | |
| Array1D & | |
| redimension( IR const & I, T const & t ) | |
| { | |
| if ( size_ == 0u ) { // No data | |
| return dimension( I, t ); | |
| } else if ( I.size() <= capacity_ ) { // Use existing capacity | |
| size_type const new_size( I.size() ); | |
| if ( new_size > size_ ) { // Initialize new tail elements | |
| for ( size_type i = size_; i < new_size; ++i ) { | |
| new ( data_ + i ) T( t ); | |
| } | |
| } | |
| std::ptrdiff_t const off( I_.l() - I.l() ); | |
| if ( off > 0 ) { // Move elements up | |
| size_type const offu( off ); | |
| size_type const stop( offu < new_size ? std::min( size_, new_size - offu ) : 0u ); | |
| move_or_copy_backward( data_, data_ + stop, data_ + stop + off ); | |
| std::fill_n( data_, std::min( offu, std::min( size_, new_size ) ), t ); | |
| } else if ( off < 0 ) { // Move elements down | |
| size_type const offu( -off ); | |
| size_type const stop( offu < size_ ? std::min( size_, new_size + offu ) : 0u ); | |
| if ( offu < stop ) { | |
| move_or_copy( data_ + offu, data_ + stop, data_ ); | |
| std::fill_n( data_ + ( stop - offu ), std::min( size_, new_size ) - ( stop - offu ), t ); | |
| } else { | |
| std::fill_n( data_, std::min( size_, new_size ), t ); | |
| } | |
| } | |
| if ( new_size < size_ ) { // Destruct removed tail elements | |
| for ( size_type i = new_size; i < size_; ++i ) { | |
| data_[ i ].~T(); | |
| } | |
| } | |
| I_ = I; | |
| shift_set( I_.l() ); | |
| size_ = new_size; | |
| return *this; | |
| } else { // Allocate new space | |
| Array1D o( I, InitializerSentinel{} ); | |
| auto const l_( l() ); | |
| auto const I_l_( I.l() ); | |
| auto const l_max_( std::max( l_, I_l_ ) ); | |
| auto const u_( u() ); | |
| auto const I_u_( I.u() ); | |
| auto const u_min_( std::min( u_, I_u_ ) ); | |
| if ( I_l_ < l_ ) { // Fill new lower elements | |
| for ( int i = I_l_, e = std::min( l_ - 1, I_u_ ); i <= e; ++i ) { | |
| new ( &o( i ) ) T( t ); | |
| } | |
| } | |
| if ( l_max_ <= u_min_ ) { // Ranges overlap | |
| for ( int i = l_max_; i <= u_min_; ++i ) { | |
| new ( &o( i ) ) T( move_if( operator ()( i ) ) ); | |
| } | |
| } | |
| if ( u_ < I_u_ ) { // Fill new upper elements | |
| for ( int i = std::max( u_ + 1, I_l_ ); i <= I_u_; ++i ) { | |
| new ( &o( i ) ) T( t ); | |
| } | |
| } | |
| swap1( o ); | |
| return *this; | |
| } | |
| } | |
| // Data-Preserving Redimension by Array Template | |
| template< typename U > | |
| Array1D & | |
| redimension( Array1< U > const & a ) | |
| { | |
| return redimension( a.I_ ); | |
| } | |
| // Data-Preserving Redimension by Array + Fill Value Template | |
| template< typename U > | |
| Array1D & | |
| redimension( Array1< U > const & a, T const & t ) | |
| { | |
| return redimension( a.I_, t ); | |
| } | |
| // Append Value: Grow by 1 | |
| Array1D & | |
| append( T const & t ) | |
| { | |
| if ( capacity_ == size_ ) { // Grow by 1 | |
| Array1D o( IndexRange( l(), u() + 1 ), InitializerSentinel{} ); | |
| for ( int i = l(), e = u(); i <= e; ++i ) { | |
| new ( &o( i ) ) T( move_if( operator ()( i ) ) ); | |
| } | |
| swap1( o ); | |
| new ( data_ + size_ - 1 ) T( t ); | |
| } else { | |
| I_.grow(); | |
| ++size_; | |
| operator ()( u() ) = t; | |
| } | |
| return *this; | |
| } | |
| // Append Value: Grow by 1 | |
| template< typename U = T, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| Array1D & | |
| append( T && t ) | |
| { | |
| if ( capacity_ == size_ ) { // Grow by 1 | |
| Array1D o( IndexRange( l(), u() + 1 ), InitializerSentinel{} ); | |
| for ( int i = l(), e = u(); i <= e; ++i ) { | |
| new ( &o( i ) ) T( std::move( operator ()( i ) ) ); | |
| } | |
| swap1( o ); | |
| new ( data_ + size_ - 1 ) T( std::move( t ) ); | |
| } else { | |
| I_.grow(); | |
| ++size_; | |
| operator ()( u() ) = std::move( t ); | |
| } | |
| return *this; | |
| } | |
| // Swap | |
| Array1D & | |
| swap( Array1D & v ) | |
| { | |
| using std::swap; | |
| swap1( v ); | |
| return *this; | |
| } | |
| public: // std::vector-like API | |
| // First Value | |
| T const & | |
| front() const | |
| { | |
| assert( size_ > 0u ); | |
| return operator []( 0u ); | |
| } | |
| // First Value | |
| T & | |
| front() | |
| { | |
| assert( size_ > 0u ); | |
| return operator []( 0u ); | |
| } | |
| // Last Value | |
| T const & | |
| back() const | |
| { | |
| assert( size_ > 0u ); | |
| return operator []( size_ - 1 ); | |
| } | |
| // Last Value | |
| T & | |
| back() | |
| { | |
| assert( size_ > 0u ); | |
| return operator []( size_ - 1 ); | |
| } | |
| // Append Value by Copy | |
| Array1D & | |
| push_back( T const & t ) | |
| { | |
| I_.grow(); | |
| Base::do_push_back_copy( t ); | |
| return *this; | |
| } | |
| // Append Value by Move | |
| template< typename U = T, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| Array1D & | |
| push_back( T && t ) | |
| { | |
| I_.grow(); | |
| Base::do_push_back_move( std::move( t ) ); | |
| return *this; | |
| } | |
| // Remove Last Value | |
| Array1D & | |
| pop_back() | |
| { | |
| if ( size_ > 0u ) { | |
| I_.shrink(); | |
| Base::do_pop_back(); | |
| } | |
| return *this; | |
| } | |
| // Insert Value by Copy | |
| iterator | |
| insert( const_iterator pos, T const & t ) | |
| { | |
| I_.grow(); | |
| return Base::do_insert_copy( pos, t ); | |
| } | |
| // Insert Value by Move | |
| template< typename U = T, class = typename std::enable_if< std::is_move_assignable< U >::value >::type > | |
| iterator | |
| insert( const_iterator pos, T && t ) | |
| { | |
| I_.grow(); | |
| return Base::do_insert_move( pos, std::move( t ) ); | |
| } | |
| // Insert Multiple Copies of a Value | |
| iterator | |
| insert( const_iterator pos, size_type n, T const & t ) | |
| { | |
| I_.grow( static_cast< int >( n ) ); | |
| return Base::do_insert_n( pos, n, t ); | |
| } | |
| // Insert Iterator Range | |
| template< typename Iterator, class = typename std::enable_if< | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::input_iterator_tag >::value || | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::forward_iterator_tag >::value || | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::bidirectional_iterator_tag >::value || | |
| std::is_same< typename std::iterator_traits< Iterator >::iterator_category, std::random_access_iterator_tag >::value | |
| >::type > | |
| iterator | |
| insert( const_iterator pos, Iterator first, Iterator last ) | |
| { | |
| I_.grow( static_cast< int >( std::distance( first, last ) ) ); | |
| return Base::do_insert_iterator( pos, first, last ); | |
| } | |
| // Insert Initializer List | |
| iterator | |
| insert( const_iterator pos, std::initializer_list< T > il ) | |
| { | |
| I_.grow( static_cast< int >( il.size() ) ); | |
| return Base::do_insert_initializer_list( pos, il ); | |
| } | |
| // Insert Value Constructed in Place | |
| template< typename... Args > | |
| iterator | |
| emplace( const_iterator pos, Args &&... args ) | |
| { | |
| I_.grow(); | |
| return Base::do_emplace( pos, std::forward< Args >( args )... ); | |
| } | |
| // Append Value Constructed in Place | |
| template< typename... Args > | |
| Array1D & | |
| emplace_back( Args &&... args ) | |
| { | |
| I_.grow(); | |
| Base::do_emplace_back( std::forward< Args >( args )... ); | |
| return *this; | |
| } | |
| // Erase Iterator | |
| iterator | |
| erase( const_iterator pos ) | |
| { | |
| I_.shrink(); | |
| return Base::do_erase( pos ); | |
| } | |
| // Erase Iterator Range | |
| iterator | |
| erase( const_iterator first, const_iterator last ) | |
| { | |
| I_.shrink( static_cast< int >( std::distance( first, last ) ) ); | |
| return Base::do_erase_iterator( first, last ); | |
| } | |
| // Reserve Capacity | |
| Array1D & | |
| reserve( size_type const n ) | |
| { | |
| Base::reserve_capacity( n ); | |
| return *this; | |
| } | |
| protected: // Functions | |
| // Dimension by IndexRange | |
| bool | |
| dimension_assign( IR const & I ) | |
| { | |
| return size_real( I ); | |
| } | |
| // Initialize to Default State | |
| void | |
| initialize() | |
| { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| std::uninitialized_fill_n( data_, size_, Traits::initial_array_value() ); | |
| #else | |
| for ( size_type i = 0; i < size_; ++i ) { | |
| new ( data_ + i ) T; | |
| } | |
| #endif | |
| } | |
| // Initialize by Function | |
| void | |
| initialize( InitializerFunction const & fxn ) | |
| { | |
| initialize(); | |
| fxn( *this ); | |
| } | |
| // Assignment to Default State | |
| void | |
| assign() | |
| { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| std::fill_n( data_, size_, Traits::initial_array_value() ); | |
| #endif | |
| } | |
| private: // Functions | |
| // Set Up for IndexRange Constructor | |
| void | |
| setup_real() | |
| { | |
| shift_set( I_.l() ); | |
| } | |
| // Size by IndexRange | |
| bool | |
| size_real( IR const & I ) | |
| { | |
| I_.assign( I ); | |
| shift_only_set( I_.l() ); | |
| return resize( size_of( I_ ) ); | |
| } | |
| // Dimension by IndexRange | |
| void | |
| dimension_real( IR const & I ) | |
| { | |
| if ( size_real( I ) ) { | |
| initialize(); | |
| } else { | |
| #if defined(OBJEXXFCL_ARRAY_INIT) || defined(OBJEXXFCL_ARRAY_INIT_DEBUG) | |
| assign(); | |
| #endif | |
| } | |
| } | |
| // Dimension by IndexRange + Initializer Value | |
| void | |
| dimension_real( IR const & I, T const & t ) | |
| { | |
| if ( size_real( I ) ) { | |
| initialize( t ); | |
| } else { | |
| assign( t ); | |
| } | |
| } | |
| // Dimension by IndexRange + Initializer Function | |
| void | |
| dimension_real( IR const & I, InitializerFunction const & fxn ) | |
| { | |
| if ( size_real( I ) ) initialize(); | |
| fxn( *this ); | |
| } | |
| }; // Array1D | |
| // Swap | |
| template< typename T > | |
| inline | |
| void | |
| swap( Array1D< T > & a, Array1D< T > & b ) | |
| { | |
| a.swap( b ); | |
| } | |
| // Comparison: Elemental | |
| // Array == Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| eq_elemental( a, b, r ); | |
| return r; | |
| } | |
| // Array != Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| ne_elemental( a, b, r ); | |
| return r; | |
| } | |
| // Array < Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| lt_elemental( a, b, r ); | |
| return r; | |
| } | |
| // Array <= Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| le_elemental( a, b, r ); | |
| return r; | |
| } | |
| // Array > Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| gt_elemental( a, b, r ); | |
| return r; | |
| } | |
| // Array >= Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| ge_elemental( a, b, r ); | |
| return r; | |
| } | |
| // Array == Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| eq_elemental( a, t, r ); | |
| return r; | |
| } | |
| // Array != Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| ne_elemental( a, t, r ); | |
| return r; | |
| } | |
| // Array < Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| lt_elemental( a, t, r ); | |
| return r; | |
| } | |
| // Array <= Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| le_elemental( a, t, r ); | |
| return r; | |
| } | |
| // Array > Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| gt_elemental( a, t, r ); | |
| return r; | |
| } | |
| // Array >= Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| ge_elemental( a, t, r ); | |
| return r; | |
| } | |
| // Value == Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( T const & t, Array1< T > const & b ) | |
| { | |
| return ( b == t ); | |
| } | |
| // Value != Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( T const & t, Array1< T > const & b ) | |
| { | |
| return ( b != t ); | |
| } | |
| // Value < Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( T const & t, Array1< T > const & b ) | |
| { | |
| return ( b > t ); | |
| } | |
| // Value <= Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( T const & t, Array1< T > const & b ) | |
| { | |
| return ( b >= t ); | |
| } | |
| // Value > Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( T const & t, Array1< T > const & b ) | |
| { | |
| return ( b < t ); | |
| } | |
| // Value >= Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( T const & t, Array1< T > const & b ) | |
| { | |
| return ( b <= t ); | |
| } | |
| // Comparison: Elemental: Slice | |
| // Slice == Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) == b( i ) ); | |
| } | |
| return r; | |
| } | |
| // Slice != Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) != b( i ) ); | |
| } | |
| return r; | |
| } | |
| // Slice < Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) < b( i ) ); | |
| } | |
| return r; | |
| } | |
| // Slice <= Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) <= b( i ) ); | |
| } | |
| return r; | |
| } | |
| // Slice > Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) > b( i ) ); | |
| } | |
| return r; | |
| } | |
| // Slice >= Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) >= b( i ) ); | |
| } | |
| return r; | |
| } | |
| // Slice == Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| BArray::size_type l( 0u ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i, ++l ) { | |
| r( i ) = ( a( i ) == b[ l ] ); | |
| } | |
| return r; | |
| } | |
| // Slice != Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| BArray::size_type l( 0u ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i, ++l ) { | |
| r( i ) = ( a( i ) != b[ l ] ); | |
| } | |
| return r; | |
| } | |
| // Slice < Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| BArray::size_type l( 0u ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i, ++l ) { | |
| r( i ) = ( a( i ) < b[ l ] ); | |
| } | |
| return r; | |
| } | |
| // Slice <= Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| BArray::size_type l( 0u ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i, ++l ) { | |
| r( i ) = ( a( i ) <= b[ l ] ); | |
| } | |
| return r; | |
| } | |
| // Slice > Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| BArray::size_type l( 0u ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i, ++l ) { | |
| r( i ) = ( a( i ) > b[ l ] ); | |
| } | |
| return r; | |
| } | |
| // Slice >= Array | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| BArray::size_type l( 0u ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i, ++l ) { | |
| r( i ) = ( a( i ) >= b[ l ] ); | |
| } | |
| return r; | |
| } | |
| // Array == Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return ( b == a ); | |
| } | |
| // Array != Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return ( b != a ); | |
| } | |
| // Array < Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return ( b > a ); | |
| } | |
| // Array <= Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return ( b >= a ); | |
| } | |
| // Array > Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return ( b < a ); | |
| } | |
| // Array >= Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return ( b <= a ); | |
| } | |
| // Slice == Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) == t ); | |
| } | |
| return r; | |
| } | |
| // Slice != Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) != t ); | |
| } | |
| return r; | |
| } | |
| // Slice < Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) < t ); | |
| } | |
| return r; | |
| } | |
| // Slice <= Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) <= t ); | |
| } | |
| return r; | |
| } | |
| // Slice > Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) > t ); | |
| } | |
| return r; | |
| } | |
| // Slice >= Value | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< bool > r( Array1D< bool >::shape( a ) ); | |
| for ( int i = 1, e = r.u(); i <= e; ++i ) { | |
| r( i ) = ( a( i ) >= t ); | |
| } | |
| return r; | |
| } | |
| // Value == Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator ==( T const & t, Array1S< T > const & b ) | |
| { | |
| return ( b == t ); | |
| } | |
| // Value != Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator !=( T const & t, Array1S< T > const & b ) | |
| { | |
| return ( b != t ); | |
| } | |
| // Value < Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <( T const & t, Array1S< T > const & b ) | |
| { | |
| return ( b > t ); | |
| } | |
| // Value <= Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator <=( T const & t, Array1S< T > const & b ) | |
| { | |
| return ( b >= t ); | |
| } | |
| // Value > Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >( T const & t, Array1S< T > const & b ) | |
| { | |
| return ( b < t ); | |
| } | |
| // Value >= Slice | |
| template< typename T > | |
| inline | |
| Array1D< bool > | |
| operator >=( T const & t, Array1S< T > const & b ) | |
| { | |
| return ( b <= t ); | |
| } | |
| // Generator | |
| // -Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= T( -1 ); | |
| return r; | |
| } | |
| // Array + Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += b; | |
| return r; | |
| } | |
| // Array - Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r -= b; | |
| return r; | |
| } | |
| // Array * Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= b; | |
| return r; | |
| } | |
| // Array / Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r /= b; | |
| return r; | |
| } | |
| // Array + Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += t; | |
| return r; | |
| } | |
| // Value + Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( T const & t, Array1< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += t; | |
| return r; | |
| } | |
| // Array - Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r -= t; | |
| return r; | |
| } | |
| // Value - Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( T const & t, Array1< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= T( -1 ); | |
| r += t; | |
| return r; | |
| } | |
| // Array * Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= t; | |
| return r; | |
| } | |
| // Value * Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( T const & t, Array1< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= t; | |
| return r; | |
| } | |
| // Array / Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( Array1< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r /= t; | |
| return r; | |
| } | |
| // Value / Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( T const & t, Array1< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r.invert(); | |
| r *= t; | |
| return r; | |
| } | |
| // Generator: Slice | |
| // -Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1S< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= T( -1 ); | |
| return r; | |
| } | |
| // Slice + Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += b; | |
| return r; | |
| } | |
| // Slice - Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r -= b; | |
| return r; | |
| } | |
| // Slice * Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= b; | |
| return r; | |
| } | |
| // Slice / Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r /= b; | |
| return r; | |
| } | |
| // Slice + Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += b; | |
| return r; | |
| } | |
| // Slice - Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r -= b; | |
| return r; | |
| } | |
| // Slice * Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= b; | |
| return r; | |
| } | |
| // Slice / Array | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r /= b; | |
| return r; | |
| } | |
| // Array + Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += b; | |
| return r; | |
| } | |
| // Array - Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r -= b; | |
| return r; | |
| } | |
| // Array * Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= b; | |
| return r; | |
| } | |
| // Array / Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r /= b; | |
| return r; | |
| } | |
| // Slice + Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += t; | |
| return r; | |
| } | |
| // Value + Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator +( T const & t, Array1S< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r += t; | |
| return r; | |
| } | |
| // Slice - Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r -= t; | |
| return r; | |
| } | |
| // Value - Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator -( T const & t, Array1S< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= T( -1 ); | |
| r += t; | |
| return r; | |
| } | |
| // Slice * Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= t; | |
| return r; | |
| } | |
| // Value * Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator *( T const & t, Array1S< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r *= t; | |
| return r; | |
| } | |
| // Slice / Value | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( Array1S< T > const & a, T const & t ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r /= t; | |
| return r; | |
| } | |
| // Value / Slice | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| operator /( T const & t, Array1S< T > const & a ) | |
| { | |
| Array1D< T > r( Array1D< T >::one_based( a ) ); | |
| r.invert(); | |
| r *= t; | |
| return r; | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| assert( a.size() == 3u ); | |
| Array1D< T > c( 3 ); | |
| c[ 0 ] = ( a[ 1 ] * b[ 2 ] ) - ( a[ 2 ] * b[ 1 ] ); | |
| c[ 1 ] = ( a[ 2 ] * b[ 0 ] ) - ( a[ 0 ] * b[ 2 ] ); | |
| c[ 2 ] = ( a[ 0 ] * b[ 1 ] ) - ( a[ 1 ] * b[ 0 ] ); | |
| return c; | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| assert( a.size() == 3u ); | |
| Array1D< T > c( 3 ); | |
| c[ 0 ] = ( a[ 1 ] * b[ 2 ] ) - ( a[ 2 ] * b[ 1 ] ); | |
| c[ 1 ] = ( a[ 2 ] * b[ 0 ] ) - ( a[ 0 ] * b[ 2 ] ); | |
| c[ 2 ] = ( a[ 0 ] * b[ 1 ] ) - ( a[ 1 ] * b[ 0 ] ); | |
| return c; | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| assert( a.size() == 3u ); | |
| Array1D< T > c( 3 ); | |
| c[ 0 ] = ( a[ 1 ] * b[ 2 ] ) - ( a[ 2 ] * b[ 1 ] ); | |
| c[ 1 ] = ( a[ 2 ] * b[ 0 ] ) - ( a[ 0 ] * b[ 2 ] ); | |
| c[ 2 ] = ( a[ 0 ] * b[ 1 ] ) - ( a[ 1 ] * b[ 0 ] ); | |
| return c; | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| assert( conformable( a, b ) ); | |
| assert( a.size() == 3u ); | |
| Array1D< T > c( 3 ); | |
| c[ 0 ] = ( a[ 1 ] * b[ 2 ] ) - ( a[ 2 ] * b[ 1 ] ); | |
| c[ 1 ] = ( a[ 2 ] * b[ 0 ] ) - ( a[ 0 ] * b[ 2 ] ); | |
| c[ 2 ] = ( a[ 0 ] * b[ 1 ] ) - ( a[ 1 ] * b[ 0 ] ); | |
| return c; | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross_product( Array1< T > const & a, Array1< T > const & b ) | |
| { | |
| return cross( a, b ); | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross_product( Array1< T > const & a, Array1S< T > const & b ) | |
| { | |
| return cross( a, b ); | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross_product( Array1S< T > const & a, Array1< T > const & b ) | |
| { | |
| return cross( a, b ); | |
| } | |
| // Cross Product of 3-Tuples | |
| template< typename T > | |
| inline | |
| Array1D< T > | |
| cross_product( Array1S< T > const & a, Array1S< T > const & b ) | |
| { | |
| return cross( a, b ); | |
| } | |
| } // ObjexxFCL | |
| #endif // ObjexxFCL_Array1D_hh_INCLUDED | |
| // ===== Out-of-line statics (normally in IndexRange.cc) ===== | |
| namespace ObjexxFCL { | |
| IndexRange::size_type const IndexRange::npos = static_cast< size_type >( -1 ); | |
| int const IndexRange::l_min = -( static_cast< int >( ( static_cast< unsigned int >( -1 ) / 2u ) ) - 1 ); | |
| int const IndexRange::u_max = static_cast< int >( ( static_cast< unsigned int >( -1 ) / 2u ) ); | |
| } // ObjexxFCL |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment