Is it either possible to get the size of a function in bytes to see if it matches another function similar to C++ sizeof operator, or evaluate two functions some other way to see if they are both equal without actually knowing what the function/s are? Example:
local function equals(func1, func2)
-- check them and return true if equal
end
If this is not possible just say and that will satisfy my answer!
Thank you!
EDIT: The body of one function is what I need to check to see if it is the same as another function's body. The reference in memory will be different so I cannot use "==" but the function's reference name can be different.
Using == for functions only checks if they reference to the same function, which is not what you expected.
This task is rather difficult, if not impossible at all. For really simple cases, here's an idea:
function f(x) return x + 1 end
local g = function(y) return y + 1 end
f and g are two function that are equal by your definition. Assuming the file is t.lua, run:
luac -l t.lua
The output is:
main <t.lua:0,0> (4 instructions at 00000000003081c0)
0+ params, 2 slots, 1 upvalue, 1 local, 1 constant, 2 functions
1 [1] CLOSURE 0 0 ; 0000000000308330
2 [1] SETTABUP 0 -1 0 ; _ENV "f"
3 [2] CLOSURE 0 1 ; 0000000000308dc0
4 [2] RETURN 0 1
function <t.lua:1,1> (3 instructions at 0000000000308330)
1 param, 2 slots, 0 upvalues, 1 local, 1 constant, 0 functions
1 [1] ADD 1 0 -1 ; - 1
2 [1] RETURN 1 2
3 [1] RETURN 0 1
function <t.lua:2,2> (3 instructions at 0000000000308dc0)
1 param, 2 slots, 0 upvalues, 1 local, 1 constant, 0 functions
1 [2] ADD 1 0 -1 ; - 1
2 [2] RETURN 1 2
3 [2] RETURN 0 1
As you can see, the two functions have the same instructions in the virtual machine.
Will comparing the bytecode do?
local function equals(func1, func2)
return string.dump(func1) == string.dump(func2)
end
Surely, there would be some cases were the above would fail. For instance:
local function f1 (...)
local a = print
a(...)
end
local function f2 (...)
print(...)
end
local function equals (f1, f2)
return string.dump(f1) == string.dump(f2)
end
print(equals(f1,f2)) --> false
Both functions do the same thing, but they generate different bytecode. Maybe if you state what you're trying to achive, a better solution than function comparison can be provided.
Related
I am trying to write an efficient subroutine in Fortran to find the list of all duplicate vertices in an array. The tolerance (fixed using parameter paraEps) corresponds to the radius around each point in which I look for the duplicate points. The vertices and defined for Finite Element Analysis and the range of each component will depend on the 3D geometry on which the methods will be applied (I can expect that values of the components could be varied in [-10^6,10^6] with a precision of 10^-6.
Currently the following code is running on around 150k vertices but it will be used on array of 1-3M vertices.
Example:
A array of vertices. Here I just use some small list of nodes. In my case, nodes are in a 3D space with no specific distribution.
verticesArray =
[ 0 0 0,
0 1 0
1 0 0
1 0 0
1 1 1
0 1 0
1 2 3
1 2 3
0 1.0001 0
0 1.1 0
1 2 4]
The result list (0 means the vertice has no duplicate) with a tolerance of 10^-3.
list = [ 0 1 2 2 0 1 3 3 1 0 0]
I have written a first version that works fine but remains slow especially the number of vertices is large.
Notice that startItem is an integer I can specify for starting the search not from the beginning of the array.
MWE:
module test
implicit none
contains
subroutine get_dup_nodes(nbNodes,dimP,arrayIn,nbDupNodes)
!
integer,intent(in) :: nbNodes,dimP ! number of nodes and dimension
double precision,dimension(:,:),intent(in) :: arrayIn ! list of coordinates
!
integer,intent(out) :: nbDupNodes
!
double precision,dimension(dimP) :: coorNode
integer,dimension(:),allocatable :: listDup !list of duplicates
logical :: currUnique
double precision,allocatable :: distVal
integer :: itN,itM,itF,minCurrIt,currIt,nbTmp,sizeR,startItemVal
!
double precision,parameter :: paraEps=1e-3
!
!initialize variables
allocate(listDup(nbNodes))
listDup=0
nbDupNodes=0
itF=0
distVal=1.
!
do itN=1,nbNodes
!coordinate current node
coorNode=arrayIn(itN,:)
currUnique=.true.
!search for current nodes coordinates in the list of nodes
if (listDup(itN).eq.0) then
do itM=itN+1,nbNodes
! compute distance to current point
distVal = NORM2(coorNode-arrayIn(itM,:))
! if the distance is to small then duplicate
if (distVal.le.paraEps) then
!first time it is a duplicate
if (currUnique) then
currUnique=.false.
nbDupNodes=nbDupNodes+1
listDup(itN)=nbDupNodes
endif
listDup(itM)=nbDupNodes
endif
enddo
endif
enddo
print *,listDup
end subroutine get_dup_nodes
end module test
program testb
use test
implicit none
double precision,dimension(33) :: valTmp
double precision,dimension(11,3) :: verticesArray
integer :: nbd
integer :: i,j,k
valTmp = (/ 0.,0.,0.,0.,1.,0.,1.,0.,0.,1.,0.,0.,1.,1.,1.,0.,1.,0.,1.,2.,3.,1.,2.,3.,0.,1.0001,0.,0.,1.1,0.,1.,2.,4. /)
k=1
do i=1,11
do j=1,3
verticesArray(i,j)=ValTmp(k)
k=k+1
enddo
print *,verticesArray(i,:)
enddo
call get_dup_nodes(11,3,verticesArray,nbd)
end program testb
Additional request: if you have references of books about such kind of algorithm, it could be useful.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Passing a function as argument to another function
Below is a simple code for the bisection method. I would like to know how to be able to pass in any function I choose as a parameter instead of hard coding functions.
% This is an implementation of the bisection method
% for a solution to f(x) = 0 over an interval [a,b] where f(a) and f(b)
% Input: endpoints (a,b),Tolerance(TOL), Max # of iterations (No).
% Output: Value p or error message.
function bjsect(a,b,TOL,No)
% Step 0
if f(a)*f(b)>0
disp('Function fails condition of f(a),f(b) w/opposite sign'\n);
return
end
% Step 1
i = 1;
FA = f(a);
% Step 2
while i <= No
% Step 3
p = a +(b - a)/2;
FP = f(p);
% Step 4
if FP == 0 || (b - a)/2 < TOL
disp(p);
return
end
% Step 5
i = i + 1;
% Step 6
if FA*FP > 0
a = p;
else
b = p;
end
% Step 7
if i > No
disp('Method failed after No iterations\n');
return
end
end
end
% Hard coded test function
function y = f(x)
y = x - 2*sin(x);
end
I know this is an important concept so any help is greatly appreciated.
The simplest method is using anonymous functions. In your example, you would define your anonymous function outside bjsect using:
MyAnonFunc = #(x) (x - 2 * sin(x));
You can now pass MyAnonFunc into bjsect as an argument. It has the object type of function handle, which can be validated using isa. Inside bjsect simply use MyAnonFunc as if it is a function, ie: MyAnonFunc(SomeInputValue).
Note, you can of course wrap any function you've written in an anonymous function, ie:
MyAnonFunc2 = #(x) (SomeOtherCustomFunction(x, OtherInputArgs));
is perfectly valid.
EDIT: Oops, just realized this is almost certainly a duplicate of another question - thanks H. Muster, I'll flag it.
This is a question regarding coding in R.
The example I provide is didactic. Suppose I have functions called 'func1' and 'func2', where each takes two arguments (let's say scalars). I want to specify another function 'applyfunction' that has three args: the last number of the function to use ('1' or '2'), and the two arguments for the function. For example, I want to do something like this (which of course doesn't work):
applyfunction(1,2,3) where it would effectively run func1(2,3) and
applyfunction(2,9,43) where it would effectively run func2(9,43).
Any ideas?
Best, DB
You might want to look at do.call(), which calls a function with arguments supplied in a list. It is not to hard to write a wrapper around this that does exactly what you want.
function1=function(a,b)a+b
function2=function(a,b,c)a+b+c
do.call("function1",list(1,2))
do.call("function2",list(1,2,3))
EDIT: A wrapper would be:
applyfunction=function(fun,...)do.call(fun,list(...))
applyfunction("function1",1,2)
applyfunction("function2",1,2,3)
Here's another alternative. You can add more functions to the switch list.
func1 <- function(a, b) a + b
func2 <- function(a, b) a - b
applyfunction <- function(FUN, arg1, arg2) {
appFun <- switch(FUN,
func1, # FUN == 1
func2, # FUN == 2
stop("function ", FUN, " not defined")) # default
appFun(arg1, arg2)
}
applyfunction(1,2,3)
# [1] 5
applyfunction(2,9,43)
# [1] -34
applyfunction(3,9,43)
# Error in applyfunction(3, 9, 43) : function 3 not defined
If you really want it done 'by the numbers':
> applyfunction=function(n,a,b){get(paste("func",n,sep=""))(a,b)}
> func1=function(a,b){a+b}
> func2=function(a,b){a*b}
> applyfunction(1,4,3)
[1] 7
> applyfunction(2,4,3)
[1] 12
Uses get and paste to get the function associated with a name.
What about using one of the functions variables as a switch?
func1 <- function(x,y,z) {
## Function One stuff goes here
if (x == 1) {
var1 <- 1
}
## Function Two stuff goes here
if (x == 2) {
var1 <- 2
}
return(var1)
}
And, you get to use the same function, with the switch being the variable "x":
> func1(1,1,1)
[1] 1
> func1(2,1,1)
[1] 2
Here an alternate to switch or paste, just use indexing to select from a list:
function1=function(a,b) a+b
function2=function(a,b,c) a*b
applyfunc <- function(n, aa, bb){ c(function1, function2)[[n]](aa,bb) }
applyfunc(1, 4, 3)
# [1] 7
applyfunc(2, 4, 3)
#[1] 12
applyfunc(3, 4, 3)
# Error in c(function1, function2)[[n]] : subscript out of bounds
It is possible to pass 2d array to a function as a paramter ?
I initialized an array like this :
tab={}
for i=1, 10 do
tab[i]={}
for z=1, 10 do
tab[i][z]= 0
end
end
and i have function like this :
function foo(data)
...
x = data[i][z] -- here i got error
...
end
The gave the error message attempt to index field '?' (a nil value)
All variables are declared and initialized.
Your code should work if it is initialized properly.
For example, the below code sample will output 3:
function foo(data)
local i, z = 1, 2
print(data[i][z])
end
local tab={}
for i=1, 10 do
tab[i]={}
for z=1, 10 do
tab[i][z]= i + z
end
end
foo(tab)
Maybe you can share the rest of your code? The following runs with no error:
tab={}
for i=1, 10 do
tab[i]={}
for z=1, 10 do
tab[i][z]= 0
end
end
function foo(data)
print(data[3][2])
end
foo(tab)
The gave the error message attempt to index field '?' (a nil value)
I got such errors while changing metatable of some variable.
I'm attempting to write a function in assembly that will detect if a longer binary number contains a smaller binary pattern.
Example:
Does 100111 contain 1001?
When I read this problem I figured that I would do a bitwise-AND with the large number and its smaller pattern while shifting right (logical) each time in a loop.
So, in my head I thought it would do:
100111 AND 1001 = 0
Shift-right 1
010011 AND 1001 = 0
Shift-right 1
001001 AND 1001 = 1 // Pattern FOUND!
and repeat this until either the number was shifted until it was zero or the AND returned 1.
However, I think I must have something confused because this is returning 1 for most things I put in, on the first run of the loop. Am I confused on my usage of AND?
The problem is that "partial matches" also return a non-zero value for your AND check:
100111 AND 001001 = 000001
So this tests if any of the bits match, but you want to make sure all bits are the same. The result of the AND needs to be equal to the pattern you are searching:
x = 100111
if (x AND 1001 == 1001)
print "found"
Bitwise AND does not work the way you expect (judging from the samples and ignoring the notation which seems to suggest you are using bitwise AND as the logical AND of bits). AND only takes the bits that are set to 1 "into account". E.g 1111 AND 1001 == 1001.
You need to use XOR and compare against 0 for match (remember the mask the bits you are not comparing from the result). In your example a match is found when (N ^ 1001) & 1111 == 0000
In order to make sure that both the 0 and 1 bits match your search pattern, you need to do something like this:
if ((InputPattern AND SearchMask) == SearchPattern)
{
// then match
}
The SearchMask should be all 1 bits, of a length equal to your SearchPattern. For example, you could have SearchMask == 1111, SearchPattern == 1001.
You should AND and then test against the search pattern:
if ((TestPattern & SearchPattern) == SearchPattern)
{
// then match
}
(where & represents bitwise AND)