diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c98533de246bc302e60a49d6507fc527b9ed7dd..241020a5fe3bda6480394e065d2f5a4014ec3597 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,7 +212,6 @@ add_dependencies (llvm-offload-resource-headers pull_llvm) add_dependencies (LLVMDemangle pull_llvm) add_dependencies (Remarks_exports pull_llvm) add_dependencies (LLVMSupportBlake3 pull_llvm) -add_dependencies (BugpointPasses_exports pull_llvm) add_dependencies (LTO_exports pull_llvm) add_dependencies (llvm-PerfectShuffle pull_llvm) add_dependencies (SecondLib pull_llvm) diff --git a/README.md b/README.md index fffa38eb970db40a394c2d43d26004a242d39e57..29192d0be6becca419484dc81a8e74a213efe5bb 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,6 @@ For instructions to build the code consult the documentation. This framework uses a [cmake](https://cmake.org) based build system and requires the [NetCDF-C](https://www.unidata.ucar.edu/software/netcdf/) library. + +NOTE: macOS users will need to change the `CMAKE_CXX_COMPILER` to `clang++`. +Otherwise the framework will not set the includes correctly for CPU JIT. diff --git a/graph_c_binding/graph_c_binding.cpp b/graph_c_binding/graph_c_binding.cpp index 8da196f499df550fd8a2e1a2d6fad3555c0aff47..1076d0930f96037409ec9ebe38b0d702071b935e 100644 --- a/graph_c_binding/graph_c_binding.cpp +++ b/graph_c_binding/graph_c_binding.cpp @@ -1679,34 +1679,34 @@ extern "C" { //------------------------------------------------------------------------------ /// @brief Create a 1D index. /// -/// @param[in] c The graph C context. -/// @param[in] variable The variable to index. -/// @param[in] x_arg The function x argument. -/// @param[in] x_scale Scale factor x argument. -/// @param[in] x_offset Offset factor x argument. +/// @param[in] c The graph C context. +/// @param[in] variable The variable to index. +/// @param[in] arg The function x argument. +/// @param[in] scale Scale factor x argument. +/// @param[in] offset Offset factor x argument. /// @returns A 1D index node. //------------------------------------------------------------------------------ graph_node graph_index_1D(STRUCT_TAG graph_c_context *c, graph_node variable, - graph_node x_arg, - const double x_scale, - const double x_offset) { + graph_node arg, + const double scale, + const double offset) { switch (c->type) { case FLOAT: if (c->safe_math) { auto d = reinterpret_cast *> (c); auto temp = graph::index_1D(d->nodes[variable], - d->nodes[x_arg], - static_cast (x_scale), - static_cast (x_offset)); + d->nodes[arg], + static_cast (scale), + static_cast (offset)); d->nodes[temp.get()] = temp; return temp.get(); } else { auto d = reinterpret_cast *> (c); auto temp = graph::index_1D(d->nodes[variable], - d->nodes[x_arg], - static_cast (x_scale), - static_cast (x_offset)); + d->nodes[arg], + static_cast (scale), + static_cast (offset)); d->nodes[temp.get()] = temp; return temp.get(); } @@ -1715,15 +1715,15 @@ extern "C" { if (c->safe_math) { auto d = reinterpret_cast *> (c); auto temp = graph::index_1D(d->nodes[variable], - d->nodes[x_arg], - x_scale, x_offset); + d->nodes[arg], + scale, offset); d->nodes[temp.get()] = temp; return temp.get(); } else { auto d = reinterpret_cast *> (c); auto temp = graph::index_1D(d->nodes[variable], - d->nodes[x_arg], - x_scale, x_offset); + d->nodes[arg], + scale, offset); d->nodes[temp.get()] = temp; return temp.get(); } @@ -1732,36 +1732,154 @@ extern "C" { if (c->safe_math) { auto d = reinterpret_cast, true> *> (c); auto temp = graph::index_1D(d->nodes[variable], + d->nodes[arg], + std::complex (scale), + std::complex (offset)); + d->nodes[temp.get()] = temp; + return temp.get(); + } else { + auto d = reinterpret_cast> *> (c); + auto temp = graph::index_1D(d->nodes[variable], + d->nodes[arg], + std::complex (scale), + std::complex (offset)); + d->nodes[temp.get()] = temp; + return temp.get(); + } + + case COMPLEX_DOUBLE: + if (c->safe_math) { + auto d = reinterpret_cast, true> *> (c); + auto temp = graph::index_1D(d->nodes[variable], + d->nodes[arg], + std::complex (scale), + std::complex (offset)); + d->nodes[temp.get()] = temp; + return temp.get(); + } else { + auto d = reinterpret_cast> *> (c); + auto temp = graph::index_1D(d->nodes[variable], + d->nodes[arg], + std::complex (scale), + std::complex (offset)); + d->nodes[temp.get()] = temp; + return temp.get(); + } + } + } + +//------------------------------------------------------------------------------ +/// @brief Create a 2D index. +/// +/// @param[in] c The graph C context. +/// @param[in] variable The variable to index. +/// @param[in] num_cols Number of columns. +/// @param[in] x_arg The function x argument. +/// @param[in] x_scale Scale factor x argument. +/// @param[in] x_offset Offset factor x argument. +/// @param[in] y_arg The function y argument. +/// @param[in] y_scale Scale factor y argument. +/// @param[in] y_offset Offset factor y argument. +/// @returns A 2D index node. +//------------------------------------------------------------------------------ + graph_node graph_index_2D(STRUCT_TAG graph_c_context *c, + graph_node variable, + const size_t num_cols, + graph_node x_arg, + const double x_scale, + const double x_offset, + graph_node y_arg, + const double y_scale, + const double y_offset) { + switch (c->type) { + case FLOAT: + if (c->safe_math) { + auto d = reinterpret_cast *> (c); + auto temp = graph::index_2D(d->nodes[variable], num_cols, + d->nodes[x_arg], + static_cast (x_scale), + static_cast (x_offset), + d->nodes[y_arg], + static_cast (y_scale), + static_cast (y_offset)); + d->nodes[temp.get()] = temp; + return temp.get(); + } else { + auto d = reinterpret_cast *> (c); + auto temp = graph::index_2D(d->nodes[variable], num_cols, + d->nodes[x_arg], + static_cast (x_scale), + static_cast (x_offset), + d->nodes[y_arg], + static_cast (y_scale), + static_cast (y_offset)); + d->nodes[temp.get()] = temp; + return temp.get(); + } + + case DOUBLE: + if (c->safe_math) { + auto d = reinterpret_cast *> (c); + auto temp = graph::index_2D(d->nodes[variable], num_cols, + d->nodes[x_arg], y_scale, y_offset, + d->nodes[y_arg], y_scale, y_offset); + d->nodes[temp.get()] = temp; + return temp.get(); + } else { + auto d = reinterpret_cast *> (c); + auto temp = graph::index_2D(d->nodes[variable], num_cols, + d->nodes[x_arg], y_scale, y_offset, + d->nodes[y_arg], y_scale, y_offset); + d->nodes[temp.get()] = temp; + return temp.get(); + } + + case COMPLEX_FLOAT: + if (c->safe_math) { + auto d = reinterpret_cast, true> *> (c); + auto temp = graph::index_2D(d->nodes[variable], num_cols, d->nodes[x_arg], std::complex (x_scale), - std::complex (x_offset)); + std::complex (x_offset), + d->nodes[y_arg], + std::complex (y_scale), + std::complex (y_offset)); d->nodes[temp.get()] = temp; return temp.get(); } else { auto d = reinterpret_cast> *> (c); - auto temp = graph::index_1D(d->nodes[variable], + auto temp = graph::index_2D(d->nodes[variable], num_cols, d->nodes[x_arg], std::complex (x_scale), - std::complex (x_offset)); + std::complex (x_offset), + d->nodes[y_arg], + std::complex (y_scale), + std::complex (y_offset)); d->nodes[temp.get()] = temp; return temp.get(); } - + case COMPLEX_DOUBLE: if (c->safe_math) { auto d = reinterpret_cast, true> *> (c); - auto temp = graph::index_1D(d->nodes[variable], + auto temp = graph::index_2D(d->nodes[variable], num_cols, d->nodes[x_arg], std::complex (x_scale), - std::complex (x_offset)); + std::complex (x_offset), + d->nodes[y_arg], + std::complex (y_scale), + std::complex (y_offset)); d->nodes[temp.get()] = temp; return temp.get(); } else { auto d = reinterpret_cast> *> (c); - auto temp = graph::index_1D(d->nodes[variable], + auto temp = graph::index_2D(d->nodes[variable], num_cols, d->nodes[x_arg], std::complex (x_scale), - std::complex (x_offset)); + std::complex (x_offset), + d->nodes[y_arg], + std::complex (y_scale), + std::complex (y_offset)); d->nodes[temp.get()] = temp; return temp.get(); } diff --git a/graph_c_binding/graph_c_binding.h b/graph_c_binding/graph_c_binding.h index 39c56588da6122e98e63ee0b74059271143e9cff..49a27b5f9d75d9bd4429aa1d9e74f446616c36de 100644 --- a/graph_c_binding/graph_c_binding.h +++ b/graph_c_binding/graph_c_binding.h @@ -448,18 +448,42 @@ extern "C" { //------------------------------------------------------------------------------ /// @brief Create a 1D index. /// -/// @param[in] c The graph C context. -/// @param[in] variable The variable to index. -/// @param[in] x_arg The function x argument. -/// @param[in] x_scale Scale factor x argument. -/// @param[in] x_offset Offset factor x argument. +/// @param[in] c The graph C context. +/// @param[in] variable The variable to index. +/// @param[in] arg The function argument. +/// @param[in] scale Scale factor argument. +/// @param[in] offset Offset factor argument. /// @returns A 1D index node. //------------------------------------------------------------------------------ graph_node graph_index_1D(STRUCT_TAG graph_c_context *c, graph_node variable, + graph_node arg, + const double scale, + const double offset); + +//------------------------------------------------------------------------------ +/// @brief Create a 2D index. +/// +/// @param[in] c The graph C context. +/// @param[in] variable The variable to index. +/// @param[in] num_cols Number of columns. +/// @param[in] x_arg The function x argument. +/// @param[in] x_scale Scale factor x argument. +/// @param[in] x_offset Offset factor x argument. +/// @param[in] y_arg The function y argument. +/// @param[in] y_scale Scale factor y argument. +/// @param[in] y_offset Offset factor y argument. +/// @returns A 2D index node. +//------------------------------------------------------------------------------ + graph_node graph_index_2D(STRUCT_TAG graph_c_context *c, + graph_node variable, + const size_t num_cols, graph_node x_arg, const double x_scale, - const double x_offset); + const double x_offset, + graph_node y_arg, + const double y_scale, + const double y_offset); //------------------------------------------------------------------------------ /// @brief Create 2D piecewise node with complex arguments. diff --git a/graph_driver/xrays.cpp b/graph_driver/xrays.cpp index 3b5808c8cd37830398c7ef4cf07150e715d1cb6d..cb8ec2de07f3d4ef514714b6e0732e585bf77981 100644 --- a/graph_driver/xrays.cpp +++ b/graph_driver/xrays.cpp @@ -21,7 +21,7 @@ /// @param[in] mean Mean value. /// @param[in] sigma Sigma value. //------------------------------------------------------------------------------ -template +template std::normal_distribution set_distribution(const T mean, const T sigma) { return std::normal_distribution (mean, sigma); @@ -35,7 +35,7 @@ std::normal_distribution set_distribution(const T mean, /// @param[in] mean Mean value. /// @param[in] sigma Sigma value. //------------------------------------------------------------------------------ -template +template std::normal_distribution> set_distribution(const std::complex mean, const std::complex sigma) { return std::normal_distribution (std::real(mean), std::real(sigma)); @@ -53,7 +53,7 @@ std::normal_distribution> set_distribution(const std::complex /// @param[in,out] engine Random engine. /// @param[in] num_rays Numbers of rays. //------------------------------------------------------------------------------ -template +template void set_variable(const commandline::parser &cl, graph::shared_leaf var, const std::string &name, @@ -82,7 +82,7 @@ void set_variable(const commandline::parser &cl, /// @param[in,out] engine Random engine. /// @param[in] num_rays Numbers of rays. //------------------------------------------------------------------------------ -template +template void set_xy_variables(const commandline::parser &cl, graph::shared_leaf x, graph::shared_leaf y, diff --git a/graph_fortran_binding/graph_fortran_binding.f90 b/graph_fortran_binding/graph_fortran_binding.f90 index de9c3f459ff9ef2ba42b8381e0243e8753f7054c..bc5d7c63066726895cbd8781d11812ff07583c59 100644 --- a/graph_fortran_binding/graph_fortran_binding.f90 +++ b/graph_fortran_binding/graph_fortran_binding.f90 @@ -146,6 +146,7 @@ piecewise_2D_cfloat, & piecewise_2D_cdouble PROCEDURE :: index_1D => graph_context_index_1D + PROCEDURE :: index_2D => graph_context_index_2D 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 @@ -665,11 +666,42 @@ BIND(C, NAME='graph_index_1D') USE, INTRINSIC :: ISO_C_BINDING IMPLICIT NONE - TYPE(C_PTR), VALUE :: c - TYPE(C_PTR), VALUE :: variable - TYPE(C_PTR), VALUE :: arg - REAL(C_DOUBLE), VALUE :: scale - REAL(C_DOUBLE), VALUE :: offset + TYPE(C_PTR), VALUE :: c + TYPE(C_PTR), VALUE :: variable + TYPE(C_PTR), VALUE :: arg + REAL(C_DOUBLE), VALUE :: scale + REAL(C_DOUBLE), VALUE :: offset + END FUNCTION + +!------------------------------------------------------------------------------- +!> @brief Create 2D index node. +!> +!> @param[in] c The graph C context. +!> @param[in] variable The variable to index. +!> @param[in] num_cols Number of columns. +!> @param[in] x_arg The function x argument. +!> @param[in] x_scale Scale factor x argument. +!> @param[in] x_offset Offset factor x argument. +!> @param[in] y_arg The function y argument. +!> @param[in] y_scale Scale factor y argument. +!> @param[in] y_offset Offset factor y argument. +!> @returns A 2D piecewise node. +!------------------------------------------------------------------------------- + TYPE(C_PTR) FUNCTION graph_index_2D(c, variable, num_cols, & + x_arg, x_scale, x_offset, & + y_arg, y_scale, y_offset) & + BIND(C, NAME='graph_index_2D') + USE, INTRINSIC :: ISO_C_BINDING + IMPLICIT NONE + TYPE(C_PTR), VALUE :: c + TYPE(C_PTR), VALUE :: variable + INTEGER(C_LONG), VALUE :: num_cols + TYPE(C_PTR), VALUE :: x_arg + REAL(C_DOUBLE), VALUE :: x_scale + REAL(C_DOUBLE), VALUE :: x_offset + TYPE(C_PTR), VALUE :: y_arg + REAL(C_DOUBLE), VALUE :: y_scale + REAL(C_DOUBLE), VALUE :: y_offset END FUNCTION !------------------------------------------------------------------------------- @@ -1613,12 +1645,12 @@ IMPLICIT NONE ! Declare Arguments - TYPE(C_PTR) :: graph_context_piecewise_1D_float - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: arg - REAL(C_DOUBLE) :: scale - REAL(C_DOUBLE) :: offset - REAL(C_FLOAT), DIMENSION(:) :: source + TYPE(C_PTR) :: graph_context_piecewise_1D_float + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: arg + REAL(C_DOUBLE), INTENT(IN) :: scale + REAL(C_DOUBLE), INTENT(IN) :: offset + REAL(C_FLOAT), DIMENSION(:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_1D_float = & @@ -1643,12 +1675,12 @@ IMPLICIT NONE ! Declare Arguments - TYPE(C_PTR) :: graph_context_piecewise_1D_double - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: arg - REAL(C_DOUBLE) :: scale - REAL(C_DOUBLE) :: offset - REAL(C_DOUBLE), DIMENSION(:) :: source + TYPE(C_PTR) :: graph_context_piecewise_1D_double + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: arg + REAL(C_DOUBLE), INTENT(IN) :: scale + REAL(C_DOUBLE), INTENT(IN) :: offset + REAL(C_DOUBLE), DIMENSION(:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_1D_double = & @@ -1674,11 +1706,11 @@ ! Declare Arguments TYPE(C_PTR) :: graph_context_piecewise_1D_cfloat - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: arg - REAL(C_DOUBLE) :: scale - REAL(C_DOUBLE) :: offset - COMPLEX(C_FLOAT_COMPLEX), DIMENSION(:) :: source + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: arg + REAL(C_DOUBLE), INTENT(IN) :: scale + REAL(C_DOUBLE), INTENT(IN) :: offset + COMPLEX(C_FLOAT_COMPLEX), DIMENSION(:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_1D_cfloat = & @@ -1704,11 +1736,11 @@ ! Declare Arguments TYPE(C_PTR) :: graph_context_piecewise_1D_cdouble - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: arg - REAL(C_DOUBLE) :: scale - REAL(C_DOUBLE) :: offset - COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(:) :: source + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: arg + REAL(C_DOUBLE), INTENT(IN) :: scale + REAL(C_DOUBLE), INTENT(IN) :: offset + COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_1D_cdouble = & @@ -1739,14 +1771,14 @@ ! Declare Arguments TYPE(C_PTR) :: graph_context_piecewise_2D_float - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: x_arg - REAL(C_DOUBLE) :: x_scale - REAL(C_DOUBLE) :: x_offset - TYPE(C_PTR), INTENT(IN) :: y_arg - REAL(C_DOUBLE) :: y_scale - REAL(C_DOUBLE) :: y_offset - REAL(C_FLOAT), DIMENSION(:,:) :: source + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: x_arg + REAL(C_DOUBLE), INTENT(IN) :: x_scale + REAL(C_DOUBLE), INTENT(IN) :: x_offset + TYPE(C_PTR), INTENT(IN) :: y_arg + REAL(C_DOUBLE), INTENT(IN) :: y_scale + REAL(C_DOUBLE), INTENT(IN) :: y_offset + REAL(C_FLOAT), DIMENSION(:,:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_2D_float = & @@ -1780,14 +1812,14 @@ ! Declare Arguments TYPE(C_PTR) :: graph_context_piecewise_2D_double - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: x_arg - REAL(C_DOUBLE) :: x_scale - REAL(C_DOUBLE) :: x_offset - TYPE(C_PTR), INTENT(IN) :: y_arg - REAL(C_DOUBLE) :: y_scale - REAL(C_DOUBLE) :: y_offset - REAL(C_DOUBLE), DIMENSION(:,:) :: source + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: x_arg + REAL(C_DOUBLE), INTENT(IN) :: x_scale + REAL(C_DOUBLE), INTENT(IN) :: x_offset + TYPE(C_PTR), INTENT(IN) :: y_arg + REAL(C_DOUBLE), INTENT(IN) :: y_scale + REAL(C_DOUBLE), INTENT(IN) :: y_offset + REAL(C_DOUBLE), DIMENSION(:,:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_2D_double = & @@ -1821,14 +1853,14 @@ ! Declare Arguments TYPE(C_PTR) :: graph_context_piecewise_2D_cfloat - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: x_arg - REAL(C_DOUBLE) :: x_scale - REAL(C_DOUBLE) :: x_offset - TYPE(C_PTR), INTENT(IN) :: y_arg - REAL(C_DOUBLE) :: y_scale - REAL(C_DOUBLE) :: y_offset - COMPLEX(C_FLOAT_COMPLEX), DIMENSION(:,:) :: source + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: x_arg + REAL(C_DOUBLE), INTENT(IN) :: x_scale + REAL(C_DOUBLE), INTENT(IN) :: x_offset + TYPE(C_PTR), INTENT(IN) :: y_arg + REAL(C_DOUBLE), INTENT(IN) :: y_scale + REAL(C_DOUBLE), INTENT(IN) :: y_offset + COMPLEX(C_FLOAT_COMPLEX), DIMENSION(:,:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_2D_cfloat = & @@ -1862,14 +1894,14 @@ ! Declare Arguments TYPE(C_PTR) :: graph_context_piecewise_2D_cdouble - CLASS(graph_context), INTENT(INOUT) :: this - TYPE(C_PTR), INTENT(IN) :: x_arg - REAL(C_DOUBLE) :: x_scale - REAL(C_DOUBLE) :: x_offset - TYPE(C_PTR), INTENT(IN) :: y_arg - REAL(C_DOUBLE) :: y_scale - REAL(C_DOUBLE) :: y_offset - COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(:,:) :: source + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: x_arg + REAL(C_DOUBLE), INTENT(IN) :: x_scale + REAL(C_DOUBLE), INTENT(IN) :: x_offset + TYPE(C_PTR), INTENT(IN) :: y_arg + REAL(C_DOUBLE), INTENT(IN) :: y_scale + REAL(C_DOUBLE), INTENT(IN) :: y_offset + COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(:,:), INTENT(IN) :: source ! Start of executable. graph_context_piecewise_2D_cdouble = & @@ -1900,8 +1932,8 @@ CLASS(graph_context), INTENT(INOUT) :: this TYPE(C_PTR), INTENT(IN) :: variable TYPE(C_PTR), INTENT(IN) :: arg - REAL(C_DOUBLE) :: scale - REAL(C_DOUBLE) :: offset + REAL(C_DOUBLE), INTENT(IN) :: scale + REAL(C_DOUBLE), INTENT(IN) :: offset ! Start of executable. graph_context_index_1D = & @@ -1909,6 +1941,45 @@ END FUNCTION +!------------------------------------------------------------------------------- +!> @brief Create 2D index node with float buffer. +!> +!> @param[in,out] this @ref graph_context instance. +!> @param[in] variable The variable +!> @param[in] num_cols Number of columns. +!> @param[in] x_arg The function x argument. +!> @param[in] x_scale Scale factor for x argument. +!> @param[in] x_offset Offset factor for x argument. +!> @param[in] y_arg The function y argument. +!> @param[in] y_scale Scale factor for y argument. +!> @param[in] y_offset Offset factor for y argument. +!> @returns index_1D node. +!------------------------------------------------------------------------------- + FUNCTION graph_context_index_2D(this, variable, num_cols, & + x_arg, x_scale, x_offset, & + y_arg, y_scale, y_offset) + + IMPLICIT NONE + +! Declare Arguments + TYPE(C_PTR) :: graph_context_index_2D + CLASS(graph_context), INTENT(INOUT) :: this + TYPE(C_PTR), INTENT(IN) :: variable + INTEGER(C_LONG), INTENT(IN) :: num_cols + TYPE(C_PTR), INTENT(IN) :: x_arg + REAL(C_DOUBLE), INTENT(IN) :: x_scale + REAL(C_DOUBLE), INTENT(IN) :: x_offset + TYPE(C_PTR), INTENT(IN) :: y_arg + REAL(C_DOUBLE), INTENT(IN) :: y_scale + REAL(C_DOUBLE), INTENT(IN) :: y_offset + +! Start of executable. + graph_context_index_2D = & + graph_index_2D(this%c_context, variable, num_cols, & + x_arg, x_scale, x_offset, y_arg, y_scale, y_offset) + + END FUNCTION + !******************************************************************************* ! JIT !******************************************************************************* @@ -1923,7 +1994,7 @@ IMPLICIT NONE ! Declare Arguments - INTEGER(C_LONG) :: graph_context_get_max_concurrency + INTEGER(C_LONG) :: graph_context_get_max_concurrency CLASS(graph_context), INTENT(IN) :: this ! Start of executable. @@ -2057,8 +2128,8 @@ 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 + REAL(C_DOUBLE), INTENT(IN) :: tol + INTEGER(C_LONG), INTENT(IN) :: max_iter ! Start of executable. CALL graph_add_converge_item(this%c_context, LOC(inputs), & @@ -2259,7 +2330,7 @@ ! Declare Arguments CLASS(graph_context), INTENT(IN) :: this - TYPE(C_PTR), VALUE :: node + TYPE(C_PTR), INTENT(IN) :: node REAL(C_FLOAT), DIMENSION(:), INTENT(INOUT) :: destination ! Start of executable. @@ -2280,7 +2351,7 @@ ! Declare Arguments CLASS(graph_context), INTENT(IN) :: this - TYPE(C_PTR), VALUE :: node + TYPE(C_PTR), INTENT(IN) :: node REAL(C_DOUBLE), DIMENSION(:), INTENT(INOUT) :: destination ! Start of executable. @@ -2301,7 +2372,7 @@ ! Declare Arguments CLASS(graph_context), INTENT(IN) :: this - TYPE(C_PTR), VALUE :: node + TYPE(C_PTR), INTENT(IN) :: node COMPLEX(C_FLOAT_COMPLEX), DIMENSION(:), INTENT(INOUT) :: destination ! Start of executable. @@ -2322,7 +2393,7 @@ ! Declare Arguments CLASS(graph_context), INTENT(IN) :: this - TYPE(C_PTR), VALUE :: node + TYPE(C_PTR), INTENT(IN) :: node COMPLEX(C_DOUBLE_COMPLEX), DIMENSION(:), INTENT(INOUT) :: destination ! Start of executable. diff --git a/graph_framework/node.hpp b/graph_framework/node.hpp index 9e675db406a1f43f142f5c66e289e6aa473c70f7..7add76fda6a3d765e411ac51403c41138fe1780d 100644 --- a/graph_framework/node.hpp +++ b/graph_framework/node.hpp @@ -405,7 +405,9 @@ namespace graph { /// /// @returns A reduced representation of the node. //------------------------------------------------------------------------------ - virtual std::shared_ptr reduce() = 0; + virtual std::shared_ptr> reduce() { + return this->shared_from_this(); + } //------------------------------------------------------------------------------ /// @brief Transform node to derivative. @@ -759,17 +761,6 @@ namespace graph { return data; } -//------------------------------------------------------------------------------ -/// @brief Reduction method. -/// -/// For basic nodes, there's nothing to reduce. -/// -/// @returns A reduced representation of the node. -//------------------------------------------------------------------------------ - virtual shared_leaf reduce() { - return this->shared_from_this(); - } - //------------------------------------------------------------------------------ /// @brief Transform node to derivative. /// @@ -1470,17 +1461,6 @@ namespace graph { return buffer; } -//------------------------------------------------------------------------------ -/// @brief Reduction method. -/// -/// For basic nodes, there's nothing to reduce. -/// -/// @returns A reduced representation of the node. -//------------------------------------------------------------------------------ - virtual shared_leaf reduce() { - return this->shared_from_this(); - } - //------------------------------------------------------------------------------ /// @brief Transform node to derivative. /// @@ -1783,17 +1763,6 @@ namespace graph { pseudo_variable_node(shared_leaf a) : straight_node (a, pseudo_variable_node::to_string(a.get())) {} -//------------------------------------------------------------------------------ -/// @brief Reduction method. -/// -/// For basic nodes, there's nothing to reduce. -/// -/// @returns A reduced representation of the node. -//------------------------------------------------------------------------------ - virtual shared_leaf reduce() { - return this->shared_from_this(); - } - //------------------------------------------------------------------------------ /// @brief Transform node to derivative. /// diff --git a/graph_framework/piecewise.hpp b/graph_framework/piecewise.hpp index f5960a22a3902eaa4fe38ddb077de293511dbc41..b38585349f7217f1ba85b958525ad8617d4f31d5 100644 --- a/graph_framework/piecewise.hpp +++ b/graph_framework/piecewise.hpp @@ -1039,7 +1039,6 @@ void compile_index(std::ostringstream &stream, ) { if (indices.find(temp.get()) == indices.end()) { indices[temp.get()] = jit::to_string('i', temp.get()); - const size_t length = leaf_node::caches.backends[data_hash].size(); stream << " const " << jit::smallest_int_type (length) << " " << indices[temp.get()] << " = " @@ -1421,18 +1420,6 @@ void compile_index(std::ostringstream &stream, return this->right->evaluate(); } -//------------------------------------------------------------------------------ -/// @brief Reduction method. -/// -/// If all the values in the data buffer are the same. Reduce to a single -/// constant. -/// -/// @returns A reduced representation of the node. -//------------------------------------------------------------------------------ - virtual shared_leaf reduce() { - return this->shared_from_this(); - } - //------------------------------------------------------------------------------ /// @brief Transform node to derivative. /// @@ -1615,7 +1602,7 @@ void compile_index(std::ostringstream &stream, /// @returns The size of the buffer. //------------------------------------------------------------------------------ size_t get_size() const { - return this->left->size(); + return variable_cast(this->left)->size(); } }; @@ -1636,7 +1623,8 @@ void compile_index(std::ostringstream &stream, shared_leaf x, const T scale, const T offset) { - assert(variable_cast(v) && "index_1D requires a variable node for first arg."); + assert(variable_cast(v).get() && + "index_1D requires a variable node for first arg."); auto temp = std::make_shared> (v, x, scale, offset)->reduce(); @@ -1657,12 +1645,12 @@ void compile_index(std::ostringstream &stream, #endif } -/// Convenience type alias for shared piecewise 1D nodes. +/// Convenience type alias for shared index 1D nodes. template using shared_index_1D = std::shared_ptr>; //------------------------------------------------------------------------------ -/// @brief Cast to a piecewise 1D node. +/// @brief Cast to a index 1D node. /// /// @tparam T Base type of the calculation. /// @tparam SAFE_MATH Use @ref general_concepts_safe_math operations. @@ -1674,6 +1662,401 @@ void compile_index(std::ostringstream &stream, shared_index_1D index_1D_cast(shared_leaf x) { return std::dynamic_pointer_cast> (x); } + +//****************************************************************************** +// 2D Index node. +//****************************************************************************** +//------------------------------------------------------------------------------ +/// @brief Class representing a 2D index. +/// +/// This class is used to implement 2D indexes into an array. +/// +/// Indicies are selected by +/// +/// x_norm' = (x - xmin)/dx (1) +/// y_norm' = (y - ymin)/dy (2) +/// +/// @tparam T Base type of the calculation. +/// @tparam SAFE_MATH Use @ref general_concepts_safe_math operations. +//------------------------------------------------------------------------------ + template + class index_2D_node final : public triple_node { + private: +/// Scale factor for the x argument. + const T x_scale; +/// Offset factor for the x argument. + const T x_offset; +/// Scale factor for the y argument. + const T y_scale; +/// Offset factor for the y argument. + const T y_offset; +/// Number of columns. + const size_t num_columns; + +//------------------------------------------------------------------------------ +/// @brief Convert node pointer to a string with the argument. +/// +/// @param[in] v Value to index. +/// @param[in] x Argument. +/// @param[in] y Argument. +/// @return A string rep of the node. +//------------------------------------------------------------------------------ + static std::string to_string(shared_leaf v, + shared_leaf x, + shared_leaf y) { + return jit::format_to_string(v->get_hash()) + "[" + + jit::format_to_string(x->get_hash()) + "," + + jit::format_to_string(y->get_hash()) + "]"; + } + + public: +//------------------------------------------------------------------------------ +/// @brief Construct a 2D index. +/// +/// @param[in] var Node to index. +/// @param[in] n Number of columns. +/// @param[in] x X Argument. +/// @param[in] x_scale Scale factor for the argument. +/// @param[in] x_offset Offset factor for the x argument. +/// @param[in] y Y Argument. +/// @param[in] y_scale Scale factor for the y argument. +/// @param[in] y_offset Offset factor for the y argument. +//------------------------------------------------------------------------------ + index_2D_node(shared_leaf var, + const size_t n, + shared_leaf x, + const T x_scale, + const T x_offset, + shared_leaf y, + const T y_scale, + const T y_offset) : + triple_node (var, x, y, index_2D_node::to_string(var, x, y)), + num_columns(n), x_scale(x_scale), x_offset(x_offset), y_scale(y_scale), + y_offset(y_offset) { + assert(variable_cast(this->left)->size()%n == 0 && + "Expected the data buffer to be a multiple of the number of columns."); + } + +//------------------------------------------------------------------------------ +/// @brief Evaluate the results of the piecewise constant. +/// +/// Evaluate functions are only used by the minimization. So this node does not +/// evaluate the argument. Instead this only returns the data as if it were a +/// constant. +/// +/// @returns The evaluated value of the node. +//------------------------------------------------------------------------------ + virtual backend::buffer evaluate() { + return this->left->evaluate(); + } + +//------------------------------------------------------------------------------ +/// @brief Transform node to derivative. +/// +/// @param[in] x The variable to take the derivative to. +/// @return The derivative of the node. +//------------------------------------------------------------------------------ + virtual shared_leaf df(shared_leaf x) { + return constant (static_cast (this->is_match(x))); + } + +//------------------------------------------------------------------------------ +/// @brief the node. +/// +/// This node first evaluates the value of the argument then chooses the +/// correct index of the variable. +/// +/// x' = (x - xmin)/dx (1) +/// y' = (y - ymin)/dy (2) +/// +/// @param[in,out] stream String buffer stream. +/// @param[in,out] registers List of defined registers. +/// @param[in,out] indices List of defined indices. +/// @param[in] usage List of register usage count. +/// @returns The current node. +//------------------------------------------------------------------------------ + virtual shared_leaf + compile(std::ostringstream &stream, + jit::register_map ®isters, + jit::register_map &indices, + const jit::register_usage &usage) { + if (registers.find(this) == registers.end()) { + const size_t length = variable_cast(this->left)->size(); + const size_t num_rows = length/num_columns; + + shared_leaf x = this->middle->compile(stream, + registers, + indices, + usage); + shared_leaf y = this->right->compile(stream, + registers, + indices, + usage); + +#ifdef USE_INDEX_CACHE + if (indices.find(x.get()) == indices.end()) { + indices[x.get()] = jit::to_string('i', x.get()); + stream << " const " + << jit::smallest_int_type (num_rows) << " " + << indices[x.get()] << " = "; + compile_index (stream, registers[x.get()], num_rows, + x_scale, x_offset); + x->endline(stream, usage); + } + if (indices.find(y.get()) == indices.end()) { + indices[y.get()] = jit::to_string('i', y.get()); + stream << " const " + << jit::smallest_int_type (num_columns) << " " + << indices[y.get()] << " = "; + compile_index (stream, registers[y.get()], num_columns, + y_scale, y_offset); + y->endline(stream, usage); + } + + auto temp = this->middle + this->right; + if constexpr (!jit::use_metal () || + !jit::use_cuda()) { + if (indices.find(temp.get()) == indices.end()) { + indices[temp.get()] = jit::to_string('i', temp.get()); + stream << " const " + << jit::smallest_int_type (length) << " " + << indices[temp.get()] << " = " + << indices[x.get()] + << "*" << num_columns << " + " + << indices[y.get()] + << ";" << std::endl; + } + } +#endif + + registers[this] = jit::to_string('r', this); + stream << " const "; + jit::add_type (stream); + auto var = this->left->compile(stream, + registers, + indices, + usage); + stream << " " << registers[this] << " = " + << jit::to_string('v', var.get()); +#ifdef USE_INDEX_CACHE + stream << "[" + << indices[temp.get()] + << "]"; +#else + stream << "["; + compile_index (stream, registers[x.get()], num_rows, + x_scale, x_offset); + stream << "*" << num_columns << " + "; + compile_index (stream, registers[y.get()], num_columns, + y_scale, y_offset); + stream << "]"; +#endif + this->endline(stream, usage); + } + + return this->shared_from_this(); + } + +//------------------------------------------------------------------------------ +/// @brief Convert the node to latex. +//------------------------------------------------------------------------------ + virtual void to_latex() const { + std::cout << "r\\_" << reinterpret_cast (this->left.get()) + << "\\left[i\\_" + << reinterpret_cast (this->middle.get()) + << ",j\\_" + << reinterpret_cast (this->right.get()) + << "\\right]"; + } + +//------------------------------------------------------------------------------ +/// @brief Convert the node to vizgraph. +/// +/// @param[in,out] stream String buffer stream. +/// @param[in,out] registers List of defined registers. +/// @returns The current node. +//------------------------------------------------------------------------------ + virtual shared_leaf to_vizgraph(std::stringstream &stream, + jit::register_map ®isters) { + if (registers.find(this) == registers.end()) { + const std::string name = jit::to_string('r', this); + registers[this] = name; + stream << " " << name + << " [label = \"r_" << reinterpret_cast (this->left.get()) + << "\", shape = hexagon, style = filled, fillcolor = black, fontcolor = white];" << std::endl; + + auto l = this->left->to_vizgraph(stream, registers); + stream << " " << name << " -- " << registers[l.get()] << ";" << std::endl; + auto m = this->middle->to_vizgraph(stream, registers); + stream << " " << name << " -- " << registers[m.get()] << ";" << std::endl; + auto r = this->right->to_vizgraph(stream, registers); + stream << " " << name << " -- " << registers[r.get()] << ";" << std::endl; + } + + return this->shared_from_this(); + } + +//------------------------------------------------------------------------------ +/// @brief Test if node is a constant. +/// +/// @returns True if the node is a constant. +//------------------------------------------------------------------------------ + virtual bool is_constant() const { + return false; + } + +//------------------------------------------------------------------------------ +/// @brief Test if node acts like a variable. +/// +/// @returns True if the node acts like a variable. +//------------------------------------------------------------------------------ + virtual bool is_all_variables() const { + return false; + } + +//------------------------------------------------------------------------------ +/// @brief Test if the node acts like a power of variable. +/// +/// @returns True. +//------------------------------------------------------------------------------ + virtual bool is_power_like() const { + return true; + } + +//------------------------------------------------------------------------------ +/// @brief Get the exponent of a power. +/// +/// @returns The exponent of a power like node. +//------------------------------------------------------------------------------ + virtual shared_leaf get_power_exponent() const { + return one (); + } + +//------------------------------------------------------------------------------ +/// @brief Check if the args match. +/// +/// @param[in] x Node to match. +/// @returns True if the arguments match. +//------------------------------------------------------------------------------ + bool is_arg_match(shared_leaf x) { + auto temp = index_1D_cast(x); + return temp.get() && + this->right->is_match(temp->get_right()) && + (temp->get_size() == this->get_size()) && + (temp->get_scale() == this->scale) && + (temp->get_offset() == this->offset); + } + +//------------------------------------------------------------------------------ +/// @brief Get x argument scale. +/// +/// @returns The scale factor for x. +//------------------------------------------------------------------------------ + T get_x_scale() const { + return x_scale; + } + +//------------------------------------------------------------------------------ +/// @brief Get x argument offset. +/// +/// @returns The offset factor for x. +//------------------------------------------------------------------------------ + T get_x_offset() const { + return x_offset; + } + +//------------------------------------------------------------------------------ +/// @brief Get y argument scale. +/// +/// @returns The scale factor for y. +//------------------------------------------------------------------------------ + T get_y_scale() const { + return y_scale; + } + +//------------------------------------------------------------------------------ +/// @brief Get y argument offset. +/// +/// @returns The offset factor for x. +//------------------------------------------------------------------------------ + T get_y_offset() const { + return y_offset; + } + +//------------------------------------------------------------------------------ +/// @brief Get the size of the buffer. +/// +/// @returns The size of the buffer. +//------------------------------------------------------------------------------ + size_t get_size() const { + return variable_cast(this->left)->size(); + } + }; + +//------------------------------------------------------------------------------ +/// @brief Define index_2D convenience function. +/// +/// @tparam T Base type of the calculation. +/// @tparam SAFE_MATH Use @ref general_concepts_safe_math operations. +/// +/// @param[in] v Variable to index. +/// @param[in] n Number of columns. +/// @param[in] x X argument. +/// @param[in] x_scale Scale for x argument. +/// @param[in] x_offset Offset for x argument. +/// @param[in] y Argument. +/// @param[in] y_scale Scale for y argument. +/// @param[in] y_offset Offset for y argument. +/// @returns A reduced sqrt node. +//------------------------------------------------------------------------------ + template + shared_leaf index_2D(shared_leaf v, + const size_t n, + shared_leaf x, + const T x_scale, + const T x_offset, + shared_leaf y, + const T y_scale, + const T y_offset) { + assert(variable_cast(v).get() && + "index_2D requires a variable node for first arg."); + auto temp = std::make_shared> (v, n, + x, x_scale, x_offset, + y, y_scale, y_offset)->reduce(); +// Test for hash collisions. + for (size_t i = temp->get_hash(); i < std::numeric_limits::max(); i++) { + if (leaf_node::caches.nodes.find(i) == + leaf_node::caches.nodes.end()) { + leaf_node::caches.nodes[i] = temp; + return temp; + } else if (temp->is_match(leaf_node::caches.nodes[i])) { + return leaf_node::caches.nodes[i]; + } + } +#if defined(__clang__) || defined(__GNUC__) + __builtin_unreachable(); +#else + assert(false && "Should never reach."); +#endif + } + +/// Convenience type alias for shared index 2D nodes. + template + using shared_index_2D = std::shared_ptr>; + +//------------------------------------------------------------------------------ +/// @brief Cast to a index 2D node. +/// +/// @tparam T Base type of the calculation. +/// @tparam SAFE_MATH Use @ref general_concepts_safe_math operations. +/// +/// @param[in] x Leaf node to attempt cast. +/// @returns An attempted dynamic cast. +//------------------------------------------------------------------------------ + template + shared_index_2D index_2D_cast(shared_leaf x) { + return std::dynamic_pointer_cast> (x); + } } #endif /* piecewise_h */ diff --git a/graph_framework/random.hpp b/graph_framework/random.hpp index 14f5330cb60e3c05c27ef04298bb2d74429bf1a5..ceeca1a8777b44e09a50fd0592758ced0a29bbbd 100644 --- a/graph_framework/random.hpp +++ b/graph_framework/random.hpp @@ -61,15 +61,6 @@ namespace graph { return result; } -//------------------------------------------------------------------------------ -/// @brief Reduce the random_state_node. -/// -/// @returns Reduced graph from random_state. -//------------------------------------------------------------------------------ - virtual shared_leaf reduce() { - return this->shared_from_this(); - } - //------------------------------------------------------------------------------ /// @brief Transform node to derivative. /// @@ -326,15 +317,6 @@ namespace graph { return result; } -//------------------------------------------------------------------------------ -/// @brief Reduce the random node. -/// -/// @returns Reduced graph from random. -//------------------------------------------------------------------------------ - virtual shared_leaf reduce() { - return this->shared_from_this(); - } - //------------------------------------------------------------------------------ /// @brief Transform node to derivative. /// diff --git a/graph_tests/c_binding_test.c b/graph_tests/c_binding_test.c index a77ac69cac79a76d34f8637922e87e1076ac5b85..72ff6cca6511d542fde4f8b9816c0313ae8852ac 100644 --- a/graph_tests/c_binding_test.c +++ b/graph_tests/c_binding_test.c @@ -125,6 +125,7 @@ void run_tests(const enum graph_type type, graph_node i = graph_variable(c_context, 1, "i"); graph_node j = graph_variable(c_context, 1, "j"); graph_node variable = graph_variable(c_context, 3, "var"); + graph_node variable2 = graph_variable(c_context, 9, "var2"); switch (c_context->type) { case FLOAT: { float value1[3] = {2.0, 4.0, 6.0}; @@ -134,6 +135,7 @@ void run_tests(const enum graph_type type, graph_set_variable(c_context, i, &value3); graph_set_variable(c_context, j, &value4); graph_set_variable(c_context, variable, &value1); + graph_set_variable(c_context, variable2, &value2); p1 = graph_piecewise_1D(c_context, i, 1.0, 0.0, value1, 3); p2 = graph_piecewise_2D(c_context, 3, j, 1.0, 0.0, i, 1.0, 0.0, value2, 9); break; @@ -147,6 +149,7 @@ void run_tests(const enum graph_type type, graph_set_variable(c_context, i, &value3); graph_set_variable(c_context, j, &value4); graph_set_variable(c_context, variable, &value1); + graph_set_variable(c_context, variable2, &value2); p1 = graph_piecewise_1D(c_context, i, 1.0, 0.0, value1, 3); p2 = graph_piecewise_2D(c_context, 3, j, 1.0, 0.0, i, 1.0, 0.0, value2, 9); break; @@ -162,6 +165,7 @@ void run_tests(const enum graph_type type, graph_set_variable(c_context, i, &value3); graph_set_variable(c_context, j, &value4); graph_set_variable(c_context, variable, &value1); + graph_set_variable(c_context, variable2, &value2); p1 = graph_piecewise_1D(c_context, i, 1.0, 0.0, value1, 3); p2 = graph_piecewise_2D(c_context, 3, j, 1.0, 0.0, i, 1.0, 0.0, value2, 9); break; @@ -177,15 +181,17 @@ void run_tests(const enum graph_type type, graph_set_variable(c_context, i, &value3); graph_set_variable(c_context, j, &value4); graph_set_variable(c_context, variable, &value1); + graph_set_variable(c_context, variable2, &value2); p1 = graph_piecewise_1D(c_context, i, 1.0, 0.0, value1, 3); p2 = graph_piecewise_2D(c_context, 3, j, 1.0, 0.0, i, 1.0, 0.0, value2, 9); break; } } graph_node i1 = graph_index_1D(c_context, variable, i, 1.0, 0.0); + graph_node i2 = graph_index_2D(c_context, variable2, 3, i, 1.0, 0.0, j, 1.0, 0.0); - graph_node inputs2[3] = {i, j, variable}; - graph_node outputs2[3] = {p1, p2, i1}; + graph_node inputs2[4] = {i, j, variable, variable2}; + graph_node outputs2[4] = {p1, p2, i1, i2}; graph_node *map_inputs2 = NULL; graph_node *map_outputs2 = NULL; @@ -201,8 +207,8 @@ void run_tests(const enum graph_type type, map_inputs, map_outputs, 0, NULL, "c_binding", 1); graph_add_item(c_context, - inputs2, 3, - outputs2, 3, + inputs2, 4, + outputs2, 4, map_inputs2, map_outputs2, 0, NULL, "c_binding_piecewise", 1); graph_add_converge_item(c_context, &z, 1, @@ -245,7 +251,7 @@ void run_tests(const enum graph_type type, switch (c_context->type) { case FLOAT: { - float value[10]; + float value[11]; graph_copy_to_host(c_context, y, value); graph_copy_to_host(c_context, dydx, value + 1); graph_copy_to_host(c_context, dydm, value + 2); @@ -256,6 +262,7 @@ void run_tests(const enum graph_type type, graph_copy_to_host(c_context, p1, value + 7); graph_copy_to_host(c_context, p2, value + 8); graph_copy_to_host(c_context, i1, value + 9); + graph_copy_to_host(c_context, i2, value + 10); assert(value[0] == 0.5f*2.0f + 0.2f && "Value of y does not match."); assert(value[1] == 0.5f && "Value of dydx does not match."); assert(value[2] == 2.0f && "Value of dydm does not match."); @@ -270,11 +277,12 @@ void run_tests(const enum graph_type type, assert(value[7] == 4.0f && "Value of p1 does not match."); assert(value[8] == 8.0f && "Value of p2 does not match."); assert(value[9] == 4.0f && "Value of i1 does not match."); + assert(value[10] == 6.0f && "Value of i2 does not match."); break; } case DOUBLE: { - double value[10]; + double value[11]; graph_copy_to_host(c_context, y, value); graph_copy_to_host(c_context, dydx, value + 1); graph_copy_to_host(c_context, dydm, value + 2); @@ -285,6 +293,7 @@ void run_tests(const enum graph_type type, graph_copy_to_host(c_context, p1, value + 7); graph_copy_to_host(c_context, p2, value + 8); graph_copy_to_host(c_context, i1, value + 9); + graph_copy_to_host(c_context, i2, value + 10); assert(value[0] == 0.5*2.0 + 0.2 && "Value of y does not match."); assert(value[1] == 0.5 && "Value of dydx does not match."); assert(value[2] == 2.0 && "Value of dydm does not match."); @@ -299,11 +308,12 @@ void run_tests(const enum graph_type type, assert(value[7] == 4.0 && "Value of p1 does not match."); assert(value[8] == 8.0 && "Value of p2 does not match."); assert(value[9] == 4.0 && "Value of i1 does not match."); + assert(value[10] == 6.0 && "Value of i2 does not match."); break; } case COMPLEX_FLOAT: { - float complex value[10]; + float complex value[11]; graph_copy_to_host(c_context, y, value); graph_copy_to_host(c_context, dydx, value + 1); graph_copy_to_host(c_context, dydm, value + 2); @@ -314,6 +324,7 @@ void run_tests(const enum graph_type type, graph_copy_to_host(c_context, p1, value + 7); graph_copy_to_host(c_context, p2, value + 8); graph_copy_to_host(c_context, i1, value + 9); + graph_copy_to_host(c_context, i2, value + 10); assert(crealf(value[0]) == 0.5f*2.0f + 0.2f && "Value of y does not match."); assert(crealf(value[1]) == 0.5f && "Value of dydx does not match."); assert(crealf(value[2]) == 2.0f && "Value of dydm does not match."); @@ -327,12 +338,13 @@ void run_tests(const enum graph_type type, assert(crealf(value[6]) == 1.0f && "Value of root does not match."); assert(crealf(value[7]) == 4.0f && "Value of p1 does not match."); assert(crealf(value[8]) == 8.0f && "Value of p2 does not match."); - assert(crealf(value[9]) == 4.0f && "Value of p1 does not match."); + assert(crealf(value[9]) == 4.0f && "Value of i1 does not match."); + assert(crealf(value[10]) == 6.0f && "Value of i2 does not match."); break; } case COMPLEX_DOUBLE: { - double complex value[10]; + double complex value[11]; graph_copy_to_host(c_context, y, value); graph_copy_to_host(c_context, dydx, value + 1); graph_copy_to_host(c_context, dydm, value + 2); @@ -343,6 +355,7 @@ void run_tests(const enum graph_type type, graph_copy_to_host(c_context, p1, value + 7); graph_copy_to_host(c_context, p2, value + 8); graph_copy_to_host(c_context, i1, value + 9); + graph_copy_to_host(c_context, i2, value + 10); assert(creal(value[0]) == 0.5*2.0 + 0.2 && "Value of y does not match."); assert(creal(value[1]) == 0.5 && "Value of dydx does not match."); assert(creal(value[2]) == 2.0 && "Value of dydm does not match."); @@ -356,7 +369,8 @@ void run_tests(const enum graph_type type, assert(creal(value[6]) == 1.0 && "Value of root does not match."); assert(creal(value[7]) == 4.0 && "Value of p1 does not match."); assert(creal(value[8]) == 8.0 && "Value of p2 does not match."); - assert(creal(value[9]) == 4.0 && "Value of p1 does not match."); + assert(creal(value[9]) == 4.0 && "Value of i1 does not match."); + assert(creal(value[10]) == 6.0 && "Value of i2 does not match."); break; } } diff --git a/graph_tests/efit_test.cpp b/graph_tests/efit_test.cpp index 30085c8c9ca97e872605cf2db662730fc0421159..9a1567565da116f54362c0c95f112edeb1a4a408 100644 --- a/graph_tests/efit_test.cpp +++ b/graph_tests/efit_test.cpp @@ -128,7 +128,7 @@ void check_error(const T test, const T tolerance, /// /// @tparam T Base type of the calculation. //------------------------------------------------------------------------------ -template +template void run_test() { const gold_data gold; diff --git a/graph_tests/f_binding_test.f90 b/graph_tests/f_binding_test.f90 index ae850f05c559b5122a704a6c44cf5d2c6bb84641..899e0b6c1d761f486c25100a99d646e949a5cb9f 100644 --- a/graph_tests/f_binding_test.f90 +++ b/graph_tests/f_binding_test.f90 @@ -90,7 +90,9 @@ TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: variable + TYPE(C_PTR) :: variable2 TYPE(C_PTR) :: i1 + TYPE(C_PTR) :: i2 TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 @@ -161,6 +163,13 @@ variable = graph%variable(3_C_LONG, 'var' // C_NULL_CHAR) CALL graph%set_variable(variable, buffer1D) i1 = graph%index_1D(variable, i, 1.0_C_DOUBLE, 0.0_C_DOUBLE) + variable2 = graph%variable(9_C_LONG, 'var' // C_NULL_CHAR) + CALL graph%set_variable(variable2, & + RESHAPE(buffer2D, & + (/ PRODUCT(SHAPE(buffer2D)) /))) + i2 = graph%index_2D(variable2, 3_C_LONG, & + i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & + j, 1.0_C_DOUBLE, 0.0_C_DOUBLE) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & @@ -182,11 +191,12 @@ 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(variable) /), & - (/ graph_ptr(p1), graph_ptr(p2), graph_ptr(i1) /), & - graph_null_array, graph_null_array, C_NULL_PTR, & - 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) + CALL graph%add_item((/ & + graph_ptr(i), graph_ptr(j), graph_ptr(variable), graph_ptr(variable2) & + /), (/ & + graph_ptr(p1), graph_ptr(p2), graph_ptr(i1), graph_ptr(i2) & + /), graph_null_array, graph_null_array, C_NULL_PTR, & + 'f_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, & @@ -227,6 +237,8 @@ CALL assert(value(1) .eq. 8.0_C_FLOAT, 'Value of p2 does not match.') CALL graph%copy_to_host(i1, value) CALL assert(value(1) .eq. 4.0_C_FLOAT, 'Value of i1 does not match.') + CALL graph%copy_to_host(i2, value) + CALL assert(value(1) .eq. 6.0_C_FLOAT, 'Value of i2 does not match.') DEALLOCATE(graph) @@ -271,7 +283,9 @@ TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: variable + TYPE(C_PTR) :: variable2 TYPE(C_PTR) :: i1 + TYPE(C_PTR) :: i2 TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 @@ -342,6 +356,13 @@ variable = graph%variable(3_C_LONG, 'var' // C_NULL_CHAR) CALL graph%set_variable(variable, buffer1D) i1 = graph%index_1D(variable, i, 1.0_C_DOUBLE, 0.0_C_DOUBLE) + variable2 = graph%variable(9_C_LONG, 'var' // C_NULL_CHAR) + CALL graph%set_variable(variable2, & + RESHAPE(buffer2D, & + (/ PRODUCT(SHAPE(buffer2D)) /))) + i2 = graph%index_2D(variable2, 3_C_LONG, & + i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & + j, 1.0_C_DOUBLE, 0.0_C_DOUBLE) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & @@ -363,11 +384,12 @@ 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(variable) /), & - (/ graph_ptr(p1), graph_ptr(p2), graph_ptr(i1) /), & - graph_null_array, graph_null_array, C_NULL_PTR, & - 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) + CALL graph%add_item((/ & + graph_ptr(i), graph_ptr(j), graph_ptr(variable), graph_ptr(variable2) & + /), (/ & + graph_ptr(p1), graph_ptr(p2), graph_ptr(i1), graph_ptr(i2) & + /), graph_null_array, graph_null_array, C_NULL_PTR, & + 'f_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, & @@ -408,6 +430,8 @@ CALL assert(value(1) .eq. 8.0_C_DOUBLE, 'Value of p2 does not match.') CALL graph%copy_to_host(i1, value) CALL assert(value(1) .eq. 4.0_C_DOUBLE, 'Value of i1 does not match.') + CALL graph%copy_to_host(i2, value) + CALL assert(value(1) .eq. 6.0_C_DOUBLE, 'Value of i2 does not match.') DEALLOCATE(graph) @@ -452,7 +476,9 @@ TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: variable + TYPE(C_PTR) :: variable2 TYPE(C_PTR) :: i1 + TYPE(C_PTR) :: i2 TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 @@ -527,6 +553,13 @@ variable = graph%variable(3_C_LONG, 'var' // C_NULL_CHAR) CALL graph%set_variable(variable, buffer1D) i1 = graph%index_1D(variable, i, 1.0_C_DOUBLE, 0.0_C_DOUBLE) + variable2 = graph%variable(9_C_LONG, 'var' // C_NULL_CHAR) + CALL graph%set_variable(variable2, & + RESHAPE(buffer2D, & + (/ PRODUCT(SHAPE(buffer2D)) /))) + i2 = graph%index_2D(variable2, 3_C_LONG, & + i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & + j, 1.0_C_DOUBLE, 0.0_C_DOUBLE) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & @@ -548,11 +581,12 @@ 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(variable) /), & - (/ graph_ptr(p1), graph_ptr(p2), graph_ptr(i1) /), & - graph_null_array, graph_null_array, C_NULL_PTR, & - 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) + CALL graph%add_item((/ & + graph_ptr(i), graph_ptr(j), graph_ptr(variable), graph_ptr(variable2) & + /), (/ & + graph_ptr(p1), graph_ptr(p2), graph_ptr(i1), graph_ptr(i2) & + /), graph_null_array, graph_null_array, C_NULL_PTR, & + 'f_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, & @@ -601,6 +635,9 @@ CALL graph%copy_to_host(i1, value) CALL assert(REAL(value(1)) .eq. 4.0_C_FLOAT, & 'Value of i1 does not match.') + CALL graph%copy_to_host(i2, value) + CALL assert(REAL(value(1)) .eq. 6.0_C_FLOAT, & + 'Value of i2 does not match.') DEALLOCATE(graph) @@ -645,7 +682,9 @@ TYPE(C_PTR) :: p2 TYPE(C_PTR) :: j TYPE(C_PTR) :: variable + TYPE(C_PTR) :: variable2 TYPE(C_PTR) :: i1 + TYPE(C_PTR) :: i2 TYPE(C_PTR) :: z TYPE(C_PTR) :: root TYPE(C_PTR) :: root2 @@ -732,6 +771,13 @@ variable = graph%variable(3_C_LONG, 'var' // C_NULL_CHAR) CALL graph%set_variable(variable, buffer1D) i1 = graph%index_1D(variable, i, 1.0_C_DOUBLE, 0.0_C_DOUBLE) + variable2 = graph%variable(9_C_LONG, 'var' // C_NULL_CHAR) + CALL graph%set_variable(variable2, & + RESHAPE(buffer2D, & + (/ PRODUCT(SHAPE(buffer2D)) /))) + i2 = graph%index_2D(variable2, 3_C_LONG, & + i, 1.0_C_DOUBLE, 0.0_C_DOUBLE, & + j, 1.0_C_DOUBLE, 0.0_C_DOUBLE) z = graph%variable(1_C_LONG, 'z' // C_NULL_CHAR) root = graph%sub(graph%pow(z, graph%constant(3.0_C_DOUBLE)), & @@ -753,11 +799,12 @@ 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(variable) /), & - (/ graph_ptr(p1), graph_ptr(p2), graph_ptr(i1) /), & - graph_null_array, graph_null_array, C_NULL_PTR, & - 'c_binding_piecewise' // C_NULL_CHAR, 1_C_LONG) + CALL graph%add_item((/ & + graph_ptr(i), graph_ptr(j), graph_ptr(variable), graph_ptr(variable2) & + /), (/ & + graph_ptr(p1), graph_ptr(p2), graph_ptr(i1), graph_ptr(i2) & + /), graph_null_array, graph_null_array, C_NULL_PTR, & + 'f_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, & @@ -807,6 +854,9 @@ CALL graph%copy_to_host(i1, value) CALL assert(DBLE(value(1)) .eq. 4.0_C_DOUBLE, & 'Value of i1 does not match.') + CALL graph%copy_to_host(i2, value) + CALL assert(DBLE(value(1)) .eq. 6.0_C_DOUBLE, & + 'Value of i2 does not match.') DEALLOCATE(graph) diff --git a/graph_tests/jit_test.cpp b/graph_tests/jit_test.cpp index 71e8f8278f8749bec23841253657265b30b74d0a..1d12fa668bb8f744e4e8df51c463f9cf9785b108 100644 --- a/graph_tests/jit_test.cpp +++ b/graph_tests/jit_test.cpp @@ -397,7 +397,7 @@ void run_dispersion_test(equilibrium::shared /// /// @tparam T Base type of the calculation. //------------------------------------------------------------------------------ -template +template void run_dispersion_tests() { auto no_mag_eq = equilibrium::make_no_magnetic_field (); diff --git a/graph_tests/piecewise_test.cpp b/graph_tests/piecewise_test.cpp index 5cff52b132c9ddfd101541b58131fa2f4e2191a0..5647cb76ca494987b6cb7f3845e1c401301c6932 100644 --- a/graph_tests/piecewise_test.cpp +++ b/graph_tests/piecewise_test.cpp @@ -750,6 +750,31 @@ template void index_1D() { static_cast (3.0), 0.0); } +//------------------------------------------------------------------------------ +/// @brief Tests for 2D index nodes. +/// +/// @tparam T Base type of the calculation. +//------------------------------------------------------------------------------ +template void index_2D() { + auto variable = graph::variable (9, ""); + auto x = graph::variable (1, ""); + auto y = graph::variable (1, ""); + + auto index = graph::index_2D (variable, 3, + x, 1.0, 0.0, + y, 1.0, 0.0); + + variable->set({1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}); + x->set(static_cast (2.5)); + y->set(static_cast (0.5)); + + compile ({graph::variable_cast(variable), + graph::variable_cast(x), + graph::variable_cast(y)}, + {index}, {}, + static_cast (7.0), 0.0); +} + //------------------------------------------------------------------------------ /// @brief Run tests with a specified backend. /// @@ -759,6 +784,7 @@ template void run_tests() { piecewise_1D (); piecewise_2D (); index_1D (); + index_2D (); } //------------------------------------------------------------------------------ diff --git a/graph_tests/random_test.cpp b/graph_tests/random_test.cpp index e8ce1e8b0fdbb8df02d15289459343e89b1912b1..5386743a913e1df6b5f886cf732945bd5dbcc482 100644 --- a/graph_tests/random_test.cpp +++ b/graph_tests/random_test.cpp @@ -25,7 +25,7 @@ /// @param[in] offset Offset of the correlation. /// @returns The autocorrelation for a given offset. //------------------------------------------------------------------------------ -template +template T autocorrelation(const std::vector &sequence, const size_t offset) { T result = 0.0;