diff --git a/binary_output/binary_output.hpp b/binary_output/binary_output.hpp index 34a27ac..0b24b43 100644 --- a/binary_output/binary_output.hpp +++ b/binary_output/binary_output.hpp @@ -1,3 +1,10 @@ +// +// binary_output.hpp +// +// Created by Joshua Moerman on 05/22/11. +// Copyright 2011 Vadovas. All rights reserved. +// + #ifndef BINARY_OUTPUT_HPP #define BINARY_OUTPUT_HPP diff --git a/brainfuck/brainfuck.hpp b/brainfuck/brainfuck.hpp index 1b12fae..8c91e21 100644 --- a/brainfuck/brainfuck.hpp +++ b/brainfuck/brainfuck.hpp @@ -1,3 +1,10 @@ +// +// brainfuck.hpp +// +// Created by Joshua Moerman on 05/22/11. +// Copyright 2011 Vadovas. All rights reserved. +// + #include #include #include diff --git a/iterators/counting_iterator.hpp b/iterators/counting_iterator.hpp index 462ab86..4ffc0ec 100644 --- a/iterators/counting_iterator.hpp +++ b/iterators/counting_iterator.hpp @@ -1,3 +1,10 @@ +// +// counting_iterator.hpp +// +// Created by Joshua Moerman on 05/22/11. +// Copyright 2011 Vadovas. All rights reserved. +// + /* USAGE: diff --git a/nd_array/nd_array.hpp b/nd_array/nd_array.hpp new file mode 100644 index 0000000..cfe08c8 --- /dev/null +++ b/nd_array/nd_array.hpp @@ -0,0 +1,156 @@ +// +// nd_array.hpp +// +// 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>). + Showed no difference in speed compared to std::vector> (in release build), so you better can use std::vector. + + This class can be used te reinterpret a big chunk of memory as a n-dimensional array. (Could be useful if your legacy-code gives you somthing like that). + + It is templated in number of dimensions (and of course type). With extra effort you could make the dimension dynamic (ie not compile-time, but run-time), I leave that as an excercise to the reader. + */ + +#ifndef AwesomeAttractorND_nd_array_hpp +#define AwesomeAttractorND_nd_array_hpp + +#include +#include +#include +#include // C++11, right here :D (if this fails, try using tr1) + +template +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 reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + /* + NOTE: I actually wanted to make a specialisation for N = 0, but this is not possible in class scope, so it had to be in namespace-scope. Problem with the specialisation then is that the outer-class isn't specialised, while the inner is, this is also not possible. So either I had to make this class completly out of the nd_array class (which would require a lot of templating), OR I check things in an non-templated way. I chose for the latter, since it was easier to make. The first one is actually beter (it would have better types, which make dimensionality-errors a type-error, instead of an exception). + */ + template + struct proxy { + nd_array * const data; + size_t const offset; + + proxy(nd_array * const c, size_t o) + : data(c) + , offset(o) + {} + + proxy operator[](size_t y){ + if (N == 0) throw std::logic_error("called operator[] on a value"); + return proxy(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 + 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 operator[](size_t y) const { + if (N == 0) throw std::logic_error("called operator[] on a value"); + return const_proxy(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()); + } + + proxy operator[](size_t x){ + return proxy(this, x); + } + + const_proxy operator[](size_t x) const { + return const_proxy(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 sizes; +}; + +#endif