Click here to Skip to main content
15,885,985 members
Articles / Desktop Programming / MFC
Article

Template-Based Helper Classes: An application to Multidimensional Arrays

Rate me:
Please Sign up or sign in to vote.
3.31/5 (13 votes)
8 Mar 2004GPL33 min read 68.5K   466   19   20
An Implementation of Multidimensional Arrays via Template-Based Helper Classes

Introduction

Multidimensional arrays provide a simple reshaping matrix structures. It could be created and initialized as a vector, and read as 3D matrix. However, subscripting is not that easy. Subscripting operators should reduce dimension of entire multi-array. The problem becomes harder when adding region-of-interest scripting facility. Region-of-interest scripting facility allows selecting separate rows, columns, and plates in different orders. More complexities may be added to support reference indexing. A typical solution is helper classes. Boost library has implemented a helper class to multi_array<t, n=""> for reference indexing and named as multi_array_ref<t, n="">. Matrix Template Library (MTL) provided helper classes to the matrix. Two helper classes were developed to emulate row set and column set. Communication between helper classes is made via copy constructors. More helper classes are needed for every new structure. This yields to more tightly coupled classes as many programmers tend to use friend classes.

Problem Statement and Basic Idea

We need more encapsulation of helper classes with original interfacing class. This could be accomplished by adding more template arguments. Classes with different template arguments lead to separate classes. However, it makes the whole class more cohesive and prevent user from using helper classes in a wrong way. In my master thesis I needed a flexible multidimensional array with the following specs.

1. array-like subscripting operators[].
2. matlab-like region of interests subscripting facility.
3. reference-like array to allow editing a set of selected entries.

1. Array-like subscripting operators[]

This piece of code declaresa a new initialized 3D multi-dimensional array.

tensor<double, 3, 1, false> itns3(dblbegin
5, 7, 3, 1, 2,
4, 7, 2, 1, 2,
1, 8, 9, 3, 6, 
1, 3, 5, 7, 8,

1, 7, 3, 8, 2,
1, 7, 3, 8, 2,
1, 7, 3, 8, 2,
1, 7, 3, 8, 2,

5, 7, 3, 1, 2,
4, 7, 2, 1, 2,
1, 8, 9, 3, 6,
1, 3, 5, 7, 8
clend, sizebegin 3, 4, 5 clend);

Where dblbegin, sizebegin, and clend are defined as follows:

#define dblbegin clbegin(double)
#define sizebegin clbegin(_sizetype)
#define clend )

and clbegin macro is defined as:

#define clbegin(T) (commalist<T>(),

Actually cl-prefix stands for comma-list. commalist<T> template class was developed to allow comma-concatenation. I guess comma-concatenation is simpler on gnu-C++.

Now the container itns3 has three dimensions [3, 4, 5] which is 3-plates, 4-rows each, and 5-cols for each row. Now consider using subscripting operator getting first plate, how many dimensions shall this array hold? Yup, tensor<t, 2=""> with two dims. That is why the subscripting is defined as follows:

tensor<T, N-1, D, true> operator[](const _sizetype& i);
const tensor<T, N-1, D, false> operator[](const _sizetype& i) const;

Other implemetations for multi-arrays makes use of helper classes named subset, rows, cols, rowset, colset, ...


Now moving to second facility;

2. Matlab-like region-of-interests subscripting facility

Region of interest (roi) lets you to select first and third rows for all columns. Consider the following:

tensor<double, 2> itns2(dblbegin 
5, 7, 3, 1, 2,
4, 7, 2, 1, 2,
1, 8, 9, 3, 6,
1, 3, 5, 7, 8
clend, sizebegin 4, 5 clend);

Now consider selecting all rows and cols numbered [0, 4, 2, 3]

itns2[all][select(0, 4, 2, 3, -1)]=3.0;

where select, and all are defined as follows:

#define all ixrange()
#define select rangelist<_indextype>

and ixrange() is defined as follows:

typedef range<_indextype> ixrange;

This means subscripting operator should return tensor<t, n=""> and not tensor<t, n-1=""> as discussed earlier.

This means that we need a new helper class presenting the new dimension we iterate on. In simple words, we first select two rows, and the new subscripting shall select three cols. That is why we need the D template parameter! And roi-subscripting operator should be declared as follows:

const tensor<T, N, D+1, false> operator[](const tensor<_indextype, 1> idx) const;
tensor<T, N, D+1, true> operator[](const tensor<_indextype, 1> idx);

Other implemetations make use of friend helper classes, and usually named as rowset and colset.

Lets move to next requirement:

3. Reference-like array to allow editing a set of selected entries

Reference containers capture addresses of selected entries and allow you to modify them. This was usually implemented with helper classes named reference_container, array<smart_ptr<T> >, or ref_array.
A tensor has one of two states if const subscripting operators should return a copy of entries, if not, a reference to entries should be returned. One more boolean template argument is added describing the entire tensor as a reference or not.

Class and Operator Headers

Consider the following class header:

// tensor<typename, # dims, dim to iterate on, being ref or not>
template<class T, _sizetype N=1, _sizetype D=1, _booltype REF=false>
class tensor : public io
then consider the subscripting operator. It should return a lower dimensioned non-reference tensor
const tensor<T, N-1, 1, false> operator[](const _sizetype& i) const

and this returns a lowerdimensioned referenced tensor:

tensor<T, N-1, 1, true> operator[](const _sizetype& i)

Now consider the region-of-interest subscripting operator. It should return a matrix of chosen rows, and next subscripting operator should iterate on the next dimension.

const tensor<T, N, D+1> operator[](const tensor<_indextype, 1> idx) const 

and this is a referenced copy too.

tensor<T, N, D+1, true> operator[](const tensor<_indextype, 1> idx) 

Thank You

Thanks a lot for your time. I just want to clarify that this is a testing version; I hope you enjoy this.

 

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Engineer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generali ve updated the article Pin
Mo Hossny12-Feb-04 1:16
Mo Hossny12-Feb-04 1:16 
GeneralRe: i ve updated the article Pin
WREY17-Feb-04 3:28
WREY17-Feb-04 3:28 
GeneralRe: i ve updated the article Pin
Mo Hossny9-Mar-04 3:39
Mo Hossny9-Mar-04 3:39 
GeneralI am holding my vote! Pin
WREY3-Feb-04 3:07
WREY3-Feb-04 3:07 
If wanting to show people how smart you are, then you've done that, "Great!"; now let's get to the business of the other members of CodeProject.

First, I would like to ask if you were writing this article for the general membership of CodeProject (because it's in that group I classify myself)?

Having read your article (the few paragraphs there are), I figured the substance of what the article is about, will have to come from reviewing the source code, which afterwards, I realized I had almost learnt nothing (from reading both the article and the source code) about how your "Template-Based Helper Classes," translates into an "An Application for Multi-dimensional Arrays." Don't blame my lack of comprehension here! After all, your "Detail" section provided us with a fully whopping six lines of code!! (How more generous can one be?)

Looking through your 'containers.h' file to obtain what the prose of the article did not reveal (this was after spending some time looking at, 'main.cpp' to understand how concepts were going to be processed), it had my head spinning, trying to find something (an idea, a clue, a technique) of cohesion with regards to where is "starting point" and "progressive unfolding" (i.e how ideas unfold and build up into subsequent ideas).

Understand this, I am looking through 'containers.h' to see if there are ideas (or portions of code representing ideas) from which I might be able to extract knowledge I could apply for my later use.

I am NOT going to be hypocritical in saying I understood half of what the codes in 'containers.h' are about. All I know is that after spending about half an hour trying to comprehend the construct of ideas that the various classes in 'containers.h' held, I concluded there was precious little I was understanding.

Speaking for myself (and only myself), I am just one case of where your gold nugget of intelligence and cleverness presented nothing of benefit and enlightenment. There was nothing in your article from which I could fall back on to find explanation about the various classes (and their purpose). Whatever great, big, wonderful idea you carry around in your head regarding this article, sadly, still remains there, which brings me back to my original question, "Were you writing this article for the general membership of CodeProject?" (because if you were, I don't see many people asking questions and expressing gratitude for the excellent help it has provided them).

Learn from the genius himself, Einstein, who said that expressing simplicity can sometimes be most difficult. This was after he came out with his famous equation that a lot of people thought should have merit an equation more complicated than the one he published. Those people believed an equation more deep and abstruse would have justified that kind of breakthrough he presented to the scientific world. They believed, keeping knowledge hidden and out of reach of the multitude, secured their place in the kingdom of divine blessings and intellect.

If you view us as peers, then heed the words and action of Einstein, and take on that which is MOST DIFFICULT by presenting SIMPLICITY!!

At this point, I will NOT vote up or down on the merit of your article. I shall simply abstain.

Hmmm | :|

William

Fortes in fide et opere!
GeneralRe: I am holding my vote! Pin
Mo Hossny4-Feb-04 21:18
Mo Hossny4-Feb-04 21:18 
GeneralRe: I am holding my vote! Pin
Miguel Lopes9-Feb-04 11:27
Miguel Lopes9-Feb-04 11:27 
GeneralRe: I am holding my vote! Pin
WREY10-Feb-04 7:58
WREY10-Feb-04 7:58 
GeneralRe: I am holding my vote! Pin
Mo Hossny10-Feb-04 21:55
Mo Hossny10-Feb-04 21:55 
GeneralRe: I am holding my vote! Pin
Anonymous10-Feb-04 22:09
Anonymous10-Feb-04 22:09 
GeneralRe: I am holding my vote! Pin
WREY10-Feb-04 22:17
WREY10-Feb-04 22:17 
GeneralRe: I am holding my vote! Pin
Mo Hossny10-Feb-04 21:54
Mo Hossny10-Feb-04 21:54 
GeneralRe: U != You Pin
Marc Brooks11-Feb-04 13:14
Marc Brooks11-Feb-04 13:14 
GeneralRe: U != You Pin
Miguel Lopes11-Feb-04 13:33
Miguel Lopes11-Feb-04 13:33 
GeneralRe: U != You Pin
J Whattam17-Feb-04 11:28
J Whattam17-Feb-04 11:28 
GeneralRe: U != You Pin
Marc Brooks17-Feb-04 14:15
Marc Brooks17-Feb-04 14:15 
GeneralRe: U != You Pin
JonatTJX20-Feb-04 4:43
JonatTJX20-Feb-04 4:43 
GeneralRe: I am holding my vote! Pin
Anonymous10-Feb-04 22:11
Anonymous10-Feb-04 22:11 
GeneralRe: I am holding my vote! Pin
WREY10-Feb-04 22:24
WREY10-Feb-04 22:24 
GeneralRe: I am holding my vote! Pin
Anonymous10-Feb-04 23:51
Anonymous10-Feb-04 23:51 
GeneralRe: I am holding my vote! Pin
WREY11-Feb-04 7:01
WREY11-Feb-04 7:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.