FFT implemetation in Verilog: Assigning Wire input to Register type array - fft

I am trying to implement butterfly FFT algorithm in verilog.
I create K(Here 4) butterfly modules . I create modules like this.
localparam K = 4;
genvar i;
generate
for(i=0;i<N/2;i=i+1)
begin:BN
butterfly #(
.M_WDTH (3 + 2*1),
.X_WDTH (4)
)
bf (
.clk(clk),
.rst_n(rst_n),
.m_in(min),
.w(w[i]),
.xa(IN[i]),
.xb(IN[i+2]),
.x_nd(x_ndd),
.m_out(mout[i]),
.ya(OUT[i]),
.yb(OUT[i+2]),
.y_nd(y_nddd[i])
);
end
Each level I have to change input Xa and Xb for each Module (Here Number of level 3).
So I try to initialize reg type "IN"array and assign the array to input Xa and Xb. When I initialize "IN" array manually, it works perfectly.
The problem I face now, I couldn't assign Main module input X to register type "IN" array.
Main module input X ,
input wire signed [N*2*X_WDTH-1:0] X,
I have to assign this X into array "IN",
reg signed [2*X_WDTH-1:0] IN [0:N-1];
I assigned like this,
initial
begin
IN[0]= X[2*X_WDTH-1:0];
IN[1]=X[4*X_WDTH-1:2*X_WDTH];
IN[2]=X[6*X_WDTH-1:4*X_WDTH];
IN[3]= X[8*X_WDTH-1:6*X_WDTH];
IN[4]= X[10*X_WDTH-1:8*X_WDTH];
IN[5]=X[12*X_WDTH-1:10*X_WDTH];
IN[6]=X[14*X_WDTH-12*X_WDTH];
IN[7]= X[16*X_WDTH-1:14*X_WDTH];
end
I have gone through many tutorials and forums. No luck.
Can't we assign wire type to reg type array? If so how I can solve this problem.
Here is the Main module where I initialize Butterfly modules,
module Network
#(
// N
parameter N = 8,
// K.
parameter K = 3,
parameter M_WDTH=5,
parameter X_WDTH=4
)
(
input wire clk,
input wire rst_n,
// X
input wire signed [N*2*X_WDTH-1:0] X,
//Y
output wire signed [N*2*X_WDTH-1:0] Y,
output wire signed [K-1:0] y_ndd
);
wire y_nddd [K-1:0];
assign y_ndd ={y_nddd[1],y_nddd[0]};
reg [4:0] min=5'sb11111;
wire [4:0] mout [0:K-1];
reg x_ndd;
reg [2:0] count=3'b100;
reg [2*X_WDTH-1:0] w [K-1:0];
reg [2*X_WDTH-1:0] IN [0:N-1];
wire [2*X_WDTH-1:0] OUT [0:N-1];
assign Y = {OUT[3],OUT[2],OUT[1],OUT[0]};
reg [3:0] a;
initial
begin
//TODO : Here is the problem. Assigning Wire to reg array. Synthesize ok. In Simulate "red" output.
IN[0]= X[2*X_WDTH-1:0];
IN[1]=X[4*X_WDTH-1:2*X_WDTH];
IN[2]=X[6*X_WDTH-1:4*X_WDTH];
IN[3]= X[8*X_WDTH-1:6*X_WDTH];
IN[4]= X[10*X_WDTH-1:8*X_WDTH];
IN[5]=X[12*X_WDTH-1:10*X_WDTH];
IN[6]=X[14*X_WDTH-12*X_WDTH];
IN[7]= X[16*X_WDTH-1:14*X_WDTH];
//TODO :This is only a random values
w[0]=8'sb01000100;
w[1]=8'sb01000100;
w[2]=8'sb01000100;
w[3]=8'sb01000100;
end
/* levels */
genvar i;
generate
for(i=0;i<N/2;i=i+1)
begin:BN
butterfly #(
.M_WDTH (3 + 2*1),
.X_WDTH (4)
)
bf (
.clk(clk),
.rst_n(rst_n),
.m_in(min),
.w(w[i]),
.xa(IN[i]),
.xb(IN[i+N/2]),
.x_nd(x_ndd),
.m_out(mout[i]),
.ya(OUT[2*i]),
.yb(OUT[2*i+1]),
.y_nd(y_nddd[i])
);
end
endgenerate
always # (posedge clk)
begin
if (count==3'b100)
begin
count=3'b001;
x_ndd=1;
end
else
begin
count=count+1;
x_ndd=0;
end
end
always# (posedge y_ndd[0])
begin
//TODO
//Here I have to swap OUT-->IN
end
endmodule
Any help is appreciated.
Thanks in advance.

"Output is red", this likely means it is x this could be due to multiple drivers or an uninitialized value. If it was un-driven it would be z.
The main Issue I believe is that you do this :
initial begin
IN[0] = X[2*X_WDTH-1:0];
IN[1] = X[4*X_WDTH-1:2*X_WDTH];
...
The important part is the initial This is only evaluated once, at time 0. Generally everything is x at time zero. To make this an equivalent of the assign IN[0] = ... for a wire use always #* begin this is a combinatorial block which will update the values for IN when ever X changes.
always #* begin
IN[0] = X[2*X_WDTH-1:0];
IN[1] = X[4*X_WDTH-1:2*X_WDTH];
...
I am not sure why you do not just connect your X to your butterfly .xa and .xb ports directly though?
Other pointers
X is a bad variable name verilog as a wire or reg can hold four values 1,0,x or z.
In always #(posedge clk) you should be using non-blocking (<=) assignments to correctly model the behaviour of a flip-flop.
y_ndd is k bits wide but only the first 2 bits are assigned.
output signed [K-1:0] y_ndd
assign y_ndd = {y_nddd[1],y_nddd[0]};
Assignments should be in terms of their parameter width/size. For example IN has N entries but currently exactly 8 entries are assigned. There will been an issue when N!=8. Look into Indexing vectors and arrays with +:. Example:
integer idx;
always #* begin
for (idx=0; idx<N; idx=idx+1)
IN[idx] = X[ idx*2*X_WDTH +: 2*X_WDTH];
end
genvar gidx;
generate
for(gidx=0; gidx<N; gidx=gidx+1) begin
assign Y[ gidx*2*X_WDTH +: 2*X_WDTH] = OUT[gidx];
end
endgenerate

Related

Verilog Binary Coded Decimal Adder Not Outputting Correctly

I'm new to Verilog and basically trying to teach myself a Digital Logic Design module for university. I am trying to write a BCD Adder in Verilog using two Full Adders with some logic in between for conversion to BCD when needed.
Here is my code:
module binary_adder (
output [3:0] Sum,
output C_out,
input [3:0] A, B,
input C_in
);
assign {C_out, Sum} = A || B || C_in;
endmodule
module BCD_Adder (
output [3:0] Sum,
output Carry_out,
input [3:0] Addend, Augend,
input Carry_in
);
wire [3:0] Z, correction;
wire adder1C_out, carryInAdder2, adder2C_out;
binary_adder adder1 (.Sum(Z), .C_out(adder1C_out), .A(Addend), .B(Augend), .C_in(Carry_in));
assign Carry_out = (adder1C_out || (Z[3] && Z[1]) || (Z[3] && Z[2]));
assign correction = (Carry_out) ? (4'b0110) : (4'b0000);
assign carryInAdder2 = (1'b0);
binary_adder adder2 (.Sum(Sum), .C_out(adder2C_out), .A(correction), .B(Z), .C_in(carryInAdder2));
endmodule
For some reason, I keep getting the following outputs:
Submitted: A = 0000, B = 0010, Carry In = 0, Sum = 0001, Carry Out = 0
Expected: A = 0000, B = 0010, Carry In = 0, Sum = 0010, Carry Out = 0
Submitted: A = 0000, B = 0011, Carry In = 0, Sum = 0001, Carry Out = 0
Expected: A = 0000, B = 0011, Carry In = 0, Sum = 0011, Carry Out = 0
Submitted: A = 0000, B = 0100, Carry In = 0, Sum = 0001, Carry Out = 0
Expected: A = 0000, B = 0100, Carry In = 0, Sum = 0100, Carry Out = 0
It basically continues like this for all values. My A, B, Carry In and Carry Out values always match, but for some reason the output sum is always 0001. I'm not sure where I'm going wrong, the logic seems okay to me. I am very new to this and only know the basics, so any help would be greatly appreciated!
Thanks,
Wes
The logic in binary_adder does not implement addition; as it is currently written, it will just set Sum to 1 if any of A, B or C_in are non-zero.
While there are many architectures of multibit addition (see https://en.wikipedia.org/wiki/Adder_(electronics)#Adders_supporting_multiple_bits), the simplest to understand is the Ripple Carry Adder. It implements several full adders and chains them together to implement addition.
A simple implementation of this architecture looks like this:
module full_add(input A, B, Cin,
output S, Cout);
// Basic implementation of a Full Adder (see https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder)
assign S = A ^ B ^ Cin;
assign Cout = A & B | ((A ^ B) & Cin); // Note I use bit-wise operators like | and ^ instead of logical ones like ||; its important to know the difference
endmodule
module add(input [3:0] A, B,
input Cin,
output [3:0] S,
output Cout);
wire [3:0] Carries; // Internal wires for the carries between full adders in Ripple Carry
// This is an array instance which just makes [3:0], ie 4, instances of the full adder.
// Take note that a single Full Adder modules takes in single bits, but here
// I can pass bit vectors like A ([3:0]) directly which assign full_add[0].A = A[0], full_add[1].A = A[1], etc
// Common alternatives to using array instances (which are more rare) include generate statements or just instantiate the module X times
full_add f[3:0](.A(A), .B(B), .Cin({Carries[2:0], Cin}), .S(S), .Cout(Carries));
assign Cout = Carries[3];
endmodule

2 bit signed Multiplier

Design a 2-bit signed multiplier using one instantiation of your 4-bit adder. Remember that you need to sign extend your two 2-bit inputs to a full 4-bits.
This was my assignment and I came up with following code but some of my outputs are wrong. Can anyone tell me what I am doing wrong?
module mult(C,A,B);
output signed[3:0]C;
input signed[1:0]A,B;
reg signed[3:0]sA,sB;
assign sA = {A[1],A[1],A};
assign sB = {B[1],B[1],B};
wire carry;
wire signed[3:0] A1;
wire signed[3:0] A2;
wire signed[3:0] sum0;
and(A1[0],sA[0],sB[0]);
and(A1[1],sA[1],sB[0]);
and(A1[2],sA[2],sB[0]);
and(A1[3],sA[3],sB[0]);
assign A2[0] = 0;
and(A2[1],sA[0],sB[1]);
and(A2[2],sA[1],sB[1]);
and(A2[3],sA[2],sB[1]);
adder4bit a1(.A(A1),.B(A2),.Co(carry),.sum(sum0));
assign C[0] = sum0[0];
assign C[1] = sum0[1];
assign C[2] = sum0[2];
assign C[3] = sum0[3];
endmodule
module adder4bit(A,B,sum,Co);
input signed[3:0]A,B;
output signed [4:0]sum;
reg signed[4:0]a,b;
output Co;
wire Ci;
assign Ci = 1'b0;
assign a = {A[3],A};
assign b = {B[3],B};
FA a0(.A(a[0]),.B(b[0]),.Ci(Ci),.sum(sum[0]),.Co(w1));
FA a1(.A(a[1]),.B(b[1]),.Ci(w1),.sum(sum[1]),.Co(w2));
FA a2(.A(a[2]),.B(b[2]),.Ci(w2),.sum(sum[2]),.Co(w3));
FA a3(.A(a[3]),.B(b[3]),.Ci(w3),.sum(sum[3]),.Co(w4));
FA a4(.A(a[4]),.B(b[4]),.Ci(w4),.sum(sum[4]),.Co(Co));
endmodule
module FA(A,B,Ci,Co,sum);
input A,B,Ci;
output sum,Co;
assign sum = (A^B)^Ci;
assign Co = (B&Ci) | (A&Ci) | (A&B);
endmodule
There were some signals declared as reg connected to port outputs, reg must be assigned in procedural blocks.
I also made the carry bits in the adder an explicit wire vector, instead of multiple implicit wires. Implicit wires are dangerous a typo leads to a disconnection.
Also I declared the sum0 in the multiplier to have the same width as the output in of the sum port where it is connected, even though the bit 4 will not be used.
In terms of logic you made only one mistake, the A * B = A * B[0] - 2*A * B[1] instead of A * B[0] + 2*B[1] if B is a 2-bit signed integer. Because B[1] is the sign bit, thus B = B[0] - 2*B[1]. I fixed this by using the unary - directly in the port connection, I will leave it to you to write this structurally.
module mult(C,A,B);
output signed[3:0]C;
input signed[1:0]A,B;
wire signed[3:0]sA,sB;
assign sA = {A[1],A[1],A};
assign sB = {B[1],B[1],B};
wire carry;
wire signed[3:0] A1;
wire signed[3:0] A2;
wire signed[4:0] sum0;
and(A1[0],sA[0],sB[0]);
and(A1[1],sA[1],sB[0]);
and(A1[2],sA[2],sB[0]);
and(A1[3],sA[3],sB[0]);
assign A2[0] = 0;
and(A2[1],sA[0],sB[1]);
and(A2[2],sA[1],sB[1]);
and(A2[3],sA[2],sB[1]);
// FIXME: Notice that I am passing -A2, the simulator will
// negate the signal automatically. Maybe for your assignment
// you are requried to expand this using logic primitives...
adder4bit a1(.A(A1),.B(-A2),.Co(carry),.sum(sum0));
assign C[0] = sum0[0];
assign C[1] = sum0[1];
assign C[2] = sum0[2];
assign C[3] = sum0[3];
endmodule
module adder4bit(A,B,sum,Co);
input signed[3:0]A,B;
output signed [4:0]sum;
wire signed[4:0]a,b;
output Co;
wire [4:1] w;
wire Ci;
assign Ci = 1'b0;
assign a = {A[3],A};
assign b = {B[3],B};
FA a0(.A(a[0]),.B(b[0]),.Ci(Ci),.sum(sum[0]),.Co(w[1]));
FA a1(.A(a[1]),.B(b[1]),.Ci(w[1]),.sum(sum[1]),.Co(w[2]));
FA a2(.A(a[2]),.B(b[2]),.Ci(w[2]),.sum(sum[2]),.Co(w[3]));
FA a3(.A(a[3]),.B(b[3]),.Ci(w[3]),.sum(sum[3]),.Co(w[4]));
FA a4(.A(a[4]),.B(b[4]),.Ci(w[4]),.sum(sum[4]),.Co(Co));
endmodule
module FA(A,B,Ci,Co,sum);
input A,B,Ci;
output sum,Co;
assign sum = (A^B)^Ci;
assign Co = (B&Ci) | (A&Ci) | (A&B);
endmodule

Using matrices as arguments in functions and as output in subroutines in Fortran

I was trying to create a program that requires me to use matrices as input for functions and subroutines and also requires me to take matrix as subroutine output in Fortran. But, I've encountered multiple errors while doing so. I am not able to understand the source of these errors and hence how to fix them.
I'm confident of the logic but I seem to be making errors in dealing with the matrices.
Program to solve system of linear equations(Gauss elimination with partial pivoting)
Code:
program solving_equations
implicit none
real, allocatable :: a(:,:),interchanged(:,:)
real, allocatable :: x(:)
real addition,multiplying_term,alpha,maximum
integer i,j,row,rth_ele,f_maxfinder,k,n,s,inte
read(*,*)n
allocate( a( n,(n+1) ) )
allocate( x(n) )
allocate( interchanged( n,(n+1) ) )
do i=1,n
read(*,*)( a(i,j),j=1,(n+1) )
end do
do rth_ele= 1,(n-1)
row=f_maxfinder( a , n , rth_ele )
if (row==rth_ele) then
continue
else
call interchanger(a,rth_ele,row,n,interchanged)
a = interchanged
end if
do i= (rth_ele+1) , n
! once i is fixed, multiplying term is fixed too
multiplying_term=( a(i,rth_ele)/a(rth_ele,rth_ele) )
do j=1,(n+1)
a(i,j)=a(i,j)-a(rth_ele,j)*multiplying_term
end do
end do
end do
x(n)=a(n,n+1)/a(n,n)
do i=(n-1),1,-1
addition=0.0
do s=n , (i+1) , -1
addition=addition+a(i,s)*x(s)
end do
x(i)= ( ( a(i,n+1)- addition )/a(i,i) )
end do
do i=1,n
print*,x(i)
end do
endprogram solving_equations
!=================
function f_maxfinder(a,n,rth_ele)
integer inte,f_maxfinder
real maximum
maximum=a(rth_ele,rth_ele)
do inte=n,nint(rth_ele+1),-1
if( a(inte,rth_ele) > maximum ) then
maximum = a(inte,rth_ele)
f_maxfinder=inte
else
continue
end if
end do
end
subroutine interchanger( a,rth_ele,row,n,interchanged )
integer i
real alpha
real, allocatable :: interchanged(:,:)
allocate( interchanged( n,(n+1) ) )
do i=1,n+1
alpha=a(row,i)
a(row,i)=a(rth_ele,i)
a(rth_ele,i)=alpha
end do
do i=1,n
do j=1,(n+1)
interchanged(i,j)=a(i,j)
end do
end do
end
Errors:
row=f_maxfinder( a , n , rth_ele )
1
Warning: Rank mismatch in argument 'a' at (1) (scalar and rank-2)
a(row,i)=a(rth_ele,i)
Error: The function result on the lhs of the assignment at (1) must have the pointer attribute.
a(rth_ele,i)=alpha
Error: The function result on the lhs of the assignment at (1) must have the pointer attribute.
call interchanger(a,rth_ele,row,n,interchanged)
1
Error: Explicit interface required for 'interchanger' at (1): allocatable argument
Thanks!
You're missing a declaration of a as an array in f_maxfinder. implicit none is your friend - be sure to use it all the time.
interchanger has a dummy argument interchanged that is an allocatable, assumed-shape array. This requires that an explicit interface to interchanger be visible in the caller. (See my post https://stevelionel.com/drfortran/2012/01/05/doctor-fortran-gets-explicit-again/ for more on this.
The interface issue could be solved by putting the subroutines in a module and adding a use of the module in the main program.
By the way, there's no need to make a allocatable in f_maxfinder, as you are not allocating or deallocating it. It is still an assumed-shape array so the explicit interface is still required.
Here is a working example taking into account #SteveLionel's advice and the following comments:
Always use implicit none, at least once in the main program and don't forget to pass the -warn flag to the compiler.
Either use a module for functions and subroutines, then add use <module> to the main program, or simply use contains and include them inside the main program as I did below.
The interchanged array is already alcated in the main program, you don't need to re-allocate it in the interchanger subroutine, just pass it as an assumed-shape array.
Remove unused variables; alpha, maximum, k, inte.
Define a in f_maxfinder function.
Function type is better written in front of the function name for readability; see your definition of f_maxfinder and don't declare the function again in main program, unless you're using an explicit interface.
The nint procedure accepts real input, you don't need it here.
Finally add any missing variable declarations in your function/subroutine.
program solving_equations
implicit none
real, allocatable :: a(:,:), interchanged(:,:), x(:)
real :: addition, multiplying_term
integer :: i, j, row, rth_ele, n, s
read (*,*) n
allocate ( a( n,(n+1) ) )
allocate ( x( n ) )
allocate ( interchanged( n,(n+1) ) )
do i = 1,n
do j = 1,(n+1)
read (*,*) a(i,j)
end do
end do
do rth_ele = 1,(n-1)
row = f_maxfinder( a , n , rth_ele )
if (row == rth_ele) then
continue
else
call interchanger(a, rth_ele, row, n, interchanged)
a = interchanged
end if
do i = (rth_ele+1) , n
! once i is fixed, multiplying term is fixed too
multiplying_term = a(i,rth_ele) / a(rth_ele,rth_ele)
do j = 1,(n+1)
a(i,j) = a(i,j) - a(rth_ele,j) * multiplying_term
end do
end do
end do
x(n) = a(n,n+1) / a(n,n)
do i = (n-1),1,-1
addition = 0.0
do s = n,(i+1),-1
addition = addition + a(i,s) * x(s)
end do
x(i)= (a(i,n+1) - addition) / a(i,i)
end do
do i = 1,n
print *, x(i)
end do
contains
integer function f_maxfinder(a, n, rth_ele)
integer :: n, rth_ele, inte
real :: maximum, a(:,:)
maximum = a(rth_ele,rth_ele)
do inte = n,rth_ele+1,-1
if (a(inte,rth_ele) > maximum) then
maximum = a(inte,rth_ele)
f_maxfinder = inte
else
continue
end if
end do
end
subroutine interchanger( a, rth_ele, row, n, interchanged )
integer :: i, rth_ele, row, n
real :: alpha, a(:,:), interchanged(:,:)
do i = 1,n+1
alpha = a(row,i)
a(row,i) = a(rth_ele,i)
a(rth_ele,i) = alpha
end do
do i = 1,n
do j = 1,(n+1)
interchanged(i,j) = a(i,j)
end do
end do
end
end program solving_equations
Entering a sample 3-by-4 array, you get the following output (check the results, you know your algorithm):
3
4
3
6
3
7
4
6
7
4
4
2
0
2.05263186
-2.15789509
0.210526198
Process returned 0 (0x0) execution time : 1.051 s
Press any key to continue.

Verilog conditional assign outputs X where there should be 1

I am currently building a sign extender in Verilog based on the one present in the ARMv8 processor, but after the first result is extended, every subsequent result makes a 1 in the output into an X. How do I get rid of the X?
The module and the quick test bench I made are shown below.
Sign Extender:
`timescale 1ns / 1ps
module SignExtender(BusImm, ImmIns);
output [63:0] BusImm;
input [31:0] ImmIns;
wire extBit;
assign extBit = (ImmIns[31:26] == 6'bx00101) ? ImmIns[25]:
(ImmIns[31:24] == 8'bxxx10100) ? ImmIns[23]:
(ImmIns[31:21] == 11'bxxxx1000xx0) ? ImmIns[20]:
1'b0;
assign BusImm = (ImmIns[31:26] == 6'bx00101) ? {{38{extBit}}, ImmIns[25:0]}:
(ImmIns[31:24] == 8'bxxx10100) ? {{45{extBit}}, ImmIns[23:5]}:
(ImmIns[31:21] == 11'bxxxx1000xx0) ? {{55{extBit}}, ImmIns[20:12]}:
64'b0;
assign BusImm = 64'b0;
endmodule
Test Bench:
`timescale 1ns / 1ps
`define STRLEN 32
`define HalfClockPeriod 60
`define ClockPeriod `HalfClockPeriod * 2
module SignExtenderTest;
task passTest;
input [63:0] actualOut, expectedOut;
input [`STRLEN*8:0] testType;
inout [7:0] passed;
if(actualOut == expectedOut) begin $display ("%s passed", testType); passed = passed + 1; end
else $display ("%s failed: 0x%x should be 0x%x", testType, actualOut, expectedOut);
endtask
task allPassed;
input [7:0] passed;
input [7:0] numTests;
if(passed == numTests) $display ("All tests passed");
else $display("Some tests failed: %d of %d passed", passed, numTests);
endtask
reg [7:0] passed;
reg [31:0] in;
wire [63:0] out;
SignExtender uut (
.BusImm(out),
.ImmIns(in)
);
initial begin
passed = 0;
in = 32'hF84003E9;
#10;
begin
passTest(out, 63'b0, "Stuff", passed);
#10;
in = 32'hf84093ea;
#10;
passTest(out, 63'b0, "Stuff", passed);
end
end
endmodule
You seem to be treating x as a "don't-care" value in your comparisons, but it is not. x is a specific value which represents "unknown". Since you drive your input signals to all known values (0 or 1), all your == comparisons resolve to x, and your output has x in it. You should only compare bits you are interested in. For example, change:
(ImmIns[31:21] == 11'bxxxx1000xx0) ? {{55{extBit}}, ImmIns[20:12]}:
to:
( (ImmIns[27:24] == 4'b1000) && (ImmIns[21] == 1'b0) ) ? {{55{extBit}}, ImmIns[20:12]}:
You need to make similar changes to all your comparisons.
Also, you drive BusImm with 2 continuous assignments. Get rid of this line:
assign BusImm = 64'b0;
These changes get the x out of your output.
Also consider using casez. Refer to IEEE Std 1800-2017, section 12.5.1 Case statement with do-not-cares.

How to pass variadic arguments in Octave

I would like to implement a function duration = timer(n, f, arguments_of_f) that would measure how much time does a method f with arguments arguments_of_f need to run n times. My attempt was the following:
function duration = timer(n, f, arguments_of_f)
duration = 0;
for i=1:n
t0 = cputime;
f(arguments_of_f);
t1 = cputime;
duration += t1 - t0;
end
In another file, I have
function y = f(x)
y = x + 1;
end
The call d1 = timer(100, #f, 3); works as expected.
In another file, I have
function y = g(x1, x2)
y = x1 + x2;
end
but the call d2 = timer(100, #g, 1, 2); gives an error about undefined
argument x2, which is, when I look back, somehow expected, since I pass only
1 to g and 2 is never used.
So, how to implement the function timer in Octave, so that the call like
timer(4, #g, x1, ... , xK) would work? How can one pack the xs together?
So, I am looking for the analogue of Pythons *args trick:
def use_f(f, *args):
f(*args)
works if we define def f(x, y): return x + y and call use_f(f, 3, 4).
You don't need to pack all the arguments together, you just need to tell Octave that there is more than one argument coming and that they are all necessary. This is very easy to do using variadic arguments.
Your original implementation is nearly spot on: the necessary change is minimal. You need to change the variable arguments_to_f to the special name varargin, which is a magical cell array containing all your arbitrary undeclared arguments, and pass it with expansion instead of directly:
function duration = timer(n, f, varargin)
duration = 0;
for i=1:n
t0 = cputime;
f(varargin{:});
t1 = cputime;
duration += t1 - t0;
end
That's it. None of the other functions need to change.