I am trying to find the max value inside a parameterized array, I was looking at this post and came across forloop-generate. The only change I want to make is change that approach of a explicit array to parameterized array, but I am running into genvar assignment problem.
reg [$clog2(LENGTH)-1:0] arr [0:LENGTH-1];
wire [$clog2(LENGTH)-1:0] value_l1[0:LENGTH-2];
wire [$clog2(LENGTH)-1:0] index_l1[0:LENGTH-2];
genvar gen_i, gen_j, gen_k;
generate
for(gen_i = 0; gen_i < LENGTH; gen_i = gen_i + 2) begin : loop1
Compare cmp1(.A(arr[i])
,.B(arr[i+1])
,.indexA(i)
,.indexB(i+1)
,.value(value_l1[i/2])
,.index(index_l1[i/2])
);
end
gen_k = 0;
for(gen_i = 1; gen_i < $clog2(LENGTH); gen_i = gen_i + 1) begin : loop2_1
for(gen_j = 0; gen_j < LENGTH / (2*gen_i); gen_j = gen_j + 2) begin : loop2_2
Compare cmp2(.A(value_l1[gen_k + gen_j])
,.B(value_l1[gen_k + gen_j+1])
,.indexA(index_l1[gen_k + gen_j])
,.indexB(index_l1[gen_k + gen_j+1])
,.value(value_l1[(LENGTH/(2*gen_i))+(gen_j/2)])
,.index(index_l1[(LENGTH/(2*gen_i))+(gen_j/2)])
);
end
//gen_k = gen_j; // <--------- problem here
end
endgenerate
My approach is to have a list of the compared elements, and then compare that list and write back the result to the same list. For example:
original array : 0 1 2 3 4 5 6 7
would results into
compare array : 1 3 5 7 | 3 7 | 7
^ ^
| |
| largest element
|
gen_k + gen_j
then output 7 as the largest element, but I cannot do gen_k = gen_j to save the index (offset to the second part of the compare array). Is it even possible to use generate with parameterized array? If so, how can I fix this problem?
You can do this with an intermediate parameter.
for(gen_i = 1; gen_i < $clog2(LENGTH); gen_i = gen_i + 1) begin : loop2_1
parameter param_k = LENGTH / (2*gen_i) + 1;
for(gen_j = 0; gen_j < LENGTH / (2*gen_i); gen_j = gen_j + 2) begin : loop2_2
Compare cmp2(.A(value_l1[param_k + gen_j])
,.B(value_l1[param_k + gen_j+1])
,.indexA(index_l1[param_k + gen_j])
,.indexB(index_l1[param_k + gen_j+1])
,.value(value_l1[(LENGTH/(2*gen_i))+(gen_j/2)])
,.index(value_l1[(LENGTH/(2*gen_i))+(gen_j/2)])
);
end
end
Related
This is what I am trying to do, created a random array to demonstrate:
% all IDs
all_IDS = 1:216000000;
% Array 1
X = round(1550*rand(216000000,1));
Y = round(1550*rand(216000000,1));
Z = round(90*rand(216000000,1));
% Array 2
Xsub = round(1550*rand(160000,1));
Ysub = round(1550*rand(160000,1));
Zsub = round(90*rand(160000,1));
del_val =1;
% required o/p
reqd_op = zeros(1,10);
% boolean indexing
indx =1;
for jj = 1:160000
VID_X = Xsub(jj);
VID_Y = Ysub(jj);
VID_Z = Zsub(jj);
I2 = (X>VID_X-del_val & X<VID_X+del_val)& (Y>VID_Y-del_val & Y<VID_Y+del_val) & (Z>VID_Z-del_val & Z<VID_Z+del_val);
len = numel(all_IDS(I2));
reqd_op(1,indx:indx+len-1) = all_IDS(I2);
indx=indx+len;
end
The above code takes a lot of time as I am dealing with a very large array , Is there a way to eliminate the for loop, meaning, instead of doing Boolean indexing element by element - can I do it for the whole array at once ?
This will run x2.5 faster, anyway, array is too big so it still takes 0.3s per loop, so 160000 loops is like 13 hours on single cpu.
if ~exist('X','var')
% Array 1
X = round(1550*rand(216000000,1,'single'));
Y = round(1550*rand(216000000,1,'single'));
Z = round(90*rand(216000000,1,'single'));
% Array 2
Xsub = round(1550*rand(160000,1,'single'));
Ysub = round(1550*rand(160000,1,'single'));
Zsub = round(90*rand(160000,1,'single'));
end
del_val =single(1);
reqd_op = zeros(1,10,'single');% required o/p
tic
index =1;
for jj = 1:10
VID_X = Xsub(jj);
VID_Y = Ysub(jj);
VID_Z = Zsub(jj);
IdxFinal=[];
Idx1=find(abs(X-VID_X)<del_val); %little better than X>VID_X-del_val & X<VID_X+del_val)
if ~isempty(Idx1)
Idx2 = Idx1(Y(Idx1)>VID_Y-del_val & Y(Idx1)<VID_Y+del_val);
if ~isempty(Idx2)
Idx3= Idx2(Z(Idx2)>VID_Z-del_val & Z(Idx2)<VID_Z+del_val);
IdxFinal=Idx3;
end
end
len = length(IdxFinal);
index=index+len;
if len>0
reqd_op(1,index:index+len-1) = IdxFinal;
end
end
toc
I wrote a 1D array sorting code, however the first value disappears after sorting. Here is my code:
For i = 0 To 10 - 1
For j = 0 To (10 - 1) - i
If Xs(j) > Xs(j + 1) Then
tmp = Xs(j)
Xs(j) = Xs(j + 1)
Xs(j + 1) = tmp
End If
Next j
Next i
Original array:
0.995136318967065
1.92659411953677E-02
0.075211466386023
0.276865639306513
0.796949177428061
0.644136557566409
0.912439108707731
0.318021611061513
0.863316048056547
0.469710111256482
Array after sorting:
0
1.92659411953677E-02
0.075211466386023
0.276865639306513
0.318021611061513
0.469710111256482
0.644136557566409
0.796949177428061
0.863316048056547
0.912439108707731
I suspect you have dimensioned your array 0 To 10:
Dim Xs(0 To 10)
so creating 11 spaces into it. However, you have only 10 of them so you will have an Empty cell that will put itself on the first position at some point of the loop (being it evaluated as 0, which is indeed the lowest value into your dataset).
I also believe you have dimensioned your array 0 To 10 instead of 0 To 9 because, if not, you would have got an Subscript out of range error in this part of the code:
For j = 0 To (10 - 1) - i
In order to make your code work:
a) Change the Dim Xs(0 To 10) to Dim Xs(0 To 9)
b) Change the For j = 0 To (10 - 1) - i to For j = 0 To (10 - 1) - i-1
sqlRows = rst.GetRows()
i = 0
For Each element In sqlRows
If i > 0 And i < sizeOfState + 1 Then
SmartTags("visu_state_on")(i - 1) = element
ElseIf i > sizeOfState And i < 2 * sizeOfState + 1 Then
SmartTags("visu_state_off")(i - sizeOfState - 1) = element
ElseIf i > (2 * sizeOfState ) And i < 2 * sizeOfState + sizeOfMeasurement + 1 Then
SmartTags("visu_limits_right")(i - (2 * sizeOfState - 1)) = element
ElseIf i > 2 * sizeOfState + sizeOfMeasurement And i < 2 * (sizeOfStanja + sizeOfMeasurement ) + 1 Then
SmartTags("visu_limits_left")(i - (2 * sizeOfState + sizeOfMeasurement )) = element
End If
i = i + 1
Next
With code above I'm looping through array sqlRows and with variable i I'm filling other four arrays with data from sqlRows.
This solution works but I'm wondering is there more elegant way to achieve the same.
sqlRows is array with dimensions 343x1,
visu_state_on is array with dimensions 8x1,
visu_state_off is array with dimensions 8x1,
visu_limits_right is array with dimensions 160x1,
visu_limits_left is array with dimensions 160x1,
and variables sizeOfState and sizeOfMeasurement are just there that I can calculate indexes for these four arrays.
For one thing you can remove the first clause from each of your conditions, because they will always be true
i starts with the value 0 and is always incremented, so the value will never be less than zero.
If a value is not less than n + 1 (condition in previous ElseIf) then it's guaranteed to be greater than n.
Also, VBScript does have a <= comparison operator, so it's better to compare i <= n rather than i < n + 1.
I would also recommend calculating values that won't change inside the loop just once outside the loop. Re-calculating them with each loop cycle is a waste of resources.
Adding an Else branch to handle values greater than 2 * (sizeOfStanja + sizeOfMeasurement) might be a good idea too.
sqlRows = rst.GetRows()
i = 0
ref1 = 2 * sizeOfState
ref2 = ref1 + sizeOfMeasurement
ref3 = 2 * (sizeOfStanja + sizeOfMeasurement)
For Each element In sqlRows
If i <= sizeOfState Then
SmartTags("visu_state_on")(i - 1) = element
ElseIf i <= ref1 Then
SmartTags("visu_state_off")(i - sizeOfState - 1) = element
ElseIf i <= ref2 Then
SmartTags("visu_limits_right")(i - ref1 + 1) = element
ElseIf i <= ref3 Then
SmartTags("visu_limits_left")(i - ref2) = element
Else
'handle i > ref3 here
End If
i = i + 1
Next
The below code is supposed to calculate some values and place them in incremental places in the numpy.zeros() array. The calculations all perform correctly but the array stays as just zeros. I could be missing something obvious so apologies if I am.
n = 256
lam = l
a = numpy.zeros([(len(z[0]) * len(z[:,0]) + n + 1), (n + len(z[0]))])
b = numpy.zeros([numpy.size(a, 0), 1])
#data fitting equations
k = 0
for i in range(len(z[0])):
for j in range(len(z[:,0])-1):
wij = smoother(z[j][i] + lam)
a[k][(z[j][i]+lam)] = float(wij)
print a[k][(z[j][i]+lam)]
a[k][n+j] = float(-wij)
b[k][0] = float(-wij * B[j])
k = k + 1
Thanks,
Tom
Answer supplied by Jaime works fine. Use
a[1, 2]
rather than
a[1][2]
I have created a logical array of 1's and 0's using the following code:
nWindow = 10;
LowerTotInitial = std(LowerTot(1:nWindow));
UpperTotInitial = std(UpperTot(1:nWindow));
flag = 0;
flagArray = zeros(length(LowerTot), 1);
for n = 1 : nData0 - nWindow
for k = 0 : nWindow - 1
if LowerTot(n + k) < 0.1*LowerTotInitial || UpperTot(n + k) < 0.1*UpperTotInitial
flag = 1;
flagArray(n) = 1;
else
flag = 0;
end
end
end
This returns flagArray, an array of 0's and 1's. I am trying to find the index of the first 1 in the array. ie. 1 = flagArray(index). I am confused as to what is the best way to accomplish this!
What you call an entry number is referred to as an index in MATLAB-speak. To find the index of the first matching element in an array you can use the FIND function:
>> x = [0 0 1 0 1 0];
>> find(x, 1, 'first')
ans =
3
Try this ind = find(flagArray, k, 'first')
with k =1
Read this Matlab Docs - find