Open Smit-create opened 1 year ago
Commenting out that only that line, we get another error codegen error:
std::vector<llvm::Value *> args2 = convert_call_args(x, m_name);
File "/Users/thebigbool/repos2/lfortran/src/libasr/codegen/asr_to_llvm.cpp", line 5641
LFORTRAN_ASSERT(finder != nested_globals.end());
AssertFailed: finder != nested_globals.end()
This error is because of the following line:
call chkder(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), xp, fvecp, 1, err)
To make this compile, I use the following diff:
diff --git a/examples/example_lmder1.f90 b/examples/example_lmder1.f90
index 984207e..2ccadaa 100644
--- a/examples/example_lmder1.f90
+++ b/examples/example_lmder1.f90
@@ -64,7 +64,7 @@ tol = sqrt(epsilon(1._dp))
allocate(wa(5*size(x) + size(fvec)))
call lmder1(fcn, size(fvec), size(x), x, fvec, fjac, size(fjac, 1), tol, &
info, ipvt, wa, size(wa))
-print 1000, enorm(size(fvec), fvec), info, x
+!print *, enorm(size(fvec), fvec), info, x
1000 format(5x, 'FINAL L2 NORM OF THE RESIDUALS', d15.7 // &
5x, 'EXIT PARAMETER', 16x, i10 // &
5x, 'FINAL APPROXIMATE SOLUTION' // &
@@ -74,8 +74,11 @@ contains
subroutine check_deriv()
real(dp) :: xp(size(x)), fvecp(size(fvec)), err(size(fvec))
-call chkder(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), xp, fvecp, &
- 1, err)
+integer :: a, b, c
+a = size(fvec)
+b = size(x)
+c = size(fjac, 1)
+call chkder(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), xp, fvecp, 1, err)
call fcn(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), 1)
call fcn(size(fvec), size(x), x, fvec, fjac, size(fjac, 1), 2)
and that did compile fine with some linker errors as in #10
Another issue:
program example_lmder1
integer :: a = 10
real :: b(2)
call foo()
contains
subroutine foo()
call fo2(size(b), b)
end subroutine
subroutine fo2(m, vec)
integer :: m, vec(m)
print *, m
end subroutine
end program
Output:
code generation error: b isn't defined in any scope.
With https://github.com/lfortran/lfortran/pull/1035, I am able to compile this example with the following diff:
diff --git a/examples/example_lmder1.f90 b/examples/example_lmder1.f90
index 984207e..43f69b8 100644
--- a/examples/example_lmder1.f90
+++ b/examples/example_lmder1.f90
@@ -64,7 +64,8 @@ tol = sqrt(epsilon(1._dp))
allocate(wa(5*size(x) + size(fvec)))
call lmder1(fcn, size(fvec), size(x), x, fvec, fjac, size(fjac, 1), tol, &
info, ipvt, wa, size(wa))
-print 1000, enorm(size(fvec), fvec), info, x
+print *, dabs(1.0)
+!print 1000, enorm(size(fvec), fvec), info, x
It runs and then fails with a segmentation fault after a few steps.
@certik With the diff in https://github.com/certik/minpack/issues/11#issuecomment-1326495258, I am now able to compile and run example_lmder.f90
successfully with the current main
branch of lfortran
. It fails with a segmentation fault later on during execution after some steps.
One probable issue is the following:
program main
integer :: b(2)
b = [244, 1404]
call foo()
contains
subroutine foo()
b(1) = 43
b(2) = 15
call foo2(size(b), b)
end subroutine
subroutine foo2(m, vec)
integer :: m, vec(m)
print *, m, vec(1), vec(2)
end subroutine
end program
LFortran Output:
% lfortran a.f90
2 15 77306806
% lfortran a.f90
2 15 11443126
% lfortran a.f90
2 15 37153718
gfortran output:
% gfortran a.f90 && ./a.out
2 43 15
There is probably something wrong with the assignments as the following foo2
works fine(which is a bug):
subroutine foo2(m, vec)
integer :: m, vec(m)
print *, m, vec(0), vec(1)
end subroutine
LFortran output:
% lfortran a.f90
2 43 15
% lfortran a.f90
2 43 15
% lfortran a.f90
2 43 15
Thanks for this. I'll have a look.
I can reproduce the bug, so I reported it here: https://github.com/lfortran/lfortran/issues/1051
This bug is not needed for minpack, as SciPy doesn't use this code. I wrote it myself to test minpack, but if LFortran can't do it yet, then we don't need to worry.
To fix these parent scope bugs, I recommend to implement nested lambda functions in LFortran first, which @rebcabin and I have been slowly working towards. We have to fix this properly at the ASR level (one way or the other), then this will start working well. Right now these parent scopes are handled in the LLVM backend directly and I know there are bugs and it's very hard to maintain.
@certik @Smit-create for example in comment, b
is initialised only for two integer values, that means it can hold values at two indices i.e. b(0)
, b(1)
and if tried to access b(2)
will always throw junk ( which is observed in lfortran ). I am wondering why assignment b(2) = 15
allowed in gfortran and lfortran, shouldn't it throw accessing out of bounds error
?
Okay so, by the following diff I am able to compile example_lmder1.f90
without segmentation fault.
diff --git a/examples/example_lmder1.f90 b/examples/example_lmder1.f90
index 984207e..9414dfe 100644
--- a/examples/example_lmder1.f90
+++ b/examples/example_lmder1.f90
@@ -34,7 +34,7 @@ else
tmp4 = (x(2)*tmp2 + x(3)*tmp3)**2
fjac(i,1) = -1.D0
fjac(i,2) = tmp1*tmp2/tmp4
- fjac(i,3) = tmp1*tmp3/tmp4
+ ! fjac(i,3) = tmp1*tmp3/tmp4
end do
end if
end subroutine
@certik @Smit-create for example in comment,
b
is initialised only for two integer values, that means it can hold values at two indices i.e.b(0)
,b(1)
and if tried to accessb(2)
will always throw junk ( which is observed in lfortran ). I am wondering why assignmentb(2) = 15
allowed in gfortran and lfortran, shouldn't it throwaccessing out of bounds error
?
Arrays in Fortran have 1-based indexing. And so b(2)
is fine but not b(0)
.
Okay so, I observed following difference in the output for example_lmder1.f90
with diff
@@ -54,7 +57,9 @@ real(dp), allocatable :: wa(:)
! The following starting values provide a rough fit.
x = [1._dp, 1._dp, 1._dp]
-
+print *, "fvec size: ", size(fvec)
+print *, "size of x : ", size(x)
+print *, "ldfjac initial: ", size(fjac,1)
call check_deriv()
Gfortran
fvec size: 15
size of x : 3
ldfjac initial: 15
ldfjac: 15
n: 3
ldfjac: 15
n: 3
ldfjac: 15
n: 3
Derivatives check (1.0 is correct, 0.0 is incorrect):
0.34167772409443192 0.26609177862398736 0.22240032976470067 0.19230769261632810 0.16877864079222862 0.15028146168632606 0.13485790624604307 0.12117537236197391 0.11482694121292628 9.9569409124501615E-002 8.9102784011035108E-002 7.8383378719671506E-002 6.7451393119264111E-002 5.5987673912383733E-002 4.3547993352560439E-002
ldfjac here: 15
ldfjac: 15
n: 3
ldfjac: 15
n: 3
ldfjac: 15
n: 3
ldfjac: 15
n: 3
3.0000000000000000
here
LFortran
fvec size: 15 size of x : 3 ldfjac initial: 45 ldfjac: 45 n: 3 ldfjac: 45 n: 3 ldfjac: 45 n: 3 Derivatives check (1.0 is correct, 0.0 is incorrect): 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00
ldfjac here: 45 ldfjac: 45 n: 3 ldfjac: 45 n: 3 ldfjac: 45 n: 3 3.00000000000000000e+00 here
Values start to diverge just after declaration of variables in `program example_lmder1` this may lead to `segmentation fault`.
Error in comment 1 might be because of below given case
program main
integer :: x(3)
x(1) = 1
x(2) = 2
x(3) = 3
print *, "x :", x
end program
LFortran output:
lfortran a.f90
x : -1989596352
GFortran output:
gfortran a.f90 && ./a.out
x : 1 2 3
program main
integer :: x(3)
integer b
x(1) = 1
x(2) = 2
x(3) = 3
b = 10
print *, b, x
end program
LFortran output:
lfortran a.f90
10 -709536896
lfortran a.f90
10 -1272557600
lfortran a.f90
10 -1203966432
GFortran output:
gfortran a.f90 && ./a.out
10 1 2 3
Whereas
program main
integer :: x(3)
integer b
x(1) = 1
x(2) = 2
x(3) = 3
b = 10
print *, x
end program
Gives same output as gfortran.
The last example is this bug: https://github.com/lfortran/lfortran/issues/1112.
Issue for comment, lfortran/lfortran#1133
Okay so, here I can observe one cause of the divergence of values.
LFortran
[100%] Built target example_lmder1 3.00000000000000000e+00 check deriv before ldfjac initial: 45 chkder fvec in chkder epsmch = 2.22044604925999980e-16 eps = 1.49011611938801578e-08 mode = 1 n = 3 j = 1 temp = 1.49011611938801578e-08 xp(j) = 0.00000000000000000e+00 after xp(j) = 1.00000001490116119e+00 j = 2 temp = 1.49011611938801578e-08 xp(j) = 0.00000000000000000e+00 after xp(j) = 1.00000001490116119e+00 j = 3 temp = 1.49011611938801578e-08 xp(j) = 0.00000000000000000e+00 after xp(j) = 1.00000001490116119e+00 out of chkder calling fcn y(i) = 1.40000000000000013e-01 x(1) = 1.00000000000000000e+00 x(2) = 1.00000000000000000e+00 x(3) = 1.00000000000000000e+00 fvec(i) = -9.22499999999999987e-01 y(i) = 1.79999999999999993e-01 x(1) = 1.00000000000000000e+00 x(2) = -9.22499999999999987e-01 x(3) = 1.00000000000000000e+00 fvec(i) = -6.36765918460833635e-01 y(i) = 2.20000000000000001e-01 x(1) = 1.00000000000000000e+00 x(2) = -9.22499999999999987e-01 x(3) = -6.36765918460833635e-01 fvec(i) = -5.64216094286594805e-01 y(i) = 2.50000000000000000e-01 x(1) = 1.00000000000000000e+00 x(2) = -9.22499999999999987e-01 x(3) = -6.36765918460833635e-01 fvec(i) = -4.56250914601839197e-01 y(i) = 2.89999999999999980e-01 x(1) = 1.00000000000000000e+00 x(2) = -9.22499999999999987e-01 x(3) = -6.36765918460833635e-01 fvec(i) = -3.34943636313187298e-01 y(i) = 3.20000000000000007e-01 x(1) = 1.00000000000000000e+00 x(2) = -9.22499999999999987e-01 x(3) = -6.36765918460833635e-01
GFortran
[100%] Built target example_lmder1 3.0000000000000000 check deriv before ldfjac initial: 15 chkder fvec in chkder epsmch = 2.2204460492599998E-016 eps = 1.4901161193880158E-008 mode = 1 n = 3 j = 1 temp = 1.4901161193880158E-008 xp(j) = 0.0000000000000000 after xp(j) = 1.0000000149011612 j = 2 temp = 1.4901161193880158E-008 xp(j) = 0.0000000000000000 after xp(j) = 1.0000000149011612 j = 3 temp = 1.4901161193880158E-008 xp(j) = 0.0000000000000000 after xp(j) = 1.0000000149011612 out of chkder calling fcn y(i) = 0.14000000000000001 x(1) = 1.0000000000000000 x(2) = 1.0000000000000000 x(3) = 1.0000000000000000 fvec(i) = -0.92249999999999999 y(i) = 0.17999999999999999 x(1) = 1.0000000000000000 x(2) = 1.0000000000000000 x(3) = 1.0000000000000000 fvec(i) = -0.94500000000000006 y(i) = 0.22000000000000000 x(1) = 1.0000000000000000 x(2) = 1.0000000000000000 x(3) = 1.0000000000000000 fvec(i) = -0.96750000000000003 y(i) = 0.25000000000000000 x(1) = 1.0000000000000000 x(2) = 1.0000000000000000 x(3) = 1.0000000000000000 fvec(i) = -1.0000000000000000 y(i) = 0.28999999999999998 x(1) = 1.0000000000000000 x(2) = 1.0000000000000000 x(3) = 1.0000000000000000 fvec(i) = -1.0225000000000000 y(i) = 0.32000000000000001 x(1) = 1.0000000000000000 x(2) = 1.0000000000000000 x(3) = 1.0000000000000000
This is a separate bug, lfortran/lfortran#1150
The error comes from: https://github.com/certik/minpack/blob/12f30bc2d6971fde7a32d59e80c635289376e14a/examples/example_lmder1.f90#L67
Error: