Reputation: 95
I would like to create a d-dimensional tensor using d
as an input and without the if
statement as below:
if d == 2
B = zeros(r,r);
for i = 1:r
B(i,i) = 1;
end
elseif d == 3
B = zeros(r,r,r);
for i = 1:r
B(i,i,i) = 1;
end
end
Is there a more efficient way?
Upvotes: 3
Views: 135
Reputation: 112749
This does what you want for arbitrary r
and d
:
B = zeros(repmat(r,1,d)); % initiallize as d×d×···×d array filled with 0
B(linspace(1,end,r)) = 1; % write 1 in the "diagonal". end can be replaced by r^d
Some notes on how it works:
zeros
can take a vector as input, which allows the number of dimensions to be specified dynamically.1
. end
is being used within a function call. This is a not very well known feature.Equivalently, you can first build the array in linear form and then reshape it:
B = reshape(mod(1:r^d, (r^d-1)/(r-1))==1, repmat(r,1,d));
Notes:
1
, in linear indexing, is (r^d-1)/(r-1)
.reshape
allows a vector as input to specify dimensions, similar to zeros
.Upvotes: 3
Reputation: 15867
You can use accumarray:
f = @(d,r)accumarray(repmat((1:r).',1 , d), 1);
> f(2,5)
=
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
Here is the basic signature of accumarray:
accumarray( subs , val )
Using accumarray
we can create an n-dimensional array where subs
represents the position of points that will be filled in the array and val
represents the value of them.
If subs
provided as a matrix , its number of columns determines the number of dimensions of the resultant array and each row represents position of each point.
For example for d = 2
and r = 5
we want to create a (5 x 5)
array that has 1s in the following positions: [1 1],[2 2],[3 3],[4 4],[5 5]
.
Using repmat
we can create subs
:
subs = repmat ((1:5).' , 1, 2)
=
1 1
2 2
3 3
4 4
5 5
val
is set to 1
so all specified positions will be filled by 1
.
Upvotes: 4