From 8ed4a6cf78f23d5447fc6a7989254e569500b919 Mon Sep 17 00:00:00 2001 From: Joe Wallwork Date: Tue, 28 Jul 2026 16:21:39 +0100 Subject: [PATCH 1/5] Add Fortran version of square example --- 1_square/Makefile | 2 ++ 1_square/square.f90 | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 1_square/square.f90 diff --git a/1_square/Makefile b/1_square/Makefile index c223268..ac857c5 100644 --- a/1_square/Makefile +++ b/1_square/Makefile @@ -6,5 +6,7 @@ clean: %.o: %.c ../dockerscript.sh clang-12 /host/$^ -O3 -Xclang -load -Xclang /Enzyme/enzyme/build/Enzyme/ClangEnzyme-12.so -ffast-math -o /host/$@ +# TODO: Fortran build once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ 3.14 diff --git a/1_square/square.f90 b/1_square/square.f90 new file mode 100644 index 0000000..9777fbb --- /dev/null +++ b/1_square/square.f90 @@ -0,0 +1,24 @@ +program main + use enzyme, only: enzyme_autodiff + implicit none + real :: x, y, dy + + ! Evaluate the function for some arbitrary input + x = 3.0 + y = square(x) + write(*, "('square(',f0.0,')=',f0.0)") x, y + + ! Evaluate its derivative using reverse mode + dy = 0.0 + call enzyme_autodiff(square, x, dy) + write(*, "('Gradient square(',f0.0,')=',f0.0)") x, dy + + contains + + ! Function we seek to differentiate + real function square(x) + real, intent(in) :: x + square = x ** 2 + end function + +end program main From 2eca32784daff74f8d92ce7e31b84369248595cb Mon Sep 17 00:00:00 2001 From: Joe Wallwork Date: Tue, 28 Jul 2026 16:34:34 +0100 Subject: [PATCH 2/5] Add Fortran version of norm example --- 2_norm/Makefile | 2 ++ 2_norm/norm.f90 | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 2_norm/norm.f90 diff --git a/2_norm/Makefile b/2_norm/Makefile index 3229d2a..9b9cf44 100644 --- a/2_norm/Makefile +++ b/2_norm/Makefile @@ -15,5 +15,7 @@ clean: %.o: %.ll ../dockerscript.sh clang-12 -O2 /host/$^ -o /host/$@ -lm +# TODO: Fortran builds once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ 2000 diff --git a/2_norm/norm.f90 b/2_norm/norm.f90 new file mode 100644 index 0000000..d4969ef --- /dev/null +++ b/2_norm/norm.f90 @@ -0,0 +1,43 @@ +program main + use enzyme, only: enzyme_const, enzyme_dup, enzyme_autodiff + implicit none + integer, parameter :: n = 1000000 + integer, parameter :: initial_value = 20 + real :: x(n), dx(n) + real :: y(n), dy(n) + real :: start, finish, time + + ! Fill the input array with an arbitrary value + x(:) = initial_value + + ! Time the primal computation + call cpu_time(start) + call norm(n, x, y) + call cpu_time(finish) + time = finish - start + write(*, "('Serial normalize ',f0.6,1x,es11.4)") time, y(n) + + ! Zero the gradients and specify the seed + dx(:) = 0.0 + dy(:) = 1.0 + + ! Time the reverse mode computation + call cpu_time(start) + call enzyme_autodiff(norm, enzyme_const, n, & + enzyme_dup, x, dx, & + enzyme_dup, y, dy) + call cpu_time(finish) + time = finish - start + write(*, "('Gradient normalize ',f0.6,2(1x,es11.4))") time, y(n), dx(1) + +contains + + ! Function we seek to differentiate + subroutine norm(n, x, y) + integer, intent(in) :: n + real, dimension(n), intent(in) :: x + real, dimension(n), intent(out) :: y + y(:) = x / sum(x) + end subroutine norm + +end program main From a0c3520afe1573228ae064f90617e6b198a1bb84 Mon Sep 17 00:00:00 2001 From: Joe Wallwork Date: Tue, 28 Jul 2026 17:16:41 +0100 Subject: [PATCH 3/5] Add Fortran version of dot example --- 3_dot/Makefile | 2 ++ 3_dot/dot.f90 | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 3_dot/dot.f90 diff --git a/3_dot/Makefile b/3_dot/Makefile index 5c88940..922a57f 100644 --- a/3_dot/Makefile +++ b/3_dot/Makefile @@ -6,5 +6,7 @@ clean: %.o: %.c ../dockerscript.sh clang-12 /host/$^ -O3 -Xclang -load -Xclang /Enzyme/enzyme/build/Enzyme/ClangEnzyme-12.so -ffast-math -o /host/$@ +# TODO: Fortran builds once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ diff --git a/3_dot/dot.f90 b/3_dot/dot.f90 new file mode 100644 index 0000000..b6698d9 --- /dev/null +++ b/3_dot/dot.f90 @@ -0,0 +1,57 @@ +program main + use enzyme, only: enzyme_const, enzyme_dup, enzyme_autodiff + implicit none + + integer, parameter :: n = 20000000 + integer, parameter :: x = 20 + real :: a(n), b(n), c = 1 / x + real :: da(n), db(n), dc + real :: start, finish, time + integer :: i, dn + + ! Specify input + do i = 1, n + a(i) = x / i + b(i) = x + i - 1 ! NOTE: Minus one to account for 1-indexing + end do + + ! Time gradient computation with respect to all variables (A, B, and C) + da(:) = 0.0 + db(:) = 0.0 + dc = 0.0 + call cpu_time(start) + call enzyme_autodiff(dot, enzyme_const, n, & + enzyme_dup, a, da, & + enzyme_dup, b, db, & + enzyme_dup, c, dc) + call cpu_time(finish) + time = finish - start + write(*, "('Grad Normalize time=',f0.6)", advance="no") time + write(*, "(' A`(1)=',f4.1,' B`(1)=',f4.1,' C`=',f4.1)") da(1), db(1), dc + + ! Time gradient computation with respect to just B + da(:) = 0.0 + db(:) = 0.0 + dc = 0.0 + call cpu_time(start) + call enzyme_autodiff(dot, enzyme_const, n, & + enzyme_const, a, & + enzyme_dup, b, db, & + enzyme_const, c) + call cpu_time(finish) + time = finish - start + write(*, "('Constant A time=',f0.6)", advance="no") time + write(*, "(' A`(1)=',f4.1,' B`(1)=',f4.1,' C`=',f4.1)") da(1), db(1), dc + +contains + + ! Function we seek to differentiate + real function dot(n, x, y, z) + integer, intent(in) :: n + real, dimension(n), intent(in) :: x + real, dimension(n), intent(in) :: y + real, intent(in) :: z + dot = dot_product(x, y) + z + end function dot + +end program main From 433fc1a2dc0e277d33f7568423511b4c5317a452 Mon Sep 17 00:00:00 2001 From: Joe Wallwork Date: Tue, 28 Jul 2026 17:40:43 +0100 Subject: [PATCH 4/5] Add Fortran version of fwd example --- 7_fwd/Makefile | 2 ++ 7_fwd/fwd.f90 | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 7_fwd/fwd.f90 diff --git a/7_fwd/Makefile b/7_fwd/Makefile index 3d78be1..710aa14 100644 --- a/7_fwd/Makefile +++ b/7_fwd/Makefile @@ -6,5 +6,7 @@ clean: %.o: %.c ../dockerscript.sh clang-12 /host/$^ -O3 -Xclang -load -Xclang /Enzyme/enzyme/build/Enzyme/ClangEnzyme-12.so -ffast-math -o /host/$@ +# TODO: Fortran build once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ 3.14 diff --git a/7_fwd/fwd.f90 b/7_fwd/fwd.f90 new file mode 100644 index 0000000..ea58200 --- /dev/null +++ b/7_fwd/fwd.f90 @@ -0,0 +1,37 @@ +program main + use enzyme, only: enzyme_fwddiff + implicit none + + real :: a, b, c + real :: da, db, dc + + ! Specify input + a = 2.0 + b = 3.0 + + ! Specify seeds + da = 1.0 + db = 1.0 + + ! Compute forward mode derivative + call enzyme_fwddiff(my_loop, a, da, b, db, c, dc) + write(unit=6, fmt="(' a=',f2.0,' b=',f2.0,' c=',f4.0)") a, b, c + write(unit=6, fmt="(' da=',f2.0,' db=',f2.0,' dc=',f4.0)") da, db, dc + +contains + + ! Function we seek to evaluate + subroutine my_loop(x, y, z) + real, intent(in) :: x + real, intent(in) :: y + real, intent(out) :: z + real :: s + integer :: i + s = 0.0 + do i = 1, 100 + s = s + x + y + end do + z = s + end subroutine + +end program From 602e1e3543b4f35e5c220b717e4de918cda435b8 Mon Sep 17 00:00:00 2001 From: Joe Wallwork Date: Tue, 28 Jul 2026 17:41:13 +0100 Subject: [PATCH 5/5] Use consistent naming --- 1_square/square.f90 | 2 +- 2_norm/norm.f90 | 4 ++-- 3_dot/dot.f90 | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/1_square/square.f90 b/1_square/square.f90 index 9777fbb..a3acba7 100644 --- a/1_square/square.f90 +++ b/1_square/square.f90 @@ -21,4 +21,4 @@ real function square(x) square = x ** 2 end function -end program main +end program diff --git a/2_norm/norm.f90 b/2_norm/norm.f90 index d4969ef..2e89c35 100644 --- a/2_norm/norm.f90 +++ b/2_norm/norm.f90 @@ -38,6 +38,6 @@ subroutine norm(n, x, y) real, dimension(n), intent(in) :: x real, dimension(n), intent(out) :: y y(:) = x / sum(x) - end subroutine norm + end subroutine -end program main +end program diff --git a/3_dot/dot.f90 b/3_dot/dot.f90 index b6698d9..db3bfd5 100644 --- a/3_dot/dot.f90 +++ b/3_dot/dot.f90 @@ -52,6 +52,6 @@ real function dot(n, x, y, z) real, dimension(n), intent(in) :: y real, intent(in) :: z dot = dot_product(x, y) + z - end function dot + end function -end program main +end program