Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matlab style indexing of a C++ array

I would like to know what the most efficient c++ implementation of the following matlab idiom is.

Suppose I have 3 vectors in matlab, x, y and idx.

x = [13,2,5.5,22,107]
y = [-3,100,200]
idx = [1,2,5]

I want to replace positions 1,2 and 5 of x with the contents of y. In matlab I do

x[idx] = y

What is the best way to do this in c++?

like image 687
Florian Oswald Avatar asked Aug 28 '12 14:08

Florian Oswald


People also ask

Can you index an array in MATLAB?

In general, you can use indexing to access elements of any array in MATLAB regardless of its data type or dimensions.

Does MATLAB indexing start at 0 or 1?

In most programming languages, the first element of an array is element 0. In MATLAB, indexes start at 1.

Are arrays in MATLAB zero indexed?

MATLAB does not allow an index of zero into an array unless you are performing logical indexing using a vector including a logical 0 and want to ignore the corresponding element of the array into which you are indexing.

Are C arrays zero indexed?

Usage in programming languages In these three, sequence types (C arrays, Java arrays and lists, and Lisp lists and vectors) are indexed beginning with the zero subscript.


3 Answers

The Armadillo library probably comes closest as one of its goals is to make things easy for folks used to Matlab.

Here is a short example (and uvec is a typdef for vector of unsigned ints)

// set four specific elements of X to 1
uvec indices;
indices << 2 << 3 << 6 << 8;

X.elem(indices) = ones<vec>(4);

Obviously, the right-hand side could be any other vector of the same dimension as the index.

But there are few language-imposed constraints you cannot overcome:

  • zero-based indexing at the C++ level (which you could alter, but few C / C++ programmers will consider it a good idea)
  • certain operators, including [
like image 187
Dirk Eddelbuettel Avatar answered Oct 06 '22 11:10

Dirk Eddelbuettel


A loop seems simple enough, although it can be made simpler with a helper function.

// helper function to get the size of an array
template<typename T, size_t S>
constexpr size_t size(T (&)[S])
{
  return S;
}

// loop
for (size_t i = 0; i < size(idx); ++i) x[idx[i]] = y[i];

Of course, here you should check that y is large enough:

like image 45
juanchopanza Avatar answered Oct 06 '22 11:10

juanchopanza


If you want it in pretty basic C++ (with no prizes for elegance) try this:

double x[] = { 13.0, 2.0, 5.5, 22.0, 107.0 };
double y[] = { -3.0, 100.0, 200.0 };
size_t idx[] = { 1, 2, 5 };

for ( size_t i = 0; i < sizeof(x)/sizeof(double); ++i )
    cout << x[i] << " ";
cout << endl;

// Make a mutable copy of x
double x1[ sizeof(x)/sizeof(double) ];
std::copy( x, x + sizeof(x)/sizeof(double), x1 );

// The transformation
for ( size_t i = 0; i < sizeof(idx)/sizeof(double); ++i )
    x1[idx[i]] = y[i];

for ( size_t i = 0; i < sizeof(x)/sizeof(double); ++i )
    cout << x1[i] << " ";
cout << endl;

Note exactly pretty, but it does give the following:

13 2 5.5 22 107 

-3 100 5.5 22 200

(Note that I've assumed that the indexing starts from 1 rather than 0 in idx)

like image 2
Component 10 Avatar answered Oct 06 '22 10:10

Component 10