example.f90 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. ! (example.f90) -*- coding: utf-8; mode: f90 -*-
  2. ! examples/tests for guile-newra Fortran ffi
  3. ! $FORTRAN -shared -fPIC -o libexample.so example.f90 -std=f2018 -fcheck=all
  4. module example
  5. use iso_c_binding
  6. implicit none
  7. contains
  8. ! Bilinear interpolate in x, y table. x and y are indices in the sizes of the table
  9. ! [0 ... n], so the steps of x and y are accounted for in the caller.
  10. function lookup_xy(x, y, table) bind(c) result(z)
  11. real(C_DOUBLE), intent(in) :: x, y
  12. real(C_DOUBLE), intent(in) :: table(:, :)
  13. real(C_DOUBLE) :: z
  14. real(C_DOUBLE) :: dx, dy
  15. integer :: ix, iy
  16. ix = max(0, min(size(table, 1)-2, int(floor(x)))) ! x = end-of-table will use dx = 1.
  17. iy = max(0, min(size(table, 2)-2, int(floor(y)))) ! y = end-of-table will use dy = 1.
  18. dx = x-ix
  19. dy = y-iy
  20. z = + table(ix+1, iy+1)*(1-dx)*(1-dy) &
  21. + table(ix+2, iy+1)*dx*(1-dy) &
  22. + table(ix+1, iy+2)*(1-dx)*dy &
  23. + table(ix+2, iy+2)*dx*dy
  24. end function lookup_xy
  25. function lookup_xy_complex(x, y, table) bind(c) result(z)
  26. real(C_DOUBLE), intent(in) :: x, y
  27. complex(C_DOUBLE_COMPLEX), intent(in) :: table(:, :)
  28. complex(C_DOUBLE_COMPLEX) :: z
  29. real(C_DOUBLE) :: dx, dy
  30. integer :: ix, iy
  31. ix = max(0, min(size(table, 1)-2, int(floor(x)))) ! x = end-of-table will use dx = 1.
  32. iy = max(0, min(size(table, 2)-2, int(floor(y)))) ! y = end-of-table will use dy = 1.
  33. dx = x-ix
  34. dy = y-iy
  35. z = + table(ix+1, iy+1)*(1-dx)*(1-dy) &
  36. + table(ix+2, iy+1)*dx*(1-dy) &
  37. + table(ix+1, iy+2)*(1-dx)*dy &
  38. + table(ix+2, iy+2)*dx*dy
  39. end function lookup_xy_complex
  40. function conjugate(w) bind(c) result(z)
  41. complex(C_DOUBLE_COMPLEX), intent(in) :: w
  42. complex(C_DOUBLE_COMPLEX) :: z
  43. z = conjg(w)
  44. end function conjugate
  45. function ranker(arg) bind(c) result(z)
  46. real(C_DOUBLE), intent(in) :: arg(..)
  47. integer(C_INT32_T) :: z
  48. z = rank(arg)
  49. end function ranker
  50. function lbounder(arg) bind(c) result(z)
  51. real(C_DOUBLE), intent(in) :: arg(:)
  52. integer(C_INT32_T) :: z
  53. z = lbound(arg, 1)
  54. end function lbounder
  55. function valuer(arg) bind(c) result(z)
  56. real(C_DOUBLE), intent(in) :: arg(..)
  57. real(C_DOUBLE) :: z
  58. select rank(arg)
  59. rank(0) ; z = arg
  60. rank default ; z = 99
  61. end select
  62. end function valuer
  63. subroutine fillerf32(x) bind(c)
  64. real(C_FLOAT), intent(inout) :: x(:)
  65. x = x**2
  66. end subroutine fillerf32
  67. subroutine fillerf64(x) bind(c)
  68. real(C_DOUBLE), intent(inout) :: x(:)
  69. x = x**2
  70. end subroutine fillerf64
  71. function dgemv(a, v, w) bind(c) result(err)
  72. real(C_DOUBLE), intent(in) :: a(:, :)
  73. real(C_DOUBLE), intent(in) :: v(:)
  74. real(C_DOUBLE), intent(inout) :: w(:)
  75. integer(C_INT8_T) :: err
  76. integer :: i
  77. integer :: n
  78. if (size(w, 1) /= size(a, 1)) then
  79. err = 1
  80. else if (size(v, 1) /= size(a, 2)) then
  81. err = 2
  82. else
  83. n = size(v)
  84. w = 0.0
  85. do i = 1, n
  86. w = w + v(i) * a(:, i)
  87. end do
  88. err = 0
  89. end if
  90. end function dgemv
  91. end module example