I'm transitioning from MATLAB to Fortran and encountering all sorts of weird behaviors I'd never expect from MATLAB. Here's one that's got me puzzled:
Program pruebanormal
double precision :: g01eaf, x, y
character :: T*1
integer :: Iffail
Iffail = 0
T = 'L'
x = 0.0
y = g01eaf('L',0.0,Iffail)
write(*,*) 'y = ',y
end program pruebanormal
I have this fairly simple program in which I'm trying to find the pdf at x=0 of a standard N(0,1) variable (should be 0.5). g01eaf() is the NAG library function that does this for me. I'm using gfortran to compile.
Leaving the rest of the program unchanged, depending on how I write the arguments in g01eaf(), I get different answers:
a) g01eaf(T,x,Iffail)
b) g01eaf(T,0.0,Iffail)
c) g01eaf(T,x,0)
Now, under MATLAB, I would get the same (correct) answer either way: y = 0.500000. Under Fortran, however, I get:
a) y = 0.500000
b) y = 1.000000
c) Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0xB766C163
#1 0xB766C800
#2 0xB77763FF
#3 0x804982E in g01eafn_
Violación de segmento (`core' generado)
I have no words for the answer in (b) and no clue what (c) even means.
The very quick answer for the "wrong result" is that in
y = g01eaf('L',0.0,Iffail)
you are passing a different type of real variable than in
double precision x
x = 0.0 ! x is still double precision.
y = g01eaf('L',x,Iffail)
The function g01eaf probably expects double precision: you should very carefully read NAG's documentation.
y = g01eaf('L', 0d0, Iffail)
Now to elaborate.
You don't want these problems to come about too often. You want to ensure an interface is available for the function call to g01eaf. Your compiler would then complain about passing a real of default kind to the function.
Assuming you have an up-to-date version of the library, you want to do something like
use nag_library, only : g01eaf, nag_wp
implicit none
integer Iffail
real(kind=nag_wp) y
y = g01eaf('L', 0._nag_wp, Iffail)
end
Again, see the documentation. Both for the library, and for meaning of modules, etc.
For older versions, one should still have a module available, but it may be called something different, and nag_wp may not be defined (meaning you must carefully choose kinds).
The module will also lead to a complaint that Iffail requires to be able to be set, so must be a variable, not 0. This explains (c).
Related
Consider this code.
foo(int x, int y){
x = y + 1;
y = 10;
x++;
}
int n = 5;
foo(n,n);
print(n);
if we assume that the language supports pass-by-value result, what would be the answer? As far as I know, pass-by-value-result copies in and out. But I am not sure what would be n's value when it is copied to two different formal parameters. Should x and y act like references? Or should n get the value of either x or y depending on which is copied out last?
Thanks
Regardless of whether it's common pass-by-value or pass-by-value-result, then x and y would become separate copies of n, they are in no way tied to each other, except for the fact they start with the same value.
However, pass-by-value-result assigns the value back to the original variables upon function exit meaning that n would take on the value of x and y. Which one it gets first (or, more importantly, last, since that will be its final value) is open to interpretation since you haven't specified what language you're actually using.
The Wikipedia page on this entry has this to say on the subject ("call-by-copy-restore" is its terminology for what you're asking about, and I've emphasised the important bit and paraphrased to make it clearer):
The semantics of call-by-copy-restore also differ from those of call-by-reference where two or more function arguments alias one another; that is, point to the same variable in the caller's environment.
Under call-by-reference, writing to one will affect the other immediately; call-by-copy-restore avoids this by giving the function distinct copies, but leaves the result in the caller's environment undefined depending on which of the aliased arguments is copied back first. Will the copies be made in left-to-right order both on entry and on return?
I would hope that the language specification would clarify actual consistent behaviour so as to avoid all those undefined-behaviour corners you often see in C and C++ :-)
Examine the code below, slightly modified from your original since I'm inherently lazy and don't want to have to calculate the final values :-)
foo(int x, int y){
x = 7;
y = 42;
}
int n = 5;
foo(n,n);
print(n);
The immediate possibilities I see as the most likely are:
strict left to right copy-on-exit, n will become x then y, so 42.
strict right to left copy-on-exit, n will become y then x, so 7.
undefined behaviour, n may take on either, or possibly any, value.
compiler raises a diagnostic and refuses to compile, if it has no strict rule and doesn't want your code to end up behaving in a (seemingly) random manner.
I am completely baffled by this.
I noticed when a proc deep inside one of my modules is reached, where the original call was generated from command line, it works correctly than when the same proc is reached when the call flow is originated from inside another proc which is called from the command line.
I found it comes down to this one line. In the debugger, I see this
if hastype(z,radical) then
...
This gives false in the second case, and it gives true when called in the first case. It should give true in both cases.
In the debugger, I look at z, it says it has this value
1/x*sqrt(x^2*u)
Now, in the debugger command, when I type
hastype(z,radical)
It gives false. But when I type the actual value of u into the command:
hastype(1/x*sqrt(x^2*u),radical)
Now it gives true!
Everything is local to this proc:
dsolve_step:-dsolve_step_homog:-convert_to_homog := proc(f0, x, y, u)
local f, z, tmp;
1 f := f0;
2 f := subs(y = u*x,expand(f));
3 for z in op(f) do
4 ! if hastype(z,radical) then ##<=======
5 tmp := sqrt(collect(z^2,x));
6 f := subs(z = tmp,f)
end if
end do;
7 return simplify(f)
end proc
So I have no idea why hastype(z,radical) gives false, and hastype(1/x*sqrt(x^2*u),radical) gives true, when z itself is 1/x*sqrt(x^2*u).
And this happens only when I call the module as in case 2 described above.
As you can see, everything is local. z,f,tmp are local. Same call the the above
function is made from both cases. All the input is the same in both cases.
Here are screen shots from the actual debugging:
Now I check
Now I check by type the actual z value shown
It seems like scoping issue, which I can't figure what it is. May be what I am looking at, is not what it appears to be.
Again, the same call works OK when I call the module from the command line, from another worksheet.
Both worksheets (case 1 and case 2), use different math engines. (I set up Maple to start new math engine for each work sheet to be safe)
I am looking for any suggestion why this happens. The calling proc in the second case, does not use any global variables either. I always start from clean kernel (restart).
Any hint what is going on and what to look for? Or what to try to find what is the problem?
Maple 2018.1, windows 10.
Update
I found the problem. But I really think this is a bug in Maple.
I found if I use eval(z) then it works in the second case, like this:
if hastype(eval(z),radical) then
Now I get true:
I do not see why I need to add eval() there, since Maple should automatically evaluate z to its value when using for z in op(f) do and then reference z inside the loop.
So my question has changed to: Why is eval() needed here?
Any way, I have a workaround for this. But this makes no sense to me now.
convert_to_homog:=proc(f0,x,y,u)
local f,z,tmp;
f:=f0;
f:=subs(y=u*x,expand(f));
#this below can give wrong answer sometimes. It tries to
#change 1/X*sqrt(x^2) to sqrt(1)
#by moving x under the sqrt. But this is valid only when x>0
# i..e 1/x => sqrt(1/x^2) only when x>0
#keep it for now, until I implement exact solver.
for z in op(f) do
if hastype(eval(z), radical) then
tmp:=sqrt(collect(z^2,x));
f:=subs(z=tmp,f);
fi;
od;
return(simplify(f));
end proc;
Of key importance here is that (as shown by you), the value of z is involves an unevaluated call to sqrt and not something to power 1/2.
The unevaluated sqrt call is not of type radical, though what it evaluates to is of that type.
First, let's deal with such an unevaluated call to sqrt at the top-level (ie. not inside any procedure body). We first assign to name z the expression containing the unevalated call to sqrt.
We'll test the type of 1-level evaluation of name z, as well as the full evaluation of the name z.
restart;
z := '1/x*sqrt(x^2*u)';
2
sqrt(x u)
z := ----------
x
1-level evaluation of z produces its value, but with no other evaluation. The sqrt call remains unevaluated.
eval(z, 1); # 1-level evaluation
2
sqrt(x u)
----------
x
The unevaluated call to sqrt is not of type radical.
hastype(eval(z, 1), radical);
false
Now here is the full evaluation of z, which is default behavior at the top-level.
eval(z); # full evaluation
2 1/2
(x u)
---------
x
z;
2 1/2
(x u)
---------
x
Passing z to hastype now passes the full evaluation to hastype. That is, the expression passed to hastype now contains something to power 1/2, and it recognized as being of type radical.
hastype(z, radical);
true
Now read this, from a bullet point in the section "Evaluation Rules" on the help-page for TOPIC proc,
"Within a procedure, during the execution of its
statementSequence, local variables have single level
evaluation. This means that using a variable in an
expression will yield the current value of that variable,
rather than first evaluating that value."
Let's look at a similar example as above, but within a procedure.
First, we'll deal with z in the procedure. As earlier, the name z is assigned the expression containing the unevaluated sqrt call. In contrast to the top-level behavior, within the procedure the assigned local z is evaluated only 1-level.
restart;
f := proc( f0 )
local z;
lprint( f0 );
z := f0;
lprint( z );
hastype(z, radical);
end proc:
f( '1/x*sqrt(u*x^2)' );
1/x*sqrt(u*x^2)
1/x*sqrt(u*x^2)
false
And now we'll alter the procedure to deal with eval(z), which gets the expression containing something to power 1/2.
restart;
f := proc( f0 )
local z;
lprint( f0 );
z := f0;
lprint( eval(z) );
hastype(eval(z), radical);
end proc:
f( '1/x*sqrt(u*x^2)' );
1/x*sqrt(u*x^2)
1/x*(u*x^2)^(1/2)
true
So it appears that you are experiencing the documented and intended behavior for evaluation of assigned local variables within a procedure. That is not a bug.
You have only supplied a fragment of the code, and have not shown exactly what are the arguments f0, x, y, u passed to procedure convert_to_homog. But you have shown that local z is 1/x*sqrt(x^2*u) and not 1/x*(x^2*u)^(1/2) and if that is true then it is not a bug that hastype(z,radical) returns false.
With you current set up, yes, you can pass eval(z) to hastype and get the true result you expect.
But perhaps you should also re-examine why z is being assigned the unevaluated expression in the first place. Is that deliberate, or because of accidental programming earlier?
The situation I have is as follows:
I have a symbolic expression like:
syms X Y Z K
Ra=51.7;
P=[0 0 200];
Sa=sym('Ra^2==(Z-P(3))^2+(Y-P(2))^2')
Where Y and Z are defined as symbolic. Ra and P are vectors.
I need to get the gradient of Sa but I get an error:
G=gradient(Sa,[Y Z]);
Error using symengine (line 59)
The first argument must be of type 'Type::Arithmetical'.
Error in sym/gradient (line 39)
res = mupadmex('symobj::gradient',fsym.s,x.s);
But if I write the same expression as:
Sa(Y,Z)=((Z-P(3))^2+(Y-P(2))^2-Ra^2);
I get the expected result
G=gradient(Sa,[Y Z])
G(X, Y, Z) =
2*Y
2*Z - 400
Does anyone knows why this is so and if there's any way of using the implicit expression as this is a particular case but in general I have different implicit expressions and my code should be able to deal with them.
I've read the documentation on gradient and some sites, but if I found the answer I didn't notice.
I believe I could use the second form but still, I am curious about this subject.
Thanks for your time.
In the first one Sa is the entire equation, including the ==, while in the second one its a symbolic function depending on 2 variables.
Ultimately the way MATLAB seems to be handle this is that the first one is not derivable (also its dependent in another 2 sym variables, that doesn't know if they are related or not to the derived ones), while the second one gets identified as a function (symbolic) and can get derived.
I'm using Matlab 2014b. I've tried:
clear all
syms x real
assumeAlso(x>=5)
This returned:
ans =
[ 5 <= x, in(x, 'real')]
Then I tried:
int(sqrt(x^2-25)/x,x)
But this still returned a complex answer:
(x^2 - 25)^(1/2) - log(((x^2 - 25)^(1/2) + 5*i)/x)*5*i
I tried the simplify command, but still a complex answer. Now, this might be fixed in the latest version of Matlab. If so, can people let me know or offer a suggestion for getting the real answer?
The hand-calculated answer is sqrt(x^2-25)-5*asec(x/5)+C.
This behavior is present in R2017b, though when converted to floating point the imaginary components are different.
Why does this occur?
This occurs because Matlab's int function returns the full general solution when you ask for the indefinite integral. This solution is valid over the entire domain of of real values, including your restricted domain of x>=5.
With a bit of math you can show that the solution is always real for x>=5 (see complex logarithm). Or you can use more symbolic math via the isAlways function to show this:
syms x real
assume(x>=5)
y = int(sqrt(x^2-25)/x, x)
isAlways(imag(y)==0)
This returns true (logical 1). Unfortunately, Matlab's simplification routines appear to not be able to reduce this expression when assumptions are included. You might also submit this case to The MathWorks as a service request in case they'd consider improving the simplification for this and similar equations.
How can this be "fixed"?
If you want to get rid of the zero-valued imaginary part of the solution you can use sym/real:
real(y)
which returns 5*atan2(5, (x^2-25)^(1/2)) + (x^2-25)^(1/2).
Also, as #SardarUsama points out, when the full solution is converted to floating point (or variable precision) there will sometimes numeric imprecision when converting from exact symbolic form. Using the symbolic real form above should avoid this.
The answer is not really complex.
Take a look at this:
clear all; %To clear the conditions of x as real and >=5 (simple clear doesn't clear that)
syms x;
y = int(sqrt(x^2-25)/x, x)
which, as we know, gives:
y =
(x^2 - 25)^(1/2) - log(((x^2 - 25)^(1/2) + 5i)/x)*5i
Now put some real values of x≥5 to check what result it gives:
n = 1004; %We'll be putting 1000 values of x in y from 5 to 1004
yk = zeros(1000,1); %Preallocation
for k=5:n
yk(k-4) = subs(y,x,k); %Putting the value of x
end
Now let's check the imaginary part of the result we have:
>> imag(yk)
ans =
1.0e-70 *
0
0
0
0
0.028298997121333
0.028298997121333
0.028298997121333
%and so on...
Notice the multiplier 1e-70.
Let's check the maximum value of imaginary part in yk.
>> max(imag(yk))
ans =
1.131959884853339e-71
This implies that the imaginary part is extremely small and it is not a considerable amount to be worried about. Ideally it may be zero and it's coming due to imprecise calculations. Hence, it is safe to call your result real.
I'm trying to understand how to use the chi2gof function in matlab with a very simple test. Let's assume that I toss a coin 190 times and get 94 heads and 96 tails. The null hypothesis should be that i get 95h, 95t. As far as I understand the documentation, I should be able to test the hypothesis by running
[h,p,stats] = chi2gof([94,96], 'expected', [95,95])
However, this returns h = 1, which supposedly means that null hypothesis is rejected, which makes no sense. Another pecular thing is that the O parameter in stats returns as O: [0 2] - but shouldn't this be my input ([94,96])? What am I doing wrong?
What am I doing wrong?
The problem is that you are passing the cumulative outcome of your coin tosses to chi2gof. The goodness-of-fit test must be performed on the full sample. From the official documentation (reference here):
x = sample data for the hypothesis test, specified as a vector (the wrong part of your code)
Expected = expected counts for each bin (the correct part of your code)
Let's make an example using the correct variables:
ct = randsample([0 1],190,true,[0.49 0.51]);
[h,p,stats] = chi2gof(ct,'Expected',[95 95]);
The returned value of h is 0, which is absolutely correct.
Now, let's make an example that is supposed to fail:
ct = randsample([0 1],190,true,[0.05 0.95]);
[h,p,stats] = chi2gof(ct,'Expected',[95 95]);
As you can see, h returned from this second test will be equal to 1.
On a final note, don't forget to take a look at the second output argument, which is the p-value of the test and is an important element to evaluate the significance of the result.