Skip to content

Instantly share code, notes, and snippets.

@fenrir-naru
Last active December 1, 2017 09:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fenrir-naru/50624aedd1398f8b71222b7f5b6620b5 to your computer and use it in GitHub Desktop.
Save fenrir-naru/50624aedd1398f8b71222b7f5b6620b5 to your computer and use it in GitHub Desktop.
#include <iostream>
using namespace std;
template <class T>
struct A;
template <class T, bool is_transposed, bool is_partial>
struct A_View : public A<T> {
struct {
unsigned row_offset, column_offset;
} prop_partial;
A_View(const A<T> &orig,
const unsigned &row_offset = 0, const unsigned &column_offset = 0) : A<T>(orig) {
prop_partial.row_offset = row_offset;
prop_partial.column_offset = column_offset;
}
template <bool is_transposed2, bool is_partial2>
A_View(const A_View<T, is_transposed2, is_partial2> &orig,
const unsigned &row_offset = 0, const unsigned &column_offset = 0) : A<T>(orig) {
if(is_partial){
if(is_transposed == is_transposed2){
prop_partial.row_offset = orig.prop_partial.row_offset + row_offset;
prop_partial.column_offset = orig.prop_partial.column_offset + column_offset;
}else{
prop_partial.row_offset = orig.prop_partial.column_offset + row_offset;
prop_partial.column_offset = orig.prop_partial.row_offset + column_offset;
}
}else{
prop_partial.row_offset = prop_partial.column_offset = 0;
}
}
template <bool is_transposed2, bool is_partial2, class U = void>
struct Converter{
typedef A_View<T, true, is_partial2> transposed_t;
typedef A_View<T, is_transposed2, true> partial_t;
};
template <class U>
struct Converter<true, false, U>{
typedef A<T> transposed_t;
typedef A_View<T, true, true> partial_t;
};
template <class U>
struct Converter<true, true, U>{
typedef A_View<T, false, true> transposed_t;
typedef A_View<T, true, true> partial_t;
};
typename Converter<is_transposed, is_partial>::transposed_t transpose() const {
return typename Converter<is_transposed, is_partial>::transposed_t(*this);
}
typename Converter<is_transposed, is_partial>::partial_t partial(
const unsigned &row_offset = 0, const unsigned &column_offset = 0) const {
return typename Converter<is_transposed, is_partial>::partial_t(*this, row_offset, column_offset);
}
const A_View<T, is_transposed, is_partial> &check(const char *label) const {
std::cout << label << " => A_View: "
<< (is_transposed ? "transposed " : "");
if(is_partial){
std::cout << "partial(" << prop_partial.row_offset << "," << prop_partial.column_offset << ") ";
}
std::cout << std::endl;
return *this;
}
virtual const T &operator()(const unsigned &i, const unsigned &j) const {
if(is_transposed){
if(is_partial){
return A<T>::operator()(prop_partial.row_offset + j, prop_partial.column_offset + i);
}else{
return A<T>::operator()(j, i);
}
}else{
if(is_partial){
return A<T>::operator()(prop_partial.row_offset + i, prop_partial.column_offset + j);
}else{
return A<T>::operator()(i, j);
}
}
}
};
template <class T>
struct A {
T buf[10][10];
A() {
for(unsigned i(0); i < 10; ++i){
for(unsigned j(i); j < 10; ++j){
buf[i][j] = i * j;
}
}
}
typedef A_View<T, true, false> transposed_t;
typedef A_View<T, false, true> partial_t;
transposed_t transpose() const {
return transposed_t(*this);
}
partial_t partial(const unsigned &row_offset = 0, const unsigned &column_offset = 0) const {
return partial_t(*this, row_offset, column_offset);
}
const A<T> &check(const char *label) const {
std::cout << label << " => A" << std::endl;
return *this;
}
virtual const T &operator()(const unsigned &i, const unsigned &j) const {
return buf[i][j];
}
T &operator()(const unsigned &i, const unsigned &j){
return const_cast<T &>(const_cast<const A<T> &>(*this)(i, j));
}
};
int main(){
A<int> a;
cout << a.check("A")(3, 4) << endl;
cout << a.transpose().check("At")(3, 4) << endl;
cout << a.partial(1, 2).check("Ap")(3, 4) << endl;
cout << a.transpose().partial(1, 2).check("Atp")(3, 4) << endl;
cout << a.transpose().transpose().check("Att")(3, 4) << endl;
cout << a.transpose().partial(1, 2).transpose().check("Atpt")(3, 4) << endl;
cout << a.transpose().partial(1, 2).transpose().transpose().check("Atptt")(3, 4) << endl;
cout << a.transpose().partial(1, 2).partial(1, 2).transpose().check("Atppt")(3, 4) << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment