Slicing of two dimensions in SystemVerilog - multidimensional-array

In SystemVerilog, I'm trying to do the following:
wire signed [0:95][0:4][0:4][31:0] X;
wire signed [0:31][0:31][31:0] Y;
assign X[0] = Y[0:4][0:4];
assign X[1] = Y[0:4][1:5];
assign X[2] = Y[1:5][0:4];
assign X[3] = Y[1:5][1:5];
...
The error:
Error-[SE] Syntax error
Following verilog source has syntax error :
"try.sv", 399: token is '[', column 53
assign X[0] = Y[0:4][0:4];
Help please

SystemVerilog does not allow slices that represent non-contiguous regions of an array. You would have to do this with a for or foreach loop. I'm not exactly sure what your intentions are, but this should get you going.
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
X[0][i][j] = Y[i][j];

Related

How is R able to sum an integer sequence so fast?

Create a large contiguous sequence of integers:
x <- 1:1e20
How is R able to compute the sum so fast?
sum(x)
Doesn't it have to loop over 1e20 elements in the vector and sum each element?
Summing up the comments:
R introduced something called ALTREP, or ALternate REPresentation for R objects. Its intent is to do some things more efficiently. From https://www.r-project.org/dsc/2017/slides/dsc2017.pdf, some examples include:
allow vector data to be in a memory-mapped file or distributed
allow compact representation of arithmetic sequences;
allow adding meta-data to objects;
allow computations/allocations to be deferred;
support alternative representations of environments.
The second and fourth bullets seem appropriate here.
We can see a hint of this in action by looking at what I'm inferring is at the core of the R sum primitive for altreps, at https://github.com/wch/r-source/blob/7c0449d81c853f781fb13e9c7118065aedaf2f7f/src/main/altclasses.c#L262:
static SEXP compact_intseq_Sum(SEXP x, Rboolean narm)
{
#ifdef COMPACT_INTSEQ_MUTABLE
/* If the vector has been expanded it may have been modified. */
if (COMPACT_SEQ_EXPANDED(x) != R_NilValue)
return NULL;
#endif
double tmp;
SEXP info = COMPACT_SEQ_INFO(x);
R_xlen_t size = COMPACT_INTSEQ_INFO_LENGTH(info);
R_xlen_t n1 = COMPACT_INTSEQ_INFO_FIRST(info);
int inc = COMPACT_INTSEQ_INFO_INCR(info);
tmp = (size / 2.0) * (n1 + n1 + inc * (size - 1));
if(tmp > INT_MAX || tmp < R_INT_MIN)
/**** check for overflow of exact integer range? */
return ScalarReal(tmp);
else
return ScalarInteger((int) tmp);
}
Namely, the reduction of an integer sequence without gaps is trivial. It's when there are gaps or NAs that things become a bit more complicated.
In action:
vec <- 1:1e10
sum(vec)
# [1] 5e+19
sum(vec[-10])
# Error: cannot allocate vector of size 37.3 Gb
### win11, R-4.2.2
Where ideally we would see that sum(vec) == (sum(vec[-10]) + 10), but we cannot since we can't use the optimization of sequence-summing.

Memoization code for "Longest Common Substring" doesn't work as expected

I was able to think of a recursive solution for the problem "Longest Common Substring" but when I try to memoize it, it doesn't seem to work as I expected it to, and throws a wrong answer.
Here is the recursive code.
int lcs(string X, string Y,int i, int j, int count)
{
if (i == 0 || j == 0)
return count;
if (X[i - 1] == Y[j - 1])
count = lcs(X,Y,i - 1, j - 1, count + 1);
count = max(count,max(lcs(X,Y,i, j-1, 0),lcs(X,Y,i - 1, j, 0)));
return count;
}
int longestCommonSubstr(string S1, string S2, int n, int m)
{
return lcs(S1,S2,n,m,0,dp);
}
And here is the memoized code.
int lcs(string X, string Y,int i, int j, int count,vector<vector<vector<int>>>& dp)
{
if (i == 0 || j == 0)
return count;
if(dp[i - 1][j - 1][count] != -1)
return dp[i - 1][j - 1][count];
if (X[i - 1] == Y[j - 1])
count = lcs(X, Y, i - 1, j - 1, count + 1, dp);
count = max(count,max(lcs(X,Y,i, j-1, 0,dp),lcs(X,Y,i - 1, j, 0,dp)));
return dp[i-1][j-1][count]=count;
}
int longestCommonSubstr(string S1, string S2, int n, int m)
{
int maxSize=max(n,m);
vector<vector<vector<int>>> dp(n,vector<vector<int>>(m,vector<int>(maxSize,-1)));
return lcs(S1,S2,n,m,0,dp);
}
I do know that the problem can be solved using a 2D DP vector as well but my objective was to convert my original recursive solution to a memoized solution and not write a solution from scratch. And as I have 3 parameters which are changing, so it should use a 3D DP table.
Can anyone figure out what's wrong or help me out with a 3D DP solution with recursive code same or similar to mine.
Note:-
An interesting observation, the max function for some reason works from left to right on my Mac system and on Ubuntu running under parallels as well, but the same function works from right to left in Windows machine and in online compilers. I do not know the reason but I would be happy to know about it. I'm running the code in an M1 Mac, I don't know if the ARM compiler is different from x86 Mac compiler or not.
Another thing, the memoized code gives different answers depending upon which recursive call is called first on the line,
count = max(count,max(lcs(X,Y,i, j-1, 0),lcs(X,Y,i - 1, j, 0)));
If I swap the positions of the function call statements then it gives a correct output but for that specific test case and probably similar cases.
This Memo solution gives TLE as well in large test cases, and I do not know why.
I recently started studying DP and this is the only question which I wasn't able to solve by just modifying the original recursive solution. It has been two days and I just can't figure out the proper reasons.
Submission Link:- https://practice.geeksforgeeks.org/problems/longest-common-substring1452/1/#
Any help in this regard would be great.

Passing a vector and performing operations on it results in X

This is the module that I'm trying to implement. What I want to do is, receive a vector say 2 bits wide having 4 elements that I linearize and pass from the testbench to the test_module1. Now I want to de-linearize it and perform some combinational operations on it to get a fitness value based on Rosenbrock function. However, I get the fitness value as XX.
I'm unable to understand the issue here.
module test_module1 ( x, fitness);
input [4*2 -1:0] x;
output [1:0] fitness;
wire [1:0] x_i;
wire [1:0] x_im1;
wire [1:0] fitness_val = 2'b00;
wire [3:0] a;
wire [3:0] b;
wire [1:0] x_array1 [3:0];
genvar k;
assign fitness = fitness_val;
genvar j;
generate
for (j =0 ; j <4 ; j = j+1) begin
assign x_array1[j] = x[2*j +: 2];
end
for (k=1; k<4; k=k+1) begin
assign x_i = x_array1[k];
assign x_im1 = x_array1[k-1];
assign a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
assign b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
assign fitness_val = fitness_val + a[2:1] + b[2:1];
end
endgenerate
endmodule
Testbench:
module tb_tm1();
wire [1:0] fitness;
wire [4*2-1:0] x_array;
test_module1 tm1(x_array, fitness);
assign x_array = 8'b11100100;
endmodule
The output I get is like this:
The cause of the X (unknown value) is due to contention caused by multiple drivers for the same signal.
For example, signal fitness_val has 5 drivers. The 1st is the line:
wire [1:0] fitness_val = 2'b00;
This is a continuous assignment, which means the simulator is always trying to drive it to 0. The other 4 drivers are from the for k loop:
assign fitness_val = fitness_val + a[2:1] + b[2:1];
If you were to write out the loop long-hand, you would have 4 identical assign lines. fitness_val should only have 1 driver, not 5.
You have multiple drivers of all 5 signals in that for loop.
Another problem with the assign fitness_val line is that it creates a combinational loop. You should not have fitness_val on both the LHS and RHS of a continuous assignment.

Scilab, get the last index of the maximum element in a vector

Given a vector, A=[1,2,10,10,10,1], [m,k]=max(A) returns k=3.
How to get the last index of the maximum element? In this example, I want to get 5.
The most succinct way I can think of is: [m,k]=max(A($:-1:1))
Is there a better way or does scilab provide a parameter to do this? Reversing a large vertex is not a good idea in any way.
Use the find command
You can use the find command to get all indices of the maximum:
indices = find(A==max(A))
last = max(indices)
Implement it yourself
Or if you want a single pass, you can implement it yourself:
//Create a c-function with your wanted behaviour
f1=['void max_array(int in_array[],int* in_num_elements,int *out_max, int *out_index)'
'{'
'int i;'
'*out_max=in_array[0];'
'*out_index=-1;'
'for (i=0; i<*in_num_elements; i++)'
'{'
'if(in_array[i]>=*out_max)'
'{'
'*out_max=in_array[i];'
'*out_index=i;'
'}'
'}'
'}'];
//Place it in a file in the current directory
mputl(f1,'max_array.c')
//Create the shared library (a gateway, a Makefile and a loader are
//generated.
ilib_for_link('max_array','max_array.c',[],"c")
//Load the library
exec loader.sce
//Create wrapper for readability
function [m,k] = last_max(vector)
[m, k] = call('max_array', vector, 1,'i', length(vector),2,'i', 'out',[1,1],3,'i',[1,1],4,'i');
// Because c is zero-indexed add 1
k = k + 1
endfunction
//Your data
A=[1,2,10,10,10,1];
//Call function on your data
[m,k] = last_max(A)
disp("Max value is " + string(m) + " at index " + string(k) )

Why do i get this error - MATLAB

I have the image and the vector
a = imread('Lena.tiff');
v = [0,2,5,8,10,12,15,20,25];
and this M-file
function y = Funks(I, gama, c)
[m n] = size(I);
for i=1:m
for j=1:n
J(i, j) = (I(i, j) ^ gama) * c;
end
end
y = J;
imshow(y);
when I'm trying to do this:
f = Funks(a,v,2)
I am getting this error:
??? Error using ==> mpower
Integers can only be combined with integers of the same class, or scalar doubles.
Error in ==> Funks at 5
J(i, j) = (I(i, j) ^ gama) * c;
Can anybody help me, with this please?
The error is caused because you're trying to raise a number to a vector power. Translated (i.e. replacing formal arguments with actual arguments in the function call), it would be something like:
J(i, j) = (a(i, j) ^ [0,2,5,8,10,12,15,20,25]) * 2
Element-wise power .^ won't work either, because you'll try to "stuck" a vector into a scalar container.
Later edit: If you want to apply each gamma to your image, maybe this loop is more intuitive (though not the most efficient):
a = imread('Lena.tiff'); % Pics or GTFO
v = [0,2,5,8,10,12,15,20,25]; % Gamma (ar)ray -- this will burn any picture
f = cell(1, numel(v)); % Prepare container for your results
for k=1:numel(v)
f{k} = Funks(a, v(k), 2); % Save result from your function
end;
% (Afterwards you use cell array f for further processing)
Or you may take a look at the other (more efficient if maybe not clearer) solutions posted here.
Later(er?) edit: If your tiff file is CYMK, then the result of imread is a MxNx4 color matrix, which must be handled differently than usual (because it 3-dimensional).
There are two ways I would follow:
1) arrayfun
results = arrayfun(#(i) I(:).^gama(i)*c,1:numel(gama),'UniformOutput',false);
J = cellfun(#(x) reshape(x,size(I)),results,'UniformOutput',false);
2) bsxfun
results = bsxfun(#power,I(:),gama)*c;
results = num2cell(results,1);
J = cellfun(#(x) reshape(x,size(I)),results,'UniformOutput',false);
What you're trying to do makes no sense mathematically. You're trying to assign a vector to a number. Your problem is not the MATLAB programming, it's in the definition of what you're trying to do.
If you're trying to produce several images J, each of which corresponds to a certain gamma applied to the image, you should do it as follows:
function J = Funks(I, gama, c)
[m n] = size(I);
% get the number of images to produce
k = length(gama);
% Pre-allocate the output
J = zeros(m,n,k);
for i=1:m
for j=1:n
J(i, j, :) = (I(i, j) .^ gama) * c;
end
end
In the end you will get images J(:,:,1), J(:,:,2), etc.
If this is not what you want to do, then figure out your equations first.

Resources