/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2012-2017 Danny Robson */ #ifndef CRUFT_UTIL_COORD_BASE_HPP #define CRUFT_UTIL_COORD_BASE_HPP #include "init.hpp" #include "./ops.hpp" #include "../maths.hpp" #include #include #include namespace util::coord { ///////////////////////////////////////////////////////////////////////// template < std::size_t S, typename T, template class KLASS, typename ...tags > struct base : public init { static_assert (S > 0); static_assert (std::is_arithmetic::value); using value_type = T; static constexpr std::size_t dimension = S; static constexpr std::size_t elements = S; /// returns the number of elements we contain static constexpr std::size_t size (void) { return S; } // inherit the fancy elementwise constructors from `init'. using init::init; /// constructs, but does not initialise, the data. /// /// used to avoid unnecessary initialisation in many situations where /// we have arrays of these types that are about to be overwritten. it /// is a very important performance optimisation. base () = default; /// constructs an instance where all elements are initialised to `val'. constexpr explicit base (T fill) { for (decltype(S) i = 0; i < S; ++i) this->data[i] = fill; } constexpr base (const base &rhs) = default; base& operator= (const base &rhs) = default; // element accessors T& operator[] (std::size_t i) { return this->data[i]; } constexpr const T& operator[] (std::size_t i) const { return this->data[i]; } auto cbegin (void) const { return std::cbegin (this->data); } auto cend (void) const { return std::cend (this->data); } auto begin (void) const { return std::begin (this->data); } auto end (void) const { return std::end (this->data); } auto begin (void) { return std::begin (this->data); } auto end (void) { return std::end (this->data); } const T& front (void) const { return this->data[0]; } T& front (void) { return this->data[0]; } const T& back (void) const { return this->data[S-1]; } T& back (void) { return this->data[S-1]; } /////////////////////////////////////////////////////////////////////// // conversions template