My old project for strange attractors, new approach
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 

152 lines
3.4 KiB

//
// nd_array.hpp
// AwesomeAttractorND
//
// Created by Joshua Moerman on 10/25/11.
// Copyright 2011 Vadovas. All rights reserved.
//
/*
Dynamic multi-dimensional array.
With the usual c-syntax: v[x][y][z].
Memory is allocated as one big block, instead of multiple smaller blocks (which is the case with std::vector<std::vector<...>>).
Showed no difference in speed compared to std::array<std::array<...>> (in release build).
it is not yet standard compliant.
*/
#ifndef AwesomeAttractorND_nd_array_hpp
#define AwesomeAttractorND_nd_array_hpp
#include <stdexcept>
#include <numeric>
#include <iterator>
#include "array.hpp"
template <typename T, size_t dimension>
class nd_array{
public:
typedef T & reference;
typedef T const & const_reference;
typedef T * iterator;
typedef T const * const_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T * pointer;
typedef T const * const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
template <size_type N>
struct proxy {
nd_array * const data;
size_t const offset;
proxy(nd_array * const c, size_t o)
: data(c)
, offset(o)
{}
proxy<N-1> operator[](size_t y){
if (N == 0) throw std::logic_error("called operator[] on a value");
return proxy<N-1>(data, data->sizes[dimension - N]*offset + y);
}
operator reference(){
if (N != 0) throw std::logic_error("using a non-value");
return *(data->data + offset);
}
reference operator=(T const & n){
if (N != 0) throw std::logic_error("assignment to a non-value");
return *(data->data + offset) = n;
}
};
template <size_type N>
struct const_proxy {
nd_array const * const data;
size_t const offset;
const_proxy(nd_array const * const c, size_t o)
: data(c)
, offset(o)
{}
const_proxy<N-1> operator[](size_t y) const {
if (N == 0) throw std::logic_error("called operator[] on a value");
return const_proxy<N-1>(data, data->sizes[dimension - N]*offset + y);
}
operator const_reference() const {
if (N != 0) throw std::logic_error("using a non-value");
return *(data->data + offset);
}
};
nd_array(size_type width, size_type height)
: data(0)
, sizes()
{
if (dimension != 2) throw std::logic_error("wrong constructor");
sizes[0] = width;
sizes[1] = height;
data = new T[width*height];
}
nd_array(size_type width, size_type height, size_type depth)
: data(0)
, sizes()
{
if (dimension != 3) throw std::logic_error("wrong constructor");
sizes[0] = width;
sizes[1] = height;
sizes[2] = depth;
data = new T[width*height*depth];
}
~nd_array(){
delete[] data;
}
size_type get_size(size_type d) const {
return sizes[d];
}
size_type size() const {
return std::accumulate(sizes.begin(), sizes.end(), 1, std::multiplies<size_type>());
}
proxy<dimension-1> operator[](size_t x){
return proxy<dimension-1>(this, x);
}
const_proxy<dimension-1> operator[](size_t x) const {
return const_proxy<dimension-1>(this, x);
}
iterator begin(){
return data;
}
iterator end(){
size_type length = size();
return data + length;
}
const_iterator cbegin() const {
return data;
}
const_iterator cend() const {
size_type length = size();
return data + length;
}
private:
T * data;
std::array<size_type, dimension> sizes;
};
#endif