Loading graph_fortran_binding/graph_fortran_binding.f90 +196 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ PROCEDURE :: get_max_concurrency => graph_context_get_max_concurrency PROCEDURE :: set_device_number => graph_context_set_device_number PROCEDURE :: add_pre_item => graph_context_add_pre_item PROCEDURE :: add_item => graph_context_add_item PROCEDURE :: add_converge_item => graph_context_add_converge_item PROCEDURE :: df => graph_context_df END TYPE !******************************************************************************* Loading Loading @@ -842,6 +845,96 @@ INTEGER(C_LONG), VALUE :: num_particles END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow item. !> !> @param[in] c The graph C context. !> @param[in] inputs Array of input nodes. !> @param[in] num_inputs Number of inputs. !> @param[in] outputs Array of output nodes. !> @param[in] num_outputs Number of outputs. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] num_maps Number of maps. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !------------------------------------------------------------------------------- SUBROUTINE graph_add_item(c, inputs, num_inputs, & outputs, num_outputs, & map_inputs, map_outputs, num_maps, & random_state, name, num_particles) & BIND(C, NAME='graph_add_item') USE, INTRINSIC :: ISO_C_BINDING IMPLICIT NONE TYPE(C_PTR), VALUE :: c INTEGER(C_INTPTR_T), VALUE :: inputs INTEGER(C_LONG), VALUE :: num_inputs INTEGER(C_INTPTR_T), VALUE :: outputs INTEGER(C_LONG), VALUE :: num_outputs INTEGER(C_INTPTR_T), VALUE :: map_inputs INTEGER(C_INTPTR_T), VALUE :: map_outputs INTEGER(C_LONG), VALUE :: num_maps TYPE(C_PTR), VALUE :: random_state CHARACTER(kind=C_CHAR), DIMENSION(*) :: name INTEGER(C_LONG), VALUE :: num_particles END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow converge item. !> !> @param[in] c The graph C context. !> @param[in] inputs Array of input nodes. !> @param[in] num_inputs Number of inputs. !> @param[in] outputs Array of output nodes. !> @param[in] num_outputs Number of outputs. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] num_maps Number of maps. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !> @param[in] tol Tolarance to converge the function to. !> @param[in] max_iter Maximum number of iterations before giving up. !------------------------------------------------------------------------------- SUBROUTINE graph_add_converge_item(c, inputs, num_inputs, & outputs, num_outputs, & map_inputs, map_outputs, num_maps, & random_state, name, num_particles, & tol, max_iter) & BIND(C, NAME='graph_add_converge_item') USE, INTRINSIC :: ISO_C_BINDING IMPLICIT NONE TYPE(C_PTR), VALUE :: c INTEGER(C_INTPTR_T), VALUE :: inputs INTEGER(C_LONG), VALUE :: num_inputs INTEGER(C_INTPTR_T), VALUE :: outputs INTEGER(C_LONG), VALUE :: num_outputs INTEGER(C_INTPTR_T), VALUE :: map_inputs INTEGER(C_INTPTR_T), VALUE :: map_outputs INTEGER(C_LONG), VALUE :: num_maps TYPE(C_PTR), VALUE :: random_state CHARACTER(kind=C_CHAR), DIMENSION(*) :: name INTEGER(C_LONG), VALUE :: num_particles REAL(C_DOUBLE), VALUE :: tol INTEGER(C_LONG), VALUE :: max_iter END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Take derivative ∂f∂x. !> !> @param[in] c The graph C context. !> @param[in] fnode The function expression to take the derivative of. !> @param[in] xnode The expression to take the derivative with respect to. !------------------------------------------------------------------------------- TYPE(C_PTR) FUNCTION graph_df(c, fnode, xnode) & BIND(C, NAME='graph_df') USE, INTRINSIC :: ISO_C_BINDING TYPE(C_PTR), VALUE :: c TYPE(C_PTR), VALUE :: fnode TYPE(C_PTR), VALUE :: xnode END FUNCTION END INTERFACE CONTAINS Loading Loading @@ -1868,4 +1961,107 @@ END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow item. !> !> @param[in,out] this @ref graph_context instance. !> @param[in] inputs Array of input nodes. !> @param[in] outputs Array of output nodes. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !------------------------------------------------------------------------------- SUBROUTINE graph_context_add_item(this, inputs, outputs, & map_inputs, map_outputs, & random_state, name, num_particles) IMPLICIT NONE ! Declare Arguments CLASS(graph_context), INTENT(INOUT) :: this INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: outputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_outputs TYPE(C_PTR), INTENT(IN) :: random_state CHARACTER(kind=C_CHAR,len=*), INTENT(IN) :: name INTEGER(C_LONG), INTENT(IN) :: num_particles ! Start of executable. CALL graph_add_item(this%c_context, & LOC(inputs), INT(SIZE(inputs), KIND=C_LONG), & LOC(outputs), INT(SIZE(outputs), KIND=C_LONG), & LOC(map_inputs), LOC(map_outputs), & INT(SIZE(map_inputs), KIND=C_LONG), & random_state, name, num_particles) END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow converge item. !> !> @param[in,out] this @ref graph_context instance. !> @param[in] inputs Array of input nodes. !> @param[in] outputs Array of output nodes. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !------------------------------------------------------------------------------- SUBROUTINE graph_context_add_converge_item(this, inputs, outputs, & map_inputs, map_outputs, & random_state, name, & num_particles, tol, max_iter) IMPLICIT NONE ! Declare Arguments CLASS(graph_context), INTENT(INOUT) :: this INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: outputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_outputs TYPE(C_PTR), INTENT(IN) :: random_state CHARACTER(kind=C_CHAR,len=*), INTENT(IN) :: name INTEGER(C_LONG), INTENT(IN) :: num_particles REAL(C_DOUBLE), VALUE :: tol INTEGER(C_LONG), VALUE :: max_iter ! Start of executable. CALL graph_add_converge_item(this%c_context, LOC(inputs), & INT(SIZE(inputs), KIND=C_LONG), & LOC(outputs), & INT(SIZE(outputs), KIND=C_LONG), & LOC(map_inputs), LOC(map_outputs), & INT(SIZE(map_inputs), KIND=C_LONG), & random_state, name, num_particles, & tol, max_iter) END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Take derivative ∂f∂x. !> !> @param[in,out] this @ref graph_context instance. !> @param[in] fnode The function expression to take the derivative of. !> @param[in] xnode The expression to take the derivative with respect to. !------------------------------------------------------------------------------- FUNCTION graph_context_df(this, fnode, xnode) IMPLICIT NONE ! Declare Arguments TYPE(C_PTR) :: graph_context_df CLASS(graph_context), INTENT(INOUT) :: this TYPE(C_PTR), INTENT(IN) :: fnode TYPE(C_PTR), INTENT(IN) :: xnode ! Start of executable. graph_context_df = graph_df(this%c_context, fnode, xnode) END FUNCTION END MODULE graph_tests/f_binding_test.f90 +161 −21 Original line number Diff line number Diff line Loading @@ -75,6 +75,10 @@ REAL(C_FLOAT), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -86,6 +90,10 @@ REAL(C_FLOAT), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_float_context(use_safe_math) Loading @@ -105,6 +113,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -140,12 +153,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 'f_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading @@ -175,6 +210,10 @@ REAL(C_DOUBLE), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -186,6 +225,10 @@ REAL(C_DOUBLE), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_double_context(use_safe_math) Loading @@ -205,6 +248,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -240,12 +288,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 'f_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading @@ -275,6 +345,10 @@ COMPLEX(C_FLOAT_COMPLEX), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -286,6 +360,10 @@ COMPLEX(C_FLOAT_COMPLEX), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_complex_float_context(use_safe_math) Loading @@ -305,6 +383,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -344,12 +427,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading @@ -379,6 +484,10 @@ COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -390,6 +499,10 @@ COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_complex_double_context(use_safe_math) Loading @@ -409,6 +522,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -448,12 +566,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 'f_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading
graph_fortran_binding/graph_fortran_binding.f90 +196 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ PROCEDURE :: get_max_concurrency => graph_context_get_max_concurrency PROCEDURE :: set_device_number => graph_context_set_device_number PROCEDURE :: add_pre_item => graph_context_add_pre_item PROCEDURE :: add_item => graph_context_add_item PROCEDURE :: add_converge_item => graph_context_add_converge_item PROCEDURE :: df => graph_context_df END TYPE !******************************************************************************* Loading Loading @@ -842,6 +845,96 @@ INTEGER(C_LONG), VALUE :: num_particles END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow item. !> !> @param[in] c The graph C context. !> @param[in] inputs Array of input nodes. !> @param[in] num_inputs Number of inputs. !> @param[in] outputs Array of output nodes. !> @param[in] num_outputs Number of outputs. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] num_maps Number of maps. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !------------------------------------------------------------------------------- SUBROUTINE graph_add_item(c, inputs, num_inputs, & outputs, num_outputs, & map_inputs, map_outputs, num_maps, & random_state, name, num_particles) & BIND(C, NAME='graph_add_item') USE, INTRINSIC :: ISO_C_BINDING IMPLICIT NONE TYPE(C_PTR), VALUE :: c INTEGER(C_INTPTR_T), VALUE :: inputs INTEGER(C_LONG), VALUE :: num_inputs INTEGER(C_INTPTR_T), VALUE :: outputs INTEGER(C_LONG), VALUE :: num_outputs INTEGER(C_INTPTR_T), VALUE :: map_inputs INTEGER(C_INTPTR_T), VALUE :: map_outputs INTEGER(C_LONG), VALUE :: num_maps TYPE(C_PTR), VALUE :: random_state CHARACTER(kind=C_CHAR), DIMENSION(*) :: name INTEGER(C_LONG), VALUE :: num_particles END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow converge item. !> !> @param[in] c The graph C context. !> @param[in] inputs Array of input nodes. !> @param[in] num_inputs Number of inputs. !> @param[in] outputs Array of output nodes. !> @param[in] num_outputs Number of outputs. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] num_maps Number of maps. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !> @param[in] tol Tolarance to converge the function to. !> @param[in] max_iter Maximum number of iterations before giving up. !------------------------------------------------------------------------------- SUBROUTINE graph_add_converge_item(c, inputs, num_inputs, & outputs, num_outputs, & map_inputs, map_outputs, num_maps, & random_state, name, num_particles, & tol, max_iter) & BIND(C, NAME='graph_add_converge_item') USE, INTRINSIC :: ISO_C_BINDING IMPLICIT NONE TYPE(C_PTR), VALUE :: c INTEGER(C_INTPTR_T), VALUE :: inputs INTEGER(C_LONG), VALUE :: num_inputs INTEGER(C_INTPTR_T), VALUE :: outputs INTEGER(C_LONG), VALUE :: num_outputs INTEGER(C_INTPTR_T), VALUE :: map_inputs INTEGER(C_INTPTR_T), VALUE :: map_outputs INTEGER(C_LONG), VALUE :: num_maps TYPE(C_PTR), VALUE :: random_state CHARACTER(kind=C_CHAR), DIMENSION(*) :: name INTEGER(C_LONG), VALUE :: num_particles REAL(C_DOUBLE), VALUE :: tol INTEGER(C_LONG), VALUE :: max_iter END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Take derivative ∂f∂x. !> !> @param[in] c The graph C context. !> @param[in] fnode The function expression to take the derivative of. !> @param[in] xnode The expression to take the derivative with respect to. !------------------------------------------------------------------------------- TYPE(C_PTR) FUNCTION graph_df(c, fnode, xnode) & BIND(C, NAME='graph_df') USE, INTRINSIC :: ISO_C_BINDING TYPE(C_PTR), VALUE :: c TYPE(C_PTR), VALUE :: fnode TYPE(C_PTR), VALUE :: xnode END FUNCTION END INTERFACE CONTAINS Loading Loading @@ -1868,4 +1961,107 @@ END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow item. !> !> @param[in,out] this @ref graph_context instance. !> @param[in] inputs Array of input nodes. !> @param[in] outputs Array of output nodes. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !------------------------------------------------------------------------------- SUBROUTINE graph_context_add_item(this, inputs, outputs, & map_inputs, map_outputs, & random_state, name, num_particles) IMPLICIT NONE ! Declare Arguments CLASS(graph_context), INTENT(INOUT) :: this INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: outputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_outputs TYPE(C_PTR), INTENT(IN) :: random_state CHARACTER(kind=C_CHAR,len=*), INTENT(IN) :: name INTEGER(C_LONG), INTENT(IN) :: num_particles ! Start of executable. CALL graph_add_item(this%c_context, & LOC(inputs), INT(SIZE(inputs), KIND=C_LONG), & LOC(outputs), INT(SIZE(outputs), KIND=C_LONG), & LOC(map_inputs), LOC(map_outputs), & INT(SIZE(map_inputs), KIND=C_LONG), & random_state, name, num_particles) END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Add workflow converge item. !> !> @param[in,out] this @ref graph_context instance. !> @param[in] inputs Array of input nodes. !> @param[in] outputs Array of output nodes. !> @param[in] map_inputs Array of map input nodes. !> @param[in] map_outputs Array of map output nodes. !> @param[in] random_state Optional random state, can be NULL if not used. !> @param[in] name Name for the kernel. !> @param[in] num_particles Number of elements to operate on. !------------------------------------------------------------------------------- SUBROUTINE graph_context_add_converge_item(this, inputs, outputs, & map_inputs, map_outputs, & random_state, name, & num_particles, tol, max_iter) IMPLICIT NONE ! Declare Arguments CLASS(graph_context), INTENT(INOUT) :: this INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: outputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_inputs INTEGER(C_INTPTR_T), DIMENSION(:), INTENT(IN) :: map_outputs TYPE(C_PTR), INTENT(IN) :: random_state CHARACTER(kind=C_CHAR,len=*), INTENT(IN) :: name INTEGER(C_LONG), INTENT(IN) :: num_particles REAL(C_DOUBLE), VALUE :: tol INTEGER(C_LONG), VALUE :: max_iter ! Start of executable. CALL graph_add_converge_item(this%c_context, LOC(inputs), & INT(SIZE(inputs), KIND=C_LONG), & LOC(outputs), & INT(SIZE(outputs), KIND=C_LONG), & LOC(map_inputs), LOC(map_outputs), & INT(SIZE(map_inputs), KIND=C_LONG), & random_state, name, num_particles, & tol, max_iter) END SUBROUTINE !------------------------------------------------------------------------------- !> @brief Take derivative ∂f∂x. !> !> @param[in,out] this @ref graph_context instance. !> @param[in] fnode The function expression to take the derivative of. !> @param[in] xnode The expression to take the derivative with respect to. !------------------------------------------------------------------------------- FUNCTION graph_context_df(this, fnode, xnode) IMPLICIT NONE ! Declare Arguments TYPE(C_PTR) :: graph_context_df CLASS(graph_context), INTENT(INOUT) :: this TYPE(C_PTR), INTENT(IN) :: fnode TYPE(C_PTR), INTENT(IN) :: xnode ! Start of executable. graph_context_df = graph_df(this%c_context, fnode, xnode) END FUNCTION END MODULE
graph_tests/f_binding_test.f90 +161 −21 Original line number Diff line number Diff line Loading @@ -75,6 +75,10 @@ REAL(C_FLOAT), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -86,6 +90,10 @@ REAL(C_FLOAT), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_float_context(use_safe_math) Loading @@ -105,6 +113,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -140,12 +153,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 'f_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading @@ -175,6 +210,10 @@ REAL(C_DOUBLE), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -186,6 +225,10 @@ REAL(C_DOUBLE), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_double_context(use_safe_math) Loading @@ -205,6 +248,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -240,12 +288,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 'f_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading @@ -275,6 +345,10 @@ COMPLEX(C_FLOAT_COMPLEX), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -286,6 +360,10 @@ COMPLEX(C_FLOAT_COMPLEX), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_complex_float_context(use_safe_math) Loading @@ -305,6 +383,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -344,12 +427,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading Loading @@ -379,6 +484,10 @@ COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(1) :: value TYPE(C_PTR) :: px TYPE(C_PTR) :: y TYPE(C_PTR) :: dydx TYPE(C_PTR) :: dydm TYPE(C_PTR) :: dydb TYPE(C_PTR) :: dydy TYPE(C_PTR) :: one TYPE(C_PTR) :: zero INTEGER(C_LONG) :: size Loading @@ -390,6 +499,10 @@ COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(3,3) :: buffer2D TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 TYPE(C_PTR) :: dz ! Start of executable code. graph => graph_complex_double_context(use_safe_math) Loading @@ -409,6 +522,11 @@ y = graph%add(graph%mul(m, x), b) dydx = graph%df(y, x); dydm = graph%df(y, m); dydb = graph%df(y, b); dydy = graph%df(y, y); one = graph%constant(1.0_C_DOUBLE) zero = graph%constant(0.0_C_DOUBLE) Loading Loading @@ -448,12 +566,34 @@ p2 = graph%piecewise_2D(i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & j, 1.0_C_DOUBLE, 0.0_C_DOUBLE, buffer2D) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & graph%pow(z, graph%constant(2.0_C_DOUBLE))) root2 = graph%mul(root, root) dz = graph%sub(z, graph%div(root, graph%df(root, z))) CALL graph%set_device_number(graph%get_max_concurrency() - 1) CALL graph%add_pre_item(graph_null_array, (/ graph_ptr(rand) /), & graph_null_array, graph_null_array, state, & 'c_binding_pre_kernel' // C_NULL_CHAR, & 'f_binding_pre_kernel' // C_NULL_CHAR, & 1_C_LONG) CALL graph%add_item((/ graph_ptr(x) /), (/ & graph_ptr(y), & graph_ptr(dydx), & graph_ptr(dydm), & graph_ptr(dydb), & graph_ptr(dydy) & /), graph_null_array, graph_null_array, C_NULL_PTR, & 'f_binding' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_item((/ graph_ptr(i), graph_ptr(j) /), & (/ graph_ptr(p1), graph_ptr(p2) /), & graph_null_array, graph_null_array, C_NULL_PTR, & 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) CALL graph%add_converge_item((/ graph_ptr(z) /), (/ graph_ptr(root2) /), & (/ graph_ptr(z) /), (/ graph_ptr(dz) /), & C_NULL_PTR, "f_binding_converge", 1_C_LONG, & 1.0E-30_C_DOUBLE, 1000_C_LONG) DEALLOCATE(graph) Loading