Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLVM codegen error: example_lmdif1.f90 #12

Open
Pranavchiku opened this issue Dec 15, 2022 · 9 comments
Open

LLVM codegen error: example_lmdif1.f90 #12

Pranavchiku opened this issue Dec 15, 2022 · 9 comments

Comments

@Pranavchiku
Copy link

Pranavchiku commented Dec 15, 2022

Error comes from @examples/example_lmdif1.f90#L55.

This is same as comment.

Error:

code generation error: asr_to_llvm: module failed verification. Error:
FPExt only operates on FP
  %158 = fpext %array.2* %x to double

On commenting line, example_lmdif1.f90 compiles, and output is exact same as gfortran.

@Pranavchiku
Copy link
Author

Pranavchiku commented Dec 15, 2022

example_lmdif1.f90 compiles with following diff

@@ -52,7 +55,7 @@ m = size(fvec)
 n = size(x)
 allocate(wa(m*n + 5*n + m))
 call lmdif1(fcn, size(fvec), size(x), x, fvec, tol, info, iwa, wa, size(wa))
-print 1000, enorm(size(fvec), fvec), info, x
+print 1000, enorm(size(fvec), fvec), info
 1000 format(5x, 'FINAL L2 NORM OF THE RESIDUALS', d15.7 // &
             5x, 'EXIT PARAMETER', 16x, i10              // &
             5x, 'FINAL APPROXIMATE SOLUTION'            // &

OR

@@ -52,7 +55,7 @@ m = size(fvec)
 n = size(x)
 allocate(wa(m*n + 5*n + m))
 call lmdif1(fcn, size(fvec), size(x), x, fvec, tol, info, iwa, wa, size(wa))
-print 1000, enorm(size(fvec), fvec), info, x
+print 1000, enorm(size(fvec), fvec), info
+print *, x
 1000 format(5x, 'FINAL L2 NORM OF THE RESIDUALS', d15.7 // &
             5x, 'EXIT PARAMETER', 16x, i10              // &
             5x, 'FINAL APPROXIMATE SOLUTION'            // &

@Pranavchiku
Copy link
Author

Pranavchiku commented Dec 15, 2022

Values are good till a few iterations then it begins to diverge

For diff

diff --git a/examples/example_lmdif1.f90 b/examples/example_lmdif1.f90
index 7da6b75..24b27b3 100644
--- a/examples/example_lmdif1.f90
+++ b/examples/example_lmdif1.f90
@@ -13,6 +13,7 @@ real(dp), intent(in) :: x(n)
 real(dp), intent(out) :: fvec(m)
 
 integer :: i
+integer :: j = 0
 real(dp) :: tmp1, tmp2, tmp3, y(15)
 ! Suppress compiler warning:
 y(1) = iflag
@@ -25,7 +26,12 @@ do i = 1, 15
     tmp3 = tmp1
     if (i .gt. 8) tmp3 = tmp2
     fvec(i) = y(i) - (x(1) + tmp1/(x(2)*tmp2 + x(3)*tmp3))
+
+    print *, "fvec(", i, ") :", fvec(i)
+    if ( i .eq. 15 ) j = j + 1
+
 end do
+print * , "j :", j
 end subroutine
 
 end module

GFortran

   3.0000000000000000     
 epsilon(1._dp) :   2.2204460492503131E-016
 tol here :   1.4901161193847656E-008
 m here :          15
 n here :           3
 fvec(           1 ) : -0.92249999999999999     
 fvec(           2 ) : -0.94500000000000006     
 fvec(           3 ) : -0.96750000000000003     
 fvec(           4 ) :  -1.0000000000000000     
 fvec(           5 ) :  -1.0225000000000000     
 fvec(           6 ) :  -1.0549999999999999     
 fvec(           7 ) :  -1.0874999999999999     
 fvec(           8 ) :  -1.1099999999999999     
 fvec(           9 ) :  -1.2728571428571427     
 fvec(          10 ) :  -1.2533333333333334     
 fvec(          11 ) :  -1.3700000000000001     
 fvec(          12 ) :  -1.5400000000000000     
 fvec(          13 ) :  -1.8266666666666664     
 fvec(          14 ) :  -2.3999999999999999     
 fvec(          15 ) :  -4.1100000000000003     
 j :           1
 fvec(           1 ) : -0.92250001490116118     
 fvec(           2 ) : -0.94500001490116126     
 fvec(           3 ) : -0.96750001490116122     
 fvec(           4 ) :  -1.0000000149011612     
 fvec(           5 ) :  -1.0225000149011612     
 fvec(           6 ) :  -1.0550000149011611     
 fvec(           7 ) :  -1.0875000149011611     
 fvec(           8 ) :  -1.1100000149011611     
 fvec(           9 ) :  -1.2728571577583039     
 fvec(          10 ) :  -1.2533333482344946     
 fvec(          11 ) :  -1.3700000149011613     
 fvec(          12 ) :  -1.5400000149011612     
 fvec(          13 ) :  -1.8266666815678276     
 fvec(          14 ) :  -2.4000000149011611     
 fvec(          15 ) :  -4.1100000149011615     
 j :           2
 fvec(           1 ) : -0.92249999912688507     
 fvec(           2 ) : -0.94499999837018556     
 fvec(           3 ) : -0.96749999772990125     
 fvec(           4 ) : -0.99999999720603228     
 fvec(           5 ) :  -1.0224999967985786     
 fvec(           6 ) :  -1.0549999965075403     
 fvec(           7 ) :  -1.0874999963329173     
 fvec(           8 ) :  -1.1099999962747096     
 fvec(           9 ) :  -1.2728571380674838     
 fvec(          10 ) :  -1.2533333271245164     
 fvec(          11 ) :  -1.3699999918043617     
 fvec(          12 ) :  -1.5399999888241291     
 fvec(          13 ) :  -1.8266666505237421     
 fvec(          14 ) :  -2.3999999739229678     
 fvec(          15 ) :  -4.1099999441206458     
 j :           3
 fvec(           1 ) : -0.92249999994179233     
 fvec(           2 ) : -0.94499999976716942     
 fvec(           3 ) : -0.96749999947613108     
 fvec(           4 ) : -0.99999999906867743     
 fvec(           5 ) :  -1.0224999985448084     
 fvec(           6 ) :  -1.0549999979045241     
 fvec(           7 ) :  -1.0874999971478245     
 fvec(           8 ) :  -1.1099999962747096     
 fvec(           9 ) :  -1.2728571380674838     
 fvec(          10 ) :  -1.2533333271245164     
 fvec(          11 ) :  -1.3699999918043617     
 fvec(          12 ) :  -1.5399999888241291     
 fvec(          13 ) :  -1.8266666505237421     
 fvec(          14 ) :  -2.3999999739229678     
 fvec(          15 ) :  -4.1099999441206458     
 j :           4
 fvec(           1 ) :   5.8553218317936029E-003
 fvec(           2 ) :  -3.1439859491741440E-003
 fvec(           3 ) :  -9.8228667696700911E-003
 fvec(           4 ) :  -2.4342338353054771E-002
 fvec(           5 ) :  -2.6848857557622396E-002
 fvec(           6 ) :  -3.7475929916292505E-002
 fvec(           7 ) :  -4.6345510294420467E-002
 fvec(           8 ) :  -4.3569225622321295E-002
 fvec(           9 ) : -0.16383257318646571     
 fvec(          10 ) :  -8.7517036605324838E-002
 fvec(          11 ) : -0.12467528539172779     
 fvec(          12 ) : -0.17541265857133181     
 fvec(          13 ) : -0.26330828053733879     
 fvec(          14 ) : -0.43909952446935296     
 fvec(          15 ) : -0.95647325626539548 

LFortran

3.00000000000000000e+00
epsilon(1._dp) : 2.22507385850720138e-308
tol here : 1.49166814624004135e-154
m here : 15
n here : 3
fvec( 1 ) : -9.22499999999999987e-01
fvec( 2 ) : -9.45000000000000062e-01
fvec( 3 ) : -9.67500000000000027e-01
fvec( 4 ) : -1.00000000000000000e+00
fvec( 5 ) : -1.02249999999999996e+00
fvec( 6 ) : -1.05499999999999994e+00
fvec( 7 ) : -1.08749999999999991e+00
fvec( 8 ) : -1.10999999999999988e+00
fvec( 9 ) : -1.27285714285714269e+00
fvec( 10 ) : -1.25333333333333341e+00
fvec( 11 ) : -1.37000000000000011e+00
fvec( 12 ) : -1.54000000000000004e+00
fvec( 13 ) : -1.82666666666666644e+00
fvec( 14 ) : -2.39999999999999991e+00
fvec( 15 ) : -4.11000000000000032e+00
j : 1
fvec( 1 ) : -9.22500014901161181e-01
fvec( 2 ) : -9.45000014901161256e-01
fvec( 3 ) : -9.67500014901161220e-01
fvec( 4 ) : -1.00000001490116119e+00
fvec( 5 ) : -1.02250001490116116e+00
fvec( 6 ) : -1.05500001490116113e+00
fvec( 7 ) : -1.08750001490116111e+00
fvec( 8 ) : -1.11000001490116107e+00
fvec( 9 ) : -1.27285715775830388e+00
fvec( 10 ) : -1.25333334823449460e+00
fvec( 11 ) : -1.37000001490116130e+00
fvec( 12 ) : -1.54000001490116123e+00
fvec( 13 ) : -1.82666668156782763e+00
fvec( 14 ) : -2.40000001490116111e+00
fvec( 15 ) : -4.11000001490116151e+00
j : 1
fvec( 1 ) : -9.22499999126885073e-01
fvec( 2 ) : -9.44999998370185557e-01
fvec( 3 ) : -9.67499997729901251e-01
fvec( 4 ) : -9.99999997206032276e-01
fvec( 5 ) : -1.02249999679857861e+00
fvec( 6 ) : -1.05499999650754028e+00
fvec( 7 ) : -1.08749999633291727e+00
fvec( 8 ) : -1.10999999627470958e+00
fvec( 9 ) : -1.27285713806748380e+00
fvec( 10 ) : -1.25333332712451639e+00
fvec( 11 ) : -1.36999999180436172e+00
fvec( 12 ) : -1.53999998882412914e+00
fvec( 13 ) : -1.82666665052374211e+00
fvec( 14 ) : -2.39999997392296782e+00
fvec( 15 ) : -4.10999994412064584e+00
j : 1
fvec( 1 ) : -9.22499999941792326e-01
fvec( 2 ) : -9.44999999767169419e-01
fvec( 3 ) : -9.67499999476131078e-01
fvec( 4 ) : -9.99999999068677425e-01
fvec( 5 ) : -1.02249999854480844e+00
fvec( 6 ) : -1.05499999790452414e+00
fvec( 7 ) : -1.08749999714782453e+00
fvec( 8 ) : -1.10999999627470958e+00
fvec( 9 ) : -1.27285713806748380e+00
fvec( 10 ) : -1.25333332712451639e+00
fvec( 11 ) : -1.36999999180436172e+00
fvec( 12 ) : -1.53999998882412914e+00
fvec( 13 ) : -1.82666665052374211e+00
fvec( 14 ) : -2.39999997392296782e+00
fvec( 15 ) : -4.10999994412064584e+00
j : 1
fvec( 1 ) : -9.22499999999999987e-01
fvec( 2 ) : -9.45000000000000062e-01
fvec( 3 ) : -9.67500000000000027e-01
fvec( 4 ) : -1.00000000000000000e+00
fvec( 5 ) : -1.02249999999999996e+00
fvec( 6 ) : -1.05499999999999994e+00
fvec( 7 ) : -1.08749999999999991e+00
fvec( 8 ) : -1.10999999999999988e+00
fvec( 9 ) : -1.27285714285714269e+00
fvec( 10 ) : -1.25333333333333341e+00
fvec( 11 ) : -1.37000000000000011e+00
fvec( 12 ) : -1.54000000000000004e+00
fvec( 13 ) : -1.82666666666666644e+00
fvec( 14 ) : -2.39999999999999991e+00
fvec( 15 ) : -4.11000000000000032e+00
j : 1

@Pranavchiku
Copy link
Author

Pranavchiku commented Dec 20, 2022

Okay so, I investigated more and found out that the following might be cause of divergence

For following diff

diff --git a/src/lmdif.f b/src/lmdif.f
index fcb61d1..78927e4 100644
--- a/src/lmdif.f
+++ b/src/lmdif.f
@@ -198,7 +198,11 @@ c     **********
 c
 c     epsmch is the machine precision.
 c
+      print *, "factor in lmdif: ", factor
+
       epsmch = dpmpar(1)
+
+      print *, "factor in lmdif here :", factor
 c
       info = 0
       iflag = 0

and

index 6f28ed2..8c43db6 100644
--- a/src/lmdif1.f
+++ b/src/lmdif1.f
@@ -124,6 +124,8 @@ c
       mode = 1
       nprint = 0
       mp5n = m + 5*n
+      print *, 'lmdif1: calling lmdif'
+      print *, "factor: ", factor
       call lmdif(fcn,m,n,x,fvec,ftol,xtol,gtol,maxfev,epsfcn,wa(1),
      *           mode,factor,nprint,info,nfev,wa(mp5n+1),m,iwa,
      *           wa(n+1),wa(2*n+1),wa(3*n+1),wa(4*n+1),wa(5*n+1))

GFortran

 3.0000000000000000     
 lmdif1: calling lmdif
 factor:    100.00000000000000     
 factor in lmdif:    100.00000000000000     
 factor in lmdif here :   100.00000000000000    

LFortran

3.00000000000000000e+00
lmdif1: calling lmdif
factor:  1.00000000000000000e+02
factor in lmdif:  4.68599226571309371e-310
factor in lmdif here : 4.68599226571309371e-310

Value of factor changes.

@Pranavchiku
Copy link
Author

diff --git a/src/lmdif.f b/src/lmdif.f
index fcb61d1..f1bfc73 100644
--- a/src/lmdif.f
+++ b/src/lmdif.f
@@ -193,12 +193,18 @@ c     **********
      *                 one,par,pnorm,prered,p1,p5,p25,p75,p0001,ratio,
      *                 sum,temp,temp1,temp2,xnorm,zero
       double precision dpmpar,enorm
+      factor = 100.00
+      print *, "factor in lmdif here2: ", factor
       data one,p1,p5,p25,p75,p0001,zero
      *     /1.0d0,1.0d-1,5.0d-1,2.5d-1,7.5d-1,1.0d-4,0.0d0/

The above given diff complies example_lmdif exact same as GFortran.

@Pranavchiku
Copy link
Author

Variable factor initialized in lmdif1.f as 100.00 is passed as a parameter in lmdif.f whose value gets changed, this is a bug.
If we manually make factor=100.00 in lmdif.f just as shown in previous diff, we get output of LFortran same as GFortran.

@Pranavchiku
Copy link
Author

The bug is mentioned at lfortran/lfortran#1118.

@Pranavchiku
Copy link
Author

Okay so with lfortran/lfortran#1119, I get the following output

GFortran

   3.0000000000000000     
   9.0635960339045418E-002           1
   8.2410575864368327E-002   1.1330366265378435        2.3436946649075865 

LFortran

3.00000000000000000e+00
9.06359603390341356e-02 6
8.24105600064365257e-02
1.13303609732462451e+00
2.34369517380158099e+00

@Pranavchiku
Copy link
Author

The value that diverges is info whose meaning is defined @src/lmdif1.f#L84. According to it info = 6 looks better to me, as we have reached the highest precision, and no further reduction is possible in values. This divergence is because of different output values of @examples/example_lmdif1.f90#L49.

With the following diff we can see cause of divergence

diff --git a/examples/example_lmdif1.f90 b/examples/example_lmdif1.f90
index 7da6b75..73d595f 100644
--- a/examples/example_lmdif1.f90
+++ b/examples/example_lmdif1.f90
@@ -43,6 +43,7 @@ real(dp), allocatable :: wa(:)
 
 ! The following starting values provide a rough fit.
 x = [1._dp, 1._dp, 1._dp]
+print *, dabs(3.0_8)
 
 ! Set tol to the square root of the machine precision. Unless high precision
 ! solutions are required, this is the recommended setting.
@@ -51,8 +52,11 @@ tol = sqrt(epsilon(1._dp))
 m = size(fvec)
 n = size(x)
 allocate(wa(m*n + 5*n + m))
+print *, "tol: ", tol
 call lmdif1(fcn, size(fvec), size(x), x, fvec, tol, info, iwa, wa, size(wa))
-print 1000, enorm(size(fvec), fvec), info, x
+print *, enorm(size(fvec), fvec)
+print *, "info: ", info
+print *, x
 1000 format(5x, 'FINAL L2 NORM OF THE RESIDUALS', d15.7 // &
             5x, 'EXIT PARAMETER', 16x, i10              // &

GFortran

   3.0000000000000000     
 tol:    1.4901161193847656E-008
   9.0635960339045418E-002
 info:            1
   8.2410575864368327E-002   1.1330366265378435        2.3436946649075865 

LFortran

3.00000000000000000e+00
tol:  1.49166814624004135e-154
9.06359603390341356e-02
info:  6
8.24105600064365257e-02
1.13303609732462451e+00
2.34369517380158099e+00

@Pranavchiku
Copy link
Author

On using the following diff, the output of GFortran and LFortran matches upto 1e-11 / 1e-12.

diff --git a/examples/example_lmdif1.f90 b/examples/example_lmdif1.f90
index 7da6b75..8ef8a04 100644
--- a/examples/example_lmdif1.f90
+++ b/examples/example_lmdif1.f90
@@ -43,16 +43,21 @@ real(dp), allocatable :: wa(:)
 
 ! The following starting values provide a rough fit.
 x = [1._dp, 1._dp, 1._dp]
+print *, dabs(3.0_8)
 
 ! Set tol to the square root of the machine precision. Unless high precision
 ! solutions are required, this is the recommended setting.
 tol = sqrt(epsilon(1._dp))
+tol = 1.4901161193847656E-008

GFortran

   3.0000000000000000     
 tol:    1.4901161193847656E-008
   9.0635960339045418E-002
 info:            1
   8.2410575864368327E-002   1.1330366265378435        2.3436946649075865 

LFortran

3.00000000000000000e+00
tol:  1.49011611938476562e-08
9.06359603390454183e-02
info:  1
8.24105758643683267e-02
1.13303662653784354e+00
2.34369466490758649e+00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant