diff --git a/.github/workflows/release_src_artifact.yml b/.github/workflows/release_src_artifact.yml index c616c8db5b..41b01d4f72 100644 --- a/.github/workflows/release_src_artifact.yml +++ b/.github/workflows/release_src_artifact.yml @@ -9,7 +9,7 @@ name: ci jobs: upload_src_tarball: name: Upload release source tarball - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - name: Fetch Repo Info run: | @@ -40,7 +40,7 @@ jobs: libopenblas-dev \ ocl-icd-opencl-dev \ nvidia-cuda-toolkit \ - libboost1.68-dev + libboost-dev - name: CMake Configure run: | diff --git a/.gitignore b/.gitignore index d56dd8ccf0..933736dba0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ #CMakeCache.txt #./CMakeFiles/ +CMakeUserPresets.json build*/ Release/ #Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt index 12d6e557c9..4ce33555e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include(CheckLanguage) include(CMakeModules/AF_vcpkg_options.cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") -project(ArrayFire VERSION 3.9.0 LANGUAGES C CXX) +project(ArrayFire VERSION 3.10.0 LANGUAGES C CXX) include(AFconfigure_deps_vars) include(AFBuildConfigurations) @@ -41,6 +41,9 @@ set_policies( CMP0074 CMP0077 CMP0079) +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.27") + cmake_policy(SET CMP0146 OLD) +endif() arrayfire_set_cmake_default_variables() option(AF_WITH_EXTERNAL_PACKAGES_ONLY "Build ArrayFire with External packages only" OFF) @@ -53,6 +56,7 @@ endif() if(SYCL_COMPILER_NAME STREQUAL "dpcpp" OR SYCL_COMPILER_NAME STREQUAL "dpcpp.exe" OR SYCL_COMPILER_NAME STREQUAL "icpx" OR SYCL_COMPILER_NAME STREQUAL "icx.exe") set(MKL_THREAD_LAYER "TBB" CACHE STRING "The thread layer to choose for MKL") + set(TBB_ROOT "$ENV{TBBROOT}") set(MKL_INTERFACE "ilp64") set(MKL_INTERFACE_INTEGER_SIZE 8) else() @@ -107,6 +111,7 @@ option(AF_WITH_SPDLOG_HEADER_ONLY "Build ArrayFire with header only version of s option(AF_WITH_FMT_HEADER_ONLY "Build ArrayFire with header only version of fmt" OFF) option(AF_WITH_FAST_MATH "Use lower precision but high performance numeric optimizations" OFF) option(AF_CTEST_SEPARATED "Run tests separately when called from ctest(increases test times)" OFF) +option(AF_SKIP_UNSUPPORTED_TESTS "Skip tests where functions are unsupported by the backend instead of failing" OFF) if(AF_WITH_STATIC_CUDA_NUMERIC_LIBS) option(AF_WITH_PRUNE_STATIC_CUDA_NUMERIC_LIBS "Prune CUDA static libraries to reduce binary size.(WARNING: May break some libs on older CUDA toolkits for some compute arch)" OFF) @@ -138,10 +143,8 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) if(DEFINED ENV{MKLROOT} AND NOT DEFINED MKL_ROOT) set(MKL_ROOT "$ENV{MKLROOT}") endif() - set(DPCPP_COMPILER ON) - set(MKL_THREADING "tbb_thread") - set(MKL_INTERFACE "ilp64") - find_package(MKL 2023.1) + set(SYCL_COMPILER ON) + find_package(MKL) endif() af_multiple_option(NAME AF_COMPUTE_LIBRARY @@ -285,6 +288,9 @@ else() target_compile_options(spdlog PRIVATE $<$:-fp-model precise>) + install(TARGETS spdlog + COMPONENT common_backend_dependencies + DESTINATION ${AF_INSTALL_BIN_DIR}) set_target_properties(af_spdlog PROPERTIES INTERFACE_LINK_LIBRARIES "spdlog") @@ -527,6 +533,14 @@ install(FILES ${ArrayFire_BINARY_DIR}/cmake/install/ArrayFireConfig.cmake DESTINATION ${AF_INSTALL_CMAKE_DIR} COMPONENT cmake) +if(WIN32 AND AF_INSTALL_STANDALONE) + find_program(MSVC_REDIST NAMES vc_redist.x64.exe + PATHS "$ENV{VCINSTALLDIR}Redist\\MSVC\\v${MSVC_TOOLSET_VERSION}") + get_filename_component(MSVC_REDIST_INSTALLER ${MSVC_REDIST} NAME) + install(PROGRAMS ${MSVC_REDIST} COMPONENT common_backend_dependencies + DESTINATION ${AF_INSTALL_BIN_DIR}) +endif() + if(BUILD_WITH_MKL AND AF_INSTALL_STANDALONE) if(TARGET MKL::ThreadingLibrary) get_filename_component(mkl_tl ${MKL_ThreadingLibrary_LINK_LIBRARY} REALPATH) @@ -545,8 +559,18 @@ if(BUILD_WITH_MKL AND AF_INSTALL_STANDALONE) ${mkl_int} DESTINATION ${AF_INSTALL_LIB_DIR} COMPONENT mkl_dependencies) + + # LP64 library is required for the CPU and OpenCL back ends, so install it too + if(MKL_INTERFACE_INTEGER_SIZE EQUAL 8) + get_filename_component(mkl_int_lp ${MKL_InterfaceLP_LINK_LIBRARY} REALPATH) + install(FILES + ${mkl_int_lp} + DESTINATION ${AF_INSTALL_LIB_DIR} + COMPONENT mkl_dependencies) + endif() endif() + if(UNIX) get_filename_component(mkl_rnt ${MKL_RT_LINK_LIBRARY} REALPATH) get_filename_component(mkl_shd ${MKL_Core_LINK_LIBRARY} REALPATH) get_filename_component(mkl_tly ${MKL_ThreadLayer_LINK_LIBRARY} REALPATH) @@ -554,6 +578,11 @@ if(BUILD_WITH_MKL AND AF_INSTALL_STANDALONE) ${mkl_rnt} ${mkl_shd} ${mkl_tly} + DESTINATION ${AF_INSTALL_LIB_DIR} + COMPONENT mkl_dependencies) + endif() + + install(FILES $ $ $ @@ -565,6 +594,38 @@ if(BUILD_WITH_MKL AND AF_INSTALL_STANDALONE) ${AF_ADDITIONAL_MKL_LIBRARIES} DESTINATION ${AF_INSTALL_LIB_DIR} COMPONENT mkl_dependencies) + if(AF_BUILD_ONEAPI) + if(WIN32) + get_filename_component(mkl_sycl_lapack ${MKL_SyclLapack_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_dft ${MKL_SyclDft_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_blas ${MKL_SyclBlas_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_sparse ${MKL_SyclSparse_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_data ${MKL_SyclDataFitting_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_rng ${MKL_SyclRNG_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_stats ${MKL_SyclStats_DLL_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_vm ${MKL_SyclVM_DLL_LIBRARY} REALPATH) + else() + get_filename_component(mkl_sycl_lapack ${MKL_SyclLapack_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_dft ${MKL_SyclDft_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_blas ${MKL_SyclBlas_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_sparse ${MKL_SyclSparse_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_data ${MKL_SyclDataFitting_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_rng ${MKL_SyclRNG_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_stats ${MKL_SyclStats_LINK_LIBRARY} REALPATH) + get_filename_component(mkl_sycl_vm ${MKL_SyclVM_LINK_LIBRARY} REALPATH) + endif() + install(FILES + ${mkl_sycl_lapack} + ${mkl_sycl_dft} + ${mkl_sycl_blas} + ${mkl_sycl_sparse} + ${mkl_sycl_data} + ${mkl_sycl_rng} + ${mkl_sycl_stats} + ${mkl_sycl_vm} + DESTINATION ${AF_INSTALL_LIB_DIR} + COMPONENT mkl_dependencies) + endif() endif() endif() diff --git a/CMakeModules/AF_vcpkg_options.cmake b/CMakeModules/AF_vcpkg_options.cmake index 09701af274..c84adcee82 100644 --- a/CMakeModules/AF_vcpkg_options.cmake +++ b/CMakeModules/AF_vcpkg_options.cmake @@ -6,7 +6,6 @@ # http://arrayfire.com/licenses/BSD-3-Clause set(ENV{VCPKG_FEATURE_FLAGS} "versions") -set(ENV{VCPKG_KEEP_ENV_VARS} "MKLROOT") set(VCPKG_MANIFEST_NO_DEFAULT_FEATURES ON) set(VCPKG_OVERLAY_TRIPLETS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/vcpkg/vcpkg-triplets) @@ -28,9 +27,7 @@ if(BUILD_TESTING) list(APPEND VCPKG_MANIFEST_FEATURES "tests") endif() -if(AF_COMPUTE_LIBRARY STREQUAL "Intel-MKL") - list(APPEND VCPKG_MANIFEST_FEATURES "mkl") -else() +if(NOT AF_COMPUTE_LIBRARY STREQUAL "Intel-MKL") list(APPEND VCPKG_MANIFEST_FEATURES "openblasfftw") endif() diff --git a/CMakeModules/CMakeSYCLInformation.cmake b/CMakeModules/CMakeSYCLInformation.cmake index df850959f1..b5ec7876db 100644 --- a/CMakeModules/CMakeSYCLInformation.cmake +++ b/CMakeModules/CMakeSYCLInformation.cmake @@ -41,6 +41,11 @@ include(Compiler/${CMAKE_SYCL_COMPILER_ID} OPTIONAL) __compiler_intel_llvm(SYCL) if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") + string(APPEND CMAKE_SYCL_FLAGS_INIT " /DWIN32 /D_WINDOWS") + string(APPEND CMAKE_SYCL_FLAGS_DEBUG_INIT " /Zi /Ob0 /Od /RTC1") + string(APPEND CMAKE_SYCL_FLAGS_MINSIZEREL_INIT " /O1 /Ob1 /DNDEBUG") + string(APPEND CMAKE_SYCL_FLAGS_RELEASE_INIT " /O2 /Ob2 /DNDEBUG") + string(APPEND CMAKE_SYCL_FLAGS_RELWITHDEBINFO_INIT " /Zi /O2 /Ob1 /DNDEBUG") set(CMAKE_SYCL_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TP) set(CMAKE_SYCL_CLANG_TIDY_DRIVER_MODE "cl") set(CMAKE_SYCL_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") @@ -353,6 +358,21 @@ if(NOT CMAKE_SYCL_LINK_EXECUTABLE) " -o ") endif() +if(CMAKE_HOST_WIN32) + set(MSVC_RUNTIME "") + if("${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL "MultiThreaded") + set(MSVC_RUNTIME "-MT") + elseif("${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL "MultiThreadedDLL") + set(MSVC_RUNTIME "-MD") + elseif("${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL "MultiThreadedDebug") + set(MSVC_RUNTIME "-MTd") + elseif("${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL "MultiThreadedDebugDLL") + set(MSVC_RUNTIME "-MDd") + else() + set(MSVC_RUNTIME "-MD$<$:d>") + endif() + set(CMAKE_MSVC_RUNTIME_LIBRARY "") +endif() mark_as_advanced( CMAKE_VERBOSE_MAKEFILE diff --git a/CMakeModules/CMakeTestSYCLCompiler.cmake b/CMakeModules/CMakeTestSYCLCompiler.cmake index e2f37a2da0..ef38081b37 100644 --- a/CMakeModules/CMakeTestSYCLCompiler.cmake +++ b/CMakeModules/CMakeTestSYCLCompiler.cmake @@ -66,8 +66,13 @@ if(NOT CMAKE_SYCL_COMPILER_WORKS) endif() # Try to identify the compiler features -include(CMakeDetermineCompileFeatures) -CMAKE_DETERMINE_COMPILE_FEATURES(SYCL) +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.30.0) + include(CMakeDetermineCompilerSupport) + CMAKE_DETERMINE_COMPILER_SUPPORT(CXX) +else() + include(CMakeDetermineCompileFeatures) + CMAKE_DETERMINE_COMPILE_FEATURES(CXX) +endif() set(CMAKE_TRY_COMPILE_CONFIGURATION "") # Re-configure to save learned information. diff --git a/CMakeModules/CPackConfig.cmake b/CMakeModules/CPackConfig.cmake index 6cd13a1d71..8cf0880faa 100644 --- a/CMakeModules/CPackConfig.cmake +++ b/CMakeModules/CPackConfig.cmake @@ -43,9 +43,9 @@ set(CPACK_PACKAGE_NAME "${LIBRARY_NAME}") set(CPACK_PACKAGE_VENDOR "${VENDOR_NAME}") set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${LIBRARY_NAME}) set(CPACK_PACKAGE_CONTACT "ArrayFire ") -set(MY_CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/assets/${APP_LOW_NAME}.ico") +set(MY_CPACK_PACKAGE_ICON "${ASSETS_DIR}/${APP_LOW_NAME}.ico") -file(TO_NATIVE_PATH "${CMAKE_SOURCE_DIR}/assets/" NATIVE_ASSETS_PATH) +file(TO_NATIVE_PATH "${ASSETS_DIR}/" NATIVE_ASSETS_PATH) string(REPLACE "\\" "\\\\" NATIVE_ASSETS_PATH ${NATIVE_ASSETS_PATH}) set(CPACK_AF_ASSETS_DIR "${NATIVE_ASSETS_PATH}") @@ -137,6 +137,9 @@ elseif(WIN32) else (CMAKE_CL_64) set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") endif (CMAKE_CL_64) + configure_file( + ${PROJECT_SOURCE_DIR}/CMakeModules/nsis/NSIS.definitions.nsh.in + ${CMAKE_CURRENT_BINARY_DIR}/NSIS.definitions.nsh) else() set(CPACK_RESOURCE_FILE_LICENSE "${ArrayFire_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_README "${ArrayFire_SOURCE_DIR}/README.md") diff --git a/CMakeModules/CPackProjectConfig.cmake b/CMakeModules/CPackProjectConfig.cmake index 6cd6e20088..f75591f8bb 100644 --- a/CMakeModules/CPackProjectConfig.cmake +++ b/CMakeModules/CPackProjectConfig.cmake @@ -161,9 +161,12 @@ if(NOT CPACK_GENERATOR MATCHES "DEB") DESCRIPTION "ArrayFire development files including headers and configuration files" EXPANDED) - cpack_add_component_group(debug - DISPLAY_NAME "ArrayFire Debug Symbols" - DESCRIPTION "ArrayFire Debug symbols") + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR + CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + cpack_add_component_group(debug + DISPLAY_NAME "ArrayFire Debug Symbols" + DESCRIPTION "ArrayFire Debug symbols") + endif() endif() set(arrayfire_cuda_runtime_name "CUDA Runtime(${CPACK_CUDA_VERSION_MAJOR}.${CPACK_CUDA_VERSION_MINOR})") @@ -287,7 +290,7 @@ af_component( DEB_USE_SHLIBDEPS DEB_PROVIDES "arrayfire-cuda (= ${CPACK_PACKAGE_VERSION}), arrayfire-cuda${CPACK_PACKAGE_VERSION_MAJOR} (= ${CPACK_PACKAGE_VERSION}), libarrayfire-cuda${CPACK_PACKAGE_VERSION_MAJOR} (= ${CPACK_PACKAGE_VERSION})" DEB_REPLACES "arrayfire-cuda (<< ${CPACK_PACKAGE_VERSION}), arrayfire-cuda${CPACK_PACKAGE_VERSION_MAJOR} (<< ${CPACK_PACKAGE_VERSION})" - DEB_OPTIONAL libcudnn8 forge libfreeimage3 + DEB_OPTIONAL cudnn9-cuda-${CPACK_CUDA_VERSION_MAJOR}-${CPACK_CUDA_VERSION_MINOR} forge libfreeimage3 ) af_component( @@ -343,6 +346,42 @@ af_component( DEB_OPTIONAL "cmake (>= 3.0)" ) +af_component( + COMPONENT oneapi + DISPLAY_NAME "oneAPI Runtime" + SUMMARY "ArrayFire oneAPI backend shared libraries" + DESCRIPTION "ArrayFire oneAPI backend shared libraries" + REQUIRES ${oneapi_deps_comps} licenses + OPTIONAL forge + GROUP afruntime + INSTALL_TYPES All Runtime + + DEB_PACKAGE_NAME ${deb_oneapi_runtime_package_name} + DEB_PROVIDES "arrayfire-oneapi (= ${CPACK_PACKAGE_VERSION}), arrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR} (= ${CPACK_PACKAGE_VERSION}), libarrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR} (= ${CPACK_PACKAGE_VERSION})" + DEB_REPLACES "arrayfire-oneapi (<< ${CPACK_PACKAGE_VERSION}), arrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR} (<< ${CPACK_PACKAGE_VERSION}), libarrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR} (<< ${CPACK_PACKAGE_VERSION})" + DEB_REQUIRES ${deb_oneapi_runtime_requirements} + DEB_USE_SHLIBDEPS + DEB_ADD_POSTINST + DEB_OPTIONAL forge libfreeimage3 +) + +af_component( + COMPONENT oneapi_dev + DISPLAY_NAME "oneAPI Dev" + SUMMARY "ArrayFire oneAPI backend development files" + DESCRIPTION "ArrayFire oneAPI backend development files" + REQUIRES oneapi headers cmake + GROUP afdevelopment + INSTALL_TYPES All Development + + DEB_PACKAGE_NAME arrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR}-dev + DEB_PROVIDES "arrayfire-oneapi-dev (= ${CPACK_PACKAGE_VERSION}), arrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR}-dev (= ${CPACK_PACKAGE_VERSION}), libarrayfire-oneapi-dev (= ${CPACK_PACKAGE_VERSION})" + DEB_REPLACES "arrayfire-oneapi-dev (<< ${CPACK_PACKAGE_VERSION}), arrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR}-dev (<< ${CPACK_PACKAGE_VERSION}), libarrayfire-oneapi-dev (<< ${CPACK_PACKAGE_VERSION})" + DEB_REQUIRES "arrayfire-oneapi${CPACK_PACKAGE_VERSION_MAJOR} (>= ${CPACK_PACKAGE_VERSION}), arrayfire-headers (>= ${CPACK_PACKAGE_VERSION})" + DEB_RECOMMENDS "arrayfire-cmake (>= ${CPACK_PACKAGE_VERSION})" + DEB_OPTIONAL "cmake (>= 3.0)" +) + af_component( COMPONENT unified DISPLAY_NAME "Unified Runtime" @@ -437,37 +476,48 @@ endif() # Debug symbols in debian installers are created using the DEBINFO property if(NOT APPLE AND NOT CPACK_GENERATOR MATCHES "DEB") - af_component( - COMPONENT afopencl_debug_symbols - DISPLAY_NAME "OpenCL Debug Symbols" - DESCRIPTION "Debug symbols for the OpenCL backend." - GROUP debug - DISABLED - INSTALL_TYPES Development) - - af_component( - COMPONENT afcuda_debug_symbols - DISPLAY_NAME "CUDA Debug Symbols" - DESCRIPTION "Debug symbols for CUDA backend backend." - GROUP debug - DISABLED - INSTALL_TYPES Development) - - af_component( - COMPONENT afcpu_debug_symbols - DISPLAY_NAME "CPU Debug Symbols" - DESCRIPTION "Debug symbols for CPU backend backend." - GROUP debug - DISABLED - INSTALL_TYPES Development) - - af_component( - COMPONENT af_debug_symbols - DISPLAY_NAME "Unified Debug Symbols" - DESCRIPTION "Debug symbols for the Unified backend." - GROUP debug - DISABLED - INSTALL_TYPES Development) + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR + CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + af_component( + COMPONENT afoneapi_debug_symbols + DISPLAY_NAME "oneAPI Debug Symbols" + DESCRIPTION "Debug symbols for the oneAPI backend." + GROUP debug + DISABLED + INSTALL_TYPES Development) + + af_component( + COMPONENT afopencl_debug_symbols + DISPLAY_NAME "OpenCL Debug Symbols" + DESCRIPTION "Debug symbols for the OpenCL backend." + GROUP debug + DISABLED + INSTALL_TYPES Development) + + af_component( + COMPONENT afcuda_debug_symbols + DISPLAY_NAME "CUDA Debug Symbols" + DESCRIPTION "Debug symbols for CUDA backend backend." + GROUP debug + DISABLED + INSTALL_TYPES Development) + + af_component( + COMPONENT afcpu_debug_symbols + DISPLAY_NAME "CPU Debug Symbols" + DESCRIPTION "Debug symbols for CPU backend backend." + GROUP debug + DISABLED + INSTALL_TYPES Development) + + af_component( + COMPONENT af_debug_symbols + DISPLAY_NAME "Unified Debug Symbols" + DESCRIPTION "Debug symbols for the Unified backend." + GROUP debug + DISABLED + INSTALL_TYPES Development) + endif() endif() # if (AF_INSTALL_FORGE_DEV) diff --git a/CMakeModules/FindAF_MKL.cmake b/CMakeModules/FindAF_MKL.cmake index a58809d495..18037ca4fc 100644 --- a/CMakeModules/FindAF_MKL.cmake +++ b/CMakeModules/FindAF_MKL.cmake @@ -74,8 +74,12 @@ include(CheckTypeSize) include(FindPackageHandleStandardArgs) -check_type_size("int" INT_SIZE - BUILTIN_TYPES_ONLY LANGUAGE C) +if(DEFINED MKL_INTERFACE_INTEGER_SIZE) + set(INT_SIZE ${MKL_INTERFACE_INTEGER_SIZE}) +else() + check_type_size("int" INT_SIZE + BUILTIN_TYPES_ONLY LANGUAGE C) +endif() set(MKL_THREAD_LAYER "TBB" CACHE STRING "The thread layer to choose for MKL") set_property(CACHE MKL_THREAD_LAYER PROPERTY STRINGS "TBB" "GNU OpenMP" "Intel OpenMP" "Sequential") @@ -299,9 +303,15 @@ function(find_mkl_library) NAMES ${CMAKE_SHARED_LIBRARY_PREFIX}${mkl_args_LIBRARY_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_SHARED_LIBRARY_PREFIX}${mkl_args_LIBRARY_NAME}${md_suffix}${CMAKE_SHARED_LIBRARY_SUFFIX} + ${CMAKE_SHARED_LIBRARY_PREFIX}${mkl_args_LIBRARY_NAME}.2${CMAKE_SHARED_LIBRARY_SUFFIX} + ${CMAKE_SHARED_LIBRARY_PREFIX}${mkl_args_LIBRARY_NAME}.5${CMAKE_SHARED_LIBRARY_SUFFIX} + ${CMAKE_SHARED_LIBRARY_PREFIX}${mkl_args_LIBRARY_NAME}12${CMAKE_SHARED_LIBRARY_SUFFIX} lib${mkl_args_LIBRARY_NAME}${md_suffix}${CMAKE_SHARED_LIBRARY_SUFFIX} $ENV{LIB} $ENV{LIBRARY_PATH} + PATHS + ${MKL_ROOT}/bin + ${TBB_ROOT}/bin PATH_SUFFIXES IntelSWTools/compilers_and_libraries/windows/redist/intel64/mkl IntelSWTools/compilers_and_libraries/windows/redist/intel64/compiler @@ -321,6 +331,18 @@ endfunction() find_mkl_library(NAME Core LIBRARY_NAME mkl_core SEARCH_STATIC) find_mkl_library(NAME RT LIBRARY_NAME mkl_rt) +if(AF_BUILD_ONEAPI) + find_mkl_library(NAME Sycl LIBRARY_NAME sycl DLL_ONLY) + find_mkl_library(NAME SyclLapack LIBRARY_NAME mkl_sycl_lapack DLL_ONLY) + find_mkl_library(NAME SyclDft LIBRARY_NAME mkl_sycl_dft DLL_ONLY) + find_mkl_library(NAME SyclBlas LIBRARY_NAME mkl_sycl_blas DLL_ONLY) + find_mkl_library(NAME SyclSparse LIBRARY_NAME mkl_sycl_sparse DLL_ONLY) + find_mkl_library(NAME SyclDataFitting LIBRARY_NAME mkl_sycl_data_fitting DLL_ONLY) + find_mkl_library(NAME SyclRNG LIBRARY_NAME mkl_sycl_rng DLL_ONLY) + find_mkl_library(NAME SyclStats LIBRARY_NAME mkl_sycl_stats DLL_ONLY) + find_mkl_library(NAME SyclVM LIBRARY_NAME mkl_sycl_vm DLL_ONLY) +endif() + # MKL can link against Intel OpenMP, GNU OpenMP, TBB, and Sequential if(MKL_THREAD_LAYER STREQUAL "Intel OpenMP") find_mkl_library(NAME ThreadLayer LIBRARY_NAME mkl_intel_thread SEARCH_STATIC) @@ -348,10 +370,13 @@ endif() if("${INT_SIZE}" EQUAL 4) set(MKL_INTERFACE_INTEGER_SIZE 4) + set(MKL_INTERFACE "lp64") find_mkl_library(NAME Interface LIBRARY_NAME mkl_intel_lp64 SEARCH_STATIC) else() set(MKL_INTERFACE_INTEGER_SIZE 8) + set(MKL_INTERFACE "ilp64") find_mkl_library(NAME Interface LIBRARY_NAME mkl_intel_ilp64 SEARCH_STATIC) + find_mkl_library(NAME InterfaceLP LIBRARY_NAME mkl_intel_lp64 SEARCH_STATIC) endif() set(MKL_KernelLibraries "mkl_def;mkl_mc;mkl_mc3;mkl_avx;mkl_avx2;mkl_avx512") diff --git a/CMakeModules/FindFreeImage.cmake b/CMakeModules/FindFreeImage.cmake index b049ec06a3..3b2d3fca29 100644 --- a/CMakeModules/FindFreeImage.cmake +++ b/CMakeModules/FindFreeImage.cmake @@ -75,12 +75,14 @@ find_library(FreeImage_STATIC_LIBRARY DOC "The FreeImage static library") if (WIN32) + get_filename_component(FreeImage_LIB_PATH ${FreeImage_LINK_LIBRARY} DIRECTORY) find_file(FreeImage_DLL_LIBRARY NAMES ${CMAKE_SHARED_LIBRARY_PREFIX}FreeImage${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_SHARED_LIBRARY_PREFIX}freeimage${CMAKE_SHARED_LIBRARY_SUFFIX} PATHS ${FreeImage_ROOT} + ${FreeImage_LIB_PATH}/../bin DOC "The FreeImage dll") mark_as_advanced(FreeImage_DLL_LIBRARY) endif () diff --git a/CMakeModules/FindcuDNN.cmake b/CMakeModules/FindcuDNN.cmake index 4c28d3c854..98641f4198 100644 --- a/CMakeModules/FindcuDNN.cmake +++ b/CMakeModules/FindcuDNN.cmake @@ -169,13 +169,17 @@ if(cuDNN_INCLUDE_DIRS) endmacro() af_find_cudnn_libs("") # gets base cudnn shared library - if(cuDNN_VERSION_MAJOR VERSION_GREATER 8 OR cuDNN_VERSION_MAJOR VERSION_EQUAL 8) + if(cuDNN_VERSION_MAJOR VERSION_EQUAL 8) af_find_cudnn_libs("_adv_infer") af_find_cudnn_libs("_adv_train") af_find_cudnn_libs("_cnn_infer") af_find_cudnn_libs("_cnn_train") af_find_cudnn_libs("_ops_infer") af_find_cudnn_libs("_ops_train") + elseif(cuDNN_VERSION_MAJOR VERSION_GREATER_EQUAL 9) + af_find_cudnn_libs("_adv") + af_find_cudnn_libs("_cnn") + af_find_cudnn_libs("_ops") endif() endif() diff --git a/CMakeModules/build_CLBlast.cmake b/CMakeModules/build_CLBlast.cmake index 933531cdf2..a0d9fab435 100644 --- a/CMakeModules/build_CLBlast.cmake +++ b/CMakeModules/build_CLBlast.cmake @@ -26,7 +26,7 @@ if(TARGET clblast OR AF_WITH_EXTERNAL_PACKAGES_ONLY) else() af_dep_check_and_populate(${clblast_prefix} URI https://github.com/cnugteren/CLBlast.git - REF 4500a03440e2cc54998c0edab366babf5e504d67 + REF 1.6.3 ) include(ExternalProject) @@ -69,6 +69,7 @@ else() BUILD_BYPRODUCTS ${CLBlast_location} CONFIGURE_COMMAND ${CMAKE_COMMAND} ${extproj_gen_opts} -Wno-dev + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS}" -DOVERRIDE_MSVC_FLAGS_TO_MT:BOOL=OFF diff --git a/CMakeModules/build_cl2hpp.cmake b/CMakeModules/build_cl2hpp.cmake index 0a3fef2de0..b38c4bc1d1 100644 --- a/CMakeModules/build_cl2hpp.cmake +++ b/CMakeModules/build_cl2hpp.cmake @@ -27,7 +27,7 @@ if(NOT TARGET OpenCL::cl2hpp) elseif (NOT TARGET OpenCL::cl2hpp OR NOT TARGET cl2hpp) af_dep_check_and_populate(${cl2hpp_prefix} URI https://github.com/KhronosGroup/OpenCL-CLHPP.git - REF v2022.09.30) + REF v2024.10.24) find_path(cl2hpp_var NAMES CL/cl2.hpp diff --git a/CMakeModules/nsis/NSIS.InstallOptions.ini.in b/CMakeModules/nsis/NSIS.InstallOptions.ini.in index d92d77959c..cc17d8268a 100644 --- a/CMakeModules/nsis/NSIS.InstallOptions.ini.in +++ b/CMakeModules/nsis/NSIS.InstallOptions.ini.in @@ -3,7 +3,7 @@ NumFields=5 [Field 1] Type=label -Text=By default @CPACK_PACKAGE_INSTALL_DIRECTORY@ does not add its directory to the system PATH. +Text=By default @CPACK_PACKAGE_INSTALL_DIRECTORY@ will add its directory to the system PATH. This will make the dynamic libraries available to all users and software on the system. Left=0 Right=-1 Top=0 @@ -16,7 +16,7 @@ Left=0 Right=-1 Top=30 Bottom=40 -State=1 +State=0 [Field 3] Type=radiobutton @@ -25,7 +25,7 @@ Left=0 Right=-1 Top=40 Bottom=50 -State=0 +State=1 [Field 4] Type=radiobutton diff --git a/CMakeModules/nsis/NSIS.definitions.nsh.in b/CMakeModules/nsis/NSIS.definitions.nsh.in index 4c6e8998b7..1062271940 100644 --- a/CMakeModules/nsis/NSIS.definitions.nsh.in +++ b/CMakeModules/nsis/NSIS.definitions.nsh.in @@ -3,23 +3,23 @@ !define MUI_WELCOMEPAGE_TEXT \ "ArrayFire is a high performance software library for parallel computing with an easy-to-use API.\r\n\r\n\ Its array based function set makes parallel programming simple.\r\n\r\n\ -ArrayFire's multiple backends (CUDA, OpenCL and native CPU) make it platform independent and highly portable.\r\n\r\n\ +ArrayFire's multiple backends (CUDA, OneAPI, OpenCL, and native CPU) make it platform independent and highly portable.\r\n\r\n\ A few lines of code in ArrayFire can replace dozens of lines of parallel compute code, \ saving you valuable time and lowering development costs.\r\n\r\n\ Follow these steps to install the ArrayFire libraries." -!define MUI_ICON "@CPACK_AF_ASSETS_DIR@@CPACK_PACKAGE_NAME@.ico" -!define MUI_UNICON "@CPACK_AF_ASSETS_DIR@@CPACK_PACKAGE_NAME@.ico" +!define MUI_ICON "@CPACK_AF_ASSETS_DIR@@APP_LOW_NAME@.ico" +!define MUI_UNICON "@CPACK_AF_ASSETS_DIR@@APP_LOW_NAME@.ico" -!define MUI_WELCOMEFINISHPAGE_BITMAP "@CPACK_AF_ASSETS_DIR@@CPACK_PACKAGE_NAME@_sym.bmp" -!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@CPACK_AF_ASSETS_DIR@@CPACK_PACKAGE_NAME@_sym.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP "@CPACK_AF_ASSETS_DIR@@APP_LOW_NAME@_sym.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@CPACK_AF_ASSETS_DIR@@APP_LOW_NAME@_sym.bmp" !define MUI_WELCOMEFINISHPAGE_UNBITMAP_NOSTRETCH !define MUI_UNWELCOMEFINISHPAGE_BITMAP_NOSTRETCH !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_RIGHT -!define MUI_HEADERIMAGE_BITMAP "@CPACK_AF_ASSETS_DIR@@CPACK_PACKAGE_NAME@_logo.bmp" -!define MUI_HEADERIMAGE_UNBITMAP "@CPACK_AF_ASSETS_DIR@@CPACK_PACKAGE_NAME@_logo.bmp" +!define MUI_HEADERIMAGE_BITMAP "@CPACK_AF_ASSETS_DIR@@APP_LOW_NAME@_logo.bmp" +!define MUI_HEADERIMAGE_UNBITMAP "@CPACK_AF_ASSETS_DIR@@APP_LOW_NAME@_logo.bmp" !define MUI_HEADERIMAGE_BITMAP_NOSTRETCH !define MUI_HEADERIMAGE_UNBITMAP_NOSTRETCH !define MUI_ABORTWARNING diff --git a/CMakeModules/nsis/NSIS.template.in b/CMakeModules/nsis/NSIS.template.in index bc3a44f233..3eaad1c383 100644 --- a/CMakeModules/nsis/NSIS.template.in +++ b/CMakeModules/nsis/NSIS.template.in @@ -714,7 +714,7 @@ Section "-Core installation" ; make sure windows knows about the change SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - MessageBox MB_OK "Added AF_PATH environment variable for all users.$\n$\nIf you chose not to modify PATH in the installer, please manually add $\"%AF_PATH%\lib$\" to the user or system PATH variable for running applications using ArrayFire." + MessageBox MB_OK "Added AF_PATH environment variable for all users.$\n$\nIf you chose not to modify PATH in the installer, please manually add $\"%AF_PATH%\lib$\" to the user or system PATH variable for running applications using ArrayFire." /SD IDOK ; Write special uninstall registry entries @@ -740,6 +740,11 @@ Section "-Core installation" SectionEnd +Section "-Visual C++ installation" + ExecWait "$INSTDIR\lib\vc_redist.x64.exe /install /passive" + Delete "$INSTDIR\lib\vc_redist.x64.exe" +SectionEnd + Section "-Add to path" Push $INSTDIR\lib StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath diff --git a/CMakeModules/select_compute_arch.cmake b/CMakeModules/select_compute_arch.cmake index 16abb8e6cd..e09490a7e5 100644 --- a/CMakeModules/select_compute_arch.cmake +++ b/CMakeModules/select_compute_arch.cmake @@ -7,7 +7,7 @@ # ARCH_AND_PTX : NAME | NUM.NUM | NUM.NUM(NUM.NUM) | NUM.NUM+PTX # NAME: Fermi Kepler Maxwell Kepler+Tegra Kepler+Tesla Maxwell+Tegra Pascal Volta Turing Ampere # NUM: Any number. Only those pairs are currently accepted by NVCC though: -# 2.0 2.1 3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.2 7.0 7.2 7.5 8.0 8.6 +# 2.0 2.1 3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.2 7.0 7.2 7.5 8.0 8.6 9.0 # Returns LIST of flags to be added to CUDA_NVCC_FLAGS in ${out_variable} # Additionally, sets ${out_variable}_readable to the resulting numeric list # Example: @@ -92,6 +92,25 @@ if(CUDA_VERSION VERSION_GREATER_EQUAL "11.1") set(CUDA_LIMIT_GPU_ARCHITECTURE "9.0") endif() +if(CUDA_VERSION VERSION_GREATER_EQUAL "11.8") + list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "8.9") + list(APPEND CUDA_ALL_GPU_ARCHITECTURES "8.9") + + set(_CUDA_MAX_COMMON_ARCHITECTURE "8.9+PTX") + set(CUDA_LIMIT_GPU_ARCHITECTURE "9.0") +endif() + +if(CUDA_VERSION VERSION_GREATER_EQUAL "12.0") + list(APPEND CUDA_KNOWN_GPU_ARCHITECTURES "Hopper") + list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "9.0") + list(APPEND CUDA_ALL_GPU_ARCHITECTURES "9.0") + + set(_CUDA_MAX_COMMON_ARCHITECTURE "9.0+PTX") + set(CUDA_LIMIT_GPU_ARCHITECTURE "9.0") + + list(REMOVE_ITEM CUDA_ALL_GPU_ARCHITECTURES "3.5" "3.7") +endif() + list(APPEND CUDA_COMMON_GPU_ARCHITECTURES "${_CUDA_MAX_COMMON_ARCHITECTURE}") # Check with: cmake -DCUDA_VERSION=7.0 -P select_compute_arch.cmake @@ -246,6 +265,9 @@ function(CUDA_SELECT_NVCC_ARCH_FLAGS out_variable) elseif(${arch_name} STREQUAL "Ampere") set(arch_bin 8.0) set(arch_ptx 8.0) + elseif(${arch_name} STREQUAL "Hopper") + set(arch_bin 9.0) + set(arch_ptx 9.0) else() message(SEND_ERROR "Unknown CUDA Architecture Name ${arch_name} in CUDA_SELECT_NVCC_ARCH_FLAGS") endif() diff --git a/LICENSE b/LICENSE index 8f4c645ca1..d63051d62b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2022, ArrayFire +Copyright (c) 2014-2025, ArrayFire All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index fed0820455..eb6dc6a5f6 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ -

-ArrayFire is a general-purpose tensor library that simplifies the process of -software development for the parallel architectures found in CPUs, GPUs, and -other hardware acceleration devices. The library serves users in every technical -computing market. +ArrayFire is a general-purpose tensor library that simplifies the software +development process for the parallel architectures found in CPUs, GPUs, and +other hardware acceleration devices. The library serves users in every +technical computing market. Several of ArrayFire's benefits include: -* Hundreds of accelerated [tensor computing functions](https://arrayfire.org/docs/group__arrayfire__func.htm), in the following areas: +* Hundreds of accelerated [tensor computing + functions](https://arrayfire.org/docs/group__arrayfire__func.htm), in the + following areas: * Array handling * Computer vision * Image processing @@ -22,8 +23,9 @@ Several of ArrayFire's benefits include: [well-documented](http://arrayfire.org/docs) API * Rigorous benchmarks and tests ensuring top performance and numerical accuracy * Cross-platform compatibility with support for CUDA, oneAPI, OpenCL, and - native CPU on Windows, Mac, and Linux -* Built-in visualization functions through [Forge](https://github.com/arrayfire/forge) + native CPU on Windows, Mac, and Linux +* Built-in visualization functions through + [Forge](https://github.com/arrayfire/forge) * Commercially friendly open-source licensing * Enterprise support from [ArrayFire](http://arrayfire.com) @@ -34,19 +36,22 @@ translated into near-optimal kernels that execute on the computational device. ArrayFire runs on devices ranging from low-power mobile phones to high-power GPU-enabled supercomputers. ArrayFire runs on CPUs from all major vendors -(Intel, AMD, ARM), GPUs from the prominent manufacturers (NVIDIA, AMD, and -Qualcomm), as well as a variety of other accelerator devices on Windows, Mac, -and Linux. +(Intel, AMD, ARM), GPUs from the prominent manufacturers (AMD, Intel, NVIDIA, +and Qualcomm), as well as a variety of other accelerator devices on Windows, +Mac, and Linux. # Getting ArrayFire -Instructions to [install][32] or to build ArrayFire from source can be found on the [wiki][1]. +Instructions to [install][32] or to build ArrayFire from source can be found on +the [wiki][1]. ### Conway's Game of Life Using ArrayFire Visit the [Wikipedia page][2] for a description of Conway's Game of Life. -Conway's Game of Life + ```cpp static const float h_kernel[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1 }; @@ -66,7 +71,9 @@ The complete source code can be found [here][3]. ### Perceptron -Perceptron + ```cpp array predict(const array &X, const array &W) { @@ -132,9 +139,10 @@ Mission](https://github.com/arrayfire/arrayfire/wiki/The-ArrayFire-Mission-State for fast scientific computing for all. Contributions of any kind are welcome! Please refer to [the -wiki](https://github.com/arrayfire/arrayfire/wiki) and our [Code of Conduct](33) -to learn more about how you can get involved with the ArrayFire Community -through [Sponsorship](https://github.com/arrayfire/arrayfire/wiki/Sponsorship), +wiki](https://github.com/arrayfire/arrayfire/wiki) and our [Code of +Conduct](33) to learn more about how you can get involved with the ArrayFire +Community through +[Sponsorship](https://github.com/arrayfire/arrayfire/wiki/Sponsorship), [Developer Commits](https://github.com/arrayfire/arrayfire/wiki/Contributing-Code-to-ArrayFire), or [Governance](https://github.com/arrayfire/arrayfire/wiki/Governance). @@ -146,8 +154,8 @@ license](LICENSE). If you wish to cite ArrayFire in an academic publication, please use the following [citation document](.github/CITATION.md). ArrayFire development is funded by AccelerEyes LLC and several third parties, -please see the list of [acknowledgements](ACKNOWLEDGEMENTS.md) for an expression -of our gratitude. +please see the list of [acknowledgements](ACKNOWLEDGEMENTS.md) for an +expression of our gratitude. # Support and Contact Info @@ -157,10 +165,10 @@ of our gratitude. # Trademark Policy -The literal mark "ArrayFire" and ArrayFire logos are trademarks of -AccelerEyes LLC (dba ArrayFire). -If you wish to use either of these marks in your own project, please consult -[ArrayFire's Trademark Policy](http://arrayfire.com/trademark-policy/) +The literal mark "ArrayFire" and ArrayFire logos are trademarks of AccelerEyes +LLC (dba ArrayFire). If you wish to use either of these marks in your own +project, please consult [ArrayFire's Trademark +Policy](http://arrayfire.com/trademark-policy/) [1]: https://github.com/arrayfire/arrayfire/wiki [2]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life diff --git a/docs/details/algorithm.dox b/docs/details/algorithm.dox index 055750098c..69633524e2 100644 --- a/docs/details/algorithm.dox +++ b/docs/details/algorithm.dox @@ -22,7 +22,7 @@ Input Type | Output Type --------------------|--------------------- f32, f64, c32, c64 | same as input s32, s64, u32, u64 | same as input -s16 | s32 +s16, s8 | s32 u16, u8, b8 | u32 \copydoc batch_detail_algo @@ -54,7 +54,7 @@ Input Type | Output Type --------------------|--------------------- f32, f64, c32, c64 | same as input s32, s64, u32, u64 | same as input -s16 | s32 +s16, s8 | s32 u16, u8, b8 | u32 f16 | f32 @@ -76,7 +76,7 @@ Input Type | Output Type --------------------|--------------------- f32, f64, c32, c64 | same as input s32, u32, s64, u64 | same as input -s16 | s32 +s16, s8 | s32 u16, u8, b8 | u32 \copydoc batch_detail_algo @@ -108,7 +108,7 @@ Input Type | Output Type --------------------|--------------------- f32, f64, c32, c64 | same as input s32, u32, s64, u64 | same as input -s16 | s32 +s16, s8 | s32 u16, u8, b8 | u32 f16 | f32 @@ -340,7 +340,7 @@ Input Type | Output Type --------------------|--------------------- f32, f64, c32, c64 | same as input s32, s64, u32, u64 | same as input -s16 | s32 +s16, s8 | s32 u16, u8, b8 | u32 \copydoc batch_detail_algo diff --git a/docs/details/blas.dox b/docs/details/blas.dox index 943e77a502..ac0aa99673 100644 --- a/docs/details/blas.dox +++ b/docs/details/blas.dox @@ -32,6 +32,10 @@ memory allocations either on host or device. for Sparse-Dense matrix multiplication. See the notes of the function for usage and restrictions. +\par +\note Limited support for \ref s8 was added to the CUDA backend in ArrayFire +v3.10.0. See \ref af_gemm "s8 Support" notes for details. + \ingroup blas_mat ======================================================================= diff --git a/docs/details/image.dox b/docs/details/image.dox index a93f1ebaed..312b88c880 100644 --- a/docs/details/image.dox +++ b/docs/details/image.dox @@ -1007,6 +1007,7 @@ Iterative deconvolution function excepts \ref af::array of the following types o - \ref f32 - \ref s16 - \ref u16 + - \ref s8 - \ref u8 \note The type of output \ref af::array from deconvolution will be double if @@ -1044,6 +1045,7 @@ Inverse deconvolution function excepts \ref af::array of the following types onl - \ref f32 - \ref s16 - \ref u16 + - \ref s8 - \ref u8 \note The type of output \ref af::array from deconvolution will be double diff --git a/docs/doxygen.mk b/docs/doxygen.mk index 914ebb35b4..9f46a1e37b 100644 --- a/docs/doxygen.mk +++ b/docs/doxygen.mk @@ -1,4 +1,4 @@ -# Doxyfile 1.9.6 +# Doxyfile 1.9.7 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -377,6 +377,17 @@ MARKDOWN_SUPPORT = YES TOC_INCLUDE_HEADINGS = 0 +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN Use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0. and GITHUB Use the lower case version of title +# with any whitespace replaced by '-' and punctations characters removed.. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or @@ -501,6 +512,14 @@ LOOKUP_CACHE_SIZE = 0 NUM_PROC_THREADS = 0 +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = YES + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -886,7 +905,14 @@ WARN_IF_UNDOC_ENUM_VAL = NO # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. -# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = NO @@ -1012,9 +1038,6 @@ EXCLUDE_PATTERNS = *.cpp # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # ANamespace::AClass, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = @@ -1405,15 +1428,6 @@ HTML_COLORSTYLE_SAT = 219 HTML_COLORSTYLE_GAMMA = 70 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = YES - # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will @@ -1563,6 +1577,16 @@ BINARY_TOC = NO TOC_EXPAND = NO +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help @@ -2051,9 +2075,16 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode -# command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. +# The LATEX_BATCHMODE tag ignals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -2074,14 +2105,6 @@ LATEX_HIDE_INDICES = NO LATEX_BIB_STYLE = plain -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO - # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # path from which the emoji images will be read. If a relative path is entered, # it will be relative to the LATEX_OUTPUT directory. If left blank the @@ -2247,7 +2270,7 @@ DOCBOOK_OUTPUT = docbook #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. @@ -2422,16 +2445,9 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to diagram generator tools #--------------------------------------------------------------------------- -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_PATH = - # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2440,7 +2456,7 @@ HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO # The default value is: NO. @@ -2493,13 +2509,15 @@ DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a -# graph for each documented class showing the direct and indirect inheritance -# relations. In case HAVE_DOT is set as well dot will be used to draw the graph, -# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set -# to TEXT the direct and indirect inheritance relations will be shown as texts / -# links. -# Possible values are: NO, YES, TEXT and GRAPH. +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. CLASS_GRAPH = YES @@ -2640,7 +2658,7 @@ DIR_GRAPH_MAX_DEPTH = 1 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). +# https://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). @@ -2677,11 +2695,12 @@ DOT_PATH = DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCFILE_DIRS = +DIA_PATH = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2758,3 +2777,19 @@ GENERATE_LEGEND = YES # The default value is: YES. DOT_CLEANUP = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, doxygen will call the tool as prog -T +# -o . The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = diff --git a/docs/pages/README.md b/docs/pages/README.md index 7c22adf87c..6ecb68ce4e 100644 --- a/docs/pages/README.md +++ b/docs/pages/README.md @@ -52,7 +52,7 @@ vectors, matrices, volumes, and It supports common [data types](\ref gettingstarted_datatypes), including single and double precision floating point values, complex numbers, booleans, -and 32-bit signed and unsigned integers. +and 8/16/32-bit signed and unsigned integers. #### Extending ArrayFire diff --git a/docs/pages/getting_started.md b/docs/pages/getting_started.md index 19660f8cc8..2bd3b4d1f6 100644 --- a/docs/pages/getting_started.md +++ b/docs/pages/getting_started.md @@ -28,7 +28,8 @@ can represent one of many different [basic data types](\ref af_dtype): * [b8](\ref b8) 8-bit boolean values (`bool`) * [s32](\ref s32) 32-bit signed integer (`int`) * [u32](\ref u32) 32-bit unsigned integer (`unsigned`) -* [u8](\ref u8) 8-bit unsigned values (`unsigned char`) +* [s8](\ref s8) 8-bit signed integer (`signed char`) +* [u8](\ref u8) 8-bit unsigned integer (`unsigned char`) * [s64](\ref s64) 64-bit signed integer (`intl`) * [u64](\ref u64) 64-bit unsigned integer (`uintl`) * [s16](\ref s16) 16-bit signed integer (`short`) diff --git a/docs/pages/install.md b/docs/pages/install.md index 555e702a1b..01b268af34 100644 --- a/docs/pages/install.md +++ b/docs/pages/install.md @@ -6,10 +6,9 @@ target architecture and operating system. Although ArrayFire can be [built from source](https://github.com/arrayfire/arrayfire), the installers conveniently package necessary dependencies. -Install the latest device drivers before using ArrayFire. If you are going to -target the CPU using ArrayFire’s OpenCL backend, install the OpenCL -runtime. Drivers and runtimes should be downloaded and installed from the -device vendor’s website. +Install the latest device drivers before using ArrayFire. If you target the +CPU using ArrayFire’s OpenCL backend, install the OpenCL runtime. Drivers and +runtimes should be downloaded and installed from each device vendor's website. # Install Instructions {#InstallInstructions} @@ -19,15 +18,11 @@ device vendor’s website. ## Windows {#Windows} -Prior to installing ArrayFire on Windows, -[download](https://www.microsoft.com/download/details.aspx?id=48145) -install the Visual Studio 2015 (x64) runtime libraries. +Once the ArrayFire has been downloaded, run the installer. -Once the ArrayFire installer has been downloaded, run the installer. If you -choose not to modify the path during the installation procedure, you'll need -to manually add ArrayFire to the path for all users. Simply append -`%%AF_PATH%/lib` to the PATH variable so that the loader can find ArrayFire -DLLs. +The installer offers the option to automatically add ArrayFire to the path for +all users. If the installer did not do this, simply append `%%AF_PATH%/lib` to +the PATH variable so that the loader can find ArrayFire DLLs. For more information on using ArrayFire on Windows, visit the following [page](http://arrayfire.org/docs/using_on_windows.htm). @@ -36,42 +31,42 @@ For more information on using ArrayFire on Windows, visit the following There are two ways to install ArrayFire on Linux. 1. Package Manager -2. Using ArrayFire Linux Installer +2. Using the ArrayFire Linux Installer As of today, approach (1) is only supported for Ubuntu 18.04 and 20.04. Please -go through [our GitHub wiki -page](https://github.com/arrayfire/arrayfire/wiki/Install-ArrayFire-From-Linux-Package-Managers) -for the detailed instructions. +go through [the GitHub +wiki[page](https://github.com/arrayfire/arrayfire/wiki/Install-ArrayFire-From-Linux-Package-Managers) +for detailed instructions. -For approach (2), once you have downloaded the ArrayFire installer, execute -the installer from the terminal as shown below. Set the `--prefix` argument to -the directory you would like to install ArrayFire to - we recommend `/opt`. +For approach (2), once the ArrayFire installer is downloaded, execute the +installer from the terminal as shown below. Set the `--prefix` argument to the +target install directory; we recommend `/opt`. - ./Arrayfire_*_Linux_x86_64.sh --include-subdir --prefix=/opt + ./ArrayFire_*_Linux_x86_64.sh --include-subdir --prefix=/opt -Given sudo permissions, you can add the ArrayFire libraries via `ldconfig` like -so: +Given sudo permissions, the ArrayFire libraries can be added to the path via +`ldconfig` like so: echo /opt/arrayfire/lib64 > /etc/ld.so.conf.d/arrayfire.conf sudo ldconfig -Otherwise, you will need to set the `LD_LIBRARY_PATH` environment variable in -order to let your shared library loader find the ArrayFire libraries. +Otherwise, the `LD_LIBRARY_PATH` environment variable can be set so that the +shared library loader can find the ArrayFire libraries. For more information on using ArrayFire on Linux, visit the following [page](http://arrayfire.org/docs/using_on_linux.htm). ### Graphics support -ArrayFire allows you to do high performance visualizations via our +ArrayFire enables high-performance visualizations via the [Forge](https://github.com/arrayfire/forge) library. On Linux, there are a few -dependencies you will need to install to enable graphics support: +dependencies to install to enable graphics support: -FreeImage -Fontconfig -GLU (OpenGL Utility Library) +* FreeImage +* Fontconfig +* GLU (OpenGL Utility Library) -We show how to install these dependencies on common Linux distributions: +To install these dependencies on common Linux distributions: __Debian, Ubuntu (14.04 and above), and other Debian derivatives__ @@ -84,9 +79,9 @@ __Fedora, Redhat, CentOS__ ## macOS {#macOS} -Once you have downloaded the ArrayFire installer, execute the installer by -either double clicking on the ArrayFire `pkg` file or running the following -command from your terminal: +Once the ArrayFire installer has been downloaded, execute the installer by +either double-clicking on the ArrayFire `pkg` file or running the following +command: sudo installer -pkg Arrayfire-*_OSX.pkg -target / @@ -95,11 +90,10 @@ For more information on using ArrayFire on macOS, visit the following ## NVIDIA Tegra devices -ArrayFire is capable of running on TX1 and TX2 devices. The TK1 is no longer -supported. +ArrayFire is capable of running TX2 devices. -Prior to installing ArrayFire, make sure you have the latest version of JetPack -(v2.3 and above) or L4T (v24.2 and above) on your device. +Before installing ArrayFire, make sure the latest version of JetPack (v2.3 and +above) or L4T (v24.2 and above) is installed. ### Tegra prerequisites @@ -109,27 +103,25 @@ The following dependencies are required for Tegra devices: ## Testing installation -After ArrayFire is finished installing, we recommend building and running a few -of the provided examples to verify things are working as expected. +After ArrayFire is finished installing, we recommend building and running a +few of the provided examples to verify things are working as expected. -On Unix-like systems: +On Windows, open the CMakeLists.txt file from CMake-GUI. Once the project is +configured and generated, build and run the examples from Visual Studio. + +On Linux, run the following commands: cp -r /opt/arrayfire/share/ArrayFire/examples /tmp/examples cd /tmp/examples mkdir build cd build - cmake -DASSETS_DIR:PATH=/tmp .. + cmake .. make - ./helloworld/helloworld_{cpu,cuda,opencl} - -On Windows, open the CMakeLists.txt file from CMake-GUI and set `ASSETS_DIR` -variable to the parent folder of examples folder. Once the project is -configured and generated, you can build and run the examples from Visual -Studio. + ./helloworld/helloworld_{cpu,cuda,oneapi,opencl} ## Getting help * Google Groups: https://groups.google.com/forum/#!forum/arrayfire-users -* ArrayFire Services: [Consulting](https://arrayfire.com/consulting/) | [Support](https://arrayfire.com/support/) | [Training](https://arrayfire.com/training/) +* ArrayFire Services: [Consulting](https://arrayfire.com/consulting/) | [Training](https://arrayfire.com/training/) * ArrayFire Blogs: http://arrayfire.com/blog/ -* Email: +* Email: diff --git a/docs/pages/interop_cuda.md b/docs/pages/interop_cuda.md index dae46ae027..2132dfcb2c 100644 --- a/docs/pages/interop_cuda.md +++ b/docs/pages/interop_cuda.md @@ -80,8 +80,7 @@ int main() { // 5. Determine ArrayFire's CUDA stream int af_id = af::getDevice(); - int cuda_id = afcu::getNativeId(af_id); - cudaStream_t af_cuda_stream = afcu::getStream(cuda_id); + cudaStream_t af_cuda_stream = afcu::getStream(af_id); // 6. Set arguments and run your kernel in ArrayFire's stream // Here launch with 1 block of 10 threads diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 464eba664d..1b55fea448 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -10,13 +10,15 @@ v3.9.0 - Add broadcast support \PR{2871} - Improve OpenCL CPU JIT performance \PR{3257} \PR{3392} - Optimize thread/block calculations of several kernels \PR{3144} -- Add support for fast math compiliation when building ArrayFire \PR{3334 \PR{3337} +- Add support for fast math compiliation when building ArrayFire \PR{3334} + \PR{3337} - Optimize performance of fftconvolve when using floats \PR{3338} - Add support for CUDA 12.1 and 12.2 - Better handling of empty arrays \PR{3398} - Better handling of memory in linear algebra functions in OpenCL \PR{3423} - Better logging with JIT kernels \PR{3468} -- Optimize memory manager/JIT interactions for small number of buffers \PR{3468} +- Optimize memory manager/JIT interactions for small number of buffers + \PR{3468} - Documentation improvements \PR{3485} - Optimize reorder function \PR{3488} @@ -24,21 +26,24 @@ v3.9.0 - Improve Errors when creating OpenCL contexts from devices \PR{3257} - Improvements to vcpkg builds \PR{3376 \PR{3476} - Fix reduce by key when nan's are present \PR{3261} -- Fix error in convolve where the ndims parameter was forced to be equal to 2 \PR{3277} -- Make constructors that accept dim_t to be explicit to avoid invalid conversions \PR{3259} -- Fix error in randu when compiling against clang 14 \PR{3333} +- Fix error in convolve where the ndims parameter was forced to be equal to 2 + \PR{3277} +- Make constructors that accept dim_t to be explicit to avoid invalid + conversions \PR{3259} +- Fix error in randu when compiling against clang 14 \PR{3333} - Fix bug in OpenCL linear algebra functions \PR{3398} -- Fix bug with thread local variables when device was changed \PR{3420} \PR{3421} -- Fix bug in qr related to uninitialized memory \PR{3422} +- Fix bug with thread local variables when device was changed \PR{3420} + \PR{3421} +- Fix bug in qr related to uninitialized memory \PR{3422} - Fix bug in shift where the array had an empty middle dimension \PR{3488} - ## Contributions Special thanks to our contributors: [Willy Born](https://github.com/willyborn) [Mike Mullen](https://github.com/mfzmullen) + v3.8.3 ====== @@ -101,6 +106,7 @@ Special thanks to our contributors: [Jacob Kahn](https://github.com/jacobkahn) [Willy Born](https://github.com/willyborn) + v3.8.1 ====== diff --git a/docs/pages/using_on_linux.md b/docs/pages/using_on_linux.md index 7dbff74d2a..91035426c5 100644 --- a/docs/pages/using_on_linux.md +++ b/docs/pages/using_on_linux.md @@ -4,9 +4,9 @@ Using ArrayFire on Linux {#using_on_linux} Once you have [installed](\ref installing) ArrayFire on your system, the next thing to do is set up your build system. On Linux, you can create ArrayFire projects using almost any editor, compiler, or build system. The only -requirements are that you include the ArrayFire header directories and link with -the ArrayFire library you intend to use i.e. CUDA, OpenCL, CPU, or Unified -backends. +requirements are that you include the ArrayFire header directories and link +with the ArrayFire library you intend to use i.e. CUDA, OpenCL, oneAPI, CPU, +or Unified backends. ## The big picture {#big-picture-linux} @@ -15,17 +15,18 @@ installer will populate files in the following sub-directories: include/arrayfire.h - Primary ArrayFire include file include/af/*.h - Additional include files - lib/libaf* - CPU, CUDA, oneAPI and OpenCL libraries (.a, .so) + lib/libaf* - CPU, CUDA, oneAPI, and OpenCL libraries (.a, .so) lib/libforge* - Visualization library lib/libcu* - CUDA backend dependencies lib/libOpenCL.so - OpenCL ICD Loader library share/ArrayFire/cmake/* - CMake config (find) scripts share/ArrayFire/examples/* - All ArrayFire examples -Because ArrayFire follows standard installation practices, you can use basically -any build system to create and compile projects that use ArrayFire. Among the -many possible build systems on Linux we suggest using ArrayFire with either -CMake or Makefiles with CMake being our preferred build system. +Because ArrayFire follows standard installation practices, you can use +basically any build system to create and compile projects that use +ArrayFire. Among the many possible build systems on Linux we suggest using +ArrayFire with either CMake or Makefiles with CMake being our preferred build +system. ## Prerequisite software @@ -57,8 +58,8 @@ apt install build-essential cmake cmake-curses-gui ## CMake We recommend that the CMake build system be used to create ArrayFire projects. -As [discussed above](#big-picture-linux), ArrayFire ships with a series of CMake -scripts to make finding and using our library easy. +As [discussed above](#big-picture-linux), ArrayFire ships with a series of +CMake scripts to make finding and using our library easy. First create a file called `CMakeLists.txt` in your project directory: @@ -74,19 +75,19 @@ and populate it with the following code: # Unified backend lets you choose the backend at runtime target_link_libraries( ArrayFire::af) -where `my_executable` is the name of the executable you wish to create. See the -[CMake documentation](https://cmake.org/documentation/) for more information on -how to use CMake. To link with a specific backend directly, replace the -`ArrayFire::af` with the following for their respective backends. +where `my_executable` is the name of the executable you wish to create. See +the [CMake documentation](https://cmake.org/documentation/) for more +information on how to use CMake. To link with a specific backend directly, +replace the `ArrayFire::af` with the following for their respective backends. * `ArrayFire::afcpu` for CPU backend. * `ArrayFire::afcuda` for CUDA backend. * `ArrayFire::afoneapi` for oneAPI backend. * `ArrayFire::afopencl` for OpenCL backend. -Next we need to instruct CMake to create build instructions and then compile. We -suggest using CMake's out-of-source build functionality to keep your build and -source files cleanly separated. To do this open the CMake GUI. +Next we need to instruct CMake to create build instructions and then +compile. We suggest using CMake's out-of-source build functionality to keep +your build and source files cleanly separated. To do this open the CMake GUI. cd your-project-directory mkdir build @@ -98,8 +99,9 @@ source files cleanly separated. To do this open the CMake GUI. still help you out. When you execute CMake specify the path to ArrayFire installation root as `ArrayFire_DIR` variable. -For example, if ArrayFire were installed locally to `/home/user/ArrayFire` then -you would modify the `cmake` command above to contain the following definition: +For example, if ArrayFire were installed locally to `/home/user/ArrayFire` +then you would modify the `cmake` command above to contain the following +definition: cmake -DArrayFire_DIR=/home/user/ArrayFire .. @@ -107,18 +109,18 @@ You can also specify this information in the `ccmake` command-line interface. ## Makefiles -Building ArrayFire projects with Makefiles is fairly similar to CMake except you -must specify all paths and libraries manually. +Building ArrayFire projects with Makefiles is fairly similar to CMake except +you must specify all paths and libraries manually. As with any `make` project, you need to specify the include path to the directory containing `arrayfire.h` file. This should be `-I /opt/arrayfire/include` if you followed our installation instructions. -Similarly, you will need to specify the path to the ArrayFire library using the -`-L` option (e.g. `-L/opt/arrayfire/lib`) followed by the specific ArrayFire -library you wish to use using the `-l` option (for example `-lafcpu`, -`-lafopencl`, `-lafoneapi`, `-lafcuda`, or `-laf` for the CPU, OpenCL, oneAPI -and CUDA, and unified backends, respectively. +Similarly, you will need to specify the path to the ArrayFire library using +the `-L` option (e.g. `-L/opt/arrayfire/lib`) followed by the specific +ArrayFire library you wish to use using the `-l` option (for example +`-lafcpu`, `-lafopencl`, `-lafoneapi`, `-lafcuda`, or `-laf` for the CPU, +OpenCL, oneAPI, and CUDA, and unified backends, respectively. Here is a minimal example Makefile which uses ArrayFire's CPU backend: diff --git a/docs/pages/using_on_windows.md b/docs/pages/using_on_windows.md index 072445a4ae..b9084723d1 100644 --- a/docs/pages/using_on_windows.md +++ b/docs/pages/using_on_windows.md @@ -2,7 +2,8 @@ Using ArrayFire with Microsoft Windows and Visual Studio {#using_on_windows} ============================================================================ If you have not already done so, please make sure you have installed, -configured, and tested ArrayFire following the [installation instructions](#installing). +configured, and tested ArrayFire following the [installation +instructions](#installing). # The big picture {#big-picture-windows} @@ -10,70 +11,60 @@ The ArrayFire Windows installer creates the following: 1. **AF_PATH** environment variable to point to the installation location. The default install location is `C:\Program Files\ArrayFire\v3` 2. **AF_PATH/include** : Header files for ArrayFire (include directory) -3. **AF_PATH/lib** : All ArrayFire backends libraries, dlls and dependency dlls - (library directory) -4. **AF_PATH/examples** : Examples to get started. +3. **AF_PATH/lib** : All ArrayFire backend libraries, dlls, and dependency + dlls (library directory) +4. **AF_PATH/examples** : Examples to get started 5. **AF_PATH/cmake** : CMake config files 6. **AF_PATH/uninstall.exe** : Uninstaller -The installer will prompt the user for following three options. -* Do not add **%%AF_PATH%/lib** to PATH -* Add **%%AF_PATH%/lib** to PATH environment variable of current user -* Add **%%AF_PATH%/lib** to PATH environment variable for all users - -If you chose not to modify PATH during installation please make sure to do so -manually so that all applications using ArrayFire libraries will be able to find -the required DLLs. - # Build and Run Helloworld {#section1} This can be done in two ways either by using CMake build tool or using Visual Studio directly. ## Using CMake {#section1part1} -1. Download and install [CMake](https://cmake.org/download/), preferrably the +1. Download and install [CMake](https://cmake.org/download/), preferably the latest version. 2. Open CMake-GUI and set the field __Where is the source code__ to the root directory of examples. 3. Set the field __Where to build the binaries__ to - **path_to_examples_root_dir/build** and click the `Configure` button towards - the lower left bottom. -4. CMake will prompt you asking if it has to create the `build` directory if - it's not already present. Click yes to create the build directory. -5. Before the configuration begins, CMake will show you a list(drop-down menu) - of available Visual Studio versions on your system to chose from. Select one - and check the radio button that says **Use default native compilers** and - click finish button in the bottom right corner. -6. CMake will show you errors in red text if any once configuration is finished. - Ideally, you wouldn't need to do anything and CMake should be able to find - ArrayFire automatically. Please let us know if it didn't on your machine. + **path_to_examples_root_dir/build** and click the `Configure` button. +4. CMake will prompt you to create the `build` directory if not already + present. Click "yes" to create the build directory. +5. Before the configuration begins, CMake will show you a list (drop-down + menu) of available Visual Studio versions. Select one and check the radio + button that says **Use default native compilers** and click finish. +6. CMake will show you errors in red text, if any, once configuration is + finished. Sometimes a second configuration is necessary. 7. Click **Generate** button to generate the Visual Studio solution files for the examples. 8. Click **Open Project** button that is right next to **Generate** button to open the solution file. -9. You will see a bunch of examples segregated into three sets named after the - compute backends of ArrayFire: cpu, cuda & opencl if you have installed all - backends. Select the helloworld project from any of the installed backends - and mark it as startup project and hit `F5`. +9. You will see the examples segregated into four sets named after the compute + backends of ArrayFire: cpu, cuda, oneapi, & opencl, if you installed all + backends. Select the helloworld project from any of the installed backends, + mark it as startup project, and hit `F5`. 10. Once the helloworld example builds, you will see a console window with the output from helloworld program. ## Using Visual Studio {#section1part2} -1. Open Visual Studio of your choice and create an empty C++ project. -2. Right click the project and add an existing source file +1. Open Visual Studio and create an empty C++ project. +2. Right-click the project and add an existing source file `examples/helloworld/helloworld.cpp` to this project. 3. Add `"$(AF_PATH)/include;"` to _Project Properties -> C/C++ -> General -> Additional Include Directories_. 4. Add `"$(AF_PATH)/lib;"` to _Project Properties -> Linker -> General -> Additional Library Directories_. -5. Add `afcpu.lib` or `afcuda.lib` or `afopencl.lib` to _Project Properties -> - Linker -> Input -> Additional Dependencies_. based on your preferred backend. -6. (Optional) You may choose to define `NOMINMAX`, `AF_` and/or - `AF_` in your projects. This can be added to _Project - Properties -> C/C++ -> General -> Preprocessor-> Preprocessory definitions_. -7. Build and run the project. You will see a console window with the output from - helloworld program. +5. Add `afcpu.lib`, `afcuda.lib`, `afoneapi.lib`, or `afopencl.lib` to + _Project Properties -> Linker -> Input -> Additional Dependencies_. based + on your preferred backend. +6. (Optional) You may choose to define `NOMINMAX`, + `AF_`, or `AF_` in your + projects. This can be added to _Project Properties -> C/C++ -> General -> + Preprocessor-> Preprocessory definitions_. +7. Build and run the project. You will see a console window with the output + from helloworld program. # Using ArrayFire within Existing Visual Studio Projects {#section2} This is divided into three parts: @@ -83,10 +74,10 @@ This is divided into three parts: ## Part A: Adding ArrayFire to an existing solution (Single Backend) {#section2partA} -Note: If you plan on using Native CUDA code in the project, use the steps under -[Part B](#section2partB). +Note: If you plan on using Native CUDA code in the project, use the steps +under [Part B](#section2partB). -Adding a single backend to an existing project is quite simple. +Adding a single backend to an existing project is quite simple: 1. Add `"$(AF_PATH)/include;"` to _Project Properties -> C/C++ -> General -> Additional Include Directories_. @@ -97,8 +88,9 @@ Adding a single backend to an existing project is quite simple. preferred backend. ## Part B: Adding ArrayFire CUDA to a new/existing CUDA project {#section2partB} -Lastly, if your project contains custom CUDA code, the instructions are slightly -different as it requires using a CUDA NVCC Project: + +Lastly, if your project contains custom CUDA code, the instructions are +slightly different as it requires using a CUDA NVCC Project: 1. Create a custom "CUDA NVCC project" in Visual Studio 2. Add `"$(AF_PATH)/include;"` to _Project Properties -> CUDA C/C++ -> General @@ -108,7 +100,8 @@ different as it requires using a CUDA NVCC Project: 4. Add `afcpu.lib`, `afcuda.lib`, `afopencl.lib`, or `af.lib` to _Project Properties -> Linker -> Input -> Additional Dependencies_. based on your preferred backend. -### Part C: Project with all ArrayFire backends {#section2partC} +## Part C: Project with all ArrayFire backends {#section2partC} + If you wish to create a project that allows you to use all the ArrayFire backends with ease, you should use `af.lib` in step 3 from [Part A](#section2partA). @@ -116,11 +109,12 @@ A](#section2partA). You can alternately download the template project from [ArrayFire Template Projects](https://github.com/arrayfire/arrayfire-project-templates) -# Using ArrayFire with CMake -ArrayFire ships with a series of CMake scripts to make finding and using our +# Using ArrayFire with CMake + +ArrayFire ships with a series of CMake scripts to make finding and using the library easy. -First create a file called `CMakeLists.txt` in your project directory: +First, create a file called `CMakeLists.txt` in your project directory: cd your-project-directory touch CMakeLists.txt @@ -130,13 +124,13 @@ and populate it with the following code: find_package(ArrayFire) add_executable( [list your source files here]) - # To use Unified backend, do the following. - # Unified backend lets you choose the backend at runtime + # The Unified backend lets you choose the backend at runtime. + # To use the Unified backend, do the following: target_link_libraries( ArrayFire::af) -where `` is the name of the executable you wish to create. See the -[CMake documentation](https://cmake.org/documentation/) for more information on -how to use CMake. To link with a specific backend directly, replace the +, where `` is the name of the executable to create. See the +[CMake documentation](https://cmake.org/documentation/) for more information +on how to use CMake. To link with a specific backend directly, replace the `ArrayFire::af` with the following for their respective backends. * `ArrayFire::afcpu` for CPU backend. @@ -144,13 +138,13 @@ how to use CMake. To link with a specific backend directly, replace the * `ArrayFire::afoneapi` for oneAPI backend. * `ArrayFire::afopencl` for OpenCL backend. -Next we need to instruct CMake to create build instructions and then compile. We -suggest using CMake's out-of-source build functionality to keep your build and -source files cleanly separated. To do this open the CMake GUI. +Next, instruct CMake to create build instructions and compile them. We suggest +using CMake's out-of-source build functionality to keep your build and source +files cleanly separated. To do this, open the CMake GUI. -* Under source directory, add the path to your project -* Under build directory, add the path to your project and append /build -* Click configure and choose a 64 bit Visual Studio generator. -* If configuration was successful, click generate. This will create a - my-project.sln file under build. Click `Open Project` in CMake-GUI to open the - solution and compile the ALL_BUILD project. +* Under "source directory", add the path to your project. +* Under "build directory", add the path to your project and append /build. +* Click "configure" and choose a 64-bit Visual Studio generator. +* If the configuration was successful, click "generate". This will create a + my-project.sln file under build. Click `Open Project` in CMake-GUI to open + the solution and compile the ALL_BUILD project. diff --git a/examples/benchmarks/CMakeLists.txt b/examples/benchmarks/CMakeLists.txt index 9cf8197317..4fd0853e58 100644 --- a/examples/benchmarks/CMakeLists.txt +++ b/examples/benchmarks/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Benchmarks VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) if(ArrayFire_CPU_FOUND) add_executable(blas_cpu blas.cpp) diff --git a/examples/computer_vision/CMakeLists.txt b/examples/computer_vision/CMakeLists.txt index 7113816566..2683eb1931 100644 --- a/examples/computer_vision/CMakeLists.txt +++ b/examples/computer_vision/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Computer-Vision VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) add_definitions("-DASSETS_DIR=\"${ASSETS_DIR}\"") diff --git a/examples/financial/CMakeLists.txt b/examples/financial/CMakeLists.txt index f2b82d4de8..f365f88b47 100644 --- a/examples/financial/CMakeLists.txt +++ b/examples/financial/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Financial VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) if(ArrayFire_CPU_FOUND) # Black-Scholes Options diff --git a/examples/getting_started/CMakeLists.txt b/examples/getting_started/CMakeLists.txt index 790afd3d1f..a9d1ce4bcb 100644 --- a/examples/getting_started/CMakeLists.txt +++ b/examples/getting_started/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Getting-Started VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) if(ArrayFire_CPU_FOUND) # Convolve examples diff --git a/examples/graphics/CMakeLists.txt b/examples/graphics/CMakeLists.txt index dd2918b641..6140142343 100644 --- a/examples/graphics/CMakeLists.txt +++ b/examples/graphics/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Graphics VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) add_definitions("-DASSETS_DIR=\"${ASSETS_DIR}\"") diff --git a/examples/graphics/field.cpp b/examples/graphics/field.cpp index a723791fc8..f493c7ecd6 100644 --- a/examples/graphics/field.cpp +++ b/examples/graphics/field.cpp @@ -22,7 +22,7 @@ int main(int, char**) { af::info(); af::Window myWindow(1024, 1024, "2D Vector Field example: ArrayFire"); - myWindow.grid(1, 2); + myWindow.grid(2, 2); array dataRange = seq(MINIMUM, MAXIMUM, STEP); @@ -38,12 +38,21 @@ int main(int, char**) { array saddle = join(1, flat(x), -1.0f * flat(y)); array bvals = sin(scale * (x * x + y * y)); - array hbowl = join(1, constant(1, x.elements()), flat(bvals)); + array hbowl = join(1, constant(1., x.elements()), flat(bvals)); hbowl.eval(); + // 2D points myWindow(0, 0).vectorField(points, saddle, "Saddle point"); myWindow(0, 1).vectorField( points, hbowl, "hilly bowl (in a loop with varying amplitude)"); + + // 2D coordinates + myWindow(1, 0).vectorField(2.0 * flat(x), flat(y), flat(x), + -flat(y), "Saddle point"); + myWindow(1, 1).vectorField( + 2.0 * flat(x), flat(y), constant(1., x.elements()), flat(bvals), + "hilly bowl (in a loop with varying amplitude)"); + myWindow.show(); scale -= 0.0010f; diff --git a/examples/helloworld/CMakeLists.txt b/examples/helloworld/CMakeLists.txt index 0aa58ca2c9..b3a02e9fc6 100644 --- a/examples/helloworld/CMakeLists.txt +++ b/examples/helloworld/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-HelloWorld VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) if(ArrayFire_CPU_FOUND) # Hello World example diff --git a/examples/image_processing/CMakeLists.txt b/examples/image_processing/CMakeLists.txt index cfcd109922..e4ab1d3d8a 100644 --- a/examples/image_processing/CMakeLists.txt +++ b/examples/image_processing/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Image-Processing VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) add_definitions("-DASSETS_DIR=\"${ASSETS_DIR}\"") diff --git a/examples/lin_algebra/CMakeLists.txt b/examples/lin_algebra/CMakeLists.txt index b08aceeeee..89b9c89600 100644 --- a/examples/lin_algebra/CMakeLists.txt +++ b/examples/lin_algebra/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Linear-Algebra VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) if(ArrayFire_CPU_FOUND) # Cholesky example diff --git a/examples/machine_learning/CMakeLists.txt b/examples/machine_learning/CMakeLists.txt index d1cbcc9541..480f3f7f12 100644 --- a/examples/machine_learning/CMakeLists.txt +++ b/examples/machine_learning/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Linear-Algebra VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) add_definitions("-DASSETS_DIR=\"${ASSETS_DIR}\"") diff --git a/examples/machine_learning/kmeans.cpp b/examples/machine_learning/kmeans.cpp index e40cc34368..963d6a609f 100644 --- a/examples/machine_learning/kmeans.cpp +++ b/examples/machine_learning/kmeans.cpp @@ -17,7 +17,7 @@ using namespace af; array distance(array data, array means) { - int n = data.dims(0); // Number of features + int n = data.dims(0); // Number of data points int k = means.dims(1); // Number of means array data2 = tile(data, 1, k, 1); @@ -60,8 +60,8 @@ array new_means(array data, array clusters, int k) { // means: output, vector of means void kmeans(array &means, array &clusters, const array in, int k, int iter = 100) { - unsigned n = in.dims(0); // Num features - unsigned d = in.dims(2); // feature length + unsigned n = in.dims(0); // Num of data points + unsigned d = in.dims(2); // Num of features (will only be 1 in spider image example) // reshape input array data = in * 0; diff --git a/examples/machine_learning/mnist_common.h b/examples/machine_learning/mnist_common.h index a32d21932c..8d079df75a 100644 --- a/examples/machine_learning/mnist_common.h +++ b/examples/machine_learning/mnist_common.h @@ -13,7 +13,7 @@ #include "../common/idxio.h" bool compare(const std::pair l, const std::pair r) { - return l.first >= r.first; + return l.first > r.first; } typedef std::pair sort_type; @@ -145,7 +145,7 @@ static void display_results(const af::array &test_images, (test_images(span, span, i) > 0.1f).as(u8).host(); for (int j = 0; j < 28; j++) { for (int k = 0; k < 28; k++) { - std::cout << (img[j * 28 + k] ? "\u2588" : " ") << " "; + std::cout << (img[k * 28 + j] ? "\u2588" : " ") << " "; } std::cout << std::endl; } diff --git a/examples/machine_learning/naive_bayes.cpp b/examples/machine_learning/naive_bayes.cpp index 9fe6456f0e..aadca32bc0 100644 --- a/examples/machine_learning/naive_bayes.cpp +++ b/examples/machine_learning/naive_bayes.cpp @@ -135,8 +135,8 @@ void naive_bayes_demo(bool console, int perc) { if (!console) { test_images = test_images.T(); test_labels = test_labels.T(); - // FIXME: Crashing in mnist_common.h::classify - // display_results(test_images, res_labels, test_labels , 20); + + display_results(test_images, res_labels, test_labels, 20); } } diff --git a/examples/pde/CMakeLists.txt b/examples/pde/CMakeLists.txt index 23a89ace31..57f689a9e9 100644 --- a/examples/pde/CMakeLists.txt +++ b/examples/pde/CMakeLists.txt @@ -10,25 +10,49 @@ project(ArrayFire-Example-PDE VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) + +add_definitions("-DASSETS_DIR=\"${ASSETS_DIR}\"") if(ArrayFire_CPU_FOUND) # Shallow Water simulation example add_executable(swe_cpu swe.cpp) target_link_libraries(swe_cpu ArrayFire::afcpu) + + # Black Hole Raytracing example + add_executable(bhrt_cpu bhrt.cpp) + target_link_libraries(bhrt_cpu ArrayFire::afcpu) + + add_executable(boltzmann_cfd_cpu boltzmann_cfd.cpp) + target_link_libraries(boltzmann_cfd_cpu ArrayFire::afcpu) endif() if(ArrayFire_CUDA_FOUND) add_executable(swe_cuda swe.cpp) target_link_libraries(swe_cuda ArrayFire::afcuda) + + add_executable(bhrt_cuda bhrt.cpp) + target_link_libraries(bhrt_cuda ArrayFire::afcuda) + + add_executable(boltzmann_cfd_cuda boltzmann_cfd.cpp) + target_link_libraries(boltzmann_cfd_cuda ArrayFire::afcuda) endif() if(ArrayFire_OpenCL_FOUND) add_executable(swe_opencl swe.cpp) target_link_libraries(swe_opencl ArrayFire::afopencl) + + add_executable(bhrt_opencl bhrt.cpp) + target_link_libraries(bhrt_opencl ArrayFire::afopencl) + + add_executable(boltzmann_cfd_opencl boltzmann_cfd.cpp) + target_link_libraries(boltzmann_cfd_opencl ArrayFire::afopencl) endif() if(ArrayFire_oneAPI_FOUND) add_executable(swe_oneapi swe.cpp) target_link_libraries(swe_oneapi ArrayFire::afoneapi) + + add_executable(boltzmann_cfd_oneapi boltzmann_cfd.cpp) + target_link_libraries(boltzmann_cfd_oneapi ArrayFire::afoneapi) endif() diff --git a/examples/pde/bhrt.cpp b/examples/pde/bhrt.cpp new file mode 100644 index 0000000000..55e116a330 --- /dev/null +++ b/examples/pde/bhrt.cpp @@ -0,0 +1,1139 @@ +/******************************************************* + * Copyright (c) 2024, ArrayFire + * All rights reserved. + * + * This file is distributed under 3-clause BSD license. + * The complete license agreement can be obtained at: + * http://arrayfire.com/licenses/BSD-3-Clause + ********************************************************/ + +/* + This is a Black Hole Raytracer. + For this raytracer we are using backwards path tracing to compute the + resulting image The path of the rays shot from the camera are simulated step + by step from the null geodesics light follows in spacetime. The geodesics are + computed from the spacetime metric of the space. This project has three + metrics that can be used: Schwarzchild, Kerr, and Ellis. + + For more information on the black hole raytracing, check out + Riazuelo, A. (2015). Seeing relativity -- I. Ray tracing in a Schwarzschild + metric to explore the maximal analytic extension of the metric and making a + proper rendering of the stars. ArXiv. + https://doi.org/10.1142/S0218271819500421 + + For more information on raytracing, check out + Raytracing in a Weekend Series, https://raytracing.github.io/ + + Image being used for the background is Westerlund 2 from + NASA, ESA, the Hubble Heritage Team (STScI/AURA), A. Nota (ESA/STScI), and + the Westerlund 2 Science Team See + http://www.spacetelescope.org/images/heic1509a/ for details. + + The default scene is the rotating black hole using the Kerr metric set by + the global variable 'scene' The parameters of the blackholes/wormholes may be + changed at the top with the simulation constants The parameters of the image + may be changed in the 'raytracing' function. +*/ +#include + +#include +#include +#include +#include +#include +#include + +enum class Scene { ROTATE_BH, STATIC_BH, WORMHOLE }; + +// Scene being computed +static constexpr Scene scene = Scene::ROTATE_BH; + +// **** Simulation Constants **** +static constexpr double M = 0.5; // Black Hole Mass +static constexpr double J = 0.249; // Black Hole Rotation (J < M^2) +static constexpr double b = 3.0; // Wormhole drainhole parameter + +/** + * @brief Generates a string progress bar + * + * @param current current job + * @param total total number of jobs + * @param start_info progress bar prior info + */ +void status_bar(int64_t current, int64_t total, const std::string& start_info) { + auto precision = std::cout.precision(); + static auto prev_time = std::chrono::high_resolution_clock::now(); + static auto prev = current - 1; + static auto prev2 = prev; + static auto prev2_time = prev_time; + + auto curr_time = std::chrono::high_resolution_clock::now(); + + double percent = 100.0 * (double)(current + 1) / (double)total; + std::string str = "["; + for (int i = 0; i < 50; ++i) { + if (percent >= i * 2) + str += "="; + else + str += " "; + } + str += "]"; + + auto time = + current != prev + ? (total - current) * (curr_time - prev_time) / (current - prev) + : (total - current) * (curr_time - prev2_time) / (current - prev2); + + if (current != prev && prev != prev2) { + prev2 = prev; + prev2_time = prev_time; + } + prev = current; + prev_time = curr_time; + + if (current != total) { + using namespace std::chrono_literals; + std::cout << start_info << " " << std::fixed << std::setprecision(1) + << percent << "% " << str << " Time Remaining: "; + if (std::chrono::duration_cast(time).count() > + 300) + std::cout << std::chrono::duration_cast(time) + .count() + << " min"; + else + std::cout << std::chrono::duration_cast(time) + .count() + << " s"; + + std::cout << std::string(5, ' ') << '\r'; + } else + std::cout << "\rDone!" << std::string(120, ' ') << std::endl; + + std::cout << std::setprecision(precision) << std::defaultfloat; +} + +/** + * @brief Returns the euclidean dot product for two cartesian vectors with 3 + * coords + * + * @param lhs + * @param rhs + * @return af::array + */ +af::array dot3(const af::array& lhs, const af::array& rhs) { + return af::sum(lhs * rhs, 0); +} + +/** + * @brief Returns the euclidean norm for a cartesian vector with 3 coords + * + * @param vector + * @return af::array + */ +af::array norm3(const af::array& vector) { + return af::sqrt(dot3(vector, vector)); +} + +/** + * @brief Returns the normalized vector for a cartesian vector with 3 coords + * + * @param vector + * @return af::array + */ +af::array normalize3(const af::array& vector) { return vector / norm3(vector); } + +af::exception make_error(const char* string) { + std::cout << string << std::endl; + return af::exception(string); +} + +/** + * @brief Transforms degrees to radians + * + * @param degrees + * @return double + */ +double radians(double degrees) { return degrees * af::Pi / 180.0; } + +/** + * @brief Computes the cross_product of two euclidean vectors + * + * @param lhs + * @param rhs + * @return af::array + */ +af::array cross_product(const af::array& lhs, const af::array& rhs) { + if (lhs.dims() != rhs.dims()) + throw make_error("Arrays must have the same dimensions"); + else if (lhs.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + return af::join( + 0, + lhs(1, af::span, af::span) * rhs(2, af::span, af::span) - + lhs(2, af::span, af::span) * rhs(1, af::span, af::span), + lhs(2, af::span, af::span) * rhs(0, af::span, af::span) - + lhs(0, af::span, af::span) * rhs(2, af::span, af::span), + lhs(0, af::span, af::span) * rhs(1, af::span, af::span) - + lhs(1, af::span, af::span) * rhs(0, af::span, af::span)); +} + +/** + * @brief Transform the position vectors from cartesian to spherical coordinates + * + * @param pos + * @return af::array + */ +af::array cart_to_sph_position(const af::array& pos) { + if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array x = pos(0, af::span); + af::array y = pos(1, af::span); + af::array z = pos(2, af::span); + + af::array r = af::sqrt(x * x + y * y + z * z); + af::array o = af::acos(z / r); + af::array p = af::atan2(y, x); + + af::array transformed_pos = af::join(0, r, o, p); + + return transformed_pos; +} + +/** + * @brief Transform the velocity vectors from cartesian to spherical coordinates + * + * @param vel + * @param pos + * @return af::array + */ +af::array cart_to_sph_velocity(const af::array& vel, const af::array& pos) { + if (vel.dims() != pos.dims()) + throw make_error("Arrays must have the same dimensions"); + else if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array x = pos(0, af::span); + af::array y = pos(1, af::span); + af::array z = pos(2, af::span); + + af::array r = af::sqrt(x * x + y * y + z * z); + af::array o = af::acos(z / r); + af::array p = af::atan2(y, x); + + af::array ux = vel(0, af::span); + af::array uy = vel(1, af::span); + af::array uz = vel(2, af::span); + + af::array ur = (ux * x + uy * y + uz * z) / r; + af::array up = (uy * af::cos(p) - ux * af::sin(p)) / (r * af::sin(o)); + af::array uo = + (af::cos(o) * (ux * af::cos(p) + uy * af::sin(p)) - uz * af::sin(o)) / + r; + af::array transformed_vel = af::join(0, ur, uo, up); + + return transformed_vel; +} + +/** + * @brief Transform the velocity vectors from cartesian to spherical coordinates + * + * @param vel + * @param pos + * @return af::array + */ +af::array sph_to_cart_velocity(const af::array& vel, const af::array& pos) { + if (vel.dims() != pos.dims()) + throw make_error("Arrays must have the same dimensions"); + else if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array r = pos(0, af::span); + af::array o = pos(1, af::span); + af::array p = pos(2, af::span); + + af::array ur = vel(0, af::span); + af::array uo = vel(1, af::span); + af::array up = vel(2, af::span); + + af::array ux = (ur * af::sin(o) + uo * r * af::cos(o)) * af::cos(p) - + up * r * af::sin(o) * af::sin(p); + af::array uy = (ur * af::sin(o) + uo * r * af::cos(o)) * af::sin(p) + + up * r * af::sin(o) * af::cos(p); + af::array uz = ur * af::cos(o) - uo * r * af::sin(o); + af::array transformed_vel = af::join(0, ux, uy, uz); + + return transformed_vel; +} + +/** + * @brief Transform the position vectors from cartesian to oblate coordinates + * + * @param vel + * @param pos + * @return af::array + */ +af::array cart_to_oblate_position(const af::array& pos) { + if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array x = pos(0, af::span); + af::array y = pos(1, af::span); + af::array z = pos(2, af::span); + auto a = J / M; + auto diff = x * x + y * y + z * z - a * a; + + af::array r = + af::sqrt((diff + af::sqrt(diff * diff + z * z * a * a * 4.0)) / 2.0); + af::array o = af::acos(z / r); + af::array p = af::atan2(y, x); + + af::array transformed_pos = af::join(0, r, o, p); + + return transformed_pos; +} + +/** + * @brief Transform the position vectors from oblate to cartesian coordinates + * + * @param vel + * @param pos + * @return af::array + */ +af::array oblate_to_cart_position(const af::array& pos) { + if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array r = pos(0, af::span); + af::array o = pos(1, af::span); + af::array p = pos(2, af::span); + auto a = J / M; + auto R = af::sqrt(r * r + a * a); + + af::array x = R * af::sin(o) * af::cos(p); + af::array y = R * af::sin(o) * af::sin(p); + af::array z = r * af::cos(o); + + af::array transformed_pos = af::join(0, x, y, z); + + return transformed_pos; +} + +/** + * @brief Transform the velocity vectors from oblate to cartesian coordinates + * + * @param vel + * @param pos + * @return af::array + */ +af::array oblate_to_cart_velocity(const af::array& vel, const af::array& pos) { + if (vel.dims() != pos.dims()) + throw make_error("Arrays must have the same dimensions"); + else if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array r = pos(0, af::span); + af::array o = pos(1, af::span); + af::array p = pos(2, af::span); + + af::array ur = vel(0, af::span); + af::array uo = vel(1, af::span); + af::array up = vel(2, af::span); + + double a = J / M; + af::array ra = af::sqrt(r * r + a * a); + + af::array ux = + (ur * r * af::sin(o) / ra + uo * ra * af::cos(o)) * af::cos(p) - + up * r * af::sin(o) * af::sin(p); + af::array uy = + (ur * r * af::sin(o) / ra + uo * ra * af::cos(o)) * af::sin(p) + + up * r * af::sin(o) * af::cos(p); + af::array uz = ur * af::cos(o) - uo * r * af::sin(o); + af::array transformed_vel = af::join(0, ux, uy, uz); + + return transformed_vel; +} + +/** + * @brief Transform the velocity vectors from cartesian to oblate coordinates + * + * @param vel + * @param pos + * @return af::array + */ +af::array cart_to_oblate_velocity(const af::array& vel, const af::array& pos) { + if (vel.dims() != pos.dims()) + throw make_error("Arrays must have the same dimensions"); + else if (pos.dims()[0] != 3) + throw make_error("Arrays must have 3 principal coordintes"); + + af::array x = pos(0, af::span); + af::array y = pos(1, af::span); + af::array z = pos(2, af::span); + + auto a = J / M; + auto diff = x * x + y * y + z * z - a * a; + + af::array r = + af::sqrt((diff + af::sqrt(diff * diff + z * z * a * a * 4.0)) / 2.0); + af::array o = af::acos(z / r); + af::array p = af::atan2(y, x); + + af::array ux = vel(0, af::span); + af::array uy = vel(1, af::span); + af::array uz = vel(2, af::span); + + af::array ra = r * r + a * a; + af::array ur = ((ux * x + uy * y) * r + uz * ra * z / r) / + (r * r + af::pow(a * af::cos(o), 2.0)); + af::array up = (uy * x - ux * y) / (x * x + y * y); + af::array uo = ((ux * x + uy * y) / af::tan(o) - uz * z * af::tan(o)) / + (r * r + af::pow(a * af::cos(o), 2.0)); + af::array transformed_vel = af::join(0, ur, uo, up); + + return transformed_vel; +} + +/** + * @brief Transform the position vectors from spherical to cartesian coordinates + * + * @param pos + * @return af::array + */ +af::array sph_to_cart_position(const af::array& pos) { + af::array r = pos(0, af::span); + af::array o = pos(1, af::span); + af::array p = pos(2, af::span); + + af::array x = r * af::sin(o) * af::cos(p); + af::array y = r * af::sin(o) * af::sin(p); + af::array z = r * af::cos(o); + + af::array transformed_pos = af::join(0, x, y, z); + + return transformed_pos; +} + +/** + * @brief Computes the inverse of a 4x4 matrix with the layout + * [ a 0 0 b ] + * [ 0 c 0 0 ] + * [ 0 0 d 0 ] + * [ b 0 0 e ] + * + * @param metric af::array with the shape af::dims4(4, 4, M, N) + * + * @return af::array with the shape af::dims4(4, 4, M, N) + */ +af::array inv_metric(const af::array& metric) { + af::array a = metric(0, 0, af::span); + af::array b = metric(3, 0, af::span); + af::array c = metric(1, 1, af::span); + af::array d = metric(2, 2, af::span); + af::array e = metric(3, 3, af::span); + + af::array det = b * b - a * e; + + auto res = af::constant(0, 4, 4, metric.dims()[2], metric.dims()[3], f64); + + res(0, 0, af::span) = -e / det; + res(0, 3, af::span) = b / det; + res(3, 0, af::span) = b / det; + res(1, 1, af::span) = 1.0 / c; + res(2, 2, af::span) = 1.0 / d; + res(3, 3, af::span) = -a / det; + + return res; +} + +/** + * @brief Computes the 4x4 metric matrix for the given 4-vector positions + * + * @param pos af::dim4(4, N) + * @return af::array af::dim4(4, 4, 1, N) + */ +af::array metric4(const af::array& pos) { + if (pos.dims()[0] != 4) + throw make_error("Arrays must have 4 principal coordinates"); + + auto dims = pos.dims(); + + af::array t = af::moddims(pos(0, af::span), 1, 1, dims[1]); + af::array r = af::moddims(pos(1, af::span), 1, 1, dims[1]); + af::array o = af::moddims(pos(2, af::span), 1, 1, dims[1]); + af::array p = af::moddims(pos(3, af::span), 1, 1, dims[1]); + + af::array gtt, gtr, gto, gtp, grt, grr, gro, grp, got, gor, goo, gop, gpt, + gpr, gpo, gpp; + + switch (scene) { + // ******* Kerr Black Hole Metric ******* + case Scene::ROTATE_BH: { + auto rs = 2.0 * M; + auto a = J / M; + auto delta = (r - rs) * r + a * a; + auto sigma = r * r + af::pow(a * af::cos(o), 2); + + gtt = 1.0 - r * rs / sigma; + gtr = af::constant(0.0, 1, 1, dims[1], f64); + gto = af::constant(0.0, 1, 1, dims[1], f64); + gtp = rs * r * a * af::pow(af::sin(o), 2.0) / sigma; + grr = -sigma / delta; + gro = af::constant(0.0, 1, 1, dims[1], f64); + grp = af::constant(0.0, 1, 1, dims[1], f64); + goo = -sigma; + gop = af::constant(0.0, 1, 1, dims[1], f64); + gpp = + -(r * r + a * a + rs * r * af::pow(a * af::sin(o), 2) / sigma) * + af::pow(af::sin(o), 2); + + break; + } + + // ******* Schwarzchild Black Hole Metric ******* + case Scene::STATIC_BH: { + gtt = 1.0 - 2.0 * M / r; + gtr = af::constant(0.0, 1, 1, dims[1], f64); + gto = af::constant(0.0, 1, 1, dims[1], f64); + gtp = af::constant(0.0, 1, 1, dims[1], f64); + grr = -1.0 / (1.0 - 2.0 * M / r); + gro = af::constant(0.0, 1, 1, dims[1], f64); + grp = af::constant(0.0, 1, 1, dims[1], f64); + goo = -r * r; + gop = af::constant(0.0, 1, 1, dims[1], f64); + gpp = -af::pow(r * af::sin(o), 2); + + break; + } + + // ******* Ellis Wormhole Metric ******* + case Scene::WORMHOLE: { + gtt = af::constant(1.0, 1, 1, dims[1], f64); + gtr = af::constant(0.0, 1, 1, dims[1], f64); + gto = af::constant(0.0, 1, 1, dims[1], f64); + gtp = af::constant(0.0, 1, 1, dims[1], f64); + grr = -af::constant(1.0, 1, 1, dims[1], f64); + gro = af::constant(0.0, 1, 1, dims[1], f64); + grp = af::constant(0.0, 1, 1, dims[1], f64); + goo = -(r * r + b * b); + gop = af::constant(0.0, 1, 1, dims[1], f64); + gpp = -(r * r + b * b) * af::pow(af::sin(o), 2); + + break; + } + + default: throw; + } + + auto res = af::join( + 0, af::join(1, gtt, gtr, gto, gtp), af::join(1, gtr, grr, gro, grp), + af::join(1, gto, gro, goo, gop), af::join(1, gtp, grp, gop, gpp)); + + return res; +} + +/** + * @brief Computes the dot product as defined by a metric between two 4-vector + * velocities + * + * @param pos + * @param lhs + * @param rhs + * @return af::array + */ +af::array dot_product(const af::array& pos, const af::array& lhs, + const af::array& rhs) { + if (pos.dims() != lhs.dims()) + throw make_error( + "Position and lhs velocity must have the same dimensions"); + else if (lhs.dims() != rhs.dims()) + throw make_error( + "Position and rhs velocity must have the same dimensions"); + else if (rhs.dims()[0] != 4) + throw make_error("Arrays must have 4 principal coordinates"); + + return af::matmul(af::moddims(lhs, 1, 4, lhs.dims()[1]), metric4(pos), + af::moddims(rhs, 4, 1, rhs.dims()[1])); +} + +af::array norm4(const af::array& pos, const af::array& vel) { + return dot_product(pos, vel, vel); +} + +af::array partials(const af::array& pos4, uint32_t index, double rel_diff, + double abs_diff) { + double arr[4] = {0.0}; + arr[index] = 1.0; + + auto pos_diff = pos4 * rel_diff + abs_diff; + auto h4 = pos_diff * af::array(af::dim4(4, 1), arr); + af::array h = + af::moddims(pos_diff(index, af::span), af::dim4(1, 1, pos4.dims()[1])); + + return (-metric4(pos4 + h4 * 2.0) + metric4(pos4 + h4) * 8.0 - + metric4(pos4 - h4) * 8.0 + metric4(pos4 - h4 * 2.0)) / + (h * 12.0); +} + +/** + * @brief Computes the geodesics from the established metric, 4-vector positions + * and velocities + * + * @param pos4 + * @param vel4 + * @return af::array + */ +af::array geodesics(const af::array& pos4, const af::array& vel4) { + auto N = vel4.dims()[1]; + + af::array uu = af::matmul(af::moddims(vel4, af::dim4(4, 1, N)), + af::moddims(vel4, af::dim4(1, 4, N))); + uu = af::moddims(uu, af::dim4(1, 4, 4, N)); + + af::array metric = metric4(pos4); + af::array invmetric = af::moddims(inv_metric(metric), af::dim4(4, 4, 1, N)); + + // Compute the partials of the metric with respect to coordinates indices + af::array dt = af::constant(0, 4, 4, 1, N, f64); + + auto dr = partials(pos4, 1, 1e-6, 1e-12); + auto dtheta = partials(pos4, 2, 1e-6, 1e-12); + auto dphi = partials(pos4, 3, 1e-6, 1e-12); + + dr = af::moddims(dr, af::dim4(4, 4, 1, N)); + dtheta = af::moddims(dtheta, af::dim4(4, 4, 1, N)); + dphi = af::moddims(dphi, af::dim4(4, 4, 1, N)); + + // Compute the einsum for each of the christoffel terms + af::array partials = af::join(2, dt, dr, dtheta, dphi); + af::array p1 = af::matmul(invmetric, partials); + af::array p2 = af::reorder(p1, 0, 2, 1, 3); + af::array p3 = af::matmul(invmetric, af::reorder(partials, 2, 0, 1, 3)); + + auto christoffels = -0.5 * (p1 + p2 - p3); + + // Use the geodesics equation to find the 4-vector acceleration + return af::moddims(af::sum(af::sum(christoffels * uu, 1), 2), + af::dim4(4, N)); +} + +/** + * @brief Camera struct + * + * Contains all the data pertaining to the parameters for the image as seen from + * the camera + * + */ +struct Camera { + af::array position; + af::array lookat; + double fov; + double focal_length; + uint32_t width; + uint32_t height; + + af::array direction; + af::array vertical; + af::array horizontal; + double aspect_ratio; + + Camera(const af::array& position_, const af::array& lookat_, double fov_, + double focal_length_, uint32_t viewport_width_, + uint32_t viewport_height_) + : position(position_) + , lookat(lookat_) + , fov(fov_) + , focal_length(focal_length_) + , width(viewport_width_) + , height(viewport_height_) { + auto global_vertical = af::array(3, {0.0, 0.0, 1.0}); + + // Compute the camera three main axes + direction = normalize3(lookat - position); + horizontal = normalize3(cross_product(direction, global_vertical)); + vertical = normalize3(cross_product(direction, horizontal)); + + aspect_ratio = (double)width / (double)height; + } + + /** + * @brief Generates the initial rays 4-vector position and velocities + * (direction) for the simulation + * + * @return std::pair (pos4, vel4) + */ + std::pair generate_viewport_4rays() { + auto& camera_direction = direction; + auto& camera_horizontal = horizontal; + auto& camera_vertical = vertical; + auto& camera_position = position; + auto vfov = fov; + + double viewport_height = 2.0 * focal_length * std::tan(vfov / 2.0); + double viewport_width = aspect_ratio * viewport_height; + + // Create rays in equally spaced directions of the viewport + af::array viewport_rays = af::constant(0, 3, width, height, f64); + viewport_rays += + (af::iota(af::dim4(1, width, 1), af::dim4(1, 1, height), f64) / + (width - 1) - + 0.5) * + viewport_width * camera_horizontal; + viewport_rays += + (af::iota(af::dim4(1, 1, height), af::dim4(1, width, 1), f64) / + (height - 1) - + 0.5) * + viewport_height * camera_vertical; + viewport_rays += focal_length * camera_direction; + viewport_rays = af::moddims(af::reorder(viewport_rays, 1, 2, 0), + af::dim4(width * height, 3)) + .T(); + + // Compute the initial position from which the rays are launched + af::array viewport_position = viewport_rays + camera_position; + af::array viewport_sph_pos; + if (scene != Scene::ROTATE_BH) + viewport_sph_pos = cart_to_sph_position(viewport_position); + else + viewport_sph_pos = cart_to_oblate_position(viewport_position); + + // Normalize the ray directions + viewport_rays = normalize3(viewport_rays); + + // Generate the position 4-vector + af::array camera_sph_pos; + if (scene != Scene::ROTATE_BH) + camera_sph_pos = cart_to_sph_position(camera_position); + else + camera_sph_pos = cart_to_oblate_position(camera_position); + + af::array camera_pos4 = + af::join(0, af::constant(0.0, 1, f64), camera_sph_pos); + double camera_velocity = + 1.0 / + af::sqrt(norm4(camera_pos4, af::array(4, {1.0, 0.0, 0.0, 0.0}))) + .scalar(); + af::array camera_vel4 = af::array(4, {camera_velocity, 0.0, 0.0, 0.0}); + + af::array viewport_rays_pos4 = af::join( + 0, af::constant(0.0, 1, width * height, f64), viewport_sph_pos); + + // Generate the velocity 4-vector by setting the camera to be stationary + // with respect to an observer at infinity + af::array vv; + if (scene != Scene::ROTATE_BH) + vv = cart_to_sph_velocity(viewport_rays, viewport_position); + else + vv = cart_to_oblate_velocity(viewport_rays, viewport_position); + + af::array vvr = vv(0, af::span); + af::array vvo = vv(1, af::span); + af::array vvp = vv(2, af::span); + auto viewport_sph_rays4 = + af::join(0, af::constant(1, 1, width * height, f64), vvr, vvo, vvp); + + af::array dot = af::moddims( + af::matmul(metric4(viewport_rays_pos4), + af::moddims(viewport_sph_rays4 * viewport_sph_rays4, + af::dim4(4, 1, width * height))), + af::dim4(4, width * height)); + + // Normalize the 4-velocity vectors + af::array viewport_vel = + af::sqrt(-af::array(dot(0, af::span)) / + (dot(1, af::span) + dot(2, af::span) + dot(3, af::span))); + af::array viewport_rays_vel4 = + af::join(0, af::constant(camera_velocity, 1, width * height, f64), + vv * viewport_vel * camera_velocity); + + return {viewport_rays_pos4, viewport_rays_vel4}; + } +}; + +/** + * @brief Object struct + * + * Contains the methods for testing if a ray has collided with the object + * + */ +struct Object { + using HasHit = af::array; + using HitPos = af::array; + + /** + * @brief Gets the color of the pixel that correspond to the ray that has + * intersected with the object + * + * @param ray_begin begining + * @param ray_end + * @return af::array + */ + virtual af::array get_color(const af::array& ray_begin, + const af::array& ray_end) const = 0; + + /** + * @brief Returns a bool array if the rays have hit the object and the + * correspoding position where the ray has hit + * + * @param ray_begin + * @param ray_end + * @return std::pair + */ + virtual std::pair intersect( + const af::array& ray_begin, const af::array& ray_end) const = 0; +}; + +struct AccretionDisk : public Object { + af::array disk_color; + af::array center; + af::array normal; + double inner_radius; + double outter_radius; + + AccretionDisk(const af::array& center, const af::array& normal, + double inner_radius, double outter_radius) + : disk_color(af::array(3, {209.f, 77.f, 0.f})) + , center(center) + , normal(normal) + , inner_radius(inner_radius) + , outter_radius(outter_radius) { + // disk_color = af::array(3, {254.f, 168.f, 29.f}); + } + + std::pair intersect( + const af::array& ray_begin, const af::array& ray_end) const override { + uint32_t count = ray_begin.dims()[1]; + + // Compute intersection of ray with a plane + af::array has_hit = af::constant(0, count).as(b8); + af::array hit_pos = ray_end; + af::array a = dot3(normal, center - ray_begin); + af::array b = dot3(normal, ray_end - ray_begin); + af::array t = af::select(b != 0.0, a / b, (double)0.0); + + af::array plane_intersect = (ray_end - ray_begin) * t + ray_begin; + af::array dist = norm3(plane_intersect - center); + + t = af::abs(t); + + // Determine if the intersection falls inside the disk radius and occurs + // with the current ray segment + has_hit = af::moddims((dist < outter_radius) && (t <= 1.0) && + (t > 0.0) && (dist > inner_radius), + af::dim4(count)); + hit_pos = plane_intersect; + + return {has_hit, hit_pos}; + } + + af::array get_color(const af::array& ray_begin, + const af::array& ray_end) const override { + auto pair = intersect(ray_begin, ray_end); + af::array hit = pair.first; + af::array pos = pair.second; + + auto val = 1.f - (norm3(pos - center).T() - inner_radius) / + (outter_radius - inner_radius); + + af::array color = + disk_color.T() * 1.5f * (val * val * (val * -2.f + 3.f)).as(f32); + + return af::select(af::tile(hit, af::dim4(1, 3)), color, 0.f); + } +}; +/** + * @brief Background struct + * + * Contains the methods for getting the color of background image + * + */ +struct Background { + af::array image; + + Background(const af::array& image_) { image = image_; } + + af::array get_color(const af::array& ray_dir) const { + auto spherical_dir = cart_to_sph_position(ray_dir); + + auto img_height = image.dims()[0]; + auto img_width = image.dims()[1]; + auto count = ray_dir.dims()[1]; + + // Spherical mapping of the direction to a pixel of the image + af::array o = spherical_dir(1, af::span); + af::array p = spherical_dir(2, af::span); + + auto x = (p / af::Pi + 1.0) * img_width / 2.0; + auto y = (o / af::Pi) * img_height; + + // Interpolate the colors of the image from the calculated pixel + // positions + af::array colors = af::approx2(image, af::moddims(y.as(f32), count), + af::moddims(x.as(f32), count), + af::interpType::AF_INTERP_CUBIC_SPLINE); + + // Zero out the color of any null rays + colors = af::moddims(colors, af::dim4(count, 3)); + af::replace(colors, !af::isNaN(colors), 0.f); + + return colors; + } +}; + +/** + * @brief Transform the array of pixels to the correct image format to display + * + * @param image + * @param width + * @param height + * @return af::array + */ +af::array rearrange_image(const af::array& image, uint32_t width, + uint32_t height) { + return af::clamp(af::moddims(image, af::dim4(width, height, 3)).T(), 0.0, + 255.0) + .as(f32) / + 255.f; +} + +/** + * @brief Returns an rgb image containing the raytraced black hole from the + * camera rays, spacetime metric, objects living in the space, and background + * + * @param initial_pos initial position from where the rays are launched + * @param initial_vel initial velocities (directions) the rays have + * @param objects the objects the rays can collide with + * @param background the background of the scene + * @param time how long are the rays traced through space + * @param steps how many steps should be taken to trace the rays path + * @param width width of the image the camera produces + * @param height height of the image the camera produces + * @param checks the intervals between steps to check if the rays have collided + * with an object + * @return af::array + */ +af::array generate_image(const af::array& initial_pos, + const af::array& initial_vel, + const std::vector >& objects, + const Background& background, uint32_t width, + uint32_t height, double time, double tol, + uint32_t checks = 10) { + uint32_t lines = initial_pos.dims()[1]; + + auto def_step = 0.5 * pow(tol, 0.25); + auto dt = af::constant(def_step, 1, lines, f64); + auto t = af::constant(0.0, 1, lines, f64); + auto index = af::iota(lines); + auto selected = t < time; + + auto result = af::constant(0, lines, 3, f32); + + auto pos = initial_pos; + auto vel = initial_vel; + + af::Window window{(int)width, (int)height, "Black Hole Raytracing"}; + + af::array bg_col = af::constant(0.f, lines, 3); + af::array begin_pos, end_pos; + af::array bh_nohit; + + if (scene != Scene::ROTATE_BH) + begin_pos = sph_to_cart_position(pos(af::seq(1, 3), af::span)); + else + begin_pos = oblate_to_cart_position(pos(af::seq(1, 3), af::span)); + end_pos = begin_pos; + + int i = 0; + + while (t.dims()[1] != 0 && af::anyTrue(t < time) && + af::anyTrue(dt != 0.0)) { + // Displays the current progress and approximate time needed to finish + // it + status_bar((lines - t.dims()[1]) * time + + af::sum(af::clamp(t, 0.0, time)), + time * lines, "Progress:"); + + // RK34 method for second order differential equation + auto dt2 = dt * dt; + auto k1 = geodesics(pos, vel); + auto k2 = geodesics(pos + vel * dt / 4.0 + k1 * dt2 / 32.0, + vel + k1 * dt / 4.0); + auto k3 = geodesics(pos + vel * dt / 2.0 + (k1 + k2) * dt2 / 16.0, + vel + k2 * dt / 2.0); + auto k4 = geodesics(pos + vel * dt + (k1 - k2 + k3 * 2.0) * dt2 / 4.0, + vel + (k1 - k2 * 2.0 + 2.0 * k3) * dt); + + auto diff4 = (k1 + k2 * 8.0 + k3 * 2.0 + k4) / 24.0; + auto diff3 = (k2 * 8.0 + k4) / 18.0; + + auto err = (af::max)(af::abs(diff4 - diff3), 0) * dt2; + auto maxerr = tol * (1.0 + (af::max)(af::abs(pos), 0)); + + auto rdt = af::constant(0, 1, dt.dims()[1], f64); + af::replace(rdt, err > maxerr, dt); + + auto rdt2 = rdt * rdt; + + pos += vel * rdt + (k1 + k2 * 8.0 + k3 * 2.0 + k4) * rdt2 / 24.0; + vel += (k1 + k3 * 4.0 + k4) * rdt / 6.0; + t += rdt; + + auto q = af::clamp(0.8 * af::pow(maxerr / err, 0.25), 0.0, 5.0); + + // Select the next time step + dt = af::select(q * dt < (time - t), q * dt, af::abs(time - t)); + + // Update image + if (i % checks == (checks - 1)) { + af::array ray_dir; + if (scene != Scene::ROTATE_BH) { + end_pos(af::span, index) = + sph_to_cart_position(pos(af::seq(1, 3), af::span)); + ray_dir = sph_to_cart_velocity(vel(af::seq(1, 3), af::span), + pos(af::seq(1, 3), af::span)); + } else { + end_pos(af::span, index) = + oblate_to_cart_position(pos(af::seq(1, 3), af::span)); + ray_dir = oblate_to_cart_velocity(vel(af::seq(1, 3), af::span), + pos(af::seq(1, 3), af::span)); + } + + af::array s_begin_pos = begin_pos(af::span, index); + af::array s_end_pos = end_pos(af::span, index); + + // Check if light ray intersect an object + for (const auto& obj : objects) { + result(index, af::span) += + obj->get_color(s_begin_pos, s_end_pos); + } + + // Update background colors from rays + bg_col(index, af::span) = background.get_color(ray_dir); + + // Display image + window.image(rearrange_image(result + bg_col, width, height)); + + begin_pos = end_pos; + } + + // Stop rays entering the event horizon + switch (scene) { + case Scene::ROTATE_BH: { + auto a = J / M; + bh_nohit = + (pos(1, af::span) > 1.01 * (M + std::sqrt(M * M - a * a))); + selected = bh_nohit && (t < time); + + break; + } + + case Scene::STATIC_BH: { + bh_nohit = pos(1, af::span) > 2.0 * M * 1.01; + selected = bh_nohit && (t < time); + + break; + } + + case Scene::WORMHOLE: { + selected = (t < time); + } + default: break; + } + + // Remove finished rays from computation + if (af::sum(selected.as(f32)) / (float)index.dims()[0] < 0.75) { + if (scene == Scene::STATIC_BH || scene == Scene::ROTATE_BH) + bg_col(af::array(index(!bh_nohit)), af::span) = 0.f; + + index = index(selected); + pos = pos(af::span, selected); + vel = vel(af::span, selected); + dt = dt(af::span, selected); + t = t(af::span, selected); + + // Free finished rays memory + af::deviceGC(); + } + + ++i; + } + + result += bg_col; + + return rearrange_image(result, width, height); +} + +void raytracing(uint32_t width, uint32_t height) { + // Set the parameters of the raytraced image + double vfov = radians(90.0); + double focal_length = 0.01; + + // Set the parameters of the camera + af::array global_vertical = af::array(3, {0.0, 0.0, 1.0}); + af::array camera_position = af::array(3, {-7.0, 6.0, 2.0}); + af::array camera_lookat = af::array(3, {0.0, 0.0, 0.0}); + double accretion_inner_radius = M * 3.0; + double accretion_outter_radius = M * 8.0; + double simulation_tolerance = 1e-6; + double max_simulation_time = 12.; + uint32_t num_steps_per_collide_check = 1; + + // Set the background of the scene + auto bg_image = + af::loadimage(ASSETS_DIR "/examples/images/westerlund.jpg", true); + auto background = Background(bg_image); + + // Set the objects living in the scene + std::vector > objects; + if (scene != Scene::WORMHOLE) + objects.push_back(std::make_unique( + af::array(3, {0.0, 0.0, 0.0}), af::array(3, {0.0, 0.0, 1.0}), + accretion_inner_radius, accretion_outter_radius)); + + // Generate rays from the camera + auto camera = Camera(camera_position, camera_lookat, vfov, focal_length, + width, height); + auto pair = camera.generate_viewport_4rays(); + + auto ray4_pos = pair.first; + auto ray4_vel = pair.second; + + auto begin = std::chrono::high_resolution_clock::now(); + // Generate raytraced image + auto image = generate_image( + ray4_pos, ray4_vel, objects, background, width, height, + max_simulation_time, simulation_tolerance, num_steps_per_collide_check); + + auto end = std::chrono::high_resolution_clock::now(); + + std::cout + << "\nSimulation took: " + << std::chrono::duration_cast(end - begin).count() + << " s" << std::endl; + + // Save image + af::saveImage("result.png", image); +} + +int main(int argc, char** argv) { + int device = argc > 1 ? std::atoi(argv[1]) : 0; + + int width = argc > 2 ? std::atoi(argv[2]) : 200; + int height = argc > 3 ? std::atoi(argv[3]) : 200; + + try { + af::setDevice(device); + af::info(); + + std::cout << "** ArrayFire Black Hole Raytracing Demo\n\n"; + + raytracing(width, height); + } catch (const af::exception& e) { + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/examples/pde/boltzmann_cfd.cpp b/examples/pde/boltzmann_cfd.cpp new file mode 100644 index 0000000000..38882f3c5c --- /dev/null +++ b/examples/pde/boltzmann_cfd.cpp @@ -0,0 +1,570 @@ +/******************************************************* + * Copyright (c) 2023, ArrayFire + * All rights reserved. + * + * This file is distributed under 3-clause BSD license. + * The complete license agreement can be obtained at: + * http://arrayfire.com/licenses/BSD-3-Clause + ********************************************************/ + +/* + This is a Computational Fluid Dynamics Simulation using the Lattice + Boltzmann Method For this simulation we are using D2N9 (2 dimensions, 9 + neighbors) with bounce-back boundary conditions For more information on the + simulation equations, check out + https://en.wikipedia.org/wiki/Lattice_Boltzmann_methods#Mathematical_equations_for_simulations + + The initial conditions of the fluid are obtained from three images that + specify their properties using the function read_initial_condition_arrays. + These images can be modified to simulate different cases +*/ + +#include +#include +#include +#include + +/* + Values of the D2N9 grid follow the following order structure: + + + -1 0 1 + * ----------------------> x + -1 | 6 3 0 + | + 0 | 7 4 1 + | + 1 | 8 5 2 + | + v + y + + The (-1, 0, 1) refer to the x and y offsets with respect to a single cell + and the (0-8) refer to indices of each cell in the 3x3 grid + + Eg. Element with index 4 is the center of the grid which has an x-offset = + ex_vals[4] = 0 and y-offset = ey_vals[4] = 0 with its quantities being + weighted with weight wt_vals[4] = 16/36 +*/ + +static const float ex_vals[] = {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}; + +static const float ey_vals[] = {1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0}; + +static const float wt_vals[] = {1.0f / 36.0f, 4.0f / 36.0f, 1.0f / 36.0f, + 4.0f / 36.0f, 16.0f / 36.0f, 4.0f / 36.0f, + 1.0f / 36.0f, 4.0f / 36.0f, 1.0f / 36.0f}; + +static const int opposite_indices[] = {8, 7, 6, 5, 4, 3, 2, 1, 0}; + +struct Simulation { + // Fluid quantities + af::array ux; + af::array uy; + af::array rho; + af::array sigma; + af::array f; + af::array feq; + + // Constant velocity boundary conditions positions + af::array set_boundaries; + + // Simulation Parameters + size_t grid_width; + size_t grid_height; + float density; + float velocity; + float reynolds; + + // Helper arrays stored for computation + af::array ex; + af::array ey; + af::array wt; + + af::array ex_T; + af::array ey_T; + af::array wt_T; + + af::array ex_; + af::array ey_; +}; + +/** + * @brief Create a simulation object containing all the initial parameters and + * condition of the simulation + * + * @details + * For the ux, uy, and boundary images, we use RGB values for to define the + * specific quantites for each grid cell/pixel + * + * /// R & B for ux & uy + * + * For ux and uy, Red means positive value while Blue means negative value. The + * speed value for both ux and uy is computed as $(R - B) * velocity / 255$. + * + * For example, for the same pixel in the two images if we had ux = RGB(255,0,0) + * and uy = RGB(0,0,255) means that cell's fluid has an x-velocity of +v and + * y-velocity of -v where v is the velocity quantity pass to this function. + * + * Note that having the same value in the R and B components will cancel each + * other out, i.e., have the fluid has 0 velocity in that direction similar to + * having it be 0. + * + * /// G for ux & uy + * + * The G component is reserved for an object or obstacle. Any non-zero value for + * the green component represents a hard boundary in the simulation + * + * /// RGB for boundary + * + * Any non-zero value for any of the components in the RGB value of the pixel + * means that the initial values passed for ux and uy will remain constant + * throught the simulation + * + */ +Simulation create_simulation(uint32_t grid_width, uint32_t grid_height, + float density, float velocity, float reynolds, + const char* ux_image_filename, + const char* uy_image_filename, + const char* boundaries_filename) { + Simulation sim; + + sim.grid_width = grid_width; + sim.grid_height = grid_height; + sim.velocity = velocity; + sim.density = density; + sim.reynolds = reynolds; + + try { + sim.ux = af::loadImage(ux_image_filename, true); + } catch (const af::exception& e) { + std::cerr << e.what() << std::endl; + sim.ux = af::constant(0, grid_width, grid_height, 3); + } + + auto ux_dim = sim.ux.dims(); + if (ux_dim[0] != grid_width || ux_dim[1] != grid_height) { + std::cerr + << "Fluid flow ux image has dimensions different to the simulation" + << std::endl; + throw std::runtime_error{ + "Fluid flow ux image has dimensions different to the simulation"}; + } + + try { + sim.uy = af::loadImage(uy_image_filename, true); + } catch (const af::exception& e) { + std::cerr << e.what() << std::endl; + sim.uy = af::constant(0, grid_width, grid_height, 3); + } + + auto uy_dim = sim.uy.dims(); + if (uy_dim[0] != grid_width || uy_dim[1] != grid_height) { + std::cerr + << "Fluid flow uy image has dimensions different to the simulation" + << std::endl; + throw std::runtime_error{ + "Fluid flow uy image has dimensions different to the simulation"}; + } + + try { + sim.set_boundaries = af::loadImage(boundaries_filename, false); + } catch (const af::exception& e) { + std::cerr << e.what() << std::endl; + sim.set_boundaries = af::constant(0, grid_width, grid_height); + } + + auto b_dim = sim.set_boundaries.dims(); + if (b_dim[0] != grid_width || b_dim[1] != grid_height) { + std::cerr + << "Fluid boundary image has dimensions different to the simulation" + << std::endl; + throw std::runtime_error{ + "Fluid boundary image has dimensions different to the simulation"}; + } + + sim.ux = (sim.ux(af::span, af::span, 0).T() - + sim.ux(af::span, af::span, 2).T()) * + velocity / 255.f; + sim.uy = (sim.uy(af::span, af::span, 0).T() - + sim.uy(af::span, af::span, 2).T()) * + velocity / 255.f; + sim.set_boundaries = sim.set_boundaries.T() > 0; + + return sim; +} + +/** + * @brief Initializes internal values used for computation + * + */ +void initialize(Simulation& sim) { + auto& ux = sim.ux; + auto& uy = sim.uy; + auto& rho = sim.rho; + auto& sigma = sim.sigma; + auto& f = sim.f; + auto& feq = sim.feq; + + auto& ex = sim.ex; + auto& ey = sim.ey; + auto& wt = sim.wt; + auto& ex_ = sim.ex_; + auto& ey_ = sim.ey_; + auto& ex_T = sim.ex_T; + auto& ey_T = sim.ey_T; + auto& wt_T = sim.wt_T; + + auto density = sim.density; + auto velocity = sim.velocity; + auto xcount = sim.grid_width; + auto ycount = sim.grid_height; + + ex = af::array(1, 1, 9, ex_vals); + ey = af::array(1, 1, 9, ey_vals); + wt = af::array(1, 1, 9, wt_vals); + + ex_T = af::array(1, 9, ex_vals); + ey_T = af::array(1, 9, ey_vals); + wt_T = af::moddims(wt, af::dim4(1, 9)); + + rho = af::constant(density, xcount, ycount, f32); + sigma = af::constant(0, xcount, ycount, f32); + + f = af::constant(0, xcount, ycount, 9, f32); + + ex_ = af::tile(ex, xcount, ycount, 1); + ey_ = af::tile(ey, xcount, ycount, 1); + + // Initialization of the distribution function + auto edotu = ex_ * ux + ey_ * uy; + auto udotu = ux * ux + uy * uy; + + feq = rho * wt * + ((edotu * edotu * 4.5f) - (udotu * 1.5f) + (edotu * 3.0f) + 1.0f); + f = feq; +} + +/** + * @brief Updates the particle distribution functions for the new simulation + * frame + * + */ +void collide_stream(Simulation& sim) { + auto& ux = sim.ux; + auto& uy = sim.uy; + auto& rho = sim.rho; + auto& sigma = sim.sigma; + auto& f = sim.f; + auto& feq = sim.feq; + auto& set_boundaries = sim.set_boundaries; + + auto& ex = sim.ex; + auto& ey = sim.ey; + auto& wt = sim.wt; + auto& ex_ = sim.ex_; + auto& ey_ = sim.ey_; + auto& ex_T = sim.ex_T; + auto& ey_T = sim.ey_T; + auto& wt_T = sim.wt_T; + + auto density = sim.density; + auto velocity = sim.velocity; + auto reynolds = sim.reynolds; + auto xcount = sim.grid_width; + auto ycount = sim.grid_height; + + const float viscosity = + velocity * std::sqrt(static_cast(xcount * ycount)) / reynolds; + const float tau = 0.5f + 3.0f * viscosity; + const float csky = 0.16f; + + auto edotu = ex_ * ux + ey_ * uy; + auto udotu = ux * ux + uy * uy; + + // Compute the new distribution function + feq = + rho * wt * (edotu * edotu * 4.5f - udotu * 1.5f + edotu * 3.0f + 1.0f); + + auto taut = + af::sqrt(sigma * (csky * csky * 18.0f * 0.25f) + (tau * tau * 0.25f)) - + (tau * 0.5f); + + // Compute the shifted distribution functions + auto fplus = f - (f - feq) / (taut + tau); + + // Compute new particle distribution according to the corresponding D2N9 + // weights + for (int i = 0; i < 9; ++i) { + int xshift = static_cast(ex_vals[i]); + int yshift = static_cast(ey_vals[i]); + + fplus(af::span, af::span, i) = + af::shift(fplus(af::span, af::span, i), xshift, yshift); + } + + // Keep the boundary conditions at the borders the same + af::replace(fplus, af::tile(!set_boundaries, af::dim4(1, 1, 9)), f); + + // Update the particle distribution + f = fplus; + + // Computing u dot e at the each of the boundaries + af::array ux_top = ux.rows(0, 2); + ux_top = + af::moddims(af::tile(ux_top, af::dim4(1, 3)).T(), af::dim4(ycount, 9)); + af::array ux_bot = ux.rows(xcount - 3, xcount - 1); + ux_bot = + af::moddims(af::tile(ux_bot, af::dim4(1, 3)).T(), af::dim4(ycount, 9)); + + af::array uy_top = uy.rows(0, 2); + uy_top = + af::moddims(af::tile(uy_top, af::dim4(1, 3)).T(), af::dim4(ycount, 9)); + af::array uy_bot = uy.rows(xcount - 3, xcount - 1); + uy_bot = + af::moddims(af::tile(uy_bot, af::dim4(1, 3)).T(), af::dim4(ycount, 9)); + + auto ux_lft = af::tile(ux.cols(0, 2), af::dim4(1, 3)); + auto uy_lft = af::tile(uy.cols(0, 2), af::dim4(1, 3)); + auto ux_rht = af::tile(ux.cols(ycount - 3, ycount - 1), af::dim4(1, 3)); + auto uy_rht = af::tile(uy.cols(ycount - 3, ycount - 1), af::dim4(1, 3)); + + auto ubdoute_top = ux_top * ex_T + uy_top * ey_T; + auto ubdoute_bot = ux_bot * ex_T + uy_bot * ey_T; + auto ubdoute_lft = ux_lft * ex_T + uy_lft * ey_T; + auto ubdoute_rht = ux_rht * ex_T + uy_rht * ey_T; + + // Computing bounce-back boundary conditions + auto fnew_top = af::moddims(fplus.row(1), af::dim4(ycount, 9)) - + 6.0 * density * wt_T * ubdoute_top; + auto fnew_bot = af::moddims(fplus.row(xcount - 2), af::dim4(ycount, 9)) - + 6.0 * density * wt_T * ubdoute_bot; + auto fnew_lft = af::moddims(fplus.col(1), af::dim4(xcount, 9)) - + 6.0 * density * wt_T * ubdoute_lft; + auto fnew_rht = af::moddims(fplus.col(ycount - 2), af::dim4(xcount, 9)) - + 6.0 * density * wt_T * ubdoute_rht; + + // Update the values near the boundaries with the correct bounce-back + // boundary + for (int i = 0; i < 9; ++i) { + int xshift = static_cast(ex_vals[i]); + int yshift = static_cast(ey_vals[i]); + if (xshift == 1) + f(1, af::span, opposite_indices[i]) = fnew_top(af::span, i); + if (xshift == -1) + f(xcount - 2, af::span, opposite_indices[i]) = + fnew_bot(af::span, i); + if (yshift == 1) + f(af::span, 1, opposite_indices[i]) = fnew_lft(af::span, i); + if (yshift == -1) + f(af::span, ycount - 2, opposite_indices[i]) = + fnew_rht(af::span, i); + } +} + +/** + * @brief Updates the velocity field, density and strain at each point in the + * grid + * + */ +void update(Simulation& sim) { + auto& ux = sim.ux; + auto& uy = sim.uy; + auto& rho = sim.rho; + auto& sigma = sim.sigma; + auto& f = sim.f; + auto& feq = sim.feq; + auto& ex = sim.ex; + auto& ey = sim.ey; + + auto e_tile = af::join(3, af::constant(1, 1, 1, 9), ex, ey); + auto result = af::sum(f * e_tile, 2); + + rho = result(af::span, af::span, af::span, 0); + result /= rho; + ux = result(af::span, af::span, af::span, 1); + uy = result(af::span, af::span, af::span, 2); + + // Above code equivalent to + // rho = af::sum(f, 2); + // ux = af::sum(f * ex, 2) / rho; + // uy = af::sum(f * ey, 2) / rho; + + auto product = f - feq; + auto e_product = af::join(3, ex * ex, ex * ey * std::sqrt(2), ey * ey); + + sigma = af::sqrt(af::sum(af::pow(af::sum(product * e_product, 2), 2), 3)); + + // Above code equivalent to + + // auto xx = af::sum(product * ex * ex, 2); + // auto xy = af::sum(product * ex * ey, 2); + // auto yy = af::sum(product * ey * ey, 2); + + // sigma = af::sqrt(xx * xx + xy * xy * 2 + yy * yy); +} + +af::array generate_image(size_t width, size_t height, const Simulation& sim) { + const auto& ux = sim.ux; + const auto& uy = sim.uy; + const auto& boundaries = sim.set_boundaries; + auto velocity = sim.velocity; + + float image_scale = + static_cast(width) / static_cast(sim.grid_width - 1); + + // Relative Flow speed at each cell + auto val = af::sqrt(ux * ux + uy * uy) / velocity; + + af::replace(val, val != 0 || !boundaries, -1.0); + + // Scaling and interpolating flow speed to the window size + if (width != sim.grid_width || height != sim.grid_height) + val = + af::approx2(val, af::iota(width, af::dim4(1, height)) / image_scale, + af::iota(height, af::dim4(1, width)).T() / image_scale); + + // Flip image + val = val.T(); + + auto image = af::constant(0, height, width, 3); + auto image2 = image; + + // Add custom coloring + image(af::span, af::span, 0) = val * 2; + image(af::span, af::span, 1) = val * 2; + image(af::span, af::span, 2) = 1.0 - val * 2; + + image2(af::span, af::span, 0) = 1; + image2(af::span, af::span, 1) = -2 * val + 2; + image2(af::span, af::span, 2) = 0; + + auto tile_val = af::tile(val, 1, 1, 3); + af::replace(image, tile_val < 0.5, image2); + af::replace(image, tile_val >= 0, 0.0); + + return image; +} + +void lattice_boltzmann_cfd_demo() { + // Define the lattice for the simulation + const size_t len = 128; + const size_t grid_width = len; + const size_t grid_height = len; + + // Specify the image scaling displayed + float scale = 4.0f; + + // Forge window initialization + int height = static_cast(grid_width * scale); + int width = static_cast(grid_height * scale); + af::Window window(height, width, "Driven Cavity Flow"); + + int frame_count = 0; + int max_frames = 20000; + int simulation_frames = 100; + float total_time = 0; + float total_time2 = 0; + + // CFD fluid parameters + const float density = 2.7f; + const float velocity = 0.35f; + const float reynolds = 1e5f; + + const char* ux_image = ASSETS_DIR "/examples/images/default_ux.bmp"; + const char* uy_image = ASSETS_DIR "/examples/images/default_uy.bmp"; + const char* set_boundary_image = + ASSETS_DIR "/examples/images/default_boundary.bmp"; + + // Tesla Valve Fluid Simulation - entering from constricted side + { + // ux_image = ASSETS_DIR "/examples/images/left_tesla_ux.bmp"; + // uy_image = ASSETS_DIR "/examples/images/left_tesla_uy.bmp"; + // set_boundary_image = ASSETS_DIR + // "/examples/images/left_tesla_boundary.bmp"; + } + + // Tesla Valve Fluid Simulation - entering from transfer side + { + // ux_image = ASSETS_DIR + // "/examples/images/right_tesla_ux.bmp"; uy_image = + // ASSETS_DIR "/examples/images/right_tesla_uy.bmp"; + // set_boundary_image = ASSETS_DIR + // "/examples/images/right_tesla_boundary.bmp"; + } + + // Reads the initial values of fluid quantites and simulation parameters + Simulation sim = + create_simulation(grid_width, grid_height, density, velocity, reynolds, + ux_image, uy_image, set_boundary_image); + + // Initializes the simulation quantites + initialize(sim); + + while (!window.close() && frame_count != max_frames) { + af::sync(); + auto begin = std::chrono::high_resolution_clock::now(); + + // Computes the new particle distribution functions for the new + // simulation frame + collide_stream(sim); + + // Updates the velocity, density, and stress fields + update(sim); + + af::sync(); + auto end = std::chrono::high_resolution_clock::now(); + + // Calculate computation time of 1 simulation frame + auto duration = + std::chrono::duration_cast(end - begin) + .count(); + + // Used for computing the distribution of frame computation time + total_time += duration; + total_time2 += duration * duration; + + // Every number of `simulation_frames` display the last computed frame + // to the screen + if (frame_count % simulation_frames == 0) { + auto image = generate_image(width, height, sim); + + // Display colored image + window.image(image); + + float avg_time = total_time / (float)simulation_frames; + float stdv_time = std::sqrt(total_time2 * simulation_frames - + total_time * total_time) / + (float)simulation_frames; + + std::cout << "Average Simulation Step Time: (" << avg_time + << " +/- " << stdv_time + << ") us; Total simulation time: " << total_time + << " us; Simulation Frames: " << simulation_frames + << std::endl; + + total_time = 0; + total_time2 = 0; + } + + frame_count++; + } +} + +int main(int argc, char** argv) { + int device = argc > 1 ? std::atoi(argv[1]) : 0; + + try { + af::setDevice(device); + af::info(); + + std::cout << "** ArrayFire CFD Simulation Demo\n\n"; + + lattice_boltzmann_cfd_demo(); + } catch (const af::exception& e) { + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/examples/unified/CMakeLists.txt b/examples/unified/CMakeLists.txt index 42ab6432f0..a399f58c00 100644 --- a/examples/unified/CMakeLists.txt +++ b/examples/unified/CMakeLists.txt @@ -10,7 +10,7 @@ project(ArrayFire-Example-Unified VERSION 3.5.0 LANGUAGES CXX) -find_package(ArrayFire) +find_package(ArrayFire REQUIRED) if(ArrayFire_Unified_FOUND) # Simple unified backend example diff --git a/include/af/arith.h b/include/af/arith.h index 9b02e668b6..c75544a5ab 100644 --- a/include/af/arith.h +++ b/include/af/arith.h @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -80,7 +80,7 @@ namespace af /// \param[in] lo lower limit; can be an array or a scalar /// \param[in] hi upper limit; can be an array or a scalar /// \return clamped array - /// + /// /// \ingroup arith_func_clamp AFAPI array clamp(const array &in, const array &lo, const array &hi); #endif @@ -104,10 +104,13 @@ namespace af /// @{ /// C++ Interface to calculate the remainder. /// + /// For integers, it returns the same output as modulus (% operator) + /// For floating point numbers, it returns the same as std::remainder from + /// /// \param[in] lhs numerator; can be an array or a scalar /// \param[in] rhs denominator; can be an array or a scalar /// \return remainder - /// + /// /// \ingroup arith_func_rem AFAPI array rem (const array &lhs, const array &rhs); @@ -121,10 +124,13 @@ namespace af /// @{ /// C++ Interface to calculate the modulus. /// + /// For integers, it returns the same output as modulus (% operator) + /// For floating point numbers, it returns the same as std::fmod from + /// /// \param[in] lhs dividend; can be an array or a scalar /// \param[in] rhs divisor; can be an array or a scalar /// \return modulus - /// + /// /// \ingroup arith_func_mod AFAPI array mod (const array &lhs, const array &rhs); @@ -148,7 +154,7 @@ namespace af /// /// \param[in] in input array, typically complex /// \return phase angle (in radians) - /// + /// /// \ingroup arith_func_arg AFAPI array arg (const array &in); @@ -156,7 +162,7 @@ namespace af /// /// \param[in] in input array /// \return array containing 1's for negative values; 0's otherwise - /// + /// /// \ingroup arith_func_sign AFAPI array sign (const array &in); @@ -172,7 +178,7 @@ namespace af /// /// \param[in] in input array /// \return nearest integer not greater in magnitude than `in` - /// + /// /// \ingroup arith_func_trunc AFAPI array trunc (const array &in); @@ -330,7 +336,7 @@ namespace af /// \param[in] in input array /// \return complex array AFAPI array complex(const array& in); - + /// C++ Interface to create a complex array from two real arrays. /// /// \param[in] real_ input array to be assigned as the real component of @@ -412,7 +418,6 @@ namespace af /// \ingroup arith_func_root AFAPI array root (const double nth_root, const array &value); - /// \ingroup arith_func_pow /// @{ /// C++ Interface to raise a base to a power (or exponent). @@ -435,7 +440,6 @@ namespace af /// /// \param[in] in power /// \return 2 raised to the power - /// AFAPI array pow2 (const array &in); /// @} @@ -443,7 +447,7 @@ namespace af /// C++ Interface to evaluate the logistical sigmoid function. /// /// Computes \f$\frac{1}{1+e^{-x}}\f$. - /// + /// /// \param[in] in input /// \return sigmoid /// @@ -463,7 +467,7 @@ namespace af /// `exp(in) - 1`. /// /// This function is useful when `in` is small. - /// + /// /// \param[in] in exponent /// \return exponential minus 1 /// @@ -496,9 +500,9 @@ namespace af /// C++ Interface to evaluate the natural logarithm of 1 + input, /// `ln(1+in)`. - /// + /// /// This function is useful when `in` is small. - /// + /// /// \param[in] in input /// \return natural logarithm of `1 + input` /// @@ -904,21 +908,22 @@ extern "C" { be performed by ArrayFire. The following table shows which casts will be optimized out. outer -> inner -> outer - | inner-> | f32 | f64 | c32 | c64 | s32 | u32 | u8 | b8 | s64 | u64 | s16 | u16 | f16 | - |---------|-----|-----|-----|-----|-----|-----|----|----|-----|-----|-----|-----|-----| - | f32 | x | x | x | x | | | | | | | | | x | - | f64 | x | x | x | x | | | | | | | | | x | - | c32 | x | x | x | x | | | | | | | | | x | - | c64 | x | x | x | x | | | | | | | | | x | - | s32 | x | x | x | x | x | x | | | x | x | | | x | - | u32 | x | x | x | x | x | x | | | x | x | | | x | - | u8 | x | x | x | x | x | x | x | x | x | x | x | x | x | - | b8 | x | x | x | x | x | x | x | x | x | x | x | x | x | - | s64 | x | x | x | x | | | | | x | x | | | x | - | u64 | x | x | x | x | | | | | x | x | | | x | - | s16 | x | x | x | x | x | x | | | x | x | x | x | x | - | u16 | x | x | x | x | x | x | | | x | x | x | x | x | - | f16 | x | x | x | x | | | | | | | | | x | + | inner-> | f32 | f64 | c32 | c64 | s32 | u32 | s8 | u8 | b8 | s64 | u64 | s16 | u16 | f16 | + |---------|-----|-----|-----|-----|-----|-----|----|----|----|-----|-----|-----|-----|-----| + | f32 | x | x | x | x | | | | | | | | | | x | + | f64 | x | x | x | x | | | | | | | | | | x | + | c32 | x | x | x | x | | | | | | | | | | x | + | c64 | x | x | x | x | | | | | | | | | | x | + | s32 | x | x | x | x | x | x | | | | x | x | | | x | + | u32 | x | x | x | x | x | x | | | | x | x | | | x | + | s8 | x | x | x | x | x | x | x | x | x | x | x | x | x | x | + | u8 | x | x | x | x | x | x | x | x | x | x | x | x | x | x | + | b8 | x | x | x | x | x | x | x | x | x | x | x | x | x | x | + | s64 | x | x | x | x | | | | | | x | x | | | x | + | u64 | x | x | x | x | | | | | | x | x | | | x | + | s16 | x | x | x | x | x | x | | | | x | x | x | x | x | + | u16 | x | x | x | x | x | x | | | | x | x | x | x | x | + | f16 | x | x | x | x | | | | | | | | | | x | If you want to avoid this behavior use, af_eval after the first cast operation. This will ensure that the cast operation is performed on the @@ -984,6 +989,9 @@ extern "C" { /** C Interface to calculate the remainder. + For integers, it returns the same output as modulus (% operator) + For floating point numbers, it returns the same as `remainder` from + \param[out] out remainder \param[in] lhs numerator \param[in] rhs denominator @@ -998,6 +1006,9 @@ extern "C" { /** C Interface to calculate the modulus. + For integers, it returns the same output as modulus (% operator) + For floating point numbers, it returns the same as `fmod` from + \param[out] out modulus \param[in] lhs dividend \param[in] rhs divisor diff --git a/include/af/array.h b/include/af/array.h index 0edb9558e1..672c2716eb 100644 --- a/include/af/array.h +++ b/include/af/array.h @@ -71,7 +71,7 @@ namespace af operator array() const; operator array(); -#define ASSIGN(OP) \ +#define ASSIGN_(OP) \ array_proxy& operator OP(const array_proxy &a); \ array_proxy& operator OP(const array &a); \ array_proxy& operator OP(const double &a); \ @@ -88,17 +88,25 @@ namespace af array_proxy& operator OP(const long long &a); \ array_proxy& operator OP(const unsigned long long &a); - ASSIGN(=) - ASSIGN(+=) - ASSIGN(-=) - ASSIGN(*=) - ASSIGN(/=) -#undef ASSIGN - #if AF_API_VERSION >= 32 -#define ASSIGN(OP) \ +#define ASSIGN_32(OP) \ array_proxy& operator OP(const short &a); \ array_proxy& operator OP(const unsigned short &a); +#else +#define ASSIGN_32(OP) +#endif + +#if AF_API_VERSION >= 310 +#define ASSIGN_310(OP) \ + array_proxy& operator OP(const signed char &a); +#else +#define ASSIGN_310(OP) +#endif + +#define ASSIGN(OP) \ + ASSIGN_(OP) \ + ASSIGN_32(OP) \ + ASSIGN_310(OP) ASSIGN(=) ASSIGN(+=) @@ -106,7 +114,9 @@ namespace af ASSIGN(*=) ASSIGN(/=) #undef ASSIGN -#endif +#undef ASSIGN_ +#undef ASSIGN_32 +#undef ASSIGN_310 // af::array member functions. same behavior as those below af_array get(); @@ -655,6 +665,7 @@ namespace af /** Perform deep copy from host/device pointer to an existing array + \note Unlike all other assignment operations, this does NOT result in a copy on write. */ template void write(const T *ptr, const size_t bytes, af::source src = afHost); @@ -761,8 +772,8 @@ namespace af bool isfloating() const; /** - \brief Returns true if the array type is \ref u8, \ref b8, \ref s32 - \ref u32, \ref s64, \ref u64, \ref s16, \ref u16 + \brief Returns true if the array type is \ref s8, \ref u8, \ref b8, + \ref s32, \ref u32, \ref s64, \ref u64, \ref s16, \ref u16 */ bool isinteger() const; @@ -946,27 +957,28 @@ namespace af /// \brief Casts the array into another data type /// - /// \note Consecitive casting operations may be may be optimized out if + /// \note Consecutive casting operations may be optimized out if /// the original type of the af::array is the same as the final type. /// For example if the original type is f64 which is then cast to f32 /// and then back to f64, then the cast to f32 will be skipped and that /// operation will *NOT* be performed by ArrayFire. The following table /// shows which casts will be optimized out. outer -> inner -> outer - /// | inner-> | f32 | f64 | c32 | c64 | s32 | u32 | u8 | b8 | s64 | u64 | s16 | u16 | f16 | - /// |---------|-----|-----|-----|-----|-----|-----|----|----|-----|-----|-----|-----|-----| - /// | f32 | x | x | x | x | | | | | | | | | x | - /// | f64 | x | x | x | x | | | | | | | | | x | - /// | c32 | x | x | x | x | | | | | | | | | x | - /// | c64 | x | x | x | x | | | | | | | | | x | - /// | s32 | x | x | x | x | x | x | | | x | x | | | x | - /// | u32 | x | x | x | x | x | x | | | x | x | | | x | - /// | u8 | x | x | x | x | x | x | x | x | x | x | x | x | x | - /// | b8 | x | x | x | x | x | x | x | x | x | x | x | x | x | - /// | s64 | x | x | x | x | | | | | x | x | | | x | - /// | u64 | x | x | x | x | | | | | x | x | | | x | - /// | s16 | x | x | x | x | x | x | | | x | x | x | x | x | - /// | u16 | x | x | x | x | x | x | | | x | x | x | x | x | - /// | f16 | x | x | x | x | | | | | | | | | x | + /// | inner-> | f32 | f64 | c32 | c64 | s32 | u32 | s8 | u8 | b8 | s64 | u64 | s16 | u16 | f16 | + /// |---------|-----|-----|-----|-----|-----|-----|----|----|----|-----|-----|-----|-----|-----| + /// | f32 | x | x | x | x | | | | | | | | | | x | + /// | f64 | x | x | x | x | | | | | | | | | | x | + /// | c32 | x | x | x | x | | | | | | | | | | x | + /// | c64 | x | x | x | x | | | | | | | | | | x | + /// | s32 | x | x | x | x | x | x | | | | x | x | | | x | + /// | u32 | x | x | x | x | x | x | | | | x | x | | | x | + /// | s8 | x | x | x | x | x | x | x | x | x | x | x | x | x | x | + /// | u8 | x | x | x | x | x | x | x | x | x | x | x | x | x | x | + /// | b8 | x | x | x | x | x | x | x | x | x | x | x | x | x | x | + /// | s64 | x | x | x | x | | | | | | x | x | | | x | + /// | u64 | x | x | x | x | | | | | | x | x | | | x | + /// | s16 | x | x | x | x | x | x | | | | x | x | x | x | x | + /// | u16 | x | x | x | x | x | x | | | | x | x | x | x | x | + /// | f16 | x | x | x | x | | | | | | | | | | x | /// If you want to avoid this behavior use af_eval after the first cast /// operation. This will ensure that the cast operation is performed on /// the af::array @@ -1003,17 +1015,25 @@ namespace af array& OP2(const long long &val); /**< \copydoc OP2##(const array &) */ \ array& OP2(const unsigned long long &val); - #if AF_API_VERSION >= 32 -#define ASSIGN(OP) \ - ASSIGN_(OP) \ - array& OP(const short &val); /**< \copydoc OP##(const array &) */ \ - array& OP(const unsigned short &val); +#define ASSIGN_32(OP) \ + array& OP(const short &val); /**< \copydoc OP##(const array &) */ \ + array& OP(const unsigned short &val); +#else +#define ASSIGN_32(OP) +#endif +#if AF_API_VERSION >= 310 +#define ASSIGN_310(OP) \ + array& OP(const signed char &val); /**< \copydoc OP##(const array &) */ #else -#define ASSIGN(OP) ASSIGN_(OP) +#define ASSIGN_310(OP) #endif +#define ASSIGN(OP) \ + ASSIGN_(OP) \ + ASSIGN_32(OP) \ + ASSIGN_310(OP) /// \ingroup array_mem_operator_eq /// @{ @@ -1079,6 +1099,8 @@ namespace af #undef ASSIGN #undef ASSIGN_ +#undef ASSIGN_32 +#undef ASSIGN_310 /// /// \brief Negates the values of the array @@ -1167,17 +1189,29 @@ namespace af AFAPI array OP (const array& lhs, const cdouble& rhs); #if AF_API_VERSION >= 32 -#define BIN_OP(OP) \ - BIN_OP_(OP) \ +#define BIN_OP_32(OP) \ AFAPI array OP (const short& lhs, const array& rhs); /**< \copydoc OP##(const array&, const array&) */ \ AFAPI array OP (const unsigned short& lhs, const array& rhs); /**< \copydoc OP##(const array&, const array&) */ \ AFAPI array OP (const array& lhs, const short& rhs); /**< \copydoc OP##(const array&, const array&) */ \ AFAPI array OP (const array& lhs, const unsigned short& rhs); #else -#define BIN_OP(OP) BIN_OP_(OP) +#define BIN_OP_32(OP) #endif +#if AF_API_VERSION >= 310 +#define BIN_OP_310(OP) \ + AFAPI array OP (const signed char& lhs, const array& rhs); /**< \copydoc OP##(const array&, const array&) */ \ + AFAPI array OP (const array& lhs, const signed char& rhs); /**< \copydoc OP##(const array&, const array&) */ +#else +#define BIN_OP_310(OP) +#endif + +#define BIN_OP(OP) \ + BIN_OP_(OP) \ + BIN_OP_32(OP) \ + BIN_OP_310(OP) + /// \ingroup arith_func_add /// @{ /// \brief Adds two arrays or an array and a value. @@ -1371,6 +1405,8 @@ namespace af #undef BIN_OP #undef BIN_OP_ +#undef BIN_OP_32 +#undef BIN_OP_310 /// \ingroup arith_func_bitand /// @{ @@ -1393,6 +1429,7 @@ namespace af AFAPI array operator&(const array& lhs, const long long& rhs); AFAPI array operator&(const array& lhs, const long& rhs); AFAPI array operator&(const array& lhs, const short& rhs); + AFAPI array operator&(const array& lhs, const signed char& rhs); AFAPI array operator&(const array& lhs, const unsigned char& rhs); AFAPI array operator&(const array& lhs, const unsigned long long& rhs); AFAPI array operator&(const array& lhs, const unsigned long& rhs); @@ -1408,6 +1445,7 @@ namespace af AFAPI array operator&(const long long& lhs, const array& rhs); AFAPI array operator&(const long& lhs, const array& rhs); AFAPI array operator&(const short& lhs, const array& rhs); + AFAPI array operator&(const signed char& lhs, const array& rhs); AFAPI array operator&(const unsigned char& lhs, const array& rhs); AFAPI array operator&(const unsigned long long& lhs, const array& rhs); AFAPI array operator&(const unsigned long& lhs, const array& rhs); @@ -1436,6 +1474,7 @@ namespace af AFAPI array operator&&(const array& lhs, const long long& rhs); AFAPI array operator&&(const array& lhs, const long& rhs); AFAPI array operator&&(const array& lhs, const short& rhs); + AFAPI array operator&&(const array& lhs, const signed char& rhs); AFAPI array operator&&(const array& lhs, const unsigned char& rhs); AFAPI array operator&&(const array& lhs, const unsigned long long& rhs); AFAPI array operator&&(const array& lhs, const unsigned long& rhs); @@ -1451,6 +1490,7 @@ namespace af AFAPI array operator&&(const long long& lhs, const array& rhs); AFAPI array operator&&(const long& lhs, const array& rhs); AFAPI array operator&&(const short& lhs, const array& rhs); + AFAPI array operator&&(const signed char& lhs, const array& rhs); AFAPI array operator&&(const unsigned char& lhs, const array& rhs); AFAPI array operator&&(const unsigned long long& lhs, const array& rhs); AFAPI array operator&&(const unsigned long& lhs, const array& rhs); diff --git a/include/af/blas.h b/include/af/blas.h index 4580ea2112..05434ee861 100644 --- a/include/af/blas.h +++ b/include/af/blas.h @@ -242,6 +242,14 @@ extern "C" { \snippet test/blas.cpp ex_af_gemm_overwrite + \note s8 Support + \note Starting with ArrayFire version v3.10.0, the CUDA backend supports + \p A, \p B input arrays of type \ref s8. + \note Scalars \p alpha, \p beta must be of type \ref f32. + \note Output array \p C will be of type \ref f32. + \note
Requires + \note CUDA version >= 10 on devices with compute capability >= 5.0 + \param[in,out] C `A` * `B` = `C` \param[in] opA operation to perform on A before the multiplication \param[in] opB operation to perform on B before the multiplication diff --git a/include/af/defines.h b/include/af/defines.h index da6c5591de..42f71024fa 100644 --- a/include/af/defines.h +++ b/include/af/defines.h @@ -227,6 +227,9 @@ typedef enum { #if AF_API_VERSION >= 37 , f16 ///< 16-bit floating point value #endif +#if AF_API_VERSION >= 310 + , s8 ///< 8-bit signed integral values +#endif } af_dtype; typedef enum { diff --git a/include/af/index.h b/include/af/index.h index 3bceb96cbf..8eaaeaa0a5 100644 --- a/include/af/index.h +++ b/include/af/index.h @@ -274,7 +274,7 @@ extern "C" { /// the sequences /// \param[in] lhs is the input array /// \param[in] ndims is the number of \ref af_index_t provided - /// \param[in] indices is an af_array of \ref af_index_t objects + /// \param[in] indices is a C array of \ref af_index_t objects /// \param[in] rhs is the array whose values will be assigned to \p lhs /// /// \ingroup index_func_assign diff --git a/include/af/traits.hpp b/include/af/traits.hpp index 6c7d1bf5fa..4216c3f046 100644 --- a/include/af/traits.hpp +++ b/include/af/traits.hpp @@ -175,6 +175,18 @@ struct dtype_traits { static const char* getName() { return "half"; } }; #endif + +#if AF_API_VERSION >= 310 +template<> +struct dtype_traits { + enum { + af_type = s8 , + ctype = f32 + }; + typedef signed char base_type; + static const char* getName() { return "schar"; } +}; +#endif } #endif diff --git a/src/api/c/CMakeLists.txt b/src/api/c/CMakeLists.txt index 870d687382..d374b9a669 100644 --- a/src/api/c/CMakeLists.txt +++ b/src/api/c/CMakeLists.txt @@ -186,10 +186,6 @@ if(FreeImage_FOUND AND AF_WITH_IMAGEIO) endif() if(BUILD_WITH_MKL) - target_compile_definitions(c_api_interface - INTERFACE - AF_MKL_INTERFACE_SIZE=${MKL_INTERFACE_INTEGER_SIZE} - ) # Create mkl thread layer compile option based on cmake cache variable if(MKL_THREAD_LAYER STREQUAL "Sequential") target_compile_definitions(c_api_interface INTERFACE AF_MKL_THREAD_LAYER=0) diff --git a/src/api/c/anisotropic_diffusion.cpp b/src/api/c/anisotropic_diffusion.cpp index 3c77f8644c..6268accb3b 100644 --- a/src/api/c/anisotropic_diffusion.cpp +++ b/src/api/c/anisotropic_diffusion.cpp @@ -90,6 +90,7 @@ af_err af_anisotropic_diffusion(af_array* out, const af_array in, case u32: case s16: case u16: + case s8: case u8: output = diffusion(input, dt, K, iterations, F, eq); break; diff --git a/src/api/c/array.cpp b/src/api/c/array.cpp index 4e1877e364..d164faabdb 100644 --- a/src/api/c/array.cpp +++ b/src/api/c/array.cpp @@ -30,6 +30,7 @@ using detail::cdouble; using detail::cfloat; using detail::createDeviceDataArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -47,6 +48,7 @@ af_err af_get_data_ptr(void *data, const af_array arr) { case b8: copyData(static_cast(data), arr); break; case s32: copyData(static_cast(data), arr); break; case u32: copyData(static_cast(data), arr); break; + case s8: copyData(static_cast(data), arr); break; case u8: copyData(static_cast(data), arr); break; case s64: copyData(static_cast(data), arr); break; case u64: copyData(static_cast(data), arr); break; @@ -96,6 +98,9 @@ af_err af_create_array(af_array *result, const void *const data, case u32: out = createHandleFromData(d, static_cast(data)); break; + case s8: + out = createHandleFromData(d, static_cast(data)); + break; case u8: out = createHandleFromData(d, static_cast(data)); break; @@ -175,6 +180,7 @@ af_err af_copy_array(af_array *out, const af_array in) { case b8: res = copyArray(in); break; case s32: res = copyArray(in); break; case u32: res = copyArray(in); break; + case s8: res = copyArray(in); break; case u8: res = copyArray(in); break; case s64: res = copyArray(in); break; case u64: res = copyArray(in); break; @@ -205,6 +211,7 @@ af_err af_get_data_ref_count(int *use_count, const af_array in) { case b8: res = getUseCount(in); break; case s32: res = getUseCount(in); break; case u32: res = getUseCount(in); break; + case s8: res = getUseCount(in); break; case u8: res = getUseCount(in); break; case s64: res = getUseCount(in); break; case u64: res = getUseCount(in); break; @@ -242,6 +249,7 @@ af_err af_release_array(af_array arr) { case b8: releaseHandle(arr); break; case s32: releaseHandle(arr); break; case u32: releaseHandle(arr); break; + case s8: releaseHandle(arr); break; case u8: releaseHandle(arr); break; case s64: releaseHandle(arr); break; case u64: releaseHandle(arr); break; @@ -308,6 +316,9 @@ af_err af_write_array(af_array arr, const void *data, const size_t bytes, case u32: write_array(arr, static_cast(data), bytes, src); break; + case s8: + write_array(arr, static_cast(data), bytes, src); + break; case u8: write_array(arr, static_cast(data), bytes, src); break; @@ -433,6 +444,9 @@ af_err af_get_scalar(void *output_value, const af_array arr) { case u32: getScalar(reinterpret_cast(output_value), arr); break; + case s8: + getScalar(reinterpret_cast(output_value), arr); + break; case u8: getScalar(reinterpret_cast(output_value), arr); break; diff --git a/src/api/c/assign.cpp b/src/api/c/assign.cpp index e53b43a6c5..bdf505048d 100644 --- a/src/api/c/assign.cpp +++ b/src/api/c/assign.cpp @@ -42,6 +42,7 @@ using detail::cdouble; using detail::cfloat; using detail::createSubArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -122,6 +123,7 @@ static if_real assign(Array& out, const vector iv, case u64: assign(out, iv, getArray(in)); break; case s16: assign(out, iv, getArray(in)); break; case u16: assign(out, iv, getArray(in)); break; + case s8: assign(out, iv, getArray(in)); break; case u8: assign(out, iv, getArray(in)); break; case b8: assign(out, iv, getArray(in)); break; case f16: assign(out, iv, getArray(in)); break; @@ -201,6 +203,7 @@ af_err af_assign_seq(af_array* out, const af_array lhs, const unsigned ndims, case u64: assign(getArray(res), inSeqs, rhs); break; case s16: assign(getArray(res), inSeqs, rhs); break; case u16: assign(getArray(res), inSeqs, rhs); break; + case s8: assign(getArray(res), inSeqs, rhs); break; case u8: assign(getArray(res), inSeqs, rhs); break; case b8: assign(getArray(res), inSeqs, rhs); break; case f16: assign(getArray(res), inSeqs, rhs); break; @@ -260,8 +263,6 @@ af_err af_assign_gen(af_array* out, const af_array lhs, const dim_t ndims, return af_create_handle(out, 0, nullptr, lhsType); } - ARG_ASSERT(2, (ndims == 1) || (ndims == (dim_t)lInfo.ndims())); - if (ndims == 1 && ndims != static_cast(lInfo.ndims())) { af_array tmp_in = 0; af_array tmp_out = 0; @@ -279,7 +280,6 @@ af_err af_assign_gen(af_array* out, const af_array lhs, const dim_t ndims, ARG_ASSERT(1, (lhsType == rhsType)); ARG_ASSERT(1, (lhsDims.ndims() >= rhsDims.ndims())); - ARG_ASSERT(2, (lhsDims.ndims() >= ndims)); af_array output = 0; if (*out != lhs) { @@ -385,6 +385,7 @@ af_err af_assign_gen(af_array* out, const af_array lhs, const dim_t ndims, case s32: genAssign(output, ptr, rhs); break; case s16: genAssign(output, ptr, rhs); break; case u16: genAssign(output, ptr, rhs); break; + case s8: genAssign(output, ptr, rhs); break; case u8: genAssign(output, ptr, rhs); break; case b8: genAssign(output, ptr, rhs); break; case f16: genAssign(output, ptr, rhs); break; diff --git a/src/api/c/bilateral.cpp b/src/api/c/bilateral.cpp index 44e15c725c..aeec279ea5 100644 --- a/src/api/c/bilateral.cpp +++ b/src/api/c/bilateral.cpp @@ -19,6 +19,7 @@ using af::dim4; using detail::bilateral; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -50,6 +51,7 @@ af_err af_bilateral(af_array *out, const af_array in, const float ssigma, case b8: output = bilateral(in, ssigma, csigma); break; case s32: output = bilateral(in, ssigma, csigma); break; case u32: output = bilateral(in, ssigma, csigma); break; + case s8: output = bilateral(in, ssigma, csigma); break; case u8: output = bilateral(in, ssigma, csigma); break; case s16: output = bilateral(in, ssigma, csigma); break; case u16: output = bilateral(in, ssigma, csigma); break; diff --git a/src/api/c/binary.cpp b/src/api/c/binary.cpp index 50590568f8..eebe62bdbb 100644 --- a/src/api/c/binary.cpp +++ b/src/api/c/binary.cpp @@ -43,6 +43,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -139,6 +140,7 @@ static af_err af_arith(af_array *out, const af_array lhs, const af_array rhs, case c64: res = arithOp(lhs, rhs, odims); break; case s32: res = arithOp(lhs, rhs, odims); break; case u32: res = arithOp(lhs, rhs, odims); break; + case s8: res = arithOp(lhs, rhs, odims); break; case u8: res = arithOp(lhs, rhs, odims); break; case b8: res = arithOp(lhs, rhs, odims); break; case s64: res = arithOp(lhs, rhs, odims); break; @@ -159,6 +161,7 @@ static af_err af_arith(af_array *out, const af_array lhs, const af_array rhs, case c64: res = arithOpBroadcast(lhs, rhs); break; case s32: res = arithOpBroadcast(lhs, rhs); break; case u32: res = arithOpBroadcast(lhs, rhs); break; + case s8: res = arithOpBroadcast(lhs, rhs); break; case u8: res = arithOpBroadcast(lhs, rhs); break; case b8: res = arithOpBroadcast(lhs, rhs); break; case s64: res = arithOpBroadcast(lhs, rhs); break; @@ -195,6 +198,7 @@ static af_err af_arith_real(af_array *out, const af_array lhs, case f64: res = arithOp(lhs, rhs, odims); break; case s32: res = arithOp(lhs, rhs, odims); break; case u32: res = arithOp(lhs, rhs, odims); break; + case s8: res = arithOp(lhs, rhs, odims); break; case u8: res = arithOp(lhs, rhs, odims); break; case b8: res = arithOp(lhs, rhs, odims); break; case s64: res = arithOp(lhs, rhs, odims); break; @@ -476,7 +480,7 @@ af_err af_atan2(af_array *out, const af_array lhs, const af_array rhs, try { const af_dtype type = implicit(lhs, rhs); - if (type != f32 && type != f64) { + if (type != f16 && type != f32 && type != f64) { AF_ERROR("Only floating point arrays are supported for atan2 ", AF_ERR_NOT_SUPPORTED); } @@ -491,6 +495,7 @@ af_err af_atan2(af_array *out, const af_array lhs, const af_array rhs, af_array res; switch (type) { + case f16: res = arithOp(lhs, rhs, odims); break; case f32: res = arithOp(lhs, rhs, odims); break; case f64: res = arithOp(lhs, rhs, odims); break; default: TYPE_ERROR(0, type); @@ -507,7 +512,7 @@ af_err af_hypot(af_array *out, const af_array lhs, const af_array rhs, try { const af_dtype type = implicit(lhs, rhs); - if (type != f32 && type != f64) { + if (type != f16 && type != f32 && type != f64) { AF_ERROR("Only floating point arrays are supported for hypot ", AF_ERR_NOT_SUPPORTED); } @@ -523,6 +528,7 @@ af_err af_hypot(af_array *out, const af_array lhs, const af_array rhs, af_array res; switch (type) { + case f16: res = arithOp(lhs, rhs, odims); break; case f32: res = arithOp(lhs, rhs, odims); break; case f64: res = arithOp(lhs, rhs, odims); break; default: TYPE_ERROR(0, type); @@ -565,6 +571,7 @@ static af_err af_logic(af_array *out, const af_array lhs, const af_array rhs, case c64: res = logicOp(lhs, rhs, odims); break; case s32: res = logicOp(lhs, rhs, odims); break; case u32: res = logicOp(lhs, rhs, odims); break; + case s8: res = logicOp(lhs, rhs, odims); break; case u8: res = logicOp(lhs, rhs, odims); break; case b8: res = logicOp(lhs, rhs, odims); break; case s64: res = logicOp(lhs, rhs, odims); break; @@ -648,6 +655,7 @@ static af_err af_bitwise(af_array *out, const af_array lhs, const af_array rhs, switch (type) { case s32: res = bitOp(lhs, rhs, odims); break; case u32: res = bitOp(lhs, rhs, odims); break; + case s8: res = bitOp(lhs, rhs, odims); break; case u8: res = bitOp(lhs, rhs, odims); break; case b8: res = bitOp(lhs, rhs, odims); break; case s64: res = bitOp(lhs, rhs, odims); break; diff --git a/src/api/c/blas.cpp b/src/api/c/blas.cpp index 0cd8fddd8d..f42bc7d57c 100644 --- a/src/api/c/blas.cpp +++ b/src/api/c/blas.cpp @@ -33,6 +33,7 @@ using detail::cdouble; using detail::cfloat; using detail::gemm; using detail::matmul; +using detail::schar; namespace { template @@ -42,12 +43,12 @@ static inline af_array sparseMatmul(const af_array lhs, const af_array rhs, matmul(getSparseArray(lhs), getArray(rhs), optLhs, optRhs)); } -template +template static inline void gemm(af_array *out, af_mat_prop optLhs, af_mat_prop optRhs, - const T *alpha, const af_array lhs, const af_array rhs, - const T *betas) { - gemm(getArray(*out), optLhs, optRhs, alpha, getArray(lhs), - getArray(rhs), betas); + const To *alpha, const af_array lhs, const af_array rhs, + const To *betas) { + gemm(getArray(*out), optLhs, optRhs, alpha, getArray(lhs), + getArray(rhs), betas); } template @@ -178,6 +179,8 @@ af_err af_gemm(af_array *out, const af_mat_prop optLhs, if (*out) { output = *out; } else { + af_dtype out_type = (lhs_type != s8) ? lhs_type : f32; + const int aRowDim = (optLhs == AF_MAT_NONE) ? 0 : 1; const int bColDim = (optRhs == AF_MAT_NONE) ? 1 : 0; const int M = lDims[aRowDim]; @@ -186,7 +189,7 @@ af_err af_gemm(af_array *out, const af_mat_prop optLhs, const dim_t d3 = std::max(lDims[3], rDims[3]); const af::dim4 oDims = af::dim4(M, N, d2, d3); AF_CHECK(af_create_handle(&output, lhsInfo.ndims(), oDims.get(), - lhs_type)); + out_type)); } switch (lhs_type) { @@ -215,6 +218,11 @@ af_err af_gemm(af_array *out, const af_mat_prop optLhs, static_cast(alpha), lhs, rhs, static_cast(beta)); break; + case s8: + gemm(&output, optLhs, optRhs, + static_cast(alpha), lhs, rhs, + static_cast(beta)); + break; default: TYPE_ERROR(3, lhs_type); } @@ -246,11 +254,13 @@ af_err af_matmul(af_array *out, const af_array lhs, const af_array rhs, const dim_t d3 = std::max(lDims[3], rDims[3]); const af::dim4 oDims = af::dim4(M, N, d2, d3); - af_array gemm_out = 0; + af_dtype lhs_type = lhsInfo.getType(); + + af_array gemm_out = 0; + af_dtype gemm_out_type = (lhs_type != s8) ? lhs_type : f32; AF_CHECK(af_create_handle(&gemm_out, oDims.ndims(), oDims.get(), - lhsInfo.getType())); + gemm_out_type)); - af_dtype lhs_type = lhsInfo.getType(); switch (lhs_type) { case f16: { static const half alpha(1.0f); @@ -288,6 +298,13 @@ af_err af_matmul(af_array *out, const af_array lhs, const af_array rhs, &beta)); break; } + case s8: { + float alpha = 1.0; + float beta = 0.0; + AF_CHECK(af_gemm(&gemm_out, optLhs, optRhs, &alpha, lhs, rhs, + &beta)); + break; + } default: TYPE_ERROR(1, lhs_type); } diff --git a/src/api/c/canny.cpp b/src/api/c/canny.cpp index ef3ad029cd..b68b8d4ed0 100644 --- a/src/api/c/canny.cpp +++ b/src/api/c/canny.cpp @@ -53,6 +53,7 @@ using detail::logicOp; using detail::reduce; using detail::reduce_all; using detail::scan; +using detail::schar; using detail::sobelDerivatives; using detail::uchar; using detail::uint; @@ -265,6 +266,10 @@ af_err af_canny(af_array* out, const af_array in, const af_canny_threshold ct, output = cannyHelper(getArray(in), t1, ct, t2, sw, isf); break; + case s8: + output = cannyHelper(getArray(in), t1, ct, t2, sw, + isf); + break; case u8: output = cannyHelper(getArray(in), t1, ct, t2, sw, isf); diff --git a/src/api/c/cast.cpp b/src/api/c/cast.cpp index 328c81ca65..7b421d28bb 100644 --- a/src/api/c/cast.cpp +++ b/src/api/c/cast.cpp @@ -28,6 +28,7 @@ using arrayfire::common::half; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -54,6 +55,7 @@ static af_array cast(const af_array in, const af_dtype type) { case c64: return getHandle(castArray(in)); case s32: return getHandle(castArray(in)); case u32: return getHandle(castArray(in)); + case s8: return getHandle(castArray(in)); case u8: return getHandle(castArray(in)); case b8: return getHandle(castArray(in)); case s64: return getHandle(castArray(in)); diff --git a/src/api/c/clamp.cpp b/src/api/c/clamp.cpp index fb821d3bf3..8c31469e55 100644 --- a/src/api/c/clamp.cpp +++ b/src/api/c/clamp.cpp @@ -28,6 +28,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -64,6 +65,7 @@ af_err af_clamp(af_array* out, const af_array in, const af_array lo, case c64: res = clampOp(in, lo, hi, odims); break; case s32: res = clampOp(in, lo, hi, odims); break; case u32: res = clampOp(in, lo, hi, odims); break; + case s8: res = clampOp(in, lo, hi, odims); break; case u8: res = clampOp(in, lo, hi, odims); break; case b8: res = clampOp(in, lo, hi, odims); break; case s64: res = clampOp(in, lo, hi, odims); break; diff --git a/src/api/c/convolve.cpp b/src/api/c/convolve.cpp index abbcd2f71b..8d37c5d285 100644 --- a/src/api/c/convolve.cpp +++ b/src/api/c/convolve.cpp @@ -33,6 +33,7 @@ using detail::cdouble; using detail::cfloat; using detail::convolve; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -196,6 +197,10 @@ af_err convolve(af_array *out, const af_array signal, const af_array filter, output = convolve(signal, filter, convBT, rank, expand); break; + case s8: + output = convolve(signal, filter, convBT, rank, + expand); + break; case b8: output = convolve(signal, filter, convBT, rank, expand); @@ -311,6 +316,10 @@ af_err af_convolve2_sep(af_array *out, const af_array col_filter, output = convolve2(signal, col_filter, row_filter, expand); break; + case s8: + output = convolve2(signal, col_filter, row_filter, + expand); + break; case b8: output = convolve2(signal, col_filter, row_filter, expand); @@ -437,7 +446,7 @@ af_err af_convolve2_gradient_nn( size_t padding_ndims = padding.ndims(); size_t dilation_ndims = dilation.ndims(); ARG_ASSERT(3, stride_ndims > 0 && stride_ndims <= 2); - ARG_ASSERT(5, padding_ndims > 0 && padding_ndims <= 2); + ARG_ASSERT(5, padding_ndims >= 0 && padding_ndims <= 2); ARG_ASSERT(7, dilation_ndims > 0 && dilation_ndims <= 2); af_dtype type = oinfo.getType(); diff --git a/src/api/c/corrcoef.cpp b/src/api/c/corrcoef.cpp index fd767fb0ba..fde3788dac 100644 --- a/src/api/c/corrcoef.cpp +++ b/src/api/c/corrcoef.cpp @@ -30,6 +30,7 @@ using detail::Array; using detail::getScalar; using detail::intl; using detail::reduce_all; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -89,6 +90,7 @@ af_err af_corrcoef(double* realVal, double* imagVal, const af_array X, case u64: *realVal = corrcoef(X, Y); break; case s16: *realVal = corrcoef(X, Y); break; case u16: *realVal = corrcoef(X, Y); break; + case s8: *realVal = corrcoef(X, Y); break; case u8: *realVal = corrcoef(X, Y); break; case b8: *realVal = corrcoef(X, Y); break; default: TYPE_ERROR(1, xType); diff --git a/src/api/c/covariance.cpp b/src/api/c/covariance.cpp index f364558b11..a4241a8f0a 100644 --- a/src/api/c/covariance.cpp +++ b/src/api/c/covariance.cpp @@ -31,6 +31,7 @@ using detail::intl; using detail::mean; using detail::reduce; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -97,6 +98,7 @@ af_err af_cov_v2(af_array* out, const af_array X, const af_array Y, case u64: output = cov(X, Y, bias); break; case s16: output = cov(X, Y, bias); break; case u16: output = cov(X, Y, bias); break; + case s8: output = cov(X, Y, bias); break; case u8: output = cov(X, Y, bias); break; default: TYPE_ERROR(1, xType); } diff --git a/src/api/c/data.cpp b/src/api/c/data.cpp index 60ede3d4f6..324936e76e 100644 --- a/src/api/c/data.cpp +++ b/src/api/c/data.cpp @@ -35,6 +35,7 @@ using detail::iota; using detail::padArrayBorders; using detail::range; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -58,6 +59,7 @@ af_err af_constant(af_array *result, const double value, const unsigned ndims, case b8: out = createHandleFromValue(d, value); break; case s32: out = createHandleFromValue(d, value); break; case u32: out = createHandleFromValue(d, value); break; + case s8: out = createHandleFromValue(d, value); break; case u8: out = createHandleFromValue(d, value); break; case s64: out = createHandleFromValue(d, value); break; case u64: out = createHandleFromValue(d, value); break; @@ -159,6 +161,7 @@ af_err af_identity(af_array *out, const unsigned ndims, const dim_t *const dims, case c64: result = identity_(d); break; case s32: result = identity_(d); break; case u32: result = identity_(d); break; + case s8: result = identity_(d); break; case u8: result = identity_(d); break; case u64: result = identity_(d); break; case s64: result = identity_(d); break; @@ -202,6 +205,7 @@ af_err af_range(af_array *result, const unsigned ndims, const dim_t *const dims, case u64: out = range_(d, seq_dim); break; case s16: out = range_(d, seq_dim); break; case u16: out = range_(d, seq_dim); break; + case s8: out = range_(d, seq_dim); break; case u8: out = range_(d, seq_dim); break; case f16: out = range_(d, seq_dim); break; default: TYPE_ERROR(4, type); @@ -242,6 +246,7 @@ af_err af_iota(af_array *result, const unsigned ndims, const dim_t *const dims, case u64: out = iota_(d, t); break; case s16: out = iota_(d, t); break; case u16: out = iota_(d, t); break; + case s8: out = iota_(d, t); break; case u8: out = iota_(d, t); break; case f16: out = iota_(d, t); break; default: TYPE_ERROR(4, type); @@ -285,6 +290,7 @@ af_err af_diag_create(af_array *out, const af_array in, const int num) { case u64: result = diagCreate(in, num); break; case s16: result = diagCreate(in, num); break; case u16: result = diagCreate(in, num); break; + case s8: result = diagCreate(in, num); break; case u8: result = diagCreate(in, num); break; @@ -324,6 +330,7 @@ af_err af_diag_extract(af_array *out, const af_array in, const int num) { case u64: result = diagExtract(in, num); break; case s16: result = diagExtract(in, num); break; case u16: result = diagExtract(in, num); break; + case s8: result = diagExtract(in, num); break; case u8: result = diagExtract(in, num); break; @@ -366,6 +373,7 @@ af_err af_lower(af_array *out, const af_array in, bool is_unit_diag) { case u64: res = triangle(in, false, is_unit_diag); break; case s16: res = triangle(in, false, is_unit_diag); break; case u16: res = triangle(in, false, is_unit_diag); break; + case s8: res = triangle(in, false, is_unit_diag); break; case u8: res = triangle(in, false, is_unit_diag); break; case b8: res = triangle(in, false, is_unit_diag); break; case f16: res = triangle(in, false, is_unit_diag); break; @@ -395,6 +403,7 @@ af_err af_upper(af_array *out, const af_array in, bool is_unit_diag) { case u64: res = triangle(in, true, is_unit_diag); break; case s16: res = triangle(in, true, is_unit_diag); break; case u16: res = triangle(in, true, is_unit_diag); break; + case s8: res = triangle(in, true, is_unit_diag); break; case u8: res = triangle(in, true, is_unit_diag); break; case b8: res = triangle(in, true, is_unit_diag); break; case f16: res = triangle(in, true, is_unit_diag); break; @@ -449,6 +458,7 @@ af_err af_pad(af_array *out, const af_array in, const unsigned begin_ndims, case u64: res = pad(in, lPad, uPad, pad_type); break; case s16: res = pad(in, lPad, uPad, pad_type); break; case u16: res = pad(in, lPad, uPad, pad_type); break; + case s8: res = pad(in, lPad, uPad, pad_type); break; case u8: res = pad(in, lPad, uPad, pad_type); break; case b8: res = pad(in, lPad, uPad, pad_type); break; case f16: res = pad(in, lPad, uPad, pad_type); break; diff --git a/src/api/c/deconvolution.cpp b/src/api/c/deconvolution.cpp index f579eeadf8..19ad89e5db 100644 --- a/src/api/c/deconvolution.cpp +++ b/src/api/c/deconvolution.cpp @@ -43,6 +43,7 @@ using detail::createValueArray; using detail::logicOp; using detail::padArrayBorders; using detail::scalar; +using detail::schar; using detail::select_scalar; using detail::shift; using detail::uchar; @@ -226,6 +227,7 @@ af_err af_iterative_deconv(af_array* out, const af_array in, const af_array ker, case u16: res = iterDeconv(in, ker, iters, rfac, algo); break; + case s8: res = iterDeconv(in, ker, iters, rfac, algo); break; case u8: res = iterDeconv(in, ker, iters, rfac, algo); break; default: TYPE_ERROR(1, inputType); } @@ -323,6 +325,7 @@ af_err af_inverse_deconv(af_array* out, const af_array in, const af_array psf, case f32: res = invDeconv(in, psf, gamma, algo); break; case s16: res = invDeconv(in, psf, gamma, algo); break; case u16: res = invDeconv(in, psf, gamma, algo); break; + case s8: res = invDeconv(in, psf, gamma, algo); break; case u8: res = invDeconv(in, psf, gamma, algo); break; default: TYPE_ERROR(1, inputType); } diff --git a/src/api/c/device.cpp b/src/api/c/device.cpp index ef37888523..7427a1a4e5 100644 --- a/src/api/c/device.cpp +++ b/src/api/c/device.cpp @@ -47,6 +47,7 @@ using detail::init; using detail::intl; using detail::isDoubleSupported; using detail::isHalfSupported; +using detail::schar; using detail::setDevice; using detail::uchar; using detail::uint; @@ -290,6 +291,7 @@ af_err af_eval(af_array arr) { case c64: eval(arr); break; case s32: eval(arr); break; case u32: eval(arr); break; + case s8: eval(arr); break; case u8: eval(arr); break; case b8: eval(arr); break; case s64: eval(arr); break; @@ -344,6 +346,7 @@ af_err af_eval_multiple(int num, af_array* arrays) { case c64: evalMultiple(num, arrays); break; case s32: evalMultiple(num, arrays); break; case u32: evalMultiple(num, arrays); break; + case s8: evalMultiple(num, arrays); break; case u8: evalMultiple(num, arrays); break; case b8: evalMultiple(num, arrays); break; case s64: evalMultiple(num, arrays); break; diff --git a/src/api/c/diff.cpp b/src/api/c/diff.cpp index c579f0b53e..f75d5c1ab1 100644 --- a/src/api/c/diff.cpp +++ b/src/api/c/diff.cpp @@ -21,6 +21,7 @@ using arrayfire::getHandle; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -64,6 +65,7 @@ af_err af_diff1(af_array* out, const af_array in, const int dim) { case u64: output = diff1(in, dim); break; case s16: output = diff1(in, dim); break; case u16: output = diff1(in, dim); break; + case s8: output = diff1(in, dim); break; case u8: output = diff1(in, dim); break; default: TYPE_ERROR(1, type); } @@ -101,6 +103,7 @@ af_err af_diff2(af_array* out, const af_array in, const int dim) { case u64: output = diff2(in, dim); break; case s16: output = diff2(in, dim); break; case u16: output = diff2(in, dim); break; + case s8: output = diff2(in, dim); break; case u8: output = diff2(in, dim); break; default: TYPE_ERROR(1, type); } diff --git a/src/api/c/dog.cpp b/src/api/c/dog.cpp index fbbe94d211..848262daab 100644 --- a/src/api/c/dog.cpp +++ b/src/api/c/dog.cpp @@ -22,6 +22,7 @@ using af::dim4; using detail::arithOp; using detail::Array; using detail::convolve; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -70,6 +71,7 @@ af_err af_dog(af_array* out, const af_array in, const int radius1, case u32: output = dog(in, radius1, radius2); break; case s16: output = dog(in, radius1, radius2); break; case u16: output = dog(in, radius1, radius2); break; + case s8: output = dog(in, radius1, radius2); break; case u8: output = dog(in, radius1, radius2); break; default: TYPE_ERROR(1, type); } diff --git a/src/api/c/exampleFunction.cpp b/src/api/c/exampleFunction.cpp index 4a7a52f6bd..a58336f90c 100644 --- a/src/api/c/exampleFunction.cpp +++ b/src/api/c/exampleFunction.cpp @@ -76,6 +76,7 @@ af_err af_example_function(af_array* out, const af_array a, case f32: output = example(a, a, param); break; case s32: output = example(a, a, param); break; case u32: output = example(a, a, param); break; + case s8: output = example(a, a, param); break; case u8: output = example(a, a, param); break; case b8: output = example(a, a, param); break; case c32: output = example(a, a, param); break; diff --git a/src/api/c/fast.cpp b/src/api/c/fast.cpp index ed8822c402..08834ce4f4 100644 --- a/src/api/c/fast.cpp +++ b/src/api/c/fast.cpp @@ -22,6 +22,7 @@ using af::dim4; using detail::Array; using detail::createEmptyArray; using detail::createValueArray; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -96,6 +97,10 @@ af_err af_fast(af_features *out, const af_array in, const float thr, *out = fast(in, thr, arc_length, non_max, feature_ratio, edge); break; + case s8: + *out = fast(in, thr, arc_length, non_max, feature_ratio, + edge); + break; case u8: *out = fast(in, thr, arc_length, non_max, feature_ratio, edge); diff --git a/src/api/c/fftconvolve.cpp b/src/api/c/fftconvolve.cpp index 5e69d5d0ce..ead2247c51 100644 --- a/src/api/c/fftconvolve.cpp +++ b/src/api/c/fftconvolve.cpp @@ -35,6 +35,7 @@ using detail::createSubArray; using detail::fftconvolve; using detail::intl; using detail::real; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -211,6 +212,10 @@ af_err fft_convolve(af_array *out, const af_array signal, const af_array filter, output = fftconvolve(signal, filter, expand, convBT, baseDim); break; + case s8: + output = + fftconvolve(signal, filter, expand, convBT, baseDim); + break; case b8: output = fftconvolve(signal, filter, expand, convBT, baseDim); diff --git a/src/api/c/filters.cpp b/src/api/c/filters.cpp index dc0067f257..4c154c16fb 100644 --- a/src/api/c/filters.cpp +++ b/src/api/c/filters.cpp @@ -18,6 +18,7 @@ #include using af::dim4; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -64,6 +65,7 @@ af_err af_medfilt1(af_array *out, const af_array in, const dim_t wind_width, case u16: output = medfilt1(in, wind_width, edge_pad); break; + case s8: output = medfilt1(in, wind_width, edge_pad); break; case u8: output = medfilt1(in, wind_width, edge_pad); break; default: TYPE_ERROR(1, type); } @@ -129,6 +131,9 @@ af_err af_medfilt2(af_array *out, const af_array in, const dim_t wind_length, output = medfilt2(in, wind_length, wind_width, edge_pad); break; + case s8: + output = medfilt2(in, wind_length, wind_width, edge_pad); + break; case u8: output = medfilt2(in, wind_length, wind_width, edge_pad); break; diff --git a/src/api/c/flip.cpp b/src/api/c/flip.cpp index 080af47aac..4aea98ec73 100644 --- a/src/api/c/flip.cpp +++ b/src/api/c/flip.cpp @@ -25,6 +25,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uintl; using detail::ushort; @@ -61,6 +62,7 @@ af_err af_flip(af_array *result, const af_array in, const unsigned dim) { case u64: out = flip(in, dim); break; case s16: out = flip(in, dim); break; case u16: out = flip(in, dim); break; + case s8: out = flip(in, dim); break; case u8: out = flip(in, dim); break; default: TYPE_ERROR(1, in_type); } diff --git a/src/api/c/handle.cpp b/src/api/c/handle.cpp index 9c980af9f0..d67f4ae9a1 100644 --- a/src/api/c/handle.cpp +++ b/src/api/c/handle.cpp @@ -21,6 +21,7 @@ using detail::cdouble; using detail::cfloat; using detail::createDeviceDataArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -46,6 +47,7 @@ af_array retain(const af_array in) { case f64: return retainHandle(in); case s32: return retainHandle(in); case u32: return retainHandle(in); + case s8: return retainHandle(in); case u8: return retainHandle(in); case c32: return retainHandle(in); case c64: return retainHandle(in); @@ -70,6 +72,7 @@ af_array createHandle(const dim4 &d, af_dtype dtype) { case b8: return createHandle(d); case s32: return createHandle(d); case u32: return createHandle(d); + case s8: return createHandle(d); case u8: return createHandle(d); case s64: return createHandle(d); case u64: return createHandle(d); @@ -91,6 +94,7 @@ af_array createHandleFromValue(const dim4 &d, double val, af_dtype dtype) { case b8: return createHandleFromValue(d, val); case s32: return createHandleFromValue(d, val); case u32: return createHandleFromValue(d, val); + case s8: return createHandleFromValue(d, val); case u8: return createHandleFromValue(d, val); case s64: return createHandleFromValue(d, val); case u64: return createHandleFromValue(d, val); @@ -113,6 +117,7 @@ af_array createHandleFromDeviceData(const af::dim4 &d, af_dtype dtype, case b8: return getHandle(createDeviceDataArray(d, data, false)); case s32: return getHandle(createDeviceDataArray(d, data, false)); case u32: return getHandle(createDeviceDataArray(d, data, false)); + case s8: return getHandle(createDeviceDataArray(d, data, false)); case u8: return getHandle(createDeviceDataArray(d, data, false)); case s64: return getHandle(createDeviceDataArray(d, data, false)); case u64: return getHandle(createDeviceDataArray(d, data, false)); @@ -182,5 +187,6 @@ INSTANTIATE(char); INSTANTIATE(short); INSTANTIATE(ushort); INSTANTIATE(half); +INSTANTIATE(schar); } // namespace arrayfire diff --git a/src/api/c/hist.cpp b/src/api/c/hist.cpp index f37ba5cea1..0d8f9bfe6b 100644 --- a/src/api/c/hist.cpp +++ b/src/api/c/hist.cpp @@ -29,6 +29,7 @@ using detail::Array; using detail::copy_histogram; using detail::forgeManager; using detail::getScalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -68,19 +69,21 @@ fg_chart setup_histogram(fg_window const window, const af_array in, T freqMax = getScalar(detail::reduce_all(histogramInput)); + // For histogram, xMin and xMax should always be the first + // and last bin respectively and should not be rounded if (xMin == 0 && xMax == 0 && yMin == 0 && yMax == 0) { // No previous limits. Set without checking - xMin = static_cast(step_round(minval, false)); - xMax = static_cast(step_round(maxval, true)); + xMin = static_cast(minval); + xMax = static_cast(maxval); yMax = static_cast(step_round(freqMax, true)); // For histogram, always set yMin to 0. yMin = 0; } else { if (xMin > minval) { - xMin = static_cast(step_round(minval, false)); + xMin = static_cast(minval); } if (xMax < maxval) { - xMax = static_cast(step_round(maxval, true)); + xMax = static_cast(maxval); } if (yMax < freqMax) { yMax = static_cast(step_round(freqMax, true)); @@ -131,6 +134,10 @@ af_err af_draw_hist(const af_window window, const af_array X, chart = setup_histogram(window, X, minval, maxval, props); break; + case s8: + chart = + setup_histogram(window, X, minval, maxval, props); + break; case u8: chart = setup_histogram(window, X, minval, maxval, props); diff --git a/src/api/c/histeq.cpp b/src/api/c/histeq.cpp index da2a7579d8..faed6a238c 100644 --- a/src/api/c/histeq.cpp +++ b/src/api/c/histeq.cpp @@ -33,6 +33,7 @@ using detail::intl; using detail::lookup; using detail::reduce_all; using detail::scan; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -95,6 +96,7 @@ af_err af_hist_equal(af_array* out, const af_array in, const af_array hist) { case u16: output = hist_equal(in, hist); break; case s64: output = hist_equal(in, hist); break; case u64: output = hist_equal(in, hist); break; + case s8: output = hist_equal(in, hist); break; case u8: output = hist_equal(in, hist); break; default: TYPE_ERROR(1, dataType); } diff --git a/src/api/c/histogram.cpp b/src/api/c/histogram.cpp index aa2744bb6c..69c6d71de5 100644 --- a/src/api/c/histogram.cpp +++ b/src/api/c/histogram.cpp @@ -15,6 +15,7 @@ #include using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -74,6 +75,10 @@ af_err af_histogram(af_array *out, const af_array in, const unsigned nbins, output = histogram(in, nbins, minval, maxval, info.isLinear()); break; + case s8: + output = histogram(in, nbins, minval, maxval, + info.isLinear()); + break; case u8: output = histogram(in, nbins, minval, maxval, info.isLinear()); diff --git a/src/api/c/image.cpp b/src/api/c/image.cpp index 425530806c..4650c0ec3d 100644 --- a/src/api/c/image.cpp +++ b/src/api/c/image.cpp @@ -39,6 +39,7 @@ using detail::Array; using detail::copy_image; using detail::createValueArray; using detail::forgeManager; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -102,6 +103,7 @@ af_err af_draw_image(const af_window window, const af_array in, case u32: image = convert_and_copy_image(in); break; case s16: image = convert_and_copy_image(in); break; case u16: image = convert_and_copy_image(in); break; + case s8: image = convert_and_copy_image(in); break; case u8: image = convert_and_copy_image(in); break; default: TYPE_ERROR(1, type); } diff --git a/src/api/c/implicit.cpp b/src/api/c/implicit.cpp index f30afda7eb..d045769cbd 100644 --- a/src/api/c/implicit.cpp +++ b/src/api/c/implicit.cpp @@ -14,7 +14,7 @@ Implicit type mimics C/C++ behavior. Order of precedence: - complex > real -- double > float > uintl > intl > uint > int > uchar > char +- double > float > uintl > intl > uint > int > uchar > schar > char */ af_dtype implicit(const af_dtype lty, const af_dtype rty) { @@ -38,6 +38,7 @@ af_dtype implicit(const af_dtype lty, const af_dtype rty) { if ((lty == u16) || (rty == u16)) { return u16; } if ((lty == s16) || (rty == s16)) { return s16; } if ((lty == u8) || (rty == u8)) { return u8; } + if ((lty == s8) || (rty == s8)) { return s8; } if ((lty == b8) && (rty == b8)) { return b8; } return f32; diff --git a/src/api/c/index.cpp b/src/api/c/index.cpp index 1c7484f2bf..792a5a5af7 100644 --- a/src/api/c/index.cpp +++ b/src/api/c/index.cpp @@ -40,6 +40,7 @@ using detail::cdouble; using detail::cfloat; using detail::index; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -115,6 +116,7 @@ af_err af_index(af_array* result, const af_array in, const unsigned ndims, case u16: out = indexBySeqs(in, indices_); break; case s64: out = indexBySeqs(in, indices_); break; case u64: out = indexBySeqs(in, indices_); break; + case s8: out = indexBySeqs(in, indices_); break; case u8: out = indexBySeqs(in, indices_); break; case f16: out = indexBySeqs(in, indices_); break; default: TYPE_ERROR(1, type); @@ -148,6 +150,7 @@ static af_array lookup(const af_array& in, const af_array& idx, case u64: return lookup(in, idx, dim); case s16: return lookup(in, idx, dim); case u16: return lookup(in, idx, dim); + case s8: return lookup(in, idx, dim); case u8: return lookup(in, idx, dim); case b8: return lookup(in, idx, dim); case f16: return lookup(in, idx, dim); @@ -175,21 +178,34 @@ af_err af_lookup(af_array* out, const af_array in, const af_array indices, ARG_ASSERT(2, (idxType != b8)); af_array output = 0; + af_array idx = 0; + + if (!idxInfo.isColumn()) { + // Force a deep copy to flatten the array and handle subarrays of not column vector arrays correctly + AF_CHECK(af_copy_array(&idx, indices)); + } else { + idx = indices; + } switch (idxType) { - case f32: output = lookup(in, indices, dim); break; - case f64: output = lookup(in, indices, dim); break; + case f32: output = lookup(in, idx, dim); break; + case f64: output = lookup(in, idx, dim); break; case s32: output = lookup(in, indices, dim); break; - case u32: output = lookup(in, indices, dim); break; - case s16: output = lookup(in, indices, dim); break; - case u16: output = lookup(in, indices, dim); break; - case s64: output = lookup(in, indices, dim); break; - case u64: output = lookup(in, indices, dim); break; - case u8: output = lookup(in, indices, dim); break; - case f16: output = lookup(in, indices, dim); break; + case u32: output = lookup(in, idx, dim); break; + case s16: output = lookup(in, idx, dim); break; + case u16: output = lookup(in, idx, dim); break; + case s64: output = lookup(in, idx, dim); break; + case u64: output = lookup(in, idx, dim); break; + case s8: output = lookup(in, idx, dim); break; + case u8: output = lookup(in, idx, dim); break; + case f16: output = lookup(in, idx, dim); break; default: TYPE_ERROR(1, idxType); } std::swap(*out, output); + + if (idx != indices) { + AF_CHECK(af_release_array(idx)); // Release indices array if a copy has been made + } } CATCHALL; return AF_SUCCESS; @@ -289,6 +305,7 @@ af_err af_index_gen(af_array* out, const af_array in, const dim_t ndims, case s32: output = genIndex(in, ptr); break; case u16: output = genIndex(in, ptr); break; case s16: output = genIndex(in, ptr); break; + case s8: output = genIndex(in, ptr); break; case u8: output = genIndex(in, ptr); break; case b8: output = genIndex(in, ptr); break; case f16: output = genIndex(in, ptr); break; diff --git a/src/api/c/internal.cpp b/src/api/c/internal.cpp index 38c0c96dfe..c0314981cb 100644 --- a/src/api/c/internal.cpp +++ b/src/api/c/internal.cpp @@ -25,6 +25,7 @@ using detail::cdouble; using detail::cfloat; using detail::createStridedArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -120,6 +121,11 @@ af_err af_create_strided_array(af_array *arr, const void *data, dims, strides, offset, static_cast(in_data), isdev)); break; + case s8: + res = getHandle(createStridedArray( + dims, strides, offset, static_cast(in_data), + isdev)); + break; case f16: res = getHandle(createStridedArray( dims, strides, offset, static_cast(in_data), @@ -175,6 +181,7 @@ af_err af_get_raw_ptr(void **ptr, const af_array arr) { case s16: res = getRawPtr(getArray(arr)); break; case b8: res = getRawPtr(getArray(arr)); break; case u8: res = getRawPtr(getArray(arr)); break; + case s8: res = getRawPtr(getArray(arr)); break; case f16: res = getRawPtr(getArray(arr)); break; default: TYPE_ERROR(6, ty); } @@ -212,6 +219,7 @@ af_err af_is_owner(bool *result, const af_array arr) { case s16: res = getArray(arr).isOwner(); break; case b8: res = getArray(arr).isOwner(); break; case u8: res = getArray(arr).isOwner(); break; + case s8: res = getArray(arr).isOwner(); break; case f16: res = getArray(arr).isOwner(); break; default: TYPE_ERROR(6, ty); } @@ -241,6 +249,7 @@ af_err af_get_allocated_bytes(size_t *bytes, const af_array arr) { case s16: res = getArray(arr).getAllocatedBytes(); break; case b8: res = getArray(arr).getAllocatedBytes(); break; case u8: res = getArray(arr).getAllocatedBytes(); break; + case s8: res = getArray(arr).getAllocatedBytes(); break; case f16: res = getArray(arr).getAllocatedBytes(); break; default: TYPE_ERROR(6, ty); } diff --git a/src/api/c/join.cpp b/src/api/c/join.cpp index 4c47fbe495..d3e9cda6b5 100644 --- a/src/api/c/join.cpp +++ b/src/api/c/join.cpp @@ -26,6 +26,7 @@ using detail::cdouble; using detail::cfloat; using detail::createEmptyArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -98,6 +99,7 @@ af_err af_join(af_array *out, const int dim, const af_array first, case u64: output = join(dim, first, second); break; case s16: output = join(dim, first, second); break; case u16: output = join(dim, first, second); break; + case s8: output = join(dim, first, second); break; case u8: output = join(dim, first, second); break; case f16: output = join(dim, first, second); break; default: TYPE_ERROR(1, finfo.getType()); @@ -169,6 +171,7 @@ af_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, case u64: output = join_many(dim, n_arrays, inputs); break; case s16: output = join_many(dim, n_arrays, inputs); break; case u16: output = join_many(dim, n_arrays, inputs); break; + case s8: output = join_many(dim, n_arrays, inputs); break; case u8: output = join_many(dim, n_arrays, inputs); break; case f16: output = join_many(dim, n_arrays, inputs); break; default: TYPE_ERROR(1, assertType); diff --git a/src/api/c/match_template.cpp b/src/api/c/match_template.cpp index 6882711a7f..91d81c383c 100644 --- a/src/api/c/match_template.cpp +++ b/src/api/c/match_template.cpp @@ -19,6 +19,7 @@ using af::dim4; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -82,6 +83,10 @@ af_err af_match_template(af_array* out, const af_array search_img, case b8: output = match_template(search_img, template_img, m_type); break; + case s8: + output = + match_template(search_img, template_img, m_type); + break; case u8: output = match_template(search_img, template_img, m_type); diff --git a/src/api/c/mean.cpp b/src/api/c/mean.cpp index af9021983e..65fe057155 100644 --- a/src/api/c/mean.cpp +++ b/src/api/c/mean.cpp @@ -31,6 +31,7 @@ using detail::imag; using detail::intl; using detail::mean; using detail::real; +using detail::schar; using detail::uchar; using detail::uintl; using detail::ushort; @@ -77,6 +78,7 @@ af_err af_mean(af_array *out, const af_array in, const dim_t dim) { case u64: output = mean(in, dim); break; case s16: output = mean(in, dim); break; case u16: output = mean(in, dim); break; + case s8: output = mean(in, dim); break; case u8: output = mean(in, dim); break; case b8: output = mean(in, dim); break; case c32: output = mean(in, dim); break; @@ -127,6 +129,7 @@ af_err af_mean_weighted(af_array *out, const af_array in, case u32: case s16: case u16: + case s8: case u8: case b8: output = mean(in, w, dim); break; case f64: @@ -158,6 +161,7 @@ af_err af_mean_all(double *realVal, double *imagVal, const af_array in) { case u64: *realVal = mean(in); break; case s16: *realVal = mean(in); break; case u16: *realVal = mean(in); break; + case s8: *realVal = mean(in); break; case u8: *realVal = mean(in); break; case b8: *realVal = mean(in); break; case f16: @@ -200,6 +204,7 @@ af_err af_mean_all_weighted(double *realVal, double *imagVal, const af_array in, case u32: case s16: case u16: + case s8: case u8: case b8: case f16: *realVal = mean(in, weights); break; diff --git a/src/api/c/meanshift.cpp b/src/api/c/meanshift.cpp index 0c8322cafe..bf09bc4d2a 100644 --- a/src/api/c/meanshift.cpp +++ b/src/api/c/meanshift.cpp @@ -18,6 +18,7 @@ using af::dim4; using detail::intl; using detail::meanshift; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -84,6 +85,10 @@ af_err af_mean_shift(af_array *out, const af_array in, output = mean_shift(in, spatial_sigma, chromatic_sigma, num_iterations, is_color); break; + case s8: + output = mean_shift(in, spatial_sigma, chromatic_sigma, + num_iterations, is_color); + break; case u8: output = mean_shift(in, spatial_sigma, chromatic_sigma, num_iterations, is_color); diff --git a/src/api/c/median.cpp b/src/api/c/median.cpp index 5e22c1c36a..2fd0de18d8 100644 --- a/src/api/c/median.cpp +++ b/src/api/c/median.cpp @@ -23,6 +23,7 @@ using af::dim4; using detail::Array; using detail::division; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -169,6 +170,7 @@ af_err af_median_all(double* realVal, double* imagVal, // NOLINT case u32: *realVal = median(in); break; case s16: *realVal = median(in); break; case u16: *realVal = median(in); break; + case s8: *realVal = median(in); break; case u8: *realVal = median(in); break; default: TYPE_ERROR(1, type); } @@ -193,6 +195,7 @@ af_err af_median(af_array* out, const af_array in, const dim_t dim) { case u32: output = median(in, dim); break; case s16: output = median(in, dim); break; case u16: output = median(in, dim); break; + case s8: output = median(in, dim); break; case u8: output = median(in, dim); break; default: TYPE_ERROR(1, type); } diff --git a/src/api/c/memory.cpp b/src/api/c/memory.cpp index fbff61720e..665a51ac9c 100644 --- a/src/api/c/memory.cpp +++ b/src/api/c/memory.cpp @@ -42,6 +42,7 @@ using detail::memUnlock; using detail::pinnedAlloc; using detail::pinnedFree; using detail::printMemInfo; +using detail::schar; using detail::signalMemoryCleanup; using detail::uchar; using detail::uint; @@ -95,6 +96,9 @@ af_err af_device_array(af_array *arr, void *data, const unsigned ndims, case u16: res = getHandle(createDeviceDataArray(d, data)); break; + case s8: + res = getHandle(createDeviceDataArray(d, data)); + break; case u8: res = getHandle(createDeviceDataArray(d, data)); break; @@ -130,6 +134,7 @@ af_err af_get_device_ptr(void **data, const af_array arr) { case u64: *data = getDevicePtr(getArray(arr)); break; case s16: *data = getDevicePtr(getArray(arr)); break; case u16: *data = getDevicePtr(getArray(arr)); break; + case s8: *data = getDevicePtr(getArray(arr)); break; case u8: *data = getDevicePtr(getArray(arr)); break; case b8: *data = getDevicePtr(getArray(arr)); break; case f16: *data = getDevicePtr(getArray(arr)); break; @@ -164,6 +169,7 @@ af_err af_lock_array(const af_array arr) { case u64: lockArray(arr); break; case s16: lockArray(arr); break; case u16: lockArray(arr); break; + case s8: lockArray(arr); break; case u8: lockArray(arr); break; case b8: lockArray(arr); break; case f16: lockArray(arr); break; @@ -196,6 +202,7 @@ af_err af_is_locked_array(bool *res, const af_array arr) { case u64: *res = checkUserLock(arr); break; case s16: *res = checkUserLock(arr); break; case u16: *res = checkUserLock(arr); break; + case s8: *res = checkUserLock(arr); break; case u8: *res = checkUserLock(arr); break; case b8: *res = checkUserLock(arr); break; case f16: *res = checkUserLock(arr); break; @@ -229,6 +236,7 @@ af_err af_unlock_array(const af_array arr) { case u64: unlockArray(arr); break; case s16: unlockArray(arr); break; case u16: unlockArray(arr); break; + case s8: unlockArray(arr); break; case u8: unlockArray(arr); break; case b8: unlockArray(arr); break; case f16: unlockArray(arr); break; diff --git a/src/api/c/moddims.cpp b/src/api/c/moddims.cpp index 4f6f0f310d..f419a2fb04 100644 --- a/src/api/c/moddims.cpp +++ b/src/api/c/moddims.cpp @@ -22,6 +22,7 @@ using arrayfire::common::half; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -66,6 +67,7 @@ af_err af_moddims(af_array* out, const af_array in, const unsigned ndims, case b8: output = modDims(in, newDims); break; case s32: output = modDims(in, newDims); break; case u32: output = modDims(in, newDims); break; + case s8: output = modDims(in, newDims); break; case u8: output = modDims(in, newDims); break; case s64: output = modDims(in, newDims); break; case u64: output = modDims(in, newDims); break; @@ -99,6 +101,7 @@ af_err af_flat(af_array* out, const af_array in) { case b8: output = flat(in); break; case s32: output = flat(in); break; case u32: output = flat(in); break; + case s8: output = flat(in); break; case u8: output = flat(in); break; case s64: output = flat(in); break; case u64: output = flat(in); break; diff --git a/src/api/c/morph.cpp b/src/api/c/morph.cpp index efaf6cc53a..418b84e8a9 100644 --- a/src/api/c/morph.cpp +++ b/src/api/c/morph.cpp @@ -34,6 +34,7 @@ using detail::createEmptyArray; using detail::createValueArray; using detail::logicOp; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::unaryOp; @@ -137,6 +138,7 @@ af_err morph(af_array *out, const af_array &in, const af_array &mask, case u32: output = morph(in, mask, isDilation); break; case s16: output = morph(in, mask, isDilation); break; case u16: output = morph(in, mask, isDilation); break; + case s8: output = morph(in, mask, isDilation); break; case u8: output = morph(in, mask, isDilation); break; default: TYPE_ERROR(1, type); } @@ -170,6 +172,7 @@ af_err morph3d(af_array *out, const af_array &in, const af_array &mask, case u32: output = morph3d(in, mask, isDilation); break; case s16: output = morph3d(in, mask, isDilation); break; case u16: output = morph3d(in, mask, isDilation); break; + case s8: output = morph3d(in, mask, isDilation); break; case u8: output = morph3d(in, mask, isDilation); break; default: TYPE_ERROR(1, type); } diff --git a/src/api/c/nearest_neighbour.cpp b/src/api/c/nearest_neighbour.cpp index abc2a7b65b..10543649d9 100644 --- a/src/api/c/nearest_neighbour.cpp +++ b/src/api/c/nearest_neighbour.cpp @@ -21,6 +21,7 @@ using detail::cdouble; using detail::cfloat; using detail::createEmptyArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -128,6 +129,10 @@ af_err af_nearest_neighbour(af_array* idx, af_array* dist, const af_array query, dist_dim, n_dist, dist_type); break; + case s8: + nearest_neighbour(&oIdx, &oDist, query, train, + dist_dim, n_dist, dist_type); + break; case u8: nearest_neighbour(&oIdx, &oDist, query, train, dist_dim, n_dist, dist_type); diff --git a/src/api/c/norm.cpp b/src/api/c/norm.cpp index 84444eed58..7eef41afcc 100644 --- a/src/api/c/norm.cpp +++ b/src/api/c/norm.cpp @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include using af::dim4; +using arrayfire::common::cast; using detail::arithOp; using detail::Array; using detail::cdouble; @@ -35,15 +37,21 @@ using detail::reduce; using detail::reduce_all; using detail::scalar; +template +using normReductionResult = + typename std::conditional::value, float, + T>::type; + template double matrixNorm(const Array &A, double p) { + using RT = normReductionResult; if (p == 1) { - Array colSum = reduce(A, 0); - return getScalar(reduce_all(colSum)); + Array colSum = reduce>(A, 0); + return getScalar(reduce_all(colSum)); } if (p == af::Inf) { - Array rowSum = reduce(A, 1); - return getScalar(reduce_all(rowSum)); + Array rowSum = reduce(A, 1); + return getScalar(reduce_all(rowSum)); } AF_ERROR("This type of norm is not supported in ArrayFire\n", @@ -52,41 +60,45 @@ double matrixNorm(const Array &A, double p) { template double vectorNorm(const Array &A, double p) { - if (p == 1) { return getScalar(reduce_all(A)); } + using RT = normReductionResult; + if (p == 1) { return getScalar(reduce_all(A)); } if (p == af::Inf) { - return getScalar(reduce_all(A)); + return getScalar(reduce_all(cast(A))); } else if (p == 2) { Array A_sq = arithOp(A, A, A.dims()); - return std::sqrt(getScalar(reduce_all(A_sq))); + return std::sqrt(getScalar(reduce_all(A_sq))); } Array P = createValueArray(A.dims(), scalar(p)); Array A_p = arithOp(A, P, A.dims()); - return std::pow(getScalar(reduce_all(A_p)), T(1.0 / p)); + return std::pow(getScalar(reduce_all(A_p)), (1.0 / p)); } template double LPQNorm(const Array &A, double p, double q) { - Array A_p_norm = createEmptyArray(dim4()); + using RT = normReductionResult; + Array A_p_norm = createEmptyArray(dim4()); if (p == 1) { - A_p_norm = reduce(A, 0); + A_p_norm = reduce(A, 0); } else { - Array P = createValueArray(A.dims(), scalar(p)); - Array invP = createValueArray(A.dims(), scalar(1.0 / p)); + Array P = createValueArray(A.dims(), scalar(p)); + Array invP = createValueArray(A.dims(), scalar(1.0 / p)); - Array A_p = arithOp(A, P, A.dims()); - Array A_p_sum = reduce(A_p, 0); - A_p_norm = arithOp(A_p_sum, invP, invP.dims()); + Array A_p = arithOp(A, P, A.dims()); + Array A_p_sum = reduce(A_p, 0); + A_p_norm = arithOp(A_p_sum, invP, invP.dims()); } - if (q == 1) { return getScalar(reduce_all(A_p_norm)); } + if (q == 1) { + return getScalar(reduce_all(A_p_norm)); + } - Array Q = createValueArray(A_p_norm.dims(), scalar(q)); - Array A_p_norm_q = arithOp(A_p_norm, Q, Q.dims()); + Array Q = createValueArray(A_p_norm.dims(), scalar(q)); + Array A_p_norm_q = arithOp(A_p_norm, Q, Q.dims()); - return std::pow(getScalar(reduce_all(A_p_norm_q)), - T(1.0 / q)); + return std::pow(getScalar(reduce_all(A_p_norm_q)), + (1.0 / q)); } template @@ -98,21 +110,13 @@ double norm(const af_array a, const af_norm_type type, const double p, switch (type) { case AF_NORM_EUCLID: return vectorNorm(A, 2); - case AF_NORM_VECTOR_1: return vectorNorm(A, 1); - case AF_NORM_VECTOR_INF: return vectorNorm(A, af::Inf); - case AF_NORM_VECTOR_P: return vectorNorm(A, p); - case AF_NORM_MATRIX_1: return matrixNorm(A, 1); - case AF_NORM_MATRIX_INF: return matrixNorm(A, af::Inf); - case AF_NORM_MATRIX_2: return matrixNorm(A, 2); - case AF_NORM_MATRIX_L_PQ: return LPQNorm(A, p, q); - default: AF_ERROR("This type of norm is not supported in ArrayFire\n", AF_ERR_NOT_SUPPORTED); @@ -123,17 +127,13 @@ af_err af_norm(double *out, const af_array in, const af_norm_type type, const double p, const double q) { try { const ArrayInfo &i_info = getInfo(in); - if (i_info.ndims() > 2) { AF_ERROR("solve can not be used in batch mode", AF_ERR_BATCH); } af_dtype i_type = i_info.getType(); - ARG_ASSERT(1, i_info.isFloating()); // Only floating and complex types - *out = 0; - if (i_info.ndims() == 0) { return AF_SUCCESS; } switch (i_type) { @@ -141,6 +141,7 @@ af_err af_norm(double *out, const af_array in, const af_norm_type type, case f64: *out = norm(in, type, p, q); break; case c32: *out = norm(in, type, p, q); break; case c64: *out = norm(in, type, p, q); break; + case f16: *out = norm(in, type, p, q); break; default: TYPE_ERROR(1, i_type); } } diff --git a/src/api/c/plot.cpp b/src/api/c/plot.cpp index c2d954d481..be5aab06b1 100644 --- a/src/api/c/plot.cpp +++ b/src/api/c/plot.cpp @@ -35,6 +35,7 @@ using detail::Array; using detail::copy_plot; using detail::forgeManager; using detail::reduce; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -166,6 +167,10 @@ af_err plotWrapper(const af_window window, const af_array in, chart = setup_plot(window, in, dims[order_dim], props, ptype, marker); break; + case s8: + chart = setup_plot(window, in, dims[order_dim], props, + ptype, marker); + break; case u8: chart = setup_plot(window, in, dims[order_dim], props, ptype, marker); @@ -240,6 +245,9 @@ af_err plotWrapper(const af_window window, const af_array X, const af_array Y, case u16: chart = setup_plot(window, in, 3, props, ptype, marker); break; + case s8: + chart = setup_plot(window, in, 3, props, ptype, marker); + break; case u8: chart = setup_plot(window, in, 3, props, ptype, marker); break; @@ -307,6 +315,9 @@ af_err plotWrapper(const af_window window, const af_array X, const af_array Y, case u16: chart = setup_plot(window, in, 2, props, ptype, marker); break; + case s8: + chart = setup_plot(window, in, 2, props, ptype, marker); + break; case u8: chart = setup_plot(window, in, 2, props, ptype, marker); break; diff --git a/src/api/c/print.cpp b/src/api/c/print.cpp index 48fea73b48..2f1ae15c8d 100644 --- a/src/api/c/print.cpp +++ b/src/api/c/print.cpp @@ -36,6 +36,7 @@ using arrayfire::common::SparseArray; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -162,6 +163,7 @@ af_err af_print_array(af_array arr) { case b8: print(NULL, arr, 4); break; case s32: print(NULL, arr, 4); break; case u32: print(NULL, arr, 4); break; + case s8: print(NULL, arr, 4); break; case u8: print(NULL, arr, 4); break; case s64: print(NULL, arr, 4); break; case u64: print(NULL, arr, 4); break; @@ -201,6 +203,7 @@ af_err af_print_array_gen(const char *exp, const af_array arr, case b8: print(exp, arr, precision); break; case s32: print(exp, arr, precision); break; case u32: print(exp, arr, precision); break; + case s8: print(exp, arr, precision); break; case u8: print(exp, arr, precision); break; case s64: print(exp, arr, precision); break; case u64: print(exp, arr, precision); break; @@ -259,6 +262,9 @@ af_err af_array_to_string(char **output, const char *exp, const af_array arr, case u32: print(exp, arr, precision, ss, transpose); break; + case s8: + print(exp, arr, precision, ss, transpose); + break; case u8: print(exp, arr, precision, ss, transpose); break; diff --git a/src/api/c/random.cpp b/src/api/c/random.cpp index 915e733974..6508786f53 100644 --- a/src/api/c/random.cpp +++ b/src/api/c/random.cpp @@ -42,6 +42,7 @@ using detail::createEmptyArray; using detail::createHostDataArray; using detail::intl; using detail::normalDistribution; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -296,6 +297,7 @@ af_err af_random_uniform(af_array *out, const unsigned ndims, case u64: result = uniformDistribution_(d, e); break; case s16: result = uniformDistribution_(d, e); break; case u16: result = uniformDistribution_(d, e); break; + case s8: result = uniformDistribution_(d, e); break; case u8: result = uniformDistribution_(d, e); break; case b8: result = uniformDistribution_(d, e); break; case f16: result = uniformDistribution_(d, e); break; @@ -362,6 +364,7 @@ af_err af_randu(af_array *out, const unsigned ndims, const dim_t *const dims, case u64: result = uniformDistribution_(d, e); break; case s16: result = uniformDistribution_(d, e); break; case u16: result = uniformDistribution_(d, e); break; + case s8: result = uniformDistribution_(d, e); break; case u8: result = uniformDistribution_(d, e); break; case b8: result = uniformDistribution_(d, e); break; case f16: result = uniformDistribution_(d, e); break; diff --git a/src/api/c/reduce.cpp b/src/api/c/reduce.cpp index 8e1e670506..65d3f85209 100644 --- a/src/api/c/reduce.cpp +++ b/src/api/c/reduce.cpp @@ -30,6 +30,7 @@ using detail::getScalar; using detail::imag; using detail::intl; using detail::real; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -107,6 +108,7 @@ static af_err reduce_type(af_array *out, const af_array in, const int dim) { case s16: res = reduce(in, dim); break; case b8: res = reduce(in, dim); break; case u8: res = reduce(in, dim); break; + case s8: res = reduce(in, dim); break; case f16: res = reduce(in, dim); break; default: TYPE_ERROR(1, type); } @@ -171,6 +173,9 @@ static af_err reduce_by_key_type(af_array *keys_out, af_array *vals_out, case u8: reduce_key(keys_out, vals_out, keys, vals, dim); break; + case s8: + reduce_key(keys_out, vals_out, keys, vals, dim); + break; case f16: reduce_key(keys_out, vals_out, keys, vals, dim); break; @@ -210,6 +215,7 @@ static af_err reduce_common(af_array *out, const af_array in, const int dim) { case s16: res = reduce(in, dim); break; case b8: res = reduce(in, dim); break; case u8: res = reduce(in, dim); break; + case s8: res = reduce(in, dim); break; case f16: res = reduce(in, dim); break; default: TYPE_ERROR(1, type); } @@ -280,6 +286,11 @@ static af_err reduce_by_key_common(af_array *keys_out, af_array *vals_out, case u8: reduce_key(keys_out, vals_out, keys, vals, dim); + break; + case s8: + reduce_key(keys_out, vals_out, keys, vals, + dim); + break; case f16: reduce_key(keys_out, vals_out, keys, vals, dim); break; @@ -342,6 +353,9 @@ static af_err reduce_promote(af_array *out, const af_array in, const int dim, case u8: res = reduce(in, dim, change_nan, nanval); break; + case s8: + res = reduce(in, dim, change_nan, nanval); + break; case b8: { if (op == af_mul_t) { res = reduce(in, dim, change_nan, @@ -424,6 +438,10 @@ static af_err reduce_promote_by_key(af_array *keys_out, af_array *vals_out, reduce_key(keys_out, vals_out, keys, vals, dim, change_nan, nanval); break; + case s8: + reduce_key(keys_out, vals_out, keys, vals, dim, + change_nan, nanval); + break; case b8: reduce_key( keys_out, vals_out, keys, vals, dim, change_nan, nanval); @@ -574,6 +592,7 @@ static af_err reduce_all_type(double *real, double *imag, const af_array in) { case s16: *real = reduce_all(in); break; case b8: *real = reduce_all(in); break; case u8: *real = reduce_all(in); break; + case s8: *real = reduce_all(in); break; case f16: *real = reduce_all(in); break; // clang-format on default: TYPE_ERROR(1, type); @@ -605,6 +624,7 @@ static af_err reduce_all_type_array(af_array *out, const af_array in) { case s16: res = reduce_all_array(in); break; case b8: res = reduce_all_array(in); break; case u8: res = reduce_all_array(in); break; + case s8: res = reduce_all_array(in); break; case f16: res = reduce_all_array(in); break; // clang-format on default: TYPE_ERROR(1, type); @@ -643,6 +663,7 @@ static af_err reduce_all_common(double *real_val, double *imag_val, case s16: *real_val = reduce_all(in); break; case b8: *real_val = reduce_all(in); break; case u8: *real_val = reduce_all(in); break; + case s8: *real_val = reduce_all(in); break; case f16: *real_val = reduce_all(in); break; // clang-format on case c32: @@ -688,6 +709,7 @@ static af_err reduce_all_common_array(af_array *out, const af_array in) { case s16: res = reduce_all_array(in); break; case b8: res = reduce_all_array(in); break; case u8: res = reduce_all_array(in); break; + case s8: res = reduce_all_array(in); break; case f16: res = reduce_all_array(in); break; // clang-format on case c32: res = reduce_all_array(in); break; @@ -727,6 +749,7 @@ static af_err reduce_all_promote(double *real_val, double *imag_val, case u16: *real_val = reduce_all(in, change_nan, nanval); break; case s16: *real_val = reduce_all(in, change_nan, nanval); break; case u8: *real_val = reduce_all(in, change_nan, nanval); break; + case s8: *real_val = reduce_all(in, change_nan, nanval); break; // clang-format on case b8: { if (op == af_mul_t) { @@ -812,6 +835,9 @@ static af_err reduce_all_promote_array(af_array *out, const af_array in, case u8: res = reduce_all_array(in, change_nan, nanval); break; + case s8: + res = reduce_all_array(in, change_nan, nanval); + break; case b8: { if (op == af_mul_t) { res = reduce_all_array(in, change_nan, @@ -952,6 +978,7 @@ static af_err ireduce_common(af_array *val, af_array *idx, const af_array in, case s16: ireduce(&res, &loc, in, dim); break; case b8: ireduce(&res, &loc, in, dim); break; case u8: ireduce(&res, &loc, in, dim); break; + case s8: ireduce(&res, &loc, in, dim); break; case f16: ireduce(&res, &loc, in, dim); break; default: TYPE_ERROR(1, type); } @@ -1027,6 +1054,7 @@ static af_err rreduce_common(af_array *val, af_array *idx, const af_array in, break; case b8: rreduce(&res, &loc, in, dim, ragged_len); break; case u8: rreduce(&res, &loc, in, dim, ragged_len); break; + case s8: rreduce(&res, &loc, in, dim, ragged_len); break; case f16: rreduce(&res, &loc, in, dim, ragged_len); break; default: TYPE_ERROR(2, type); } @@ -1085,6 +1113,7 @@ static af_err ireduce_all_common(double *real_val, double *imag_val, break; case b8: *real_val = ireduce_all(loc, in); break; case u8: *real_val = ireduce_all(loc, in); break; + case s8: *real_val = ireduce_all(loc, in); break; case c32: cfval = ireduce_all(loc, in); diff --git a/src/api/c/reorder.cpp b/src/api/c/reorder.cpp index 556e1f0e20..e29fb621c0 100644 --- a/src/api/c/reorder.cpp +++ b/src/api/c/reorder.cpp @@ -25,6 +25,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -108,6 +109,7 @@ af_err af_reorder(af_array *out, const af_array in, const af::dim4 &rdims) { case b8: output = reorder(in, rdims); break; case s32: output = reorder(in, rdims); break; case u32: output = reorder(in, rdims); break; + case s8: output = reorder(in, rdims); break; case u8: output = reorder(in, rdims); break; case s64: output = reorder(in, rdims); break; case u64: output = reorder(in, rdims); break; diff --git a/src/api/c/replace.cpp b/src/api/c/replace.cpp index b8fdd75e02..7bf66cc439 100644 --- a/src/api/c/replace.cpp +++ b/src/api/c/replace.cpp @@ -27,6 +27,7 @@ using arrayfire::common::half; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::select_scalar; using detail::uchar; using detail::uint; @@ -74,6 +75,7 @@ af_err af_replace(af_array a, const af_array cond, const af_array b) { case u64: replace(a, cond, b); break; case s16: replace(a, cond, b); break; case u16: replace(a, cond, b); break; + case s8: replace(a, cond, b); break; case u8: replace(a, cond, b); break; case b8: replace(a, cond, b); break; default: TYPE_ERROR(2, ainfo.getType()); @@ -116,6 +118,7 @@ af_err replaceScalar(af_array a, const af_array cond, const ScalarType b) { case u64: replace_scalar(a, cond, b); break; case s16: replace_scalar(a, cond, b); break; case u16: replace_scalar(a, cond, b); break; + case s8: replace_scalar(a, cond, b); break; case u8: replace_scalar(a, cond, b); break; case b8: replace_scalar(a, cond, b); break; default: TYPE_ERROR(2, ainfo.getType()); diff --git a/src/api/c/resize.cpp b/src/api/c/resize.cpp index 8b6df743da..814d4df0c8 100644 --- a/src/api/c/resize.cpp +++ b/src/api/c/resize.cpp @@ -19,6 +19,7 @@ using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -68,6 +69,7 @@ af_err af_resize(af_array* out, const af_array in, const dim_t odim0, case u64: output = resize(in, odim0, odim1, method); break; case s16: output = resize(in, odim0, odim1, method); break; case u16: output = resize(in, odim0, odim1, method); break; + case s8: output = resize(in, odim0, odim1, method); break; case u8: output = resize(in, odim0, odim1, method); break; case b8: output = resize(in, odim0, odim1, method); break; default: TYPE_ERROR(1, type); diff --git a/src/api/c/rgb_gray.cpp b/src/api/c/rgb_gray.cpp index 3bea06e855..c7abe042bc 100644 --- a/src/api/c/rgb_gray.cpp +++ b/src/api/c/rgb_gray.cpp @@ -30,6 +30,7 @@ using detail::createEmptyArray; using detail::createValueArray; using detail::join; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -157,6 +158,9 @@ af_err convert(af_array* out, const af_array in, const float r, const float g, case u8: output = convert(in, r, g, b); break; + case s8: + output = convert(in, r, g, b); + break; default: TYPE_ERROR(1, iType); break; } std::swap(*out, output); diff --git a/src/api/c/rotate.cpp b/src/api/c/rotate.cpp index 762f77d7f4..50397a310a 100644 --- a/src/api/c/rotate.cpp +++ b/src/api/c/rotate.cpp @@ -19,6 +19,7 @@ using af::dim4; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -76,6 +77,7 @@ af_err af_rotate(af_array *out, const af_array in, const float theta, case u64: output = rotate(in, theta, odims, method); break; case s16: output = rotate(in, theta, odims, method); break; case u16: output = rotate(in, theta, odims, method); break; + case s8: output = rotate(in, theta, odims, method); break; case u8: case b8: output = rotate(in, theta, odims, method); break; default: TYPE_ERROR(1, itype); diff --git a/src/api/c/sat.cpp b/src/api/c/sat.cpp index 3ff72abacc..8715f4865c 100644 --- a/src/api/c/sat.cpp +++ b/src/api/c/sat.cpp @@ -18,6 +18,7 @@ using arrayfire::common::integralImage; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -44,6 +45,7 @@ af_err af_sat(af_array* out, const af_array in) { case s32: output = sat(in); break; case u32: output = sat(in); break; case b8: output = sat(in); break; + case s8: output = sat(in); break; case u8: output = sat(in); break; case s64: output = sat(in); break; case u64: output = sat(in); break; diff --git a/src/api/c/scan.cpp b/src/api/c/scan.cpp index d8a3a7a95d..cac89d6c01 100644 --- a/src/api/c/scan.cpp +++ b/src/api/c/scan.cpp @@ -21,6 +21,7 @@ using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -141,6 +142,7 @@ af_err af_accum(af_array* out, const af_array in, const int dim) { case u16: res = scan(in, dim); break; case s16: res = scan(in, dim); break; case u8: res = scan(in, dim); break; + case s8: res = scan(in, dim); break; // Make sure you are adding only "1" for every non zero value, even // if op == af_add_t case b8: res = scan(in, dim); break; @@ -204,6 +206,9 @@ af_err af_scan(af_array* out, const af_array in, const int dim, af_binary_op op, case u8: res = scan_op(in, dim, op, inclusive_scan); break; + case s8: + res = scan_op(in, dim, op, inclusive_scan); + break; case b8: res = scan_op(in, dim, op, inclusive_scan); break; @@ -252,6 +257,7 @@ af_err af_scan_by_key(af_array* out, const af_array key, const af_array in, break; case s16: case s32: + case s8: res = scan_op(key, in, dim, op, inclusive_scan); break; case u64: diff --git a/src/api/c/select.cpp b/src/api/c/select.cpp index dec47166e7..c161aa5e9b 100644 --- a/src/api/c/select.cpp +++ b/src/api/c/select.cpp @@ -26,6 +26,7 @@ using detail::cdouble; using detail::cfloat; using detail::createSelectNode; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -76,6 +77,7 @@ af_err af_select(af_array* out, const af_array cond, const af_array a, case u64: res = select(cond, a, b, odims); break; case s16: res = select(cond, a, b, odims); break; case u16: res = select(cond, a, b, odims); break; + case s8: res = select(cond, a, b, odims); break; case u8: res = select(cond, a, b, odims); break; case b8: res = select(cond, a, b, odims); break; case f16: res = select(cond, a, b, odims); break; @@ -163,6 +165,10 @@ af_err selectScalar(af_array* out, const af_array cond, const af_array e, res = select_scalar( cond, e, c, odims); break; + case s8: + res = select_scalar( + cond, e, c, odims); + break; case u8: res = select_scalar( cond, e, c, odims); diff --git a/src/api/c/set.cpp b/src/api/c/set.cpp index bf8b66e3c8..3353d7c5ee 100644 --- a/src/api/c/set.cpp +++ b/src/api/c/set.cpp @@ -18,6 +18,7 @@ using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -51,6 +52,7 @@ af_err af_set_unique(af_array* out, const af_array in, const bool is_sorted) { case s64: res = setUnique(in, is_sorted); break; case u64: res = setUnique(in, is_sorted); break; case b8: res = setUnique(in, is_sorted); break; + case s8: res = setUnique(in, is_sorted); break; case u8: res = setUnique(in, is_sorted); break; default: TYPE_ERROR(1, type); } @@ -98,6 +100,7 @@ af_err af_set_union(af_array* out, const af_array first, const af_array second, case s64: res = setUnion(first, second, is_unique); break; case u64: res = setUnion(first, second, is_unique); break; case b8: res = setUnion(first, second, is_unique); break; + case s8: res = setUnion(first, second, is_unique); break; case u8: res = setUnion(first, second, is_unique); break; default: TYPE_ERROR(1, first_type); } @@ -156,6 +159,7 @@ af_err af_set_intersect(af_array* out, const af_array first, res = setIntersect(first, second, is_unique); break; case b8: res = setIntersect(first, second, is_unique); break; + case s8: res = setIntersect(first, second, is_unique); break; case u8: res = setIntersect(first, second, is_unique); break; default: TYPE_ERROR(1, first_type); } diff --git a/src/api/c/shift.cpp b/src/api/c/shift.cpp index 42052fbfbc..cf195d2026 100644 --- a/src/api/c/shift.cpp +++ b/src/api/c/shift.cpp @@ -17,6 +17,7 @@ using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -49,6 +50,7 @@ af_err af_shift(af_array *out, const af_array in, const int sdims[4]) { case u64: output = shift(in, sdims); break; case s16: output = shift(in, sdims); break; case u16: output = shift(in, sdims); break; + case s8: output = shift(in, sdims); break; case u8: output = shift(in, sdims); break; default: TYPE_ERROR(1, type); } diff --git a/src/api/c/sobel.cpp b/src/api/c/sobel.cpp index 6184d5502a..d466db1617 100644 --- a/src/api/c/sobel.cpp +++ b/src/api/c/sobel.cpp @@ -21,6 +21,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -66,6 +67,9 @@ af_err af_sobel_operator(af_array *dx, af_array *dy, const af_array img, output = sobelDerivatives(img, ker_size); break; case b8: output = sobelDerivatives(img, ker_size); break; + case s8: + output = sobelDerivatives(img, ker_size); + break; case u8: output = sobelDerivatives(img, ker_size); break; diff --git a/src/api/c/sort.cpp b/src/api/c/sort.cpp index 4ec1c0a466..b917b8b3c5 100644 --- a/src/api/c/sort.cpp +++ b/src/api/c/sort.cpp @@ -27,6 +27,7 @@ using detail::cdouble; using detail::cfloat; using detail::createEmptyArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -59,6 +60,7 @@ af_err af_sort(af_array *out, const af_array in, const unsigned dim, case u16: val = sort(in, dim, isAscending); break; case s64: val = sort(in, dim, isAscending); break; case u64: val = sort(in, dim, isAscending); break; + case s8: val = sort(in, dim, isAscending); break; case u8: val = sort(in, dim, isAscending); break; case b8: val = sort(in, dim, isAscending); break; default: TYPE_ERROR(1, type); @@ -118,6 +120,7 @@ af_err af_sort_index(af_array *out, af_array *indices, const af_array in, case u64: sort_index(&val, &idx, in, dim, isAscending); break; + case s8: sort_index(&val, &idx, in, dim, isAscending); break; case u8: sort_index(&val, &idx, in, dim, isAscending); break; case b8: sort_index(&val, &idx, in, dim, isAscending); break; default: TYPE_ERROR(1, type); @@ -185,6 +188,9 @@ void sort_by_key_tmplt(af_array *okey, af_array *oval, const af_array ikey, case u64: sort_by_key(okey, oval, ikey, ival, dim, isAscending); break; + case s8: + sort_by_key(okey, oval, ikey, ival, dim, isAscending); + break; case u8: sort_by_key(okey, oval, ikey, ival, dim, isAscending); break; @@ -249,6 +255,10 @@ af_err af_sort_by_key(af_array *out_keys, af_array *out_values, sort_by_key_tmplt(&oKey, &oVal, keys, values, dim, isAscending); break; + case s8: + sort_by_key_tmplt(&oKey, &oVal, keys, values, dim, + isAscending); + break; case u8: sort_by_key_tmplt(&oKey, &oVal, keys, values, dim, isAscending); diff --git a/src/api/c/stdev.cpp b/src/api/c/stdev.cpp index 7f64bf3355..d5589f4d39 100644 --- a/src/api/c/stdev.cpp +++ b/src/api/c/stdev.cpp @@ -38,6 +38,7 @@ using detail::mean; using detail::reduce; using detail::reduce_all; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -111,6 +112,7 @@ af_err af_stdev_all_v2(double* realVal, double* imagVal, const af_array in, case u16: *realVal = stdev(in, bias); break; case s64: *realVal = stdev(in, bias); break; case u64: *realVal = stdev(in, bias); break; + case s8: *realVal = stdev(in, bias); break; case u8: *realVal = stdev(in, bias); break; case b8: *realVal = stdev(in, bias); break; // TODO(umar): FIXME: sqrt(complex) is not present in cuda/opencl @@ -152,6 +154,7 @@ af_err af_stdev_v2(af_array* out, const af_array in, const af_var_bias bias, case u16: output = stdev(in, dim, bias); break; case s64: output = stdev(in, dim, bias); break; case u64: output = stdev(in, dim, bias); break; + case s8: output = stdev(in, dim, bias); break; case u8: output = stdev(in, dim, bias); break; case b8: output = stdev(in, dim, bias); break; // TODO(umar): FIXME: sqrt(complex) is not present in cuda/opencl diff --git a/src/api/c/stream.cpp b/src/api/c/stream.cpp index 1be207c66d..45265e69b5 100644 --- a/src/api/c/stream.cpp +++ b/src/api/c/stream.cpp @@ -28,6 +28,7 @@ using detail::cdouble; using detail::cfloat; using detail::createHostDataArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -141,6 +142,7 @@ af_err af_save_array(int *index, const char *key, const af_array arr, case b8: id = save(key, arr, filename, append); break; case s32: id = save(key, arr, filename, append); break; case u32: id = save(key, arr, filename, append); break; + case s8: id = save(key, arr, filename, append); break; case u8: id = save(key, arr, filename, append); break; case s64: id = save(key, arr, filename, append); break; case u64: id = save(key, arr, filename, append); break; @@ -240,6 +242,7 @@ static af_array readArrayV1(const char *filename, const unsigned index) { case b8: out = readDataToArray(fs); break; case s32: out = readDataToArray(fs); break; case u32: out = readDataToArray(fs); break; + case s8: out = readDataToArray(fs); break; case u8: out = readDataToArray(fs); break; case s64: out = readDataToArray(fs); break; case u64: out = readDataToArray(fs); break; diff --git a/src/api/c/surface.cpp b/src/api/c/surface.cpp index b2a6404a33..d748677269 100644 --- a/src/api/c/surface.cpp +++ b/src/api/c/surface.cpp @@ -38,6 +38,7 @@ using detail::createEmptyArray; using detail::forgeManager; using detail::getScalar; using detail::reduce_all; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -190,6 +191,9 @@ af_err af_draw_surface(const af_window window, const af_array xVals, case u16: chart = setup_surface(window, xVals, yVals, S, props); break; + case s8: + chart = setup_surface(window, xVals, yVals, S, props); + break; case u8: chart = setup_surface(window, xVals, yVals, S, props); break; diff --git a/src/api/c/susan.cpp b/src/api/c/susan.cpp index 0621f7eb16..8ea7dc8945 100644 --- a/src/api/c/susan.cpp +++ b/src/api/c/susan.cpp @@ -24,6 +24,7 @@ using detail::cfloat; using detail::createEmptyArray; using detail::createValueArray; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::ushort; @@ -98,6 +99,10 @@ af_err af_susan(af_features* out, const af_array in, const unsigned radius, *out = susan(in, radius, diff_thr, geom_thr, feature_ratio, edge); break; + case s8: + *out = susan(in, radius, diff_thr, geom_thr, + feature_ratio, edge); + break; case u8: *out = susan(in, radius, diff_thr, geom_thr, feature_ratio, edge); diff --git a/src/api/c/tile.cpp b/src/api/c/tile.cpp index ce512e9958..2a50f12c43 100644 --- a/src/api/c/tile.cpp +++ b/src/api/c/tile.cpp @@ -26,6 +26,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -60,6 +61,7 @@ af_err af_tile(af_array *out, const af_array in, const af::dim4 &tileDims) { case u64: output = tile(in, tileDims); break; case s16: output = tile(in, tileDims); break; case u16: output = tile(in, tileDims); break; + case s8: output = tile(in, tileDims); break; case u8: output = tile(in, tileDims); break; case f16: output = tile(in, tileDims); break; default: TYPE_ERROR(1, type); diff --git a/src/api/c/transform.cpp b/src/api/c/transform.cpp index 9bdaceb149..259d13840e 100644 --- a/src/api/c/transform.cpp +++ b/src/api/c/transform.cpp @@ -19,6 +19,7 @@ using af::dim4; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -158,6 +159,7 @@ void af_transform_common(af_array *out, const af_array in, const af_array tf, case u64: transform(out, in, tf, method, inverse, perspective); break; case s16: transform(out, in, tf, method, inverse, perspective); break; case u16: transform(out, in, tf, method, inverse, perspective); break; + case s8: transform(out, in, tf, method, inverse, perspective); break; case u8: transform(out, in, tf, method, inverse, perspective); break; case b8: transform(out, in, tf, method, inverse, perspective); break; default: TYPE_ERROR(1, itype); diff --git a/src/api/c/transpose.cpp b/src/api/c/transpose.cpp index 82ae18fef2..9d2fd48cbd 100644 --- a/src/api/c/transpose.cpp +++ b/src/api/c/transpose.cpp @@ -24,6 +24,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -67,6 +68,7 @@ af_err af_transpose(af_array* out, af_array in, const bool conjugate) { case b8: output = trs(in, conjugate); break; case s32: output = trs(in, conjugate); break; case u32: output = trs(in, conjugate); break; + case s8: output = trs(in, conjugate); break; case u8: output = trs(in, conjugate); break; case s64: output = trs(in, conjugate); break; case u64: output = trs(in, conjugate); break; @@ -107,6 +109,7 @@ af_err af_transpose_inplace(af_array in, const bool conjugate) { case b8: transpose_inplace(in, conjugate); break; case s32: transpose_inplace(in, conjugate); break; case u32: transpose_inplace(in, conjugate); break; + case s8: transpose_inplace(in, conjugate); break; case u8: transpose_inplace(in, conjugate); break; case s64: transpose_inplace(in, conjugate); break; case u64: transpose_inplace(in, conjugate); break; diff --git a/src/api/c/type_util.cpp b/src/api/c/type_util.cpp index c78b85b1da..d409c0d868 100644 --- a/src/api/c/type_util.cpp +++ b/src/api/c/type_util.cpp @@ -20,6 +20,7 @@ size_t size_of(af_dtype type) { case f64: return sizeof(double); case s32: return sizeof(int); case u32: return sizeof(unsigned); + case s8: return sizeof(signed char); case u8: return sizeof(unsigned char); case b8: return sizeof(unsigned char); case c32: return sizeof(float) * 2; diff --git a/src/api/c/type_util.hpp b/src/api/c/type_util.hpp index 4214882492..8e6a7ff9cf 100644 --- a/src/api/c/type_util.hpp +++ b/src/api/c/type_util.hpp @@ -16,6 +16,11 @@ struct ToNum { inline T operator()(T val) { return val; } }; +template<> +struct ToNum { + inline int operator()(signed char val) { return static_cast(val); } +}; + template<> struct ToNum { inline int operator()(unsigned char val) { return static_cast(val); } diff --git a/src/api/c/unary.cpp b/src/api/c/unary.cpp index 6d8b584ace..505c831e74 100644 --- a/src/api/c/unary.cpp +++ b/src/api/c/unary.cpp @@ -43,6 +43,7 @@ using detail::intl; using detail::logicOp; using detail::real; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -598,6 +599,7 @@ af_err af_bitnot(af_array *out, const af_array in) { switch (type) { case s32: res = bitOpNot(in); break; case u32: res = bitOpNot(in); break; + case s8: res = bitOpNot(in); break; case u8: res = bitOpNot(in); break; case b8: res = bitOpNot(in); break; case s64: res = bitOpNot(in); break; diff --git a/src/api/c/unwrap.cpp b/src/api/c/unwrap.cpp index ee0ac2a16e..6f09a6b7eb 100644 --- a/src/api/c/unwrap.cpp +++ b/src/api/c/unwrap.cpp @@ -20,6 +20,7 @@ using detail::Array; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -81,6 +82,9 @@ af_err af_unwrap(af_array* out, const af_array in, const dim_t wx, case u16: output = unwrap(in, wx, wy, sx, sy, px, py, is_column); break; + case s8: + output = unwrap(in, wx, wy, sx, sy, px, py, is_column); + break; case u8: output = unwrap(in, wx, wy, sx, sy, px, py, is_column); break; diff --git a/src/api/c/var.cpp b/src/api/c/var.cpp index c82c1ca0cd..64a5d8f693 100644 --- a/src/api/c/var.cpp +++ b/src/api/c/var.cpp @@ -43,6 +43,7 @@ using detail::real; using detail::reduce; using detail::reduce_all; using detail::scalar; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -225,6 +226,9 @@ af_err af_var_v2(af_array* out, const af_array in, const af_var_bias bias, case u64: output = var_(in, no_weights, bias, dim); break; + case s8: + output = var_(in, no_weights, bias, dim); + break; case u8: output = var_(in, no_weights, bias, dim); break; @@ -298,6 +302,10 @@ af_err af_var_weighted(af_array* out, const af_array in, const af_array weights, output = var_(in, weights, AF_VARIANCE_POPULATION, dim); break; + case s8: + output = var_(in, weights, AF_VARIANCE_POPULATION, + dim); + break; case u8: output = var_(in, weights, AF_VARIANCE_POPULATION, dim); @@ -347,6 +355,7 @@ af_err af_var_all_v2(double* realVal, double* imagVal, const af_array in, case u16: *realVal = varAll(in, bias); break; case s64: *realVal = varAll(in, bias); break; case u64: *realVal = varAll(in, bias); break; + case s8: *realVal = varAll(in, bias); break; case u8: *realVal = varAll(in, bias); break; case b8: *realVal = varAll(in, bias); break; case f16: *realVal = varAll(in, bias); break; @@ -390,6 +399,7 @@ af_err af_var_all_weighted(double* realVal, double* imagVal, const af_array in, case u16: *realVal = varAll(in, weights); break; case s64: *realVal = varAll(in, weights); break; case u64: *realVal = varAll(in, weights); break; + case s8: *realVal = varAll(in, weights); break; case u8: *realVal = varAll(in, weights); break; case b8: *realVal = varAll(in, weights); break; case f16: *realVal = varAll(in, weights); break; @@ -453,6 +463,10 @@ af_err af_meanvar(af_array* mean, af_array* var, const af_array in, tie(*mean, *var) = meanvar(in, weights, bias, dim); break; + case s8: + tie(*mean, *var) = + meanvar(in, weights, bias, dim); + break; case u8: tie(*mean, *var) = meanvar(in, weights, bias, dim); diff --git a/src/api/c/vector_field.cpp b/src/api/c/vector_field.cpp index a46d1eed47..9eba21811c 100644 --- a/src/api/c/vector_field.cpp +++ b/src/api/c/vector_field.cpp @@ -35,6 +35,7 @@ using detail::copy_vector_field; using detail::createEmptyArray; using detail::forgeManager; using detail::reduce; +using detail::schar; using detail::transpose; using detail::uchar; using detail::uint; @@ -50,20 +51,21 @@ fg_chart setup_vector_field(fg_window window, const vector& points, vector> pnts; vector> dirs; - for (unsigned i = 0; i < points.size(); ++i) { - pnts.push_back(getArray(points[i])); - dirs.push_back(getArray(directions[i])); - } - - // Join for set up vector - dim4 odims(3, points.size()); - Array out_pnts = createEmptyArray(odims); - Array out_dirs = createEmptyArray(odims); - detail::join(out_pnts, 1, pnts); - detail::join(out_dirs, 1, dirs); - Array pIn = out_pnts; - Array dIn = out_dirs; + Array pIn = getArray(points[0]); + Array dIn = getArray(directions[0]); + if (points.size() > 1) { + for (unsigned i = 0; i < points.size(); ++i) { + pnts.push_back(getArray(points[i])); + dirs.push_back(getArray(directions[i])); + } + // Join for set up vector + const dim4 odims(pIn.dims()[0], points.size()); + pIn = createEmptyArray(odims); + dIn = createEmptyArray(odims); + detail::join(pIn, 1, pnts); + detail::join(dIn, 1, dirs); + } // do transpose if required if (transpose_) { pIn = transpose(pIn, false); @@ -182,6 +184,9 @@ af_err vectorFieldWrapper(const af_window window, const af_array points, case u16: chart = setup_vector_field(window, pnts, dirs, props); break; + case s8: + chart = setup_vector_field(window, pnts, dirs, props); + break; case u8: chart = setup_vector_field(window, pnts, dirs, props); break; @@ -288,6 +293,10 @@ af_err vectorFieldWrapper(const af_window window, const af_array xPoints, chart = setup_vector_field(window, points, directions, props); break; + case s8: + chart = setup_vector_field(window, points, directions, + props); + break; case u8: chart = setup_vector_field(window, points, directions, props); @@ -382,6 +391,10 @@ af_err vectorFieldWrapper(const af_window window, const af_array xPoints, chart = setup_vector_field(window, points, directions, props); break; + case s8: + chart = setup_vector_field(window, points, directions, + props); + break; case u8: chart = setup_vector_field(window, points, directions, props); diff --git a/src/api/c/where.cpp b/src/api/c/where.cpp index 4aeb7b60ba..6f83aed17d 100644 --- a/src/api/c/where.cpp +++ b/src/api/c/where.cpp @@ -18,6 +18,7 @@ using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -51,6 +52,7 @@ af_err af_where(af_array* idx, const af_array in) { case u64: res = where(in); break; case s16: res = where(in); break; case u16: res = where(in); break; + case s8: res = where(in); break; case u8: res = where(in); break; case b8: res = where(in); break; default: TYPE_ERROR(1, type); diff --git a/src/api/c/wrap.cpp b/src/api/c/wrap.cpp index f436f37350..e3c06a4642 100644 --- a/src/api/c/wrap.cpp +++ b/src/api/c/wrap.cpp @@ -19,6 +19,7 @@ using af::dim4; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -75,6 +76,7 @@ void af_wrap_common(af_array* out, const af_array in, const dim_t ox, case u64: wrap(out, in, wx, wy, sx, sy, px, py, is_column); break; case s16: wrap(out, in, wx, wy, sx, sy, px, py, is_column); break; case u16: wrap(out, in, wx, wy, sx, sy, px, py, is_column); break; + case s8: wrap(out, in, wx, wy, sx, sy, px, py, is_column); break; case u8: wrap(out, in, wx, wy, sx, sy, px, py, is_column); break; case b8: wrap(out, in, wx, wy, sx, sy, px, py, is_column); break; default: TYPE_ERROR(1, in_type); diff --git a/src/api/cpp/array.cpp b/src/api/cpp/array.cpp index 1d61c63c2d..418d94c52b 100644 --- a/src/api/cpp/array.cpp +++ b/src/api/cpp/array.cpp @@ -236,6 +236,7 @@ INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(unsigned) INSTANTIATE(int) +INSTANTIATE(signed char) INSTANTIATE(unsigned char) INSTANTIATE(char) INSTANTIATE(long long) @@ -701,6 +702,7 @@ MEM_FUNC(af_array, get) ASSIGN_TYPE(long long, OP) \ ASSIGN_TYPE(unsigned long long, OP) \ ASSIGN_TYPE(char, OP) \ + ASSIGN_TYPE(signed char, OP) \ ASSIGN_TYPE(unsigned char, OP) \ ASSIGN_TYPE(bool, OP) \ ASSIGN_TYPE(short, OP) \ @@ -828,6 +830,7 @@ array &array::operator=(const array &other) { ASSIGN_TYPE(long long, OP) \ ASSIGN_TYPE(unsigned long long, OP) \ ASSIGN_TYPE(char, OP) \ + ASSIGN_TYPE(signed char, OP) \ ASSIGN_TYPE(unsigned char, OP) \ ASSIGN_TYPE(bool, OP) \ ASSIGN_TYPE(short, OP) \ @@ -863,6 +866,7 @@ ASSIGN_OP(/=, af_div) ASSIGN_TYPE(long long, OP) \ ASSIGN_TYPE(unsigned long long, OP) \ ASSIGN_TYPE(char, OP) \ + ASSIGN_TYPE(signed char, OP) \ ASSIGN_TYPE(unsigned char, OP) \ ASSIGN_TYPE(bool, OP) \ ASSIGN_TYPE(short, OP) \ @@ -939,6 +943,7 @@ af::dtype implicit_dtype(af::dtype scalar_type, af::dtype array_type) { BINARY_TYPE(long long, OP, release_func, s64) \ BINARY_TYPE(unsigned long long, OP, release_func, u64) \ BINARY_TYPE(char, OP, release_func, b8) \ + BINARY_TYPE(signed char, OP, release_func, s8) \ BINARY_TYPE(unsigned char, OP, release_func, u8) \ BINARY_TYPE(bool, OP, release_func, b8) \ BINARY_TYPE(short, OP, release_func, s16) \ @@ -1038,6 +1043,7 @@ INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(unsigned) INSTANTIATE(int) +INSTANTIATE(signed char) INSTANTIATE(unsigned char) INSTANTIATE(char) INSTANTIATE(long long) @@ -1080,6 +1086,7 @@ INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(unsigned) INSTANTIATE(int) +INSTANTIATE(signed char) INSTANTIATE(unsigned char) INSTANTIATE(char) INSTANTIATE(long long) diff --git a/src/api/cpp/corrcoef.cpp b/src/api/cpp/corrcoef.cpp index f90be68b5f..dbedad5aee 100644 --- a/src/api/cpp/corrcoef.cpp +++ b/src/api/cpp/corrcoef.cpp @@ -26,6 +26,7 @@ INSTANTIATE_CORRCOEF(double); INSTANTIATE_CORRCOEF(int); INSTANTIATE_CORRCOEF(unsigned int); INSTANTIATE_CORRCOEF(char); +INSTANTIATE_CORRCOEF(signed char); INSTANTIATE_CORRCOEF(unsigned char); INSTANTIATE_CORRCOEF(long long); INSTANTIATE_CORRCOEF(unsigned long long); diff --git a/src/api/cpp/data.cpp b/src/api/cpp/data.cpp index 3f86520bd0..f5eb8c2544 100644 --- a/src/api/cpp/data.cpp +++ b/src/api/cpp/data.cpp @@ -130,6 +130,7 @@ CONSTANT(float); CONSTANT(int); CONSTANT(unsigned); CONSTANT(char); +CONSTANT(signed char); CONSTANT(unsigned char); CONSTANT(cfloat); CONSTANT(cdouble); diff --git a/src/api/cpp/device.cpp b/src/api/cpp/device.cpp index 89aab84754..b62589097e 100644 --- a/src/api/cpp/device.cpp +++ b/src/api/cpp/device.cpp @@ -192,6 +192,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(unsigned) +INSTANTIATE(signed char) INSTANTIATE(unsigned char) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/api/cpp/mean.cpp b/src/api/cpp/mean.cpp index c03a83fa51..61693ca40d 100644 --- a/src/api/cpp/mean.cpp +++ b/src/api/cpp/mean.cpp @@ -81,6 +81,7 @@ INSTANTIATE_MEAN(double); INSTANTIATE_MEAN(int); INSTANTIATE_MEAN(unsigned int); INSTANTIATE_MEAN(char); +INSTANTIATE_MEAN(signed char); INSTANTIATE_MEAN(unsigned char); INSTANTIATE_MEAN(long long); INSTANTIATE_MEAN(unsigned long long); diff --git a/src/api/cpp/median.cpp b/src/api/cpp/median.cpp index 5f4b88fb2a..b288df74a9 100644 --- a/src/api/cpp/median.cpp +++ b/src/api/cpp/median.cpp @@ -27,6 +27,7 @@ INSTANTIATE_MEDIAN(double); INSTANTIATE_MEDIAN(int); INSTANTIATE_MEDIAN(unsigned int); INSTANTIATE_MEDIAN(char); +INSTANTIATE_MEDIAN(signed char); INSTANTIATE_MEDIAN(unsigned char); INSTANTIATE_MEDIAN(long long); INSTANTIATE_MEDIAN(unsigned long long); diff --git a/src/api/cpp/reduce.cpp b/src/api/cpp/reduce.cpp index cfdadf85ae..8dc47fcab9 100644 --- a/src/api/cpp/reduce.cpp +++ b/src/api/cpp/reduce.cpp @@ -191,6 +191,7 @@ void max(array &val, array &idx, const array &in, const int dim) { INSTANTIATE_REAL(fnC, fnCPP, short) \ INSTANTIATE_REAL(fnC, fnCPP, unsigned short) \ INSTANTIATE_REAL(fnC, fnCPP, char) \ + INSTANTIATE_REAL(fnC, fnCPP, signed char) \ INSTANTIATE_REAL(fnC, fnCPP, unsigned char) \ INSTANTIATE_CPLX(fnC, fnCPP, af_cfloat, float) \ INSTANTIATE_CPLX(fnC, fnCPP, af_cdouble, double) @@ -294,6 +295,7 @@ INSTANTIATE(product_nan, product) INSTANTIATE_COMPAT(fnCPP, fnCompat, long long) \ INSTANTIATE_COMPAT(fnCPP, fnCompat, unsigned long long) \ INSTANTIATE_COMPAT(fnCPP, fnCompat, char) \ + INSTANTIATE_COMPAT(fnCPP, fnCompat, signed char) \ INSTANTIATE_COMPAT(fnCPP, fnCompat, unsigned char) \ INSTANTIATE_COMPAT(fnCPP, fnCompat, af_cfloat) \ INSTANTIATE_COMPAT(fnCPP, fnCompat, af_cdouble) \ @@ -332,6 +334,7 @@ INSTANTIATE_COMPAT(anyTrue, anytrue, bool) INSTANTIATE_REAL(fn, int) \ INSTANTIATE_REAL(fn, unsigned) \ INSTANTIATE_REAL(fn, char) \ + INSTANTIATE_REAL(fn, signed char) \ INSTANTIATE_REAL(fn, unsigned char) \ INSTANTIATE_REAL(fn, short) \ INSTANTIATE_REAL(fn, unsigned short) \ diff --git a/src/api/cpp/stdev.cpp b/src/api/cpp/stdev.cpp index a9e22d58f6..66edaf816a 100644 --- a/src/api/cpp/stdev.cpp +++ b/src/api/cpp/stdev.cpp @@ -60,6 +60,7 @@ INSTANTIATE_STDEV(unsigned long long); INSTANTIATE_STDEV(short); INSTANTIATE_STDEV(unsigned short); INSTANTIATE_STDEV(char); +INSTANTIATE_STDEV(signed char); INSTANTIATE_STDEV(unsigned char); #undef INSTANTIATE_STDEV diff --git a/src/api/cpp/var.cpp b/src/api/cpp/var.cpp index 80cd6a63c5..66f2d76252 100644 --- a/src/api/cpp/var.cpp +++ b/src/api/cpp/var.cpp @@ -112,6 +112,7 @@ INSTANTIATE_VAR(unsigned long long); INSTANTIATE_VAR(short); INSTANTIATE_VAR(unsigned short); INSTANTIATE_VAR(char); +INSTANTIATE_VAR(signed char); INSTANTIATE_VAR(unsigned char); INSTANTIATE_VAR(af_half); INSTANTIATE_VAR(half_float::half); diff --git a/src/api/unified/CMakeLists.txt b/src/api/unified/CMakeLists.txt index ca6805c7a4..bd373acab8 100644 --- a/src/api/unified/CMakeLists.txt +++ b/src/api/unified/CMakeLists.txt @@ -82,8 +82,8 @@ target_include_directories(af target_include_directories(af SYSTEM PRIVATE $ - $<$: $> - $<$: ${CUDA_INCLUDE_DIRS}> + $<$:$> + $<$:${CUDA_INCLUDE_DIRS}> ) target_link_libraries(af diff --git a/src/api/unified/error.cpp b/src/api/unified/error.cpp index 9fd89c0166..24a2dbfac9 100644 --- a/src/api/unified/error.cpp +++ b/src/api/unified/error.cpp @@ -42,7 +42,7 @@ void af_get_last_error(char **str, dim_t *len) { typedef void (*af_func)(char **, dim_t *); void *vfn = LOAD_SYMBOL(); af_func func = nullptr; - memcpy(&func, vfn, sizeof(void *)); + memcpy(&func, &vfn, sizeof(void *)); func(str, len); } } diff --git a/src/backend/common/TemplateTypename.hpp b/src/backend/common/TemplateTypename.hpp index 47286af899..96dfb3c6fe 100644 --- a/src/backend/common/TemplateTypename.hpp +++ b/src/backend/common/TemplateTypename.hpp @@ -33,6 +33,7 @@ struct TemplateTypename { operator std::string() const noexcept { return #NAME; } \ } +SPECIALIZE(signed char, detail::schar); SPECIALIZE(unsigned char, detail::uchar); SPECIALIZE(unsigned int, detail::uint); SPECIALIZE(unsigned short, detail::ushort); diff --git a/src/backend/common/cast.cpp b/src/backend/common/cast.cpp index cc98f0504f..bcb2dfb519 100644 --- a/src/backend/common/cast.cpp +++ b/src/backend/common/cast.cpp @@ -14,6 +14,7 @@ using arrayfire::common::half; using detail::cdouble; using detail::cfloat; using detail::intl; +using detail::schar; using detail::uchar; using detail::uint; using detail::uintl; @@ -38,6 +39,7 @@ detail::Array castArray(const af_array &in) { case c64: return common::cast(getArray(in)); case s32: return common::cast(getArray(in)); case u32: return common::cast(getArray(in)); + case s8: return common::cast(getArray(in)); case u8: return common::cast(getArray(in)); case b8: return common::cast(getArray(in)); case s64: return common::cast(getArray(in)); @@ -56,6 +58,7 @@ template detail::Array castArray(const af_array &in); template detail::Array castArray(const af_array &in); template detail::Array castArray(const af_array &in); template detail::Array castArray(const af_array &in); +template detail::Array castArray(const af_array &in); template detail::Array castArray(const af_array &in); template detail::Array castArray(const af_array &in); template detail::Array castArray(const af_array &in); diff --git a/src/backend/common/cast.hpp b/src/backend/common/cast.hpp index 4186a03914..c60614a8a9 100644 --- a/src/backend/common/cast.hpp +++ b/src/backend/common/cast.hpp @@ -31,20 +31,21 @@ namespace common { /// outer -> inner -> outer /// /// inner cast -/// f32 f64 c32 c64 s32 u32 u8 b8 s64 u64 s16 u16 f16 -/// f32 x x x x x -/// f64 x x x x x -/// o c32 x x x x x -/// u c64 x x x x x -/// t s32 x x x x x x x x x -/// e u32 x x x x x x x x x -/// r u8 x x x x x x x x x x x x x -/// b8 x x x x x x x x x x x x x -/// c s64 x x x x x x x -/// a u64 x x x x x x x -/// s s16 x x x x x x x x x x x -/// t u16 x x x x x x x x x x x -/// f16 x x x x x +/// f32 f64 c32 c64 s32 u32 s8 u8 b8 s64 u64 s16 u16 f16 +/// f32 x x x x x +/// f64 x x x x x +/// o c32 x x x x x +/// u c64 x x x x x +/// t s32 x x x x x x x x x +/// e u32 x x x x x x x x x +/// r s8 x x x x x x x x x x x x x x +/// u8 x x x x x x x x x x x x x x +/// c b8 x x x x x x x x x x x x x x +/// a s64 x x x x x x x +/// s u64 x x x x x x x +/// t s16 x x x x x x x x x x x +/// u16 x x x x x x x x x x x +/// f16 x x x x x /// /// \param[in] outer The type of the second cast and the child of the /// previous cast diff --git a/src/backend/common/err_common.cpp b/src/backend/common/err_common.cpp index 60fc207a63..672afe6da0 100644 --- a/src/backend/common/err_common.cpp +++ b/src/backend/common/err_common.cpp @@ -92,8 +92,8 @@ int ArgumentError::getArgIndex() const noexcept { return argIndex; } SupportError::SupportError(const char *const func, const char *const file, const int line, const char *const back, - stacktrace st) - : AfError(func, file, line, "Unsupported Error", AF_ERR_NOT_SUPPORTED, + const char *const message, stacktrace st) + : AfError(func, file, line, message, AF_ERR_NOT_SUPPORTED, std::move(st)) , backend(back) {} diff --git a/src/backend/common/err_common.hpp b/src/backend/common/err_common.hpp index 3936cee77c..846f4b516f 100644 --- a/src/backend/common/err_common.hpp +++ b/src/backend/common/err_common.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -112,7 +113,7 @@ class SupportError : public AfError { public: SupportError(const char* const func, const char* const file, const int line, - const char* const back, + const char* const back, const char* const message, const boost::stacktrace::stacktrace st); SupportError(SupportError&& other) noexcept = default; diff --git a/src/backend/common/graphics_common.cpp b/src/backend/common/graphics_common.cpp index 217722eb36..01f94078d4 100644 --- a/src/backend/common/graphics_common.cpp +++ b/src/backend/common/graphics_common.cpp @@ -139,6 +139,7 @@ INSTANTIATE_GET_FG_TYPE(float, FG_FLOAT32); INSTANTIATE_GET_FG_TYPE(int, FG_INT32); INSTANTIATE_GET_FG_TYPE(unsigned, FG_UINT32); INSTANTIATE_GET_FG_TYPE(char, FG_INT8); +INSTANTIATE_GET_FG_TYPE(signed char, FG_INT8); INSTANTIATE_GET_FG_TYPE(unsigned char, FG_UINT8); INSTANTIATE_GET_FG_TYPE(unsigned short, FG_UINT16); INSTANTIATE_GET_FG_TYPE(short, FG_INT16); diff --git a/src/backend/common/half.hpp b/src/backend/common/half.hpp index b6585dc905..42d18be47b 100644 --- a/src/backend/common/half.hpp +++ b/src/backend/common/half.hpp @@ -87,6 +87,7 @@ using uint16_t = unsigned short; #define AF_CONSTEXPR constexpr #else #include +#include #include #include #include @@ -163,6 +164,10 @@ AF_CONSTEXPR __DH__ native_half_t int2half_impl(char value) noexcept { return __ull2half_rn(value); } template<> +AF_CONSTEXPR __DH__ native_half_t int2half_impl(signed char value) noexcept { + return __ull2half_rn(value); +} +template<> AF_CONSTEXPR __DH__ native_half_t int2half_impl(unsigned char value) noexcept { return __ull2half_rn(value); } @@ -245,9 +250,9 @@ AF_CONSTEXPR __DH__ native_half_t int2half_impl(T value) noexcept { /// \return binary representation of half-precision value template __DH__ native_half_t float2half_impl(float value) noexcept { - uint32_t bits = 0; // = *reinterpret_cast(&value); - // //violating strict aliasing! - std::memcpy(&bits, &value, sizeof(float)); + alignas(std::max(alignof(uint32_t), alignof(float))) float _value = value; + uint32_t bits = *reinterpret_cast(&_value); + constexpr uint16_t base_table[512] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -337,9 +342,10 @@ __DH__ native_half_t float2half_impl(float value) noexcept { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13}; - uint16_t hbits = - base_table[bits >> 23] + - static_cast((bits & 0x7FFFFF) >> shift_table[bits >> 23]); + alignas(std::max(alignof(uint16_t), alignof(native_half_t))) + uint16_t hbits = + base_table[bits >> 23] + + static_cast((bits & 0x7FFFFF) >> shift_table[bits >> 23]); AF_IF_CONSTEXPR(R == std::round_to_nearest) hbits += (((bits & 0x7FFFFF) >> (shift_table[bits >> 23] - 1)) | @@ -367,7 +373,8 @@ __DH__ native_half_t float2half_impl(float value) noexcept { (((bits >> 23) <= 358) & ((bits >> 23) != 256))) & (hbits < 0xFC00) & (hbits >> 15)) - ((hbits == 0x7C00) & ((bits >> 23) != 255)); - return hbits; + + return *reinterpret_cast(&hbits); } /// Convert IEEE double-precision to half-precision. @@ -379,11 +386,11 @@ __DH__ native_half_t float2half_impl(float value) noexcept { /// \return binary representation of half-precision value template __DH__ native_half_t float2half_impl(double value) { - uint64_t bits{0}; // = *reinterpret_cast(&value); //violating - // strict aliasing! - std::memcpy(&bits, &value, sizeof(double)); + alignas(std::max(alignof(uint64_t), alignof(double))) double _value = value; + uint64_t bits = *reinterpret_cast(&_value); uint32_t hi = bits >> 32, lo = bits & 0xFFFFFFFF; - uint16_t hbits = (hi >> 16) & 0x8000; + alignas(std::max(alignof(uint16_t), alignof(native_half_t))) + uint16_t hbits = (hi >> 16) & 0x8000; hi &= 0x7FFFFFFF; int exp = hi >> 20; if (exp == 2047) @@ -420,7 +427,8 @@ __DH__ native_half_t float2half_impl(double value) { ~(hbits >> 15) & (s | g); else AF_IF_CONSTEXPR(R == std::round_toward_neg_infinity) hbits += (hbits >> 15) & (g | s); - return hbits; + + return *reinterpret_cast(&hbits); } __DH__ inline float half2float_impl(native_half_t value) noexcept { @@ -790,14 +798,14 @@ __DH__ inline float half2float_impl(native_half_t value) noexcept { 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024}; - uint16_t value_bits = 0; - std::memcpy(&value_bits, &value, sizeof(uint16_t)); - uint32_t bits = + alignas(std::max(alignof(uint16_t), alignof(native_half_t))) + native_half_t _value = value; + uint16_t value_bits = *reinterpret_cast(&_value); + + alignas(std::max(alignof(uint32_t), alignof(float))) uint32_t bits = mantissa_table[offset_table[value_bits >> 10] + (value_bits & 0x3FF)] + exponent_table[value_bits >> 10]; - float out = 0.0f; - std::memcpy(&out, &bits, sizeof(float)); - return out; + return *reinterpret_cast(&bits); } #endif // __CUDACC_RTC__ @@ -857,6 +865,7 @@ AF_CONSTEXPR T half2int(native_half_t value) { #ifdef __CUDA_ARCH__ AF_IF_CONSTEXPR(std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value) { return __half2short_rn(value); } @@ -872,7 +881,9 @@ AF_CONSTEXPR T half2int(native_half_t value) { else AF_IF_CONSTEXPR(std::is_same::value) { return __half2int_rn(value); } - else { return __half2uint_rn(value); } + else { + return __half2uint_rn(value); + } #elif defined(AF_ONEAPI) return static_cast(value); #else @@ -1038,6 +1049,10 @@ class alignas(2) half { return half2int(data_); } + AF_CONSTEXPR __DH__ explicit operator signed char() const noexcept { + return half2int(data_); + } + AF_CONSTEXPR __DH__ explicit operator unsigned char() const noexcept { return half2int(data_); } diff --git a/src/backend/common/jit/BinaryNode.cpp b/src/backend/common/jit/BinaryNode.cpp index 84c5597e31..b017394876 100644 --- a/src/backend/common/jit/BinaryNode.cpp +++ b/src/backend/common/jit/BinaryNode.cpp @@ -69,6 +69,7 @@ INSTANTIATE(cdouble, double, af_cplx2_t); INSTANTIATE(unsigned short, unsigned short, op); \ INSTANTIATE(unsigned long long, unsigned long long, op); \ INSTANTIATE(long long, long long, op); \ + INSTANTIATE(signed char, signed char, op); \ INSTANTIATE(unsigned char, unsigned char, op); \ INSTANTIATE(char, char, op); \ INSTANTIATE(common::half, common::half, op); \ @@ -91,6 +92,7 @@ INSTANTIATE_ARITH(af_max_t); INSTANTIATE(unsigned short, unsigned short, op); \ INSTANTIATE(unsigned long long, unsigned long long, op); \ INSTANTIATE(long long, long long, op); \ + INSTANTIATE(signed char, signed char, op); \ INSTANTIATE(unsigned char, unsigned char, op); \ INSTANTIATE(char, char, op); \ INSTANTIATE(common::half, common::half, op); \ @@ -114,6 +116,7 @@ INSTANTIATE_FLOATOPS(af_atan2_t); INSTANTIATE(unsigned short, unsigned short, op); \ INSTANTIATE(unsigned long long, unsigned long long, op); \ INSTANTIATE(long long, long long, op); \ + INSTANTIATE(signed char, signed char, op); \ INSTANTIATE(unsigned char, unsigned char, op); \ INSTANTIATE(char, char, op); \ INSTANTIATE(int, int, op) @@ -136,6 +139,7 @@ INSTANTIATE_BITOP(af_bitxor_t); INSTANTIATE(char, unsigned short, op); \ INSTANTIATE(char, unsigned long long, op); \ INSTANTIATE(char, long long, op); \ + INSTANTIATE(char, signed char, op); \ INSTANTIATE(char, unsigned char, op); \ INSTANTIATE(char, char, op); \ INSTANTIATE(char, int, op) diff --git a/src/backend/common/jit/Node.cpp b/src/backend/common/jit/Node.cpp index f77d68e260..09c001a724 100644 --- a/src/backend/common/jit/Node.cpp +++ b/src/backend/common/jit/Node.cpp @@ -42,6 +42,7 @@ int Node::getNodesMap(Node_map_t &node_map, vector &full_nodes, } std::string getFuncName(const vector &output_nodes, + const vector &output_ids, const vector &full_nodes, const vector &full_ids, const bool is_linear, const bool loop0, const bool loop1, const bool loop2, @@ -59,6 +60,11 @@ std::string getFuncName(const vector &output_nodes, funcName += node->getNameStr(); } + for (const int id : output_ids) { + funcName += '-'; + funcName += std::to_string(id); + } + for (int i = 0; i < static_cast(full_nodes.size()); i++) { full_nodes[i]->genKerName(funcName, full_ids[i]); } diff --git a/src/backend/common/jit/Node.hpp b/src/backend/common/jit/Node.hpp index 8f2e0183b6..4641ff182c 100644 --- a/src/backend/common/jit/Node.hpp +++ b/src/backend/common/jit/Node.hpp @@ -98,6 +98,7 @@ static const char *getFullName(af::dtype type) { case u16: return detail::getFullName(); case s16: return detail::getFullName(); case b8: return detail::getFullName(); + case s8: return detail::getFullName(); case u8: return detail::getFullName(); case f16: return "half"; } @@ -117,6 +118,7 @@ static const char *getShortName(af::dtype type) { case u16: return detail::shortname(); case s16: return detail::shortname(); case b8: return detail::shortname(); + case s8: return detail::shortname(); case u8: return detail::shortname(); case f16: return "h"; } @@ -326,6 +328,7 @@ struct Node_ids { }; std::string getFuncName(const std::vector &output_nodes, + const std::vector &output_ids, const std::vector &full_nodes, const std::vector &full_ids, const bool is_linear, const bool loop0, diff --git a/src/backend/common/moddims.cpp b/src/backend/common/moddims.cpp index 6fbd99650e..cf9d8d6bb9 100644 --- a/src/backend/common/moddims.cpp +++ b/src/backend/common/moddims.cpp @@ -94,6 +94,7 @@ INSTANTIATE(double); INSTANTIATE(detail::cfloat); INSTANTIATE(detail::cdouble); INSTANTIATE(arrayfire::common::half); +INSTANTIATE(signed char); INSTANTIATE(unsigned char); INSTANTIATE(char); INSTANTIATE(unsigned short); diff --git a/src/backend/common/traits.hpp b/src/backend/common/traits.hpp index 3036d91dd0..51a4b53899 100644 --- a/src/backend/common/traits.hpp +++ b/src/backend/common/traits.hpp @@ -24,6 +24,7 @@ namespace { inline size_t dtypeSize(af::dtype type) { switch (type) { + case s8: case u8: case b8: return 1; case s16: @@ -59,7 +60,7 @@ constexpr bool isRealFloating(af::dtype type) { constexpr bool isInteger(af::dtype type) { return (type == s32 || type == u32 || type == s64 || type == u64 || - type == s16 || type == u16 || type == u8); + type == s16 || type == u16 || type == s8 || type == u8); } constexpr bool isBool(af::dtype type) { return (type == b8); } diff --git a/src/backend/common/util.cpp b/src/backend/common/util.cpp index 2d4a8e5ea0..87be74fa83 100644 --- a/src/backend/common/util.cpp +++ b/src/backend/common/util.cpp @@ -103,6 +103,7 @@ const char* getName(af_dtype type) { case u64: return "unsigned long long"; case s64: return "long long"; case u8: return "unsigned char"; + case s8: return "signed char"; case b8: return "bool"; default: return "unknown type"; } @@ -125,7 +126,13 @@ void saveKernel(const string& funcName, const string& jit_ker, // Path to a folder const string ffp = string(jitKernelsOutput) + AF_PATH_SEPARATOR + funcName + ext; + +#if defined(OS_WIN) + FILE* f = fopen(ffp.c_str(), "w"); +#else FILE* f = fopen(ffp.c_str(), "we"); +#endif + if (!f) { fprintf(stderr, "Cannot open file %s\n", ffp.c_str()); return; @@ -269,6 +276,7 @@ template string toString(int); template string toString(unsigned short); template string toString(short); template string toString(unsigned char); +template string toString(signed char); template string toString(char); template string toString(long); template string toString(long long); diff --git a/src/backend/cpu/Array.cpp b/src/backend/cpu/Array.cpp index dc0b5d5dad..276ea952b4 100644 --- a/src/backend/cpu/Array.cpp +++ b/src/backend/cpu/Array.cpp @@ -367,6 +367,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/cpu/CMakeLists.txt b/src/backend/cpu/CMakeLists.txt index b8025d53a2..8a83a55894 100644 --- a/src/backend/cpu/CMakeLists.txt +++ b/src/backend/cpu/CMakeLists.txt @@ -15,6 +15,10 @@ generate_product_version(af_cpu_ver_res_file add_library(afcpu "") add_library(ArrayFire::afcpu ALIAS afcpu) +# CPU back end needs to use MKL LP64 interface +set(MKL_INTERFACE_INTEGER_SIZE 4) +set(MKL_INTERFACE "lp64") + # CPU backend source files target_sources(afcpu PRIVATE @@ -313,6 +317,7 @@ target_link_libraries(afcpu ) if(BUILD_WITH_MKL) target_compile_definitions(afcpu PRIVATE USE_MKL) + target_compile_definitions(afcpu PRIVATE AF_MKL_INTERFACE_SIZE=${MKL_INTERFACE_INTEGER_SIZE}) if(MKL_BATCH) target_compile_definitions(afcpu PRIVATE AF_USE_MKL_BATCH) diff --git a/src/backend/cpu/assign.cpp b/src/backend/cpu/assign.cpp index cfeb5e168e..32af00e487 100644 --- a/src/backend/cpu/assign.cpp +++ b/src/backend/cpu/assign.cpp @@ -66,6 +66,7 @@ INSTANTIATE(uintl) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(int) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cpu/bilateral.cpp b/src/backend/cpu/bilateral.cpp index 027afb2c3b..19af80f3cb 100644 --- a/src/backend/cpu/bilateral.cpp +++ b/src/backend/cpu/bilateral.cpp @@ -38,6 +38,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/cpu/binary.hpp b/src/backend/cpu/binary.hpp index 3d130ba520..8d28501053 100644 --- a/src/backend/cpu/binary.hpp +++ b/src/backend/cpu/binary.hpp @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2021, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -89,8 +89,7 @@ LOGIC_CPLX_FN(double, af_or_t, ||) template static T __mod(T lhs, T rhs) { - T res = lhs % rhs; - return (res < 0) ? abs(rhs - res) : res; + return lhs % rhs; // Same as other backends } template diff --git a/src/backend/cpu/blas.cpp b/src/backend/cpu/blas.cpp index b7d158eb21..60cd9be655 100644 --- a/src/backend/cpu/blas.cpp +++ b/src/backend/cpu/blas.cpp @@ -219,9 +219,10 @@ toCblasTranspose(af_mat_prop opt) { return out; } -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta) { +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta) { const CBLAS_TRANSPOSE lOpts = toCblasTranspose(optLhs); const CBLAS_TRANSPOSE rOpts = toCblasTranspose(optRhs); @@ -236,17 +237,17 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, const int K = lDims[aColDim]; const dim4 oDims = out.dims(); - using BT = typename blas_base::type; - using CBT = const typename blas_base::type; + using BT = typename blas_base::type; + using CBT = const typename blas_base::type; - auto alpha_ = scale_type(alpha); - auto beta_ = scale_type(beta); + auto alpha_ = scale_type(alpha); + auto beta_ = scale_type(beta); #ifdef USE_MKL - auto alpha_batched = scale_type(alpha); - auto beta_batched = scale_type(beta); + auto alpha_batched = scale_type(alpha); + auto beta_batched = scale_type(beta); #endif - auto func = [=](Param output, CParam left, CParam right) { + auto func = [=](Param output, CParam left, CParam right) { dim4 lStrides = left.strides(); dim4 rStrides = right.strides(); dim4 oStrides = output.strides(); @@ -255,14 +256,14 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, if (right.dims()[bColDim] == 1) { dim_t incr = (optRhs == AF_MAT_NONE) ? rStrides[0] : rStrides[1]; - gemv_func()( + gemv_func()( CblasColMajor, lOpts, lDims[0], lDims[1], alpha_.getScale(), reinterpret_cast(left.get()), lStrides[1], reinterpret_cast(right.get()), incr, beta_.getScale(), reinterpret_cast(output.get()), oStrides[0]); } else { - gemm_func()( + gemm_func()( CblasColMajor, lOpts, rOpts, M, N, K, alpha_.getScale(), reinterpret_cast(left.get()), lStrides[1], reinterpret_cast(right.get()), rStrides[1], @@ -303,24 +304,24 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, const MKL_INT ldb = rStrides[1]; const MKL_INT ldc = oStrides[1]; - gemm_batch_func()(CblasColMajor, &lOpts, &rOpts, &M, &N, &K, - alpha_batched.getScale(), lptrs.data(), &lda, - rptrs.data(), &ldb, beta_batched.getScale(), - optrs.data(), &ldc, 1, &batchSize); + gemm_batch_func()(CblasColMajor, &lOpts, &rOpts, &M, &N, &K, + alpha_batched.getScale(), lptrs.data(), &lda, + rptrs.data(), &ldb, beta_batched.getScale(), + optrs.data(), &ldc, 1, &batchSize); #else for (int n = 0; n < batchSize; n++) { if (rDims[bColDim] == 1) { dim_t incr = (optRhs == AF_MAT_NONE) ? rStrides[0] : rStrides[1]; - gemv_func()(CblasColMajor, lOpts, lDims[0], lDims[1], - alpha_.getScale(), lptrs[n], lStrides[1], - rptrs[n], incr, beta_.getScale(), optrs[n], - oStrides[0]); + gemv_func()(CblasColMajor, lOpts, lDims[0], lDims[1], + alpha_.getScale(), lptrs[n], lStrides[1], + rptrs[n], incr, beta_.getScale(), optrs[n], + oStrides[0]); } else { - gemm_func()(CblasColMajor, lOpts, rOpts, M, N, K, - alpha_.getScale(), lptrs[n], lStrides[1], - rptrs[n], rStrides[1], beta_.getScale(), - optrs[n], oStrides[1]); + gemm_func()(CblasColMajor, lOpts, rOpts, M, N, K, + alpha_.getScale(), lptrs[n], lStrides[1], + rptrs[n], rStrides[1], beta_.getScale(), + optrs[n], oStrides[1]); } } #endif @@ -341,6 +342,14 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, copyArray(out, outArr); } +template<> +void gemm(Array &out, af_mat_prop optLhs, + af_mat_prop optRhs, const float *alpha, + const Array &lhs, const Array &rhs, + const float *beta) { + TYPE_ERROR(3, af_dtype::s8); +} + template Array dot(const Array &lhs, const Array &rhs, af_mat_prop optLhs, af_mat_prop optRhs) { diff --git a/src/backend/cpu/blas.hpp b/src/backend/cpu/blas.hpp index 1043a567e9..c16916dafb 100644 --- a/src/backend/cpu/blas.hpp +++ b/src/backend/cpu/blas.hpp @@ -13,9 +13,10 @@ namespace arrayfire { namespace cpu { -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta); +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta); template Array matmul(const Array &lhs, const Array &rhs, af_mat_prop optLhs, diff --git a/src/backend/cpu/cast.hpp b/src/backend/cpu/cast.hpp index dd756eb2b3..d51b7838b8 100644 --- a/src/backend/cpu/cast.hpp +++ b/src/backend/cpu/cast.hpp @@ -150,6 +150,7 @@ struct UnOp, std::complex, af_cast_t> { CAST_B8(float) CAST_B8(double) CAST_B8(int) +CAST_B8(schar) CAST_B8(uchar) CAST_B8(char) diff --git a/src/backend/cpu/convolve.cpp b/src/backend/cpu/convolve.cpp index 20138fd9e5..2fd0e3bce3 100644 --- a/src/backend/cpu/convolve.cpp +++ b/src/backend/cpu/convolve.cpp @@ -111,6 +111,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/cpu/copy.cpp b/src/backend/cpu/copy.cpp index b1d0985680..ea98c0f613 100644 --- a/src/backend/cpu/copy.cpp +++ b/src/backend/cpu/copy.cpp @@ -72,6 +72,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) @@ -101,6 +102,8 @@ INSTANTIATE(half) Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ + template void copyArray(Array & dst, \ + Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ template void copyArray(Array & dst, \ @@ -114,6 +117,7 @@ INSTANTIATE_COPY_ARRAY(int) INSTANTIATE_COPY_ARRAY(uint) INSTANTIATE_COPY_ARRAY(intl) INSTANTIATE_COPY_ARRAY(uintl) +INSTANTIATE_COPY_ARRAY(schar) INSTANTIATE_COPY_ARRAY(uchar) INSTANTIATE_COPY_ARRAY(char) INSTANTIATE_COPY_ARRAY(ushort) @@ -144,6 +148,7 @@ INSTANTIATE_GETSCALAR(cfloat) INSTANTIATE_GETSCALAR(cdouble) INSTANTIATE_GETSCALAR(int) INSTANTIATE_GETSCALAR(uint) +INSTANTIATE_GETSCALAR(schar) INSTANTIATE_GETSCALAR(uchar) INSTANTIATE_GETSCALAR(char) INSTANTIATE_GETSCALAR(intl) diff --git a/src/backend/cpu/diagonal.cpp b/src/backend/cpu/diagonal.cpp index eddd8c0a49..1767096ed0 100644 --- a/src/backend/cpu/diagonal.cpp +++ b/src/backend/cpu/diagonal.cpp @@ -62,6 +62,7 @@ INSTANTIATE_DIAGONAL(uint) INSTANTIATE_DIAGONAL(intl) INSTANTIATE_DIAGONAL(uintl) INSTANTIATE_DIAGONAL(char) +INSTANTIATE_DIAGONAL(schar) INSTANTIATE_DIAGONAL(uchar) INSTANTIATE_DIAGONAL(short) INSTANTIATE_DIAGONAL(ushort) diff --git a/src/backend/cpu/diff.cpp b/src/backend/cpu/diff.cpp index 8e9c67cae1..f9ced50f52 100644 --- a/src/backend/cpu/diff.cpp +++ b/src/backend/cpu/diff.cpp @@ -56,6 +56,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cpu/err_cpu.hpp b/src/backend/cpu/err_cpu.hpp index d618cecb1e..58c7b59aab 100644 --- a/src/backend/cpu/err_cpu.hpp +++ b/src/backend/cpu/err_cpu.hpp @@ -11,6 +11,6 @@ #define CPU_NOT_SUPPORTED(message) \ do { \ - throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, message, \ - boost::stacktrace::stacktrace()); \ + throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, "CPU", \ + message, boost::stacktrace::stacktrace()); \ } while (0) diff --git a/src/backend/cpu/exampleFunction.cpp b/src/backend/cpu/exampleFunction.cpp index ee7b847524..3f677bc24b 100644 --- a/src/backend/cpu/exampleFunction.cpp +++ b/src/backend/cpu/exampleFunction.cpp @@ -56,6 +56,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(cfloat) diff --git a/src/backend/cpu/fast.cpp b/src/backend/cpu/fast.cpp index b8ac38eeaf..ac93345797 100644 --- a/src/backend/cpu/fast.cpp +++ b/src/backend/cpu/fast.cpp @@ -120,6 +120,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/fftconvolve.cpp b/src/backend/cpu/fftconvolve.cpp index 728238c1ef..ff2e5b68c4 100644 --- a/src/backend/cpu/fftconvolve.cpp +++ b/src/backend/cpu/fftconvolve.cpp @@ -207,6 +207,7 @@ INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(uint) INSTANTIATE(int) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(uintl) diff --git a/src/backend/cpu/hist_graphics.cpp b/src/backend/cpu/hist_graphics.cpp index 7635004c91..a77e9fe77e 100644 --- a/src/backend/cpu/hist_graphics.cpp +++ b/src/backend/cpu/hist_graphics.cpp @@ -43,6 +43,7 @@ void copy_histogram(const Array &data, fg_histogram hist) { INSTANTIATE(float) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/histogram.cpp b/src/backend/cpu/histogram.cpp index e2f8e15433..9d9c6ba8fa 100644 --- a/src/backend/cpu/histogram.cpp +++ b/src/backend/cpu/histogram.cpp @@ -48,6 +48,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/identity.cpp b/src/backend/cpu/identity.cpp index 05695d7629..ce7f35bdb0 100644 --- a/src/backend/cpu/identity.cpp +++ b/src/backend/cpu/identity.cpp @@ -42,6 +42,7 @@ INSTANTIATE_IDENTITY(uint) INSTANTIATE_IDENTITY(intl) INSTANTIATE_IDENTITY(uintl) INSTANTIATE_IDENTITY(char) +INSTANTIATE_IDENTITY(schar) INSTANTIATE_IDENTITY(uchar) INSTANTIATE_IDENTITY(short) INSTANTIATE_IDENTITY(ushort) diff --git a/src/backend/cpu/image.cpp b/src/backend/cpu/image.cpp index f11a2db4ca..2e24dec9be 100644 --- a/src/backend/cpu/image.cpp +++ b/src/backend/cpu/image.cpp @@ -49,6 +49,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cpu/index.cpp b/src/backend/cpu/index.cpp index 315406b46d..84cff747bd 100644 --- a/src/backend/cpu/index.cpp +++ b/src/backend/cpu/index.cpp @@ -35,7 +35,16 @@ Array index(const Array& in, const af_index_t idxrs[]) { // create seq vector to retrieve output // dimensions, offsets & offsets for (unsigned x = 0; x < isSeq.size(); ++x) { - if (idxrs[x].isSeq) { seqs[x] = idxrs[x].idx.seq; } + if (idxrs[x].isSeq) { + af_seq seq = idxrs[x].idx.seq; + // Handle af_span as a sequence that covers the complete axis + if (seq.begin == af_span.begin && seq.end == af_span.end && + seq.step == af_span.step) { + seqs[x] = af_seq{0, (double)(in.dims()[x] - 1), 1}; + } else { + seqs[x] = seq; + } + } isSeq[x] = idxrs[x].isSeq; } @@ -72,6 +81,7 @@ INSTANTIATE(uintl) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(int) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cpu/iota.cpp b/src/backend/cpu/iota.cpp index 1e7155bcd9..fe50919783 100644 --- a/src/backend/cpu/iota.cpp +++ b/src/backend/cpu/iota.cpp @@ -41,6 +41,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/ireduce.cpp b/src/backend/cpu/ireduce.cpp index 435d6ea44d..a20df27c1a 100644 --- a/src/backend/cpu/ireduce.cpp +++ b/src/backend/cpu/ireduce.cpp @@ -105,6 +105,7 @@ INSTANTIATE(af_min_t, uint) INSTANTIATE(af_min_t, intl) INSTANTIATE(af_min_t, uintl) INSTANTIATE(af_min_t, char) +INSTANTIATE(af_min_t, schar) INSTANTIATE(af_min_t, uchar) INSTANTIATE(af_min_t, short) INSTANTIATE(af_min_t, ushort) @@ -120,6 +121,7 @@ INSTANTIATE(af_max_t, uint) INSTANTIATE(af_max_t, intl) INSTANTIATE(af_max_t, uintl) INSTANTIATE(af_max_t, char) +INSTANTIATE(af_max_t, schar) INSTANTIATE(af_max_t, uchar) INSTANTIATE(af_max_t, short) INSTANTIATE(af_max_t, ushort) diff --git a/src/backend/cpu/join.cpp b/src/backend/cpu/join.cpp index e9fed65df1..602f2db7f9 100644 --- a/src/backend/cpu/join.cpp +++ b/src/backend/cpu/join.cpp @@ -70,6 +70,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) @@ -90,6 +91,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cpu/kernel/index.hpp b/src/backend/cpu/kernel/index.hpp index 2a6a6d9bc4..962b0713dc 100644 --- a/src/backend/cpu/kernel/index.hpp +++ b/src/backend/cpu/kernel/index.hpp @@ -34,25 +34,27 @@ void index(Param out, CParam in, const af::dim4 dDims, for (dim_t l = 0; l < oDims[3]; ++l) { dim_t lOff = l * oStrides[3]; - dim_t inIdx3 = trimIndex(isSeq[3] ? l + iOffs[3] : ptr3[l], iDims[3]); + dim_t inIdx3 = trimIndex( + isSeq[3] ? l * seqs[3].step + iOffs[3] : ptr3[l], iDims[3]); dim_t inOff3 = inIdx3 * iStrds[3]; for (dim_t k = 0; k < oDims[2]; ++k) { - dim_t kOff = k * oStrides[2]; - dim_t inIdx2 = - trimIndex(isSeq[2] ? k + iOffs[2] : ptr2[k], iDims[2]); + dim_t kOff = k * oStrides[2]; + dim_t inIdx2 = trimIndex( + isSeq[2] ? k * seqs[2].step + iOffs[2] : ptr2[k], iDims[2]); dim_t inOff2 = inIdx2 * iStrds[2]; for (dim_t j = 0; j < oDims[1]; ++j) { - dim_t jOff = j * oStrides[1]; - dim_t inIdx1 = - trimIndex(isSeq[1] ? j + iOffs[1] : ptr1[j], iDims[1]); + dim_t jOff = j * oStrides[1]; + dim_t inIdx1 = trimIndex( + isSeq[1] ? j * seqs[1].step + iOffs[1] : ptr1[j], iDims[1]); dim_t inOff1 = inIdx1 * iStrds[1]; for (dim_t i = 0; i < oDims[0]; ++i) { - dim_t iOff = i * oStrides[0]; - dim_t inIdx0 = - trimIndex(isSeq[0] ? i + iOffs[0] : ptr0[i], iDims[0]); + dim_t iOff = i * oStrides[0]; + dim_t inIdx0 = trimIndex( + isSeq[0] ? i * seqs[0].step + iOffs[0] : ptr0[i], + iDims[0]); dim_t inOff0 = inIdx0 * iStrds[0]; dst[lOff + kOff + jOff + iOff] = diff --git a/src/backend/cpu/kernel/random_engine.hpp b/src/backend/cpu/kernel/random_engine.hpp index 09c2bff20c..0ab49f8a80 100644 --- a/src/backend/cpu/kernel/random_engine.hpp +++ b/src/backend/cpu/kernel/random_engine.hpp @@ -115,6 +115,11 @@ uchar transform(uint *val, uint index) { return v; } +template<> +schar transform(uint *val, uint index) { + return transform(val, index); +} + template<> ushort transform(uint *val, uint index) { ushort v = val[index >> 1U] >> (16U * (index & 1U)) & 0x0000ffff; diff --git a/src/backend/cpu/kernel/sort_by_key/sort_by_key_impl.cpp b/src/backend/cpu/kernel/sort_by_key/sort_by_key_impl.cpp index 6ac6875f3e..5873e93117 100644 --- a/src/backend/cpu/kernel/sort_by_key/sort_by_key_impl.cpp +++ b/src/backend/cpu/kernel/sort_by_key/sort_by_key_impl.cpp @@ -9,7 +9,7 @@ #include -// SBK_TYPES:float double int uint intl uintl short ushort char uchar +// SBK_TYPES:float double int uint intl uintl short ushort char schar uchar namespace arrayfire { namespace cpu { diff --git a/src/backend/cpu/kernel/sort_by_key_impl.hpp b/src/backend/cpu/kernel/sort_by_key_impl.hpp index acd7524a9b..e77e868d78 100644 --- a/src/backend/cpu/kernel/sort_by_key_impl.hpp +++ b/src/backend/cpu/kernel/sort_by_key_impl.hpp @@ -169,6 +169,7 @@ void sort0ByKey(Param okey, Param oval, bool isAscending) { INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, intl) \ INSTANTIATE(Tk, uintl) diff --git a/src/backend/cpu/lookup.cpp b/src/backend/cpu/lookup.cpp index 8a5c40d55c..b8c56e297c 100644 --- a/src/backend/cpu/lookup.cpp +++ b/src/backend/cpu/lookup.cpp @@ -51,6 +51,8 @@ Array lookup(const Array &input, const Array &indices, const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ + template Array lookup(const Array &, const Array &, \ + const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ template Array lookup(const Array &, const Array &, \ @@ -64,6 +66,7 @@ INSTANTIATE(int); INSTANTIATE(unsigned); INSTANTIATE(intl); INSTANTIATE(uintl); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(char); INSTANTIATE(ushort); diff --git a/src/backend/cpu/match_template.cpp b/src/backend/cpu/match_template.cpp index d3cfb26b4a..6b4d0f1b91 100644 --- a/src/backend/cpu/match_template.cpp +++ b/src/backend/cpu/match_template.cpp @@ -51,6 +51,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/cpu/math.hpp b/src/backend/cpu/math.hpp index 16a4e2abbf..06c1027edf 100644 --- a/src/backend/cpu/math.hpp +++ b/src/backend/cpu/math.hpp @@ -15,6 +15,7 @@ #include #include +#include #include #include diff --git a/src/backend/cpu/mean.cpp b/src/backend/cpu/mean.cpp index 6a256113f7..2323442110 100644 --- a/src/backend/cpu/mean.cpp +++ b/src/backend/cpu/mean.cpp @@ -141,6 +141,7 @@ INSTANTIATE(intl, double, double); INSTANTIATE(uintl, double, double); INSTANTIATE(short, float, float); INSTANTIATE(ushort, float, float); +INSTANTIATE(schar, float, float); INSTANTIATE(uchar, float, float); INSTANTIATE(char, float, float); INSTANTIATE(cfloat, float, cfloat); diff --git a/src/backend/cpu/meanshift.cpp b/src/backend/cpu/meanshift.cpp index d52b56a99e..878aa4cacb 100644 --- a/src/backend/cpu/meanshift.cpp +++ b/src/backend/cpu/meanshift.cpp @@ -50,6 +50,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/medfilt.cpp b/src/backend/cpu/medfilt.cpp index 53497be8c9..4c952fc762 100644 --- a/src/backend/cpu/medfilt.cpp +++ b/src/backend/cpu/medfilt.cpp @@ -63,6 +63,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(ushort) INSTANTIATE(short) diff --git a/src/backend/cpu/memory.cpp b/src/backend/cpu/memory.cpp index 9bbb41d458..0a32186f2e 100644 --- a/src/backend/cpu/memory.cpp +++ b/src/backend/cpu/memory.cpp @@ -106,6 +106,7 @@ INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/cpu/moments.cpp b/src/backend/cpu/moments.cpp index bd5c520eac..09db606bd4 100644 --- a/src/backend/cpu/moments.cpp +++ b/src/backend/cpu/moments.cpp @@ -49,6 +49,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cpu/morph.cpp b/src/backend/cpu/morph.cpp index add13de416..e526e7c066 100644 --- a/src/backend/cpu/morph.cpp +++ b/src/backend/cpu/morph.cpp @@ -67,6 +67,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(ushort) INSTANTIATE(short) diff --git a/src/backend/cpu/nearest_neighbour.cpp b/src/backend/cpu/nearest_neighbour.cpp index 2979090dd9..0581e97ab6 100644 --- a/src/backend/cpu/nearest_neighbour.cpp +++ b/src/backend/cpu/nearest_neighbour.cpp @@ -67,6 +67,7 @@ INSTANTIATE(int, int) INSTANTIATE(uint, uint) INSTANTIATE(intl, intl) INSTANTIATE(uintl, uintl) +INSTANTIATE(schar, int) INSTANTIATE(uchar, uint) INSTANTIATE(ushort, uint) INSTANTIATE(short, int) diff --git a/src/backend/cpu/plot.cpp b/src/backend/cpu/plot.cpp index abf1a7b397..1ca6ae7882 100644 --- a/src/backend/cpu/plot.cpp +++ b/src/backend/cpu/plot.cpp @@ -46,6 +46,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/queue.hpp b/src/backend/cpu/queue.hpp index 594396a78e..cdcfb8092f 100644 --- a/src/backend/cpu/queue.hpp +++ b/src/backend/cpu/queue.hpp @@ -38,6 +38,42 @@ class queue_impl { } }; +class event_impl { + public: + event_impl() noexcept = default; + ~event_impl() noexcept = default; + explicit event_impl(const event_impl &other) = default; + event_impl(event_impl &&other) noexcept = default; + event_impl &operator=(event_impl &&other) noexcept = default; + event_impl &operator=(event_impl &other) noexcept = default; + + explicit event_impl(const int val) {} + + event_impl &operator=(int val) noexcept { return *this; } + + int create() { + AF_ERROR("Incorrectly configured", AF_ERR_INTERNAL); + return 0; + } + + int mark(queue_impl &queue) { + AF_ERROR("Incorrectly configured", AF_ERR_INTERNAL); + return 0; + } + + int wait(queue_impl &queue) const { + AF_ERROR("Incorrectly configured", AF_ERR_INTERNAL); + return 0; + } + + int sync() const noexcept { + AF_ERROR("Incorrectly configured", AF_ERR_INTERNAL); + return 0; + } + + operator bool() const noexcept { return false; } +}; + #else #include diff --git a/src/backend/cpu/random_engine.cpp b/src/backend/cpu/random_engine.cpp index 3e1c8745c8..d42a7bdae1 100644 --- a/src/backend/cpu/random_engine.cpp +++ b/src/backend/cpu/random_engine.cpp @@ -149,6 +149,7 @@ INSTANTIATE_UNIFORM(uint) INSTANTIATE_UNIFORM(intl) INSTANTIATE_UNIFORM(uintl) INSTANTIATE_UNIFORM(char) +INSTANTIATE_UNIFORM(schar) INSTANTIATE_UNIFORM(uchar) INSTANTIATE_UNIFORM(short) INSTANTIATE_UNIFORM(ushort) diff --git a/src/backend/cpu/range.cpp b/src/backend/cpu/range.cpp index 3b782837e0..ad100da4d4 100644 --- a/src/backend/cpu/range.cpp +++ b/src/backend/cpu/range.cpp @@ -54,6 +54,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(ushort) INSTANTIATE(short) diff --git a/src/backend/cpu/reduce.cpp b/src/backend/cpu/reduce.cpp index 6ce141b316..5b13d6f96f 100644 --- a/src/backend/cpu/reduce.cpp +++ b/src/backend/cpu/reduce.cpp @@ -145,6 +145,7 @@ INSTANTIATE(af_min_t, uint, uint) INSTANTIATE(af_min_t, intl, intl) INSTANTIATE(af_min_t, uintl, uintl) INSTANTIATE(af_min_t, char, char) +INSTANTIATE(af_min_t, schar, schar) INSTANTIATE(af_min_t, uchar, uchar) INSTANTIATE(af_min_t, short, short) INSTANTIATE(af_min_t, ushort, ushort) @@ -160,6 +161,7 @@ INSTANTIATE(af_max_t, uint, uint) INSTANTIATE(af_max_t, intl, intl) INSTANTIATE(af_max_t, uintl, uintl) INSTANTIATE(af_max_t, char, char) +INSTANTIATE(af_max_t, schar, schar) INSTANTIATE(af_max_t, uchar, uchar) INSTANTIATE(af_max_t, short, short) INSTANTIATE(af_max_t, ushort, ushort) @@ -180,6 +182,8 @@ INSTANTIATE(af_add_t, uintl, uintl) INSTANTIATE(af_add_t, uintl, double) INSTANTIATE(af_add_t, char, int) INSTANTIATE(af_add_t, char, float) +INSTANTIATE(af_add_t, schar, int) +INSTANTIATE(af_add_t, schar, float) INSTANTIATE(af_add_t, uchar, uint) INSTANTIATE(af_add_t, uchar, float) INSTANTIATE(af_add_t, short, int) @@ -199,6 +203,7 @@ INSTANTIATE(af_mul_t, uint, uint) INSTANTIATE(af_mul_t, intl, intl) INSTANTIATE(af_mul_t, uintl, uintl) INSTANTIATE(af_mul_t, char, int) +INSTANTIATE(af_mul_t, schar, int) INSTANTIATE(af_mul_t, uchar, uint) INSTANTIATE(af_mul_t, short, int) INSTANTIATE(af_mul_t, ushort, uint) @@ -214,6 +219,7 @@ INSTANTIATE(af_notzero_t, uint, uint) INSTANTIATE(af_notzero_t, intl, uint) INSTANTIATE(af_notzero_t, uintl, uint) INSTANTIATE(af_notzero_t, char, uint) +INSTANTIATE(af_notzero_t, schar, uint) INSTANTIATE(af_notzero_t, uchar, uint) INSTANTIATE(af_notzero_t, short, uint) INSTANTIATE(af_notzero_t, ushort, uint) @@ -229,6 +235,7 @@ INSTANTIATE(af_or_t, uint, char) INSTANTIATE(af_or_t, intl, char) INSTANTIATE(af_or_t, uintl, char) INSTANTIATE(af_or_t, char, char) +INSTANTIATE(af_or_t, schar, char) INSTANTIATE(af_or_t, uchar, char) INSTANTIATE(af_or_t, short, char) INSTANTIATE(af_or_t, ushort, char) @@ -244,6 +251,7 @@ INSTANTIATE(af_and_t, uint, char) INSTANTIATE(af_and_t, intl, char) INSTANTIATE(af_and_t, uintl, char) INSTANTIATE(af_and_t, char, char) +INSTANTIATE(af_and_t, schar, char) INSTANTIATE(af_and_t, uchar, char) INSTANTIATE(af_and_t, short, char) INSTANTIATE(af_and_t, ushort, char) diff --git a/src/backend/cpu/reorder.cpp b/src/backend/cpu/reorder.cpp index 67233542bd..dd0a43ccac 100644 --- a/src/backend/cpu/reorder.cpp +++ b/src/backend/cpu/reorder.cpp @@ -39,6 +39,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/cpu/reshape.cpp b/src/backend/cpu/reshape.cpp index b2d46eb066..31a0053684 100644 --- a/src/backend/cpu/reshape.cpp +++ b/src/backend/cpu/reshape.cpp @@ -40,6 +40,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) @@ -68,6 +69,8 @@ INSTANTIATE(ushort) const dim4 &, short, double); \ template Array reshape( \ const Array &, const dim4 &, ushort, double); \ + template Array reshape(const Array &, \ + const dim4 &, schar, double); \ template Array reshape(const Array &, \ const dim4 &, uchar, double); \ template Array reshape(const Array &, \ @@ -79,6 +82,7 @@ INSTANTIATE_PAD_ARRAY(int) INSTANTIATE_PAD_ARRAY(uint) INSTANTIATE_PAD_ARRAY(intl) INSTANTIATE_PAD_ARRAY(uintl) +INSTANTIATE_PAD_ARRAY(schar) INSTANTIATE_PAD_ARRAY(uchar) INSTANTIATE_PAD_ARRAY(char) INSTANTIATE_PAD_ARRAY(ushort) diff --git a/src/backend/cpu/resize.cpp b/src/backend/cpu/resize.cpp index 4f899d89d8..ffc473fd4e 100644 --- a/src/backend/cpu/resize.cpp +++ b/src/backend/cpu/resize.cpp @@ -53,6 +53,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cpu/rotate.cpp b/src/backend/cpu/rotate.cpp index 0e9806a2af..bed34b7bf3 100644 --- a/src/backend/cpu/rotate.cpp +++ b/src/backend/cpu/rotate.cpp @@ -53,6 +53,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cpu/scan.cpp b/src/backend/cpu/scan.cpp index af5c4d9efe..7f6843f99a 100644 --- a/src/backend/cpu/scan.cpp +++ b/src/backend/cpu/scan.cpp @@ -84,6 +84,7 @@ Array scan(const Array& in, const int dim, bool inclusive_scan) { INSTANTIATE_SCAN(ROp, uintl, uintl) \ INSTANTIATE_SCAN(ROp, char, int) \ INSTANTIATE_SCAN(ROp, char, uint) \ + INSTANTIATE_SCAN(ROp, schar, int) \ INSTANTIATE_SCAN(ROp, uchar, uint) \ INSTANTIATE_SCAN(ROp, short, int) \ INSTANTIATE_SCAN(ROp, ushort, uint) diff --git a/src/backend/cpu/select.cpp b/src/backend/cpu/select.cpp index 96849cecd1..8258cae47a 100644 --- a/src/backend/cpu/select.cpp +++ b/src/backend/cpu/select.cpp @@ -51,6 +51,7 @@ INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/set.cpp b/src/backend/cpu/set.cpp index 838ad7675e..6db13c8760 100644 --- a/src/backend/cpu/set.cpp +++ b/src/backend/cpu/set.cpp @@ -120,6 +120,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/shift.cpp b/src/backend/cpu/shift.cpp index f8942f641f..d812cbde89 100644 --- a/src/backend/cpu/shift.cpp +++ b/src/backend/cpu/shift.cpp @@ -37,6 +37,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cpu/sobel.cpp b/src/backend/cpu/sobel.cpp index 68bddee784..5708348295 100644 --- a/src/backend/cpu/sobel.cpp +++ b/src/backend/cpu/sobel.cpp @@ -44,6 +44,7 @@ INSTANTIATE(double, double) INSTANTIATE(int, int) INSTANTIATE(uint, int) INSTANTIATE(char, int) +INSTANTIATE(schar, int) INSTANTIATE(uchar, int) INSTANTIATE(short, int) INSTANTIATE(ushort, int) diff --git a/src/backend/cpu/sort.cpp b/src/backend/cpu/sort.cpp index e5067a8dba..41c6b75147 100644 --- a/src/backend/cpu/sort.cpp +++ b/src/backend/cpu/sort.cpp @@ -98,6 +98,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/sort_by_key.cpp b/src/backend/cpu/sort_by_key.cpp index 169b598558..efe8eba2f1 100644 --- a/src/backend/cpu/sort_by_key.cpp +++ b/src/backend/cpu/sort_by_key.cpp @@ -71,6 +71,7 @@ void sort_by_key(Array &okey, Array &oval, const Array &ikey, INSTANTIATE(Tk, int) \ INSTANTIATE(Tk, uint) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ @@ -82,6 +83,7 @@ INSTANTIATE1(double) INSTANTIATE1(int) INSTANTIATE1(uint) INSTANTIATE1(char) +INSTANTIATE1(schar) INSTANTIATE1(uchar) INSTANTIATE1(short) INSTANTIATE1(ushort) diff --git a/src/backend/cpu/sort_index.cpp b/src/backend/cpu/sort_index.cpp index cec724c85d..8b1f4a1319 100644 --- a/src/backend/cpu/sort_index.cpp +++ b/src/backend/cpu/sort_index.cpp @@ -75,6 +75,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/surface.cpp b/src/backend/cpu/surface.cpp index e861dbeac7..d86bd6f469 100644 --- a/src/backend/cpu/surface.cpp +++ b/src/backend/cpu/surface.cpp @@ -47,6 +47,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/susan.cpp b/src/backend/cpu/susan.cpp index 6ab2bfba78..c5321deb16 100644 --- a/src/backend/cpu/susan.cpp +++ b/src/backend/cpu/susan.cpp @@ -73,6 +73,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/tile.cpp b/src/backend/cpu/tile.cpp index d2a8d3ab7c..884bfed40d 100644 --- a/src/backend/cpu/tile.cpp +++ b/src/backend/cpu/tile.cpp @@ -47,6 +47,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cpu/transform.cpp b/src/backend/cpu/transform.cpp index 9a57424250..bbcf689f25 100644 --- a/src/backend/cpu/transform.cpp +++ b/src/backend/cpu/transform.cpp @@ -58,6 +58,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cpu/transpose.cpp b/src/backend/cpu/transpose.cpp index 7cd713afd6..a9f6f9d3d5 100644 --- a/src/backend/cpu/transpose.cpp +++ b/src/backend/cpu/transpose.cpp @@ -51,6 +51,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/cpu/triangle.cpp b/src/backend/cpu/triangle.cpp index 8e3b0569b2..6c276ca4bd 100644 --- a/src/backend/cpu/triangle.cpp +++ b/src/backend/cpu/triangle.cpp @@ -58,6 +58,7 @@ INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/types.hpp b/src/backend/cpu/types.hpp index 27a678af82..f1f58e7006 100644 --- a/src/backend/cpu/types.hpp +++ b/src/backend/cpu/types.hpp @@ -31,6 +31,7 @@ using cdouble = std::complex; using cfloat = std::complex; using intl = long long; using uint = unsigned int; +using schar = signed char; using uchar = unsigned char; using uintl = unsigned long long; using ushort = unsigned short; diff --git a/src/backend/cpu/unwrap.cpp b/src/backend/cpu/unwrap.cpp index 49086fad49..dca2433ff8 100644 --- a/src/backend/cpu/unwrap.cpp +++ b/src/backend/cpu/unwrap.cpp @@ -55,6 +55,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cpu/vector_field.cpp b/src/backend/cpu/vector_field.cpp index 2a7549de81..efe207be09 100644 --- a/src/backend/cpu/vector_field.cpp +++ b/src/backend/cpu/vector_field.cpp @@ -58,6 +58,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/where.cpp b/src/backend/cpu/where.cpp index 3eb65015f0..30f70efcb0 100644 --- a/src/backend/cpu/where.cpp +++ b/src/backend/cpu/where.cpp @@ -73,6 +73,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cpu/wrap.cpp b/src/backend/cpu/wrap.cpp index d502bc85ad..0c0d397e3f 100644 --- a/src/backend/cpu/wrap.cpp +++ b/src/backend/cpu/wrap.cpp @@ -49,6 +49,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/Array.cpp b/src/backend/cuda/Array.cpp index 9193f329de..e0d5f73f5a 100644 --- a/src/backend/cuda/Array.cpp +++ b/src/backend/cuda/Array.cpp @@ -493,6 +493,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/cuda/CMakeLists.txt b/src/backend/cuda/CMakeLists.txt index 5ffb28dafd..5085c57717 100644 --- a/src/backend/cuda/CMakeLists.txt +++ b/src/backend/cuda/CMakeLists.txt @@ -51,6 +51,9 @@ set(CUDA_architecture_build_targets "Auto" CACHE find_cuda_helper_libs(nvrtc) find_cuda_helper_libs(nvrtc-builtins) list(APPEND nvrtc_libs ${CUDA_nvrtc_LIBRARY}) +if(UNIX) + list(APPEND nvrtc_libs ${CUDA_nvrtc-builtins_LIBRARY}) +endif() if(UNIX AND AF_WITH_STATIC_CUDA_NUMERIC_LIBS) # The libraries that may be staticly linked or may be loaded at runtime @@ -99,7 +102,12 @@ if(UNIX AND AF_WITH_STATIC_CUDA_NUMERIC_LIBS) # contains GPU accelerated stedc and bdsqr. The user has to link # libcusolver_static.a with liblapack_static.a in order to build # successfully. - af_find_static_cuda_libs(lapack_static) + # Cuda Versions >= 12.0 changed lib name to libcusolver_lapack_static.a + if (CUDA_VERSION VERSION_GREATER_EQUAL 12.0) + af_find_static_cuda_libs(cusolver_lapack_static) + else() + af_find_static_cuda_libs(lapack_static) + endif() set(af_cuda_static_flags "${af_cuda_static_flags};-lcusolver_static") else() @@ -784,7 +792,9 @@ function(afcu_collect_libs libname) NAMES "${PX}${libname}64_${lib_major}${SX}" "${PX}${libname}64_${lib_major}${lib_minor}${SX}" + "${PX}${libname}64_${lib_major}0_0${SX}" "${PX}${libname}64_${lib_major}${lib_minor}_0${SX}" + "${PX}${libname}_${lib_major}0_0${SX}" PATHS ${dlib_path_prefix} ) mark_as_advanced(CUDA_${libname}_LIBRARY_DLL) @@ -833,18 +843,24 @@ endfunction() if(AF_INSTALL_STANDALONE) if(AF_WITH_CUDNN) afcu_collect_cudnn_libs("") - if(cuDNN_VERSION_MAJOR VERSION_GREATER 8 OR cuDNN_VERSION_MAJOR VERSION_EQUAL 8) + if(cuDNN_VERSION_MAJOR VERSION_EQUAL 8) # cudnn changed how dlls are shipped starting major version 8 # except the main dll a lot of the other DLLs are loaded upon demand afcu_collect_cudnn_libs(cnn_infer) afcu_collect_cudnn_libs(cnn_train) afcu_collect_cudnn_libs(ops_infer) afcu_collect_cudnn_libs(ops_train) + elseif(cuDNN_VERSION_MAJOR VERSION_GREATER_EQUAL 9) + # infer and train libraries are now combined in version 9 + afcu_collect_cudnn_libs(cnn) + afcu_collect_cudnn_libs(ops) endif() endif() if(WIN32 OR NOT AF_WITH_STATIC_CUDA_NUMERIC_LIBS) - if(CUDA_VERSION_MAJOR VERSION_EQUAL 11) + if(CUDA_VERSION_MAJOR VERSION_EQUAL 12) + afcu_collect_libs(cufft LIB_MAJOR 11 LIB_MINOR 3) + elseif(CUDA_VERSION_MAJOR VERSION_EQUAL 11) afcu_collect_libs(cufft LIB_MAJOR 10 LIB_MINOR 4) else() afcu_collect_libs(cufft) @@ -853,14 +869,25 @@ if(AF_INSTALL_STANDALONE) if(CUDA_VERSION VERSION_GREATER 10.0) afcu_collect_libs(cublasLt) endif() - afcu_collect_libs(cusolver) + if(CUDA_VERSION_MAJOR VERSION_EQUAL 12) + afcu_collect_libs(cusolver LIB_MAJOR 11 LIB_MINOR 7) + else() + afcu_collect_libs(cusolver) + endif() afcu_collect_libs(cusparse) + if(CUDA_VERSION VERSION_GREATER 12.0) + afcu_collect_libs(nvJitLink) + endif() elseif(NOT ${use_static_cuda_lapack}) - afcu_collect_libs(cusolver) + if(CUDA_VERSION_MAJOR VERSION_EQUAL 12) + afcu_collect_libs(cusolver LIB_MAJOR 11 LIB_MINOR 7) + else() + afcu_collect_libs(cusolver) + endif() endif() if(WIN32 OR CUDA_VERSION VERSION_LESS 11.5 OR NOT AF_WITH_STATIC_CUDA_NUMERIC_LIBS) - afcu_collect_libs(nvrtc FULL_VERSION) + afcu_collect_libs(nvrtc) if(CUDA_VERSION VERSION_GREATER 10.0) afcu_collect_libs(nvrtc-builtins FULL_VERSION) else() diff --git a/src/backend/cuda/ThrustArrayFirePolicy.hpp b/src/backend/cuda/ThrustArrayFirePolicy.hpp index 189ee558b3..339d3ea088 100644 --- a/src/backend/cuda/ThrustArrayFirePolicy.hpp +++ b/src/backend/cuda/ThrustArrayFirePolicy.hpp @@ -37,7 +37,11 @@ inline void return_temporary_buffer(ThrustArrayFirePolicy, Pointer p) { } // namespace cuda } // namespace arrayfire +#if defined(_WIN32) +THRUST_NAMESPACE_BEGIN +#else namespace thrust { +#endif namespace cuda_cub { template<> __DH__ inline cudaStream_t get_stream( @@ -60,4 +64,8 @@ inline cudaError_t synchronize_stream( } } // namespace cuda_cub +#if defined(_WIN32) +THRUST_NAMESPACE_END +#else } // namespace thrust +#endif diff --git a/src/backend/cuda/all.cu b/src/backend/cuda/all.cu index 3ff42ad599..fa0681dbaf 100644 --- a/src/backend/cuda/all.cu +++ b/src/backend/cuda/all.cu @@ -24,6 +24,7 @@ INSTANTIATE(af_and_t, uint, char) INSTANTIATE(af_and_t, intl, char) INSTANTIATE(af_and_t, uintl, char) INSTANTIATE(af_and_t, char, char) +INSTANTIATE(af_and_t, schar, char) INSTANTIATE(af_and_t, uchar, char) INSTANTIATE(af_and_t, short, char) INSTANTIATE(af_and_t, ushort, char) diff --git a/src/backend/cuda/any.cu b/src/backend/cuda/any.cu index 34092c94d3..801dcb6c10 100644 --- a/src/backend/cuda/any.cu +++ b/src/backend/cuda/any.cu @@ -24,6 +24,7 @@ INSTANTIATE(af_or_t, uint, char) INSTANTIATE(af_or_t, intl, char) INSTANTIATE(af_or_t, uintl, char) INSTANTIATE(af_or_t, char, char) +INSTANTIATE(af_or_t, schar, char) INSTANTIATE(af_or_t, uchar, char) INSTANTIATE(af_or_t, short, char) INSTANTIATE(af_or_t, ushort, char) diff --git a/src/backend/cuda/assign.cpp b/src/backend/cuda/assign.cpp index 67bcbd1291..b65265dc8b 100644 --- a/src/backend/cuda/assign.cpp +++ b/src/backend/cuda/assign.cpp @@ -73,6 +73,7 @@ INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/assign_kernel_param.hpp b/src/backend/cuda/assign_kernel_param.hpp index 0591ca80ad..350893f911 100644 --- a/src/backend/cuda/assign_kernel_param.hpp +++ b/src/backend/cuda/assign_kernel_param.hpp @@ -15,6 +15,7 @@ namespace cuda { typedef struct { int offs[4]; int strds[4]; + int steps[4]; bool isSeq[4]; unsigned int* ptr[4]; } AssignKernelParam; diff --git a/src/backend/cuda/bilateral.cpp b/src/backend/cuda/bilateral.cpp index f9f828018d..6d56640fa8 100644 --- a/src/backend/cuda/bilateral.cpp +++ b/src/backend/cuda/bilateral.cpp @@ -34,6 +34,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/cuda/binary.hpp b/src/backend/cuda/binary.hpp index 20f2bea9a6..ca707f30be 100644 --- a/src/backend/cuda/binary.hpp +++ b/src/backend/cuda/binary.hpp @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -60,7 +60,7 @@ BINARY_TYPE_1(bitshiftr) }; \ template \ struct BinOp { \ - const char *name() { return "f" #fn; } \ + const char *name() { return "f" #fn "f"; } \ }; \ template \ struct BinOp { \ @@ -80,6 +80,11 @@ BINARY_TYPE_2(max) BINARY_TYPE_2(rem) BINARY_TYPE_2(mod) +template<> +struct BinOp { + const char *name() { return "hmod"; } +}; + template struct BinOp { const char *name() { return "__pow"; } diff --git a/src/backend/cuda/blas.cu b/src/backend/cuda/blas.cu index 6c88ea002a..08df398a8d 100644 --- a/src/backend/cuda/blas.cu +++ b/src/backend/cuda/blas.cu @@ -91,6 +91,17 @@ BLAS_FUNC(gemmBatched, double, D) BLAS_FUNC(gemmBatched, cdouble, Z) BLAS_FUNC(gemmBatched, __half, H) +template<> +gemm_func_def gemm_func() { + TYPE_ERROR(3, af_dtype::s8); + return gemm_func_def(); +} +template<> +gemmBatched_func_def gemmBatched_func() { + TYPE_ERROR(3, af_dtype::s8); + return gemmBatched_func_def(); +} + BLAS_FUNC_DEF(trsm) BLAS_FUNC(trsm, float, S) BLAS_FUNC(trsm, cfloat, C) @@ -161,20 +172,20 @@ cublasGemmAlgo_t selectGEMMAlgorithm<__half>() { return selectGEMMAlgorithm(); } -template +template cublasStatus_t gemmDispatch(BlasHandle handle, cublasOperation_t lOpts, cublasOperation_t rOpts, int M, int N, int K, - const T *alpha, const Array &lhs, dim_t lStride, - const Array &rhs, dim_t rStride, const T *beta, - Array &out, dim_t oleading) { + const To *alpha, const Array &lhs, dim_t lStride, + const Array &rhs, dim_t rStride, const To *beta, + Array &out, dim_t oleading) { auto prop = getDeviceProp(getActiveDeviceId()); #if __CUDACC_VER_MAJOR__ >= 10 if (prop.major > 3 && __CUDACC_VER_MAJOR__ >= 10) { return cublasGemmEx( - blasHandle(), lOpts, rOpts, M, N, K, alpha, lhs.get(), getType(), - lStride, rhs.get(), getType(), rStride, beta, out.get(), - getType(), out.strides()[1], - getComputeType(), // Compute type + blasHandle(), lOpts, rOpts, M, N, K, alpha, lhs.get(), getType(), + lStride, rhs.get(), getType(), rStride, beta, out.get(), + getType(), out.strides()[1], + getComputeType(), // Compute type // NOTE: When using the CUBLAS_GEMM_DEFAULT_TENSOR_OP algorithm // for the cublasGemm*Ex functions, the performance of the @@ -184,10 +195,10 @@ cublasStatus_t gemmDispatch(BlasHandle handle, cublasOperation_t lOpts, // this change. Does this imply that the TENSOR_OP function // performs the computation in fp16 bit even when the compute // type is CUDA_R_32F? - selectGEMMAlgorithm()); + selectGEMMAlgorithm()); } else { #endif - using Nt = typename common::kernel_type::native; + using Nt = typename common::kernel_type::native; return gemm_func()(blasHandle(), lOpts, rOpts, M, N, K, (Nt *)alpha, (Nt *)lhs.get(), lStride, (Nt *)rhs.get(), rStride, (Nt *)beta, (Nt *)out.get(), oleading); @@ -197,21 +208,21 @@ cublasStatus_t gemmDispatch(BlasHandle handle, cublasOperation_t lOpts, #endif } -template +template cublasStatus_t gemmBatchedDispatch(BlasHandle handle, cublasOperation_t lOpts, cublasOperation_t rOpts, int M, int N, int K, - const T *alpha, const T **lptrs, - int lStrides, const T **rptrs, int rStrides, - const T *beta, T **optrs, int oStrides, + const To *alpha, const Ti **lptrs, + int lStrides, const Ti **rptrs, int rStrides, + const To *beta, To **optrs, int oStrides, int batchSize) { auto prop = getDeviceProp(getActiveDeviceId()); #if __CUDACC_VER_MAJOR__ >= 10 if (prop.major > 3) { return cublasGemmBatchedEx( blasHandle(), lOpts, rOpts, M, N, K, alpha, (const void **)lptrs, - getType(), lStrides, (const void **)rptrs, getType(), - rStrides, beta, (void **)optrs, getType(), oStrides, batchSize, - getComputeType(), // compute type + getType(), lStrides, (const void **)rptrs, getType(), + rStrides, beta, (void **)optrs, getType(), oStrides, batchSize, + getComputeType(), // compute type // NOTE: When using the CUBLAS_GEMM_DEFAULT_TENSOR_OP algorithm // for the cublasGemm*Ex functions, the performance of the // fp32 numbers seem to increase dramatically. Their numerical @@ -220,10 +231,10 @@ cublasStatus_t gemmBatchedDispatch(BlasHandle handle, cublasOperation_t lOpts, // this change. Does this imply that the TENSOR_OP function // performs the computation in fp16 bit even when the compute // type is CUDA_R_32F? - selectGEMMAlgorithm()); + selectGEMMAlgorithm()); } else { #endif - using Nt = typename common::kernel_type::native; + using Nt = typename common::kernel_type::native; return gemmBatched_func()( blasHandle(), lOpts, rOpts, M, N, K, (const Nt *)alpha, (const Nt **)lptrs, lStrides, (const Nt **)rptrs, rStrides, @@ -233,9 +244,9 @@ cublasStatus_t gemmBatchedDispatch(BlasHandle handle, cublasOperation_t lOpts, #endif } -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta) { +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const To *alpha, + const Array &lhs, const Array &rhs, const To *beta) { const cublasOperation_t lOpts = toCblasTranspose(optLhs); const cublasOperation_t rOpts = toCblasTranspose(optRhs); @@ -255,14 +266,14 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, dim4 oStrides = out.strides(); if (oDims.ndims() <= 2) { - CUBLAS_CHECK(gemmDispatch(blasHandle(), lOpts, rOpts, M, N, K, alpha, - lhs, lStrides[1], rhs, rStrides[1], beta, - out, oStrides[1])); + CUBLAS_CHECK((gemmDispatch(blasHandle(), lOpts, rOpts, M, N, K, alpha, + lhs, lStrides[1], rhs, rStrides[1], beta, + out, oStrides[1]))); } else { int batchSize = oDims[2] * oDims[3]; - vector lptrs(batchSize); - vector rptrs(batchSize); - vector optrs(batchSize); + vector lptrs(batchSize); + vector rptrs(batchSize); + vector optrs(batchSize); bool is_l_d2_batched = oDims[2] == lDims[2]; bool is_l_d3_batched = oDims[3] == lDims[3]; @@ -270,9 +281,9 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, bool is_r_d2_batched = oDims[2] == rDims[2]; bool is_r_d3_batched = oDims[3] == rDims[3]; - const T *lptr = lhs.get(); - const T *rptr = rhs.get(); - T *optr = out.get(); + const Ti *lptr = lhs.get(); + const Ti *rptr = rhs.get(); + To *optr = out.get(); for (int n = 0; n < batchSize; n++) { int w = n / oDims[2]; @@ -286,7 +297,7 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, optrs[n] = optr + z * oStrides[2] + w * oStrides[3]; } - size_t bytes = batchSize * sizeof(T **); + size_t bytes = batchSize * sizeof(Ti **); auto d_lptrs = memAlloc(bytes); auto d_rptrs = memAlloc(bytes); auto d_optrs = memAlloc(bytes); @@ -302,11 +313,11 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, // afterwards CUDA_CHECK(cudaStreamSynchronize(getActiveStream())); - using Nt = typename common::kernel_type::native; + using Nt = typename common::kernel_type::native; CUBLAS_CHECK(gemmBatchedDispatch( blasHandle(), lOpts, rOpts, M, N, K, alpha, - (const T **)d_lptrs.get(), lStrides[1], (const T **)d_rptrs.get(), - rStrides[1], beta, (T **)d_optrs.get(), oStrides[1], batchSize)); + (const Ti **)d_lptrs.get(), lStrides[1], (const Ti **)d_rptrs.get(), + rStrides[1], beta, (To **)d_optrs.get(), oStrides[1], batchSize)); } } @@ -340,17 +351,18 @@ void trsm(const Array &lhs, Array &rhs, af_mat_prop trans, bool is_upper, lhs.get(), lStrides[1], rhs.get(), rStrides[1])); } -#define INSTANTIATE_GEMM(TYPE) \ - template void gemm(Array & out, af_mat_prop optLhs, \ - af_mat_prop optRhs, const TYPE *alpha, \ +#define INSTANTIATE_GEMM(TYPE, OUTTYPE) \ + template void gemm(Array & out, af_mat_prop optLhs, \ + af_mat_prop optRhs, const OUTTYPE *alpha, \ const Array &lhs, const Array &rhs, \ - const TYPE *beta); - -INSTANTIATE_GEMM(float) -INSTANTIATE_GEMM(cfloat) -INSTANTIATE_GEMM(double) -INSTANTIATE_GEMM(cdouble) -INSTANTIATE_GEMM(half) + const OUTTYPE *beta); + +INSTANTIATE_GEMM(float, float) +INSTANTIATE_GEMM(cfloat, cfloat) +INSTANTIATE_GEMM(double, double) +INSTANTIATE_GEMM(cdouble, cdouble) +INSTANTIATE_GEMM(half, half) +INSTANTIATE_GEMM(schar, float) #define INSTANTIATE_DOT(TYPE) \ template Array dot(const Array &lhs, \ diff --git a/src/backend/cuda/blas.hpp b/src/backend/cuda/blas.hpp index dc4382d013..37432911e2 100644 --- a/src/backend/cuda/blas.hpp +++ b/src/backend/cuda/blas.hpp @@ -11,9 +11,10 @@ namespace arrayfire { namespace cuda { -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta); +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta); template Array matmul(const Array &lhs, const Array &rhs, af_mat_prop optLhs, diff --git a/src/backend/cuda/cast.hpp b/src/backend/cuda/cast.hpp index 9328dd5052..214d24845a 100644 --- a/src/backend/cuda/cast.hpp +++ b/src/backend/cuda/cast.hpp @@ -34,6 +34,7 @@ struct CastOp { CAST_FN(int) CAST_FN(unsigned int) CAST_FN(unsigned char) +CAST_FN(signed char) CAST_FN(unsigned short) CAST_FN(short) CAST_FN(float) diff --git a/src/backend/cuda/convolve.cpp b/src/backend/cuda/convolve.cpp index 3a33c6f64f..043bfdcc9e 100644 --- a/src/backend/cuda/convolve.cpp +++ b/src/backend/cuda/convolve.cpp @@ -95,6 +95,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/cuda/copy.cpp b/src/backend/cuda/copy.cpp index f8472a7dfb..5d1701d965 100644 --- a/src/backend/cuda/copy.cpp +++ b/src/backend/cuda/copy.cpp @@ -113,6 +113,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) @@ -142,6 +143,8 @@ INSTANTIATE(half) Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ + template void copyArray(Array & dst, \ + Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ template void copyArray(Array & dst, \ @@ -157,6 +160,7 @@ INSTANTIATE_COPY_ARRAY(intl) INSTANTIATE_COPY_ARRAY(uintl) INSTANTIATE_COPY_ARRAY(short) INSTANTIATE_COPY_ARRAY(ushort) +INSTANTIATE_COPY_ARRAY(schar) INSTANTIATE_COPY_ARRAY(uchar) INSTANTIATE_COPY_ARRAY(char) INSTANTIATE_COPY_ARRAY(half) @@ -187,6 +191,7 @@ INSTANTIATE_GETSCALAR(cfloat) INSTANTIATE_GETSCALAR(cdouble) INSTANTIATE_GETSCALAR(int) INSTANTIATE_GETSCALAR(uint) +INSTANTIATE_GETSCALAR(schar) INSTANTIATE_GETSCALAR(uchar) INSTANTIATE_GETSCALAR(char) INSTANTIATE_GETSCALAR(intl) diff --git a/src/backend/cuda/count.cu b/src/backend/cuda/count.cu index 373def999c..3cb5806a88 100644 --- a/src/backend/cuda/count.cu +++ b/src/backend/cuda/count.cu @@ -26,6 +26,7 @@ INSTANTIATE(af_notzero_t, uintl, uint) INSTANTIATE(af_notzero_t, short, uint) INSTANTIATE(af_notzero_t, ushort, uint) INSTANTIATE(af_notzero_t, char, uint) +INSTANTIATE(af_notzero_t, schar, uint) INSTANTIATE(af_notzero_t, uchar, uint) INSTANTIATE(af_notzero_t, half, uint) } // namespace cuda diff --git a/src/backend/cuda/cudaDataType.hpp b/src/backend/cuda/cudaDataType.hpp index 1da3429e60..3746d0b4b9 100644 --- a/src/backend/cuda/cudaDataType.hpp +++ b/src/backend/cuda/cudaDataType.hpp @@ -44,6 +44,22 @@ inline cudaDataType_t getType() { return CUDA_R_16F; } +template<> +inline cudaDataType_t getType() { + return CUDA_R_8I; +} + +template<> +inline cudaDataType_t getType() { + return CUDA_R_8I; +} + +/* only supports LStride/RStride % 4 == 0 */ +template<> +inline cudaDataType_t getType() { + return CUDA_R_32I; +} + template inline cudaDataType_t getComputeType() { return getType(); diff --git a/src/backend/cuda/cudnn.cpp b/src/backend/cuda/cudnn.cpp index 39ee3305e6..5b8a500d00 100644 --- a/src/backend/cuda/cudnn.cpp +++ b/src/backend/cuda/cudnn.cpp @@ -64,6 +64,12 @@ cudnnDataType_t getCudnnDataType() { } #if CUDNN_VERSION >= 7100 +/// TODONT COMMIT +template<> +cudnnDataType_t getCudnnDataType() { + return CUDNN_DATA_INT8; +} + template<> cudnnDataType_t getCudnnDataType() { return CUDNN_DATA_UINT8; diff --git a/src/backend/cuda/device_manager.cpp b/src/backend/cuda/device_manager.cpp index 9e7cc2d68b..88cbe487a8 100644 --- a/src/backend/cuda/device_manager.cpp +++ b/src/backend/cuda/device_manager.cpp @@ -101,6 +101,12 @@ static const int jetsonComputeCapabilities[] = { // clang-format off static const cuNVRTCcompute Toolkit2MaxCompute[] = { + {12080, 9, 0, 0}, + {12070, 9, 0, 0}, + {12060, 9, 0, 0}, + {12050, 9, 0, 0}, + {12040, 9, 0, 0}, + {12030, 9, 0, 0}, {12020, 9, 0, 0}, {12010, 9, 0, 0}, {12000, 9, 0, 0}, @@ -140,9 +146,15 @@ struct ComputeCapabilityToStreamingProcessors { // clang-format off static const ToolkitDriverVersions CudaToDriverVersion[] = { - {12020, 525.60f, 527.41f}, - {12010, 525.60f, 527.41f}, - {12000, 525.60f, 527.41f}, + {12080, 525.60f, 528.33f}, + {12070, 525.60f, 528.33f}, + {12060, 525.60f, 528.33f}, + {12050, 525.60f, 528.33f}, + {12040, 525.60f, 528.33f}, + {12030, 525.60f, 528.33f}, + {12020, 525.60f, 528.33f}, + {12010, 525.60f, 528.33f}, + {12000, 525.60f, 528.33f}, {11080, 450.80f, 452.39f}, {11070, 450.80f, 452.39f}, {11060, 450.80f, 452.39f}, @@ -499,7 +511,10 @@ void DeviceManager::checkCudaVsDriverVersion() { debugRuntimeCheck(getLogger(), runtime, driver); - if (runtime > driver) { + int runtime_major = runtime / 1000; + int driver_major = driver / 1000; + + if (runtime_major > driver_major) { string msg = "ArrayFire was built with CUDA {} which requires GPU driver " "version {} or later. Please download and install the latest " diff --git a/src/backend/cuda/diagonal.cpp b/src/backend/cuda/diagonal.cpp index cbf3180a70..b5dd2b5c0b 100644 --- a/src/backend/cuda/diagonal.cpp +++ b/src/backend/cuda/diagonal.cpp @@ -54,6 +54,7 @@ INSTANTIATE_DIAGONAL(uint) INSTANTIATE_DIAGONAL(intl) INSTANTIATE_DIAGONAL(uintl) INSTANTIATE_DIAGONAL(char) +INSTANTIATE_DIAGONAL(schar) INSTANTIATE_DIAGONAL(uchar) INSTANTIATE_DIAGONAL(short) INSTANTIATE_DIAGONAL(ushort) diff --git a/src/backend/cuda/diff.cpp b/src/backend/cuda/diff.cpp index 55bb68ece0..b21ab36b72 100644 --- a/src/backend/cuda/diff.cpp +++ b/src/backend/cuda/diff.cpp @@ -55,6 +55,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/err_cuda.hpp b/src/backend/cuda/err_cuda.hpp index 77926cdd79..f6db7e6822 100644 --- a/src/backend/cuda/err_cuda.hpp +++ b/src/backend/cuda/err_cuda.hpp @@ -14,8 +14,8 @@ #define CUDA_NOT_SUPPORTED(message) \ do { \ - throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, message, \ - boost::stacktrace::stacktrace()); \ + throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, "CUDA", \ + message, boost::stacktrace::stacktrace()); \ } while (0) #define CU_CHECK(fn) \ diff --git a/src/backend/cuda/exampleFunction.cpp b/src/backend/cuda/exampleFunction.cpp index b94f9f8e54..12bf635785 100644 --- a/src/backend/cuda/exampleFunction.cpp +++ b/src/backend/cuda/exampleFunction.cpp @@ -60,6 +60,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(cfloat) diff --git a/src/backend/cuda/fast.cu b/src/backend/cuda/fast.cu index 7744d4b6d6..63e9a57cb4 100644 --- a/src/backend/cuda/fast.cu +++ b/src/backend/cuda/fast.cu @@ -62,6 +62,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/fast_pyramid.cpp b/src/backend/cuda/fast_pyramid.cpp index 97228af248..ba0b6dfbf4 100644 --- a/src/backend/cuda/fast_pyramid.cpp +++ b/src/backend/cuda/fast_pyramid.cpp @@ -120,6 +120,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/fftconvolve.cpp b/src/backend/cuda/fftconvolve.cpp index ed22d0ea85..cb8359423e 100644 --- a/src/backend/cuda/fftconvolve.cpp +++ b/src/backend/cuda/fftconvolve.cpp @@ -112,6 +112,7 @@ INSTANTIATE(float) INSTANTIATE(uint) INSTANTIATE(int) INSTANTIATE(uchar) +INSTANTIATE(schar) INSTANTIATE(char) INSTANTIATE(uintl) INSTANTIATE(intl) diff --git a/src/backend/cuda/hist_graphics.cpp b/src/backend/cuda/hist_graphics.cpp index 6678281db6..cabadeb1ad 100644 --- a/src/backend/cuda/hist_graphics.cpp +++ b/src/backend/cuda/hist_graphics.cpp @@ -69,6 +69,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace cuda diff --git a/src/backend/cuda/histogram.cpp b/src/backend/cuda/histogram.cpp index ca7e6ced86..f012d6e64b 100644 --- a/src/backend/cuda/histogram.cpp +++ b/src/backend/cuda/histogram.cpp @@ -41,6 +41,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/identity.cpp b/src/backend/cuda/identity.cpp index 995b09a9d9..ee62dcf549 100644 --- a/src/backend/cuda/identity.cpp +++ b/src/backend/cuda/identity.cpp @@ -37,6 +37,7 @@ INSTANTIATE_IDENTITY(uint) INSTANTIATE_IDENTITY(intl) INSTANTIATE_IDENTITY(uintl) INSTANTIATE_IDENTITY(char) +INSTANTIATE_IDENTITY(schar) INSTANTIATE_IDENTITY(uchar) INSTANTIATE_IDENTITY(short) INSTANTIATE_IDENTITY(ushort) diff --git a/src/backend/cuda/image.cpp b/src/backend/cuda/image.cpp index 810d36d968..23bccf616e 100644 --- a/src/backend/cuda/image.cpp +++ b/src/backend/cuda/image.cpp @@ -70,6 +70,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cuda/index.cpp b/src/backend/cuda/index.cpp index 88a95da73b..dbb7d1ad60 100644 --- a/src/backend/cuda/index.cpp +++ b/src/backend/cuda/index.cpp @@ -44,6 +44,16 @@ Array index(const Array& in, const af_index_t idxrs[]) { p.isSeq[i] = idxrs[i].isSeq; p.offs[i] = iOffs[i]; p.strds[i] = iStrds[i]; + p.steps[i] = 0; + if (idxrs[i].isSeq) { + af_seq seq = idxrs[i].idx.seq; + // The step for af_span used in the kernel must be 1 + if (seq.begin == af_span.begin && seq.end == af_span.end && + seq.step == af_span.step) + p.steps[i] = 1; + else + p.steps[i] = seq.step; + } } std::vector> idxArrs(4, createEmptyArray(dim4())); @@ -80,6 +90,7 @@ INSTANTIATE(int) INSTANTIATE(uintl) INSTANTIATE(intl) INSTANTIATE(uchar) +INSTANTIATE(schar) INSTANTIATE(char) INSTANTIATE(ushort) INSTANTIATE(short) diff --git a/src/backend/cuda/iota.cpp b/src/backend/cuda/iota.cpp index d9afef41c5..0ac6dbee74 100644 --- a/src/backend/cuda/iota.cpp +++ b/src/backend/cuda/iota.cpp @@ -38,6 +38,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/ireduce.cpp b/src/backend/cuda/ireduce.cpp index 94cd340a66..a2236230d4 100644 --- a/src/backend/cuda/ireduce.cpp +++ b/src/backend/cuda/ireduce.cpp @@ -62,6 +62,7 @@ INSTANTIATE(af_min_t, uintl) INSTANTIATE(af_min_t, short) INSTANTIATE(af_min_t, ushort) INSTANTIATE(af_min_t, char) +INSTANTIATE(af_min_t, schar) INSTANTIATE(af_min_t, uchar) INSTANTIATE(af_min_t, half) @@ -77,6 +78,7 @@ INSTANTIATE(af_max_t, uintl) INSTANTIATE(af_max_t, short) INSTANTIATE(af_max_t, ushort) INSTANTIATE(af_max_t, char) +INSTANTIATE(af_max_t, schar) INSTANTIATE(af_max_t, uchar) INSTANTIATE(af_max_t, half) } // namespace cuda diff --git a/src/backend/cuda/jit.cpp b/src/backend/cuda/jit.cpp index 146cb07db2..171ec66f61 100644 --- a/src/backend/cuda/jit.cpp +++ b/src/backend/cuda/jit.cpp @@ -244,16 +244,18 @@ struct Param { node->genOffsets(inOffsetsStream, ids_curr.id, is_linear); // Generate the core function body, needs children ids as well node->genFuncs(opsStream, ids_curr); - for (auto outIt{begin(output_ids)}, endIt{end(output_ids)}; - (outIt = find(outIt, endIt, ids_curr.id)) != endIt; ++outIt) { - // Generate also output parameters - outParamStream << (oid == 0 ? "" : ",\n") << "Param<" - << full_nodes[ids_curr.id]->getTypeStr() - << "> out" << oid; - // Generate code to write the output (offset already in ptr) - opsStream << "out" << oid << ".ptr[idx] = val" << ids_curr.id - << ";\n"; - ++oid; + for (size_t output_idx{0}; output_idx < output_ids.size(); + ++output_idx) { + if (output_ids[output_idx] == ids_curr.id) { + // Generate also output parameters + outParamStream << (oid == 0 ? "" : ",\n") << "Param<" + << full_nodes[ids_curr.id]->getTypeStr() + << "> out" << oid; + // Generate code to write the output (offset already in ptr) + opsStream << "out" << output_idx << ".ptr[idx] = val" + << ids_curr.id << ";\n"; + ++oid; + } } } @@ -322,8 +324,9 @@ static CUfunction getKernel(const vector& output_nodes, const bool is_linear, const bool loop0, const bool loop1, const bool loop2, const bool loop3) { - const string funcName{getFuncName(output_nodes, full_nodes, full_ids, - is_linear, loop0, loop1, loop2, loop3)}; + const string funcName{getFuncName(output_nodes, output_ids, full_nodes, + full_ids, is_linear, loop0, loop1, loop2, + loop3)}; // A forward lookup in module cache helps avoid recompiling // the JIT source generated from identical JIT-trees. const auto entry{ @@ -549,6 +552,7 @@ template void evalNodes(Param out, Node* node); template void evalNodes(Param out, Node* node); template void evalNodes(Param out, Node* node); template void evalNodes(Param out, Node* node); +template void evalNodes(Param out, Node* node); template void evalNodes(Param out, Node* node); template void evalNodes(Param out, Node* node); template void evalNodes(Param out, Node* node); @@ -570,6 +574,8 @@ template void evalNodes(vector>& out, const vector& node); template void evalNodes(vector>& out, const vector& node); +template void evalNodes(vector>& out, + const vector& node); template void evalNodes(vector>& out, const vector& node); template void evalNodes(vector>& out, diff --git a/src/backend/cuda/join.cpp b/src/backend/cuda/join.cpp index 3eed6f7fb5..5065412342 100644 --- a/src/backend/cuda/join.cpp +++ b/src/backend/cuda/join.cpp @@ -209,6 +209,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) @@ -229,6 +230,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) diff --git a/src/backend/cuda/kernel/convolve_separable.cpp b/src/backend/cuda/kernel/convolve_separable.cpp index 3c18a02240..14a62d1f1e 100644 --- a/src/backend/cuda/kernel/convolve_separable.cpp +++ b/src/backend/cuda/kernel/convolve_separable.cpp @@ -22,6 +22,7 @@ INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) INSTANTIATE(uchar, float) +INSTANTIATE(schar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) INSTANTIATE(short, float) diff --git a/src/backend/cuda/kernel/copy.cuh b/src/backend/cuda/kernel/copy.cuh index 9e771e8c52..20f6bfa021 100644 --- a/src/backend/cuda/kernel/copy.cuh +++ b/src/backend/cuda/kernel/copy.cuh @@ -49,6 +49,18 @@ convertType>(char value) { return compute_t(value); } +template<> +__inline__ __device__ schar +convertType, schar>(compute_t value) { + return (schar)((short)value); +} + +template<> +__inline__ __device__ compute_t +convertType>(schar value) { + return compute_t(value); +} + template<> __inline__ __device__ uchar convertType, uchar>(compute_t value) { @@ -90,6 +102,7 @@ OTHER_SPECIALIZATIONS(intl) OTHER_SPECIALIZATIONS(uintl) OTHER_SPECIALIZATIONS(short) OTHER_SPECIALIZATIONS(ushort) +OTHER_SPECIALIZATIONS(schar) OTHER_SPECIALIZATIONS(uchar) OTHER_SPECIALIZATIONS(char) OTHER_SPECIALIZATIONS(common::half) diff --git a/src/backend/cuda/kernel/index.cuh b/src/backend/cuda/kernel/index.cuh index 37b6b63d46..968e9ae0c6 100644 --- a/src/backend/cuda/kernel/index.cuh +++ b/src/backend/cuda/kernel/index.cuh @@ -43,13 +43,17 @@ __global__ void index(Param out, CParam in, const IndexKernelParam p, gw < out.dims[3]) { // calculate pointer offsets for input int i = - p.strds[0] * trimIndex(s0 ? gx + p.offs[0] : ptr0[gx], in.dims[0]); + p.strds[0] * + trimIndex(s0 ? gx * p.steps[0] + p.offs[0] : ptr0[gx], in.dims[0]); int j = - p.strds[1] * trimIndex(s1 ? gy + p.offs[1] : ptr1[gy], in.dims[1]); + p.strds[1] * + trimIndex(s1 ? gy * p.steps[1] + p.offs[1] : ptr1[gy], in.dims[1]); int k = - p.strds[2] * trimIndex(s2 ? gz + p.offs[2] : ptr2[gz], in.dims[2]); + p.strds[2] * + trimIndex(s2 ? gz * p.steps[2] + p.offs[2] : ptr2[gz], in.dims[2]); int l = - p.strds[3] * trimIndex(s3 ? gw + p.offs[3] : ptr3[gw], in.dims[3]); + p.strds[3] * + trimIndex(s3 ? gw * p.steps[3] + p.offs[3] : ptr3[gw], in.dims[3]); // offset input and output pointers const T* src = (const T*)in.ptr + (i + j + k + l); T* dst = (T*)out.ptr + (gx * out.strides[0] + gy * out.strides[1] + diff --git a/src/backend/cuda/kernel/jit.cuh b/src/backend/cuda/kernel/jit.cuh index cfb5837719..879d46f3c2 100644 --- a/src/backend/cuda/kernel/jit.cuh +++ b/src/backend/cuda/kernel/jit.cuh @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -59,14 +59,9 @@ typedef cuDoubleComplex cdouble; #define __rem(lhs, rhs) ((lhs) % (rhs)) #define __mod(lhs, rhs) ((lhs) % (rhs)) -#ifdef AF_WITH_FAST_MATH #define __pow(lhs, rhs) \ static_cast( \ pow(static_cast(lhs), static_cast(rhs))); -#else -#define __pow(lhs, rhs) \ - __float2int_rn(powf(__int2float_rn((int)lhs), __int2float_rn((int)rhs))) -#endif #define __powll(lhs, rhs) \ __double2ll_rn(pow(__ll2double_rn(lhs), __ll2double_rn(rhs))) #define __powul(lhs, rhs) \ @@ -78,6 +73,7 @@ typedef cuDoubleComplex cdouble; #define __convert_char(val) (char)((val) != 0) #define frem(lhs, rhs) remainder((lhs), (rhs)) +#define fremf(lhs, rhs) remainderf((lhs), (rhs)) // ---------------------------------------------- // COMPLEX FLOAT OPERATIONS @@ -219,6 +215,15 @@ __device__ __inline__ int __isinf<__half>(const __half in) { #endif } +__device__ __inline__ +__half hmod(const __half lhs, const __half rhs) { +#if __CUDA_ARCH__ >= 530 + return __hsub(lhs, __hmul(htrunc(__hdiv(lhs, rhs)), rhs)); +#else + return __float2half(fmodf(__half2float(lhs), __half2float(rhs))); +#endif +} + template static __device__ __inline__ int __isnan(const T in) { return isnan(in); diff --git a/src/backend/cuda/kernel/random_engine.hpp b/src/backend/cuda/kernel/random_engine.hpp index 07ba4163a2..a5e2305885 100644 --- a/src/backend/cuda/kernel/random_engine.hpp +++ b/src/backend/cuda/kernel/random_engine.hpp @@ -312,6 +312,12 @@ __device__ static void writeOut128Bytes(uchar *out, const uint &index, out[index + 15 * blockDim.x] = r4 >> 24; } +__device__ static void writeOut128Bytes(schar *out, const uint &index, + const uint &r1, const uint &r2, + const uint &r3, const uint &r4) { + writeOut128Bytes((uchar *)(out), index, r1, r2, r3, r4); +} + __device__ static void writeOut128Bytes(char *out, const uint &index, const uint &r1, const uint &r2, const uint &r3, const uint &r4) { @@ -535,6 +541,13 @@ __device__ static void partialWriteOut128Bytes(uchar *out, const uint &index, } } +__device__ static void partialWriteOut128Bytes(schar *out, const uint &index, + const uint &r1, const uint &r2, + const uint &r3, const uint &r4, + const uint &elements) { + partialWriteOut128Bytes((uchar *)(out), index, r1, r2, r3, r4, elements); +} + __device__ static void partialWriteOut128Bytes(char *out, const uint &index, const uint &r1, const uint &r2, const uint &r3, const uint &r4, diff --git a/src/backend/cuda/kernel/reduce_by_key.hpp b/src/backend/cuda/kernel/reduce_by_key.hpp index ea015aaff2..1e04a123ec 100644 --- a/src/backend/cuda/kernel/reduce_by_key.hpp +++ b/src/backend/cuda/kernel/reduce_by_key.hpp @@ -25,8 +25,6 @@ using std::unique_ptr; -const static unsigned int FULL_MASK = 0xFFFFFFFF; - namespace arrayfire { namespace cuda { namespace kernel { @@ -68,9 +66,9 @@ __global__ void test_needs_reduction(int *needs_another_reduction, if (tid < n) { k = keys_in.ptr[tid]; } - int update_key = (k == shfl_down_sync(FULL_MASK, k, 1)) && + int update_key = (k == shfl_down_sync(k, 1)) && (tid < (n - 1)) && ((threadIdx.x % 32) < 31); - int remaining_updates = any_sync(FULL_MASK, update_key); + int remaining_updates = any_sync(update_key); __syncthreads(); @@ -83,7 +81,7 @@ __global__ void test_needs_reduction(int *needs_another_reduction, && (threadIdx.x < (blockDim.x - 1)) // not last thread in block // next value valid and equal && ((tid + 1) < n) && (k == keys_in.ptr[tid + 1])); - remaining_updates = any_sync(FULL_MASK, update_key); + remaining_updates = any_sync(update_key); // TODO: single per warp? change to assignment rather than atomicOr if (remaining_updates) atomicOr(needs_another_reduction, remaining_updates); @@ -243,7 +241,7 @@ __global__ static void reduce_blocks_by_key(int *reduced_block_sizes, v = common::Binary, op>::init(); } - compute_t eq_check = (k != shfl_up_sync(FULL_MASK, k, 1)); + compute_t eq_check = (k != shfl_up_sync(k, 1)); // mark threads containing unique keys char unique_flag = (eq_check || (laneid == 0)) && (tidx < n); @@ -251,42 +249,33 @@ __global__ static void reduce_blocks_by_key(int *reduced_block_sizes, char unique_id = unique_flag; #pragma unroll for (int offset = 1; offset < 32; offset <<= 1) { - char y = shfl_up_sync(FULL_MASK, unique_id, offset); + char y = shfl_up_sync(unique_id, offset); if (laneid >= offset) unique_id += y; } // // Reduce each warp by key - char all_eq = (k == shfl_down_sync(FULL_MASK, k, 1)); - if (all_sync(FULL_MASK, - all_eq)) { // check special case of single key per warp - v = reduce(v, shfl_down_sync(FULL_MASK, v, 1)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 2)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 4)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 8)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 16)); + char all_eq = (k == shfl_down_sync(k, 1)); + if (all_sync(all_eq)) { // check special case of single key per warp + v = reduce(v, shfl_down_sync(v, 1)); + v = reduce(v, shfl_down_sync(v, 2)); + v = reduce(v, shfl_down_sync(v, 4)); + v = reduce(v, shfl_down_sync(v, 8)); + v = reduce(v, shfl_down_sync(v, 16)); } else { compute_t init = common::Binary, op>::init(); int eq_check, update_key; - unsigned shflmask; #pragma unroll for (int delta = 1; delta < 32; delta <<= 1) { eq_check = - (unique_id == shfl_down_sync(FULL_MASK, unique_id, delta)); + (unique_id == shfl_down_sync(unique_id, delta)); // checks if this thread should perform a reduction update_key = eq_check && (laneid < (32 - delta)) && ((tidx + delta) < n); - // obtains mask of all threads that should be reduced - shflmask = ballot_sync(FULL_MASK, update_key); - - // shifts mask to include source threads that should participate in - // _shfl - shflmask |= (shflmask << delta); - // shfls data from neighboring threads - compute_t uval = shfl_down_sync(shflmask, v, delta); + compute_t uval = shfl_down_sync(v, delta); // update if thread requires it v = reduce(v, (update_key ? uval : init)); @@ -479,7 +468,7 @@ __global__ static void reduce_blocks_dim_by_key( v = init; } - Tk eq_check = (k != shfl_up_sync(FULL_MASK, k, 1)); + Tk eq_check = (k != shfl_up_sync(k, 1)); // mark threads containing unique keys char unique_flag = (eq_check || (laneid == 0)) && (tidx < n); @@ -487,42 +476,33 @@ __global__ static void reduce_blocks_dim_by_key( char unique_id = unique_flag; #pragma unroll for (int offset = 1; offset < 32; offset <<= 1) { - char y = shfl_up_sync(FULL_MASK, unique_id, offset); + char y = shfl_up_sync(unique_id, offset); if (laneid >= offset) unique_id += y; } // // Reduce each warp by key - char all_eq = (k == shfl_down_sync(FULL_MASK, k, 1)); - if (all_sync(FULL_MASK, - all_eq)) { // check special case of single key per warp - v = reduce(v, shfl_down_sync(FULL_MASK, v, 1)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 2)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 4)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 8)); - v = reduce(v, shfl_down_sync(FULL_MASK, v, 16)); + char all_eq = (k == shfl_down_sync(k, 1)); + if (all_sync(all_eq)) { // check special case of single key per warp + v = reduce(v, shfl_down_sync(v, 1)); + v = reduce(v, shfl_down_sync(v, 2)); + v = reduce(v, shfl_down_sync(v, 4)); + v = reduce(v, shfl_down_sync(v, 8)); + v = reduce(v, shfl_down_sync(v, 16)); } else { compute_t init = common::Binary, op>::init(); int eq_check, update_key; - unsigned shflmask; #pragma unroll for (int delta = 1; delta < 32; delta <<= 1) { eq_check = - (unique_id == shfl_down_sync(FULL_MASK, unique_id, delta)); + (unique_id == shfl_down_sync(unique_id, delta)); // checks if this thread should perform a reduction update_key = eq_check && (laneid < (32 - delta)) && ((tidx + delta) < n); - // obtains mask of all threads that should be reduced - shflmask = ballot_sync(FULL_MASK, update_key); - - // shifts mask to include source threads that should participate in - // _shfl - shflmask |= (shflmask << delta); - // shfls data from neighboring threads - compute_t uval = shfl_down_sync(shflmask, v, delta); + compute_t uval = shfl_down_sync(v, delta); // update if thread requires it v = reduce(v, (update_key ? uval : init)); diff --git a/src/backend/cuda/kernel/shared.hpp b/src/backend/cuda/kernel/shared.hpp index 55d9f70a64..d1f15653c3 100644 --- a/src/backend/cuda/kernel/shared.hpp +++ b/src/backend/cuda/kernel/shared.hpp @@ -53,6 +53,7 @@ SPECIALIZE(int) SPECIALIZE(uint) SPECIALIZE(short) SPECIALIZE(ushort) +SPECIALIZE(schar) SPECIALIZE(uchar) SPECIALIZE(intl) SPECIALIZE(uintl) diff --git a/src/backend/cuda/kernel/shfl_intrinsics.hpp b/src/backend/cuda/kernel/shfl_intrinsics.hpp index 687abf5144..a91dc74148 100644 --- a/src/backend/cuda/kernel/shfl_intrinsics.hpp +++ b/src/backend/cuda/kernel/shfl_intrinsics.hpp @@ -11,11 +11,13 @@ namespace arrayfire { namespace cuda { namespace kernel { +constexpr unsigned int FULL_MASK = 0xffffffff; + //__all_sync wrapper template -__device__ T all_sync(unsigned mask, T var) { +__device__ T all_sync(T var) { #if (CUDA_VERSION >= 9000) - return __all_sync(mask, var); + return __all_sync(FULL_MASK, var); #else return __all(var); #endif @@ -23,9 +25,9 @@ __device__ T all_sync(unsigned mask, T var) { //__all_sync wrapper template -__device__ T any_sync(unsigned mask, T var) { +__device__ T any_sync(T var) { #if (CUDA_VERSION >= 9000) - return __any_sync(mask, var); + return __any_sync(FULL_MASK, var); #else return __any(var); #endif @@ -33,9 +35,9 @@ __device__ T any_sync(unsigned mask, T var) { //__shfl_down_sync wrapper template -__device__ T ballot_sync(unsigned mask, T var) { +__device__ T ballot_sync(T var) { #if (CUDA_VERSION >= 9000) - return __ballot_sync(mask, var); + return __ballot_sync(FULL_MASK, var); #else return __ballot(var); #endif @@ -43,19 +45,19 @@ __device__ T ballot_sync(unsigned mask, T var) { //__shfl_down_sync wrapper template -__device__ T shfl_down_sync(unsigned mask, T var, int delta) { +__device__ T shfl_down_sync(T var, int delta) { #if (CUDA_VERSION >= 9000) - return __shfl_down_sync(mask, var, delta); + return __shfl_down_sync(FULL_MASK, var, delta); #else return __shfl_down(var, delta); #endif } // specialization for cfloat template<> -inline __device__ cfloat shfl_down_sync(unsigned mask, cfloat var, int delta) { +inline __device__ cfloat shfl_down_sync(cfloat var, int delta) { #if (CUDA_VERSION >= 9000) - cfloat res = {__shfl_down_sync(mask, var.x, delta), - __shfl_down_sync(mask, var.y, delta)}; + cfloat res = {__shfl_down_sync(FULL_MASK, var.x, delta), + __shfl_down_sync(FULL_MASK, var.y, delta)}; #else cfloat res = {__shfl_down(var.x, delta), __shfl_down(var.y, delta)}; #endif @@ -63,11 +65,11 @@ inline __device__ cfloat shfl_down_sync(unsigned mask, cfloat var, int delta) { } // specialization for cdouble template<> -inline __device__ cdouble shfl_down_sync(unsigned mask, cdouble var, +inline __device__ cdouble shfl_down_sync(cdouble var, int delta) { #if (CUDA_VERSION >= 9000) - cdouble res = {__shfl_down_sync(mask, var.x, delta), - __shfl_down_sync(mask, var.y, delta)}; + cdouble res = {__shfl_down_sync(FULL_MASK, var.x, delta), + __shfl_down_sync(FULL_MASK, var.y, delta)}; #else cdouble res = {__shfl_down(var.x, delta), __shfl_down(var.y, delta)}; #endif @@ -76,19 +78,19 @@ inline __device__ cdouble shfl_down_sync(unsigned mask, cdouble var, //__shfl_up_sync wrapper template -__device__ T shfl_up_sync(unsigned mask, T var, int delta) { +__device__ T shfl_up_sync(T var, int delta) { #if (CUDA_VERSION >= 9000) - return __shfl_up_sync(mask, var, delta); + return __shfl_up_sync(FULL_MASK, var, delta); #else return __shfl_up(var, delta); #endif } // specialization for cfloat template<> -inline __device__ cfloat shfl_up_sync(unsigned mask, cfloat var, int delta) { +inline __device__ cfloat shfl_up_sync(cfloat var, int delta) { #if (CUDA_VERSION >= 9000) - cfloat res = {__shfl_up_sync(mask, var.x, delta), - __shfl_up_sync(mask, var.y, delta)}; + cfloat res = {__shfl_up_sync(FULL_MASK, var.x, delta), + __shfl_up_sync(FULL_MASK, var.y, delta)}; #else cfloat res = {__shfl_up(var.x, delta), __shfl_up(var.y, delta)}; #endif @@ -96,10 +98,10 @@ inline __device__ cfloat shfl_up_sync(unsigned mask, cfloat var, int delta) { } // specialization for cdouble template<> -inline __device__ cdouble shfl_up_sync(unsigned mask, cdouble var, int delta) { +inline __device__ cdouble shfl_up_sync(cdouble var, int delta) { #if (CUDA_VERSION >= 9000) - cdouble res = {__shfl_up_sync(mask, var.x, delta), - __shfl_up_sync(mask, var.y, delta)}; + cdouble res = {__shfl_up_sync(FULL_MASK, var.x, delta), + __shfl_up_sync(FULL_MASK, var.y, delta)}; #else cdouble res = {__shfl_up(var.x, delta), __shfl_up(var.y, delta)}; #endif diff --git a/src/backend/cuda/kernel/sparse.cuh b/src/backend/cuda/kernel/sparse.cuh index bdf0e20884..84825bdd24 100644 --- a/src/backend/cuda/kernel/sparse.cuh +++ b/src/backend/cuda/kernel/sparse.cuh @@ -17,15 +17,13 @@ namespace cuda { template __global__ void coo2Dense(Param output, CParam values, CParam rowIdx, CParam colIdx) { - int id = blockIdx.x * blockDim.x * reps + threadIdx.x; - if (id >= values.dims[0]) return; + for (int i = threadIdx.x; i < reps * blockDim.x; i += blockDim.x) { + int id = i + blockIdx.x * blockDim.x * reps; + if (id >= values.dims[0]) return; - for (int i = threadIdx.x; i <= reps * blockDim.x; i += blockDim.x) { - if (i >= values.dims[0]) return; - - T v = values.ptr[i]; - int r = rowIdx.ptr[i]; - int c = colIdx.ptr[i]; + T v = values.ptr[id]; + int r = rowIdx.ptr[id]; + int c = colIdx.ptr[id]; int offset = r + c * output.strides[1]; diff --git a/src/backend/cuda/kernel/sparse.hpp b/src/backend/cuda/kernel/sparse.hpp index 6629d0fec6..60068d3e20 100644 --- a/src/backend/cuda/kernel/sparse.hpp +++ b/src/backend/cuda/kernel/sparse.hpp @@ -30,7 +30,7 @@ void coo2dense(Param output, CParam values, CParam rowIdx, dim3 threads(256, 1, 1); - dim3 blocks(divup(output.dims[0], threads.x * reps), 1, 1); + dim3 blocks(divup(values.dims[0], threads.x * reps), 1, 1); EnqueueArgs qArgs(blocks, threads, getActiveStream()); diff --git a/src/backend/cuda/kernel/thrust_sort_by_key/thrust_sort_by_key_impl.cu b/src/backend/cuda/kernel/thrust_sort_by_key/thrust_sort_by_key_impl.cu index 19b291356c..7a7e3616c9 100644 --- a/src/backend/cuda/kernel/thrust_sort_by_key/thrust_sort_by_key_impl.cu +++ b/src/backend/cuda/kernel/thrust_sort_by_key/thrust_sort_by_key_impl.cu @@ -11,7 +11,7 @@ // This file instantiates sort_by_key as separate object files from CMake // The 3 lines below are read by CMake to determenine the instantiations -// SBK_TYPES:float double int uint intl uintl short ushort char uchar +// SBK_TYPES:float double int uint intl uintl short ushort char schar uchar // SBK_INSTS:0 1 namespace arrayfire { diff --git a/src/backend/cuda/kernel/thrust_sort_by_key_impl.hpp b/src/backend/cuda/kernel/thrust_sort_by_key_impl.hpp index e4695ac48e..e909a786de 100644 --- a/src/backend/cuda/kernel/thrust_sort_by_key_impl.hpp +++ b/src/backend/cuda/kernel/thrust_sort_by_key_impl.hpp @@ -39,6 +39,7 @@ void thrustSortByKey(Tk *keyPtr, Tv *valPtr, int elements, bool isAscending) { INSTANTIATE(Tk, cfloat) \ INSTANTIATE(Tk, cdouble) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) #define INSTANTIATE1(Tk) \ diff --git a/src/backend/cuda/lookup.cpp b/src/backend/cuda/lookup.cpp index 133db5ba26..ca5b8f79ed 100644 --- a/src/backend/cuda/lookup.cpp +++ b/src/backend/cuda/lookup.cpp @@ -54,6 +54,8 @@ Array lookup(const Array &input, const Array &indices, const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ + template Array lookup(const Array &, const Array &, \ + const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ template Array lookup(const Array &, const Array &, \ @@ -67,6 +69,7 @@ INSTANTIATE(int); INSTANTIATE(unsigned); INSTANTIATE(intl); INSTANTIATE(uintl); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(char); INSTANTIATE(short); diff --git a/src/backend/cuda/match_template.cpp b/src/backend/cuda/match_template.cpp index d82137bb5c..63b50435b7 100644 --- a/src/backend/cuda/match_template.cpp +++ b/src/backend/cuda/match_template.cpp @@ -38,6 +38,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/cuda/math.hpp b/src/backend/cuda/math.hpp index f7b11347cc..28574ac7e2 100644 --- a/src/backend/cuda/math.hpp +++ b/src/backend/cuda/math.hpp @@ -18,6 +18,7 @@ #endif //__CUDACC__ #include +#include #include #endif //__CUDACC_RTC__ @@ -191,6 +192,14 @@ inline __device__ uintl maxval() { return 1ULL << (8 * sizeof(uintl) - 1); } template<> +inline __device__ schar maxval() { + return 0x7f; +} +template<> +inline __device__ schar minval() { + return 0x80; +} +template<> inline __device__ char maxval() { return 0x7f; } diff --git a/src/backend/cuda/max.cu b/src/backend/cuda/max.cu index 03f712b303..9fe7b92409 100644 --- a/src/backend/cuda/max.cu +++ b/src/backend/cuda/max.cu @@ -24,6 +24,7 @@ INSTANTIATE(af_max_t, uint, uint) INSTANTIATE(af_max_t, intl, intl) INSTANTIATE(af_max_t, uintl, uintl) INSTANTIATE(af_max_t, char, char) +INSTANTIATE(af_max_t, schar, schar) INSTANTIATE(af_max_t, uchar, uchar) INSTANTIATE(af_max_t, short, short) INSTANTIATE(af_max_t, ushort, ushort) diff --git a/src/backend/cuda/mean.cu b/src/backend/cuda/mean.cu index 9b1eea74e9..b4dab3b866 100644 --- a/src/backend/cuda/mean.cu +++ b/src/backend/cuda/mean.cu @@ -63,6 +63,7 @@ INSTANTIATE(uintl, double, double); INSTANTIATE(short, float, float); INSTANTIATE(ushort, float, float); INSTANTIATE(uchar, float, float); +INSTANTIATE(schar, float, float); INSTANTIATE(char, float, float); INSTANTIATE(cfloat, float, cfloat); INSTANTIATE(cdouble, double, cdouble); diff --git a/src/backend/cuda/meanshift.cpp b/src/backend/cuda/meanshift.cpp index d72d1aa041..83d12cb3ef 100644 --- a/src/backend/cuda/meanshift.cpp +++ b/src/backend/cuda/meanshift.cpp @@ -38,6 +38,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/medfilt.cpp b/src/backend/cuda/medfilt.cpp index c80c95c21f..cca97dd644 100644 --- a/src/backend/cuda/medfilt.cpp +++ b/src/backend/cuda/medfilt.cpp @@ -58,6 +58,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/memory.cpp b/src/backend/cuda/memory.cpp index dafbef1ce8..616547d6af 100644 --- a/src/backend/cuda/memory.cpp +++ b/src/backend/cuda/memory.cpp @@ -117,6 +117,7 @@ INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/cuda/min.cu b/src/backend/cuda/min.cu index 72a3f1beef..b0fad5733c 100644 --- a/src/backend/cuda/min.cu +++ b/src/backend/cuda/min.cu @@ -24,6 +24,7 @@ INSTANTIATE(af_min_t, uint, uint) INSTANTIATE(af_min_t, intl, intl) INSTANTIATE(af_min_t, uintl, uintl) INSTANTIATE(af_min_t, char, char) +INSTANTIATE(af_min_t, schar, schar) INSTANTIATE(af_min_t, uchar, uchar) INSTANTIATE(af_min_t, short, short) INSTANTIATE(af_min_t, ushort, ushort) diff --git a/src/backend/cuda/moments.cpp b/src/backend/cuda/moments.cpp index 34c8cf753f..fa37b033e1 100644 --- a/src/backend/cuda/moments.cpp +++ b/src/backend/cuda/moments.cpp @@ -51,6 +51,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/cuda/morph.cpp b/src/backend/cuda/morph.cpp index a49fd5a40e..f09f20bded 100644 --- a/src/backend/cuda/morph.cpp +++ b/src/backend/cuda/morph.cpp @@ -53,6 +53,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/nearest_neighbour.cu b/src/backend/cuda/nearest_neighbour.cu index ca6a11a1c6..dc10695f8a 100644 --- a/src/backend/cuda/nearest_neighbour.cu +++ b/src/backend/cuda/nearest_neighbour.cu @@ -67,6 +67,7 @@ INSTANTIATE(int, int) INSTANTIATE(uint, uint) INSTANTIATE(intl, intl) INSTANTIATE(uintl, uintl) +INSTANTIATE(schar, int) INSTANTIATE(uchar, uint) INSTANTIATE(short, int) INSTANTIATE(ushort, uint) diff --git a/src/backend/cuda/pad_array_borders.cpp b/src/backend/cuda/pad_array_borders.cpp index bf41b5f2e7..af563733d2 100644 --- a/src/backend/cuda/pad_array_borders.cpp +++ b/src/backend/cuda/pad_array_borders.cpp @@ -48,6 +48,7 @@ INSTANTIATE_PAD_ARRAY_BORDERS(int) INSTANTIATE_PAD_ARRAY_BORDERS(uint) INSTANTIATE_PAD_ARRAY_BORDERS(intl) INSTANTIATE_PAD_ARRAY_BORDERS(uintl) +INSTANTIATE_PAD_ARRAY_BORDERS(schar) INSTANTIATE_PAD_ARRAY_BORDERS(uchar) INSTANTIATE_PAD_ARRAY_BORDERS(char) INSTANTIATE_PAD_ARRAY_BORDERS(ushort) diff --git a/src/backend/cuda/platform.cpp b/src/backend/cuda/platform.cpp index 52a22cdbaf..0de2451c4d 100644 --- a/src/backend/cuda/platform.cpp +++ b/src/backend/cuda/platform.cpp @@ -49,6 +49,7 @@ #include #include #include +#include using std::call_once; using std::make_unique; @@ -123,8 +124,10 @@ unique_handle *nnManager(const int deviceId) { if (!(*handle)) { getLogger()->error("Error initalizing cuDNN"); } }); if (error) { - string error_msg = fmt::format("Error initializing cuDNN({}): {}.", - error, errorString(error)); + string error_msg = fmt::format( + "Error initializing cuDNN({}): {}.", + static_cast::type>(error), + errorString(error)); AF_ERROR(error_msg, AF_ERR_RUNTIME); } CUDNN_CHECK(getCudnnPlugin().cudnnSetStream(cudnnHandles[deviceId], diff --git a/src/backend/cuda/plot.cpp b/src/backend/cuda/plot.cpp index e012377305..e69b149790 100644 --- a/src/backend/cuda/plot.cpp +++ b/src/backend/cuda/plot.cpp @@ -70,6 +70,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace cuda diff --git a/src/backend/cuda/product.cu b/src/backend/cuda/product.cu index c4fff43b93..fb26c95562 100644 --- a/src/backend/cuda/product.cu +++ b/src/backend/cuda/product.cu @@ -24,6 +24,7 @@ INSTANTIATE(af_mul_t, uint, uint) INSTANTIATE(af_mul_t, intl, intl) INSTANTIATE(af_mul_t, uintl, uintl) INSTANTIATE(af_mul_t, char, int) +INSTANTIATE(af_mul_t, schar, int) INSTANTIATE(af_mul_t, uchar, uint) INSTANTIATE(af_mul_t, short, int) INSTANTIATE(af_mul_t, ushort, uint) diff --git a/src/backend/cuda/qr.cpp b/src/backend/cuda/qr.cpp index c28a41523f..f388944127 100644 --- a/src/backend/cuda/qr.cpp +++ b/src/backend/cuda/qr.cpp @@ -67,6 +67,16 @@ struct mqr_func_def_t { int, T *, int, int *); }; +template +struct mqr_buf_func_def_t { + using mqr_buf_func_def = cusolverStatus_t (*)(cusolverDnHandle_t, + cublasSideMode_t, + cublasOperation_t, int, int, int, + const T *, int, const T *, T *, + int, int *); +}; + + #define QR_FUNC_DEF(FUNC) \ template \ typename FUNC##_func_def_t::FUNC##_func_def FUNC##_func(); \ @@ -94,15 +104,25 @@ QR_FUNC(geqrf, double, D) QR_FUNC(geqrf, cfloat, C) QR_FUNC(geqrf, cdouble, Z) -#define MQR_FUNC_DEF(FUNC) \ - template \ - typename FUNC##_func_def_t::FUNC##_func_def FUNC##_func(); +#define MQR_FUNC_DEF(FUNC) \ + template \ + typename FUNC##_func_def_t::FUNC##_func_def FUNC##_func(); \ + \ + template \ + typename FUNC##_buf_func_def_t::FUNC##_buf_func_def FUNC##_buf_func(); #define MQR_FUNC(FUNC, TYPE, PREFIX) \ template<> \ typename FUNC##_func_def_t::FUNC##_func_def FUNC##_func() { \ return (FUNC##_func_def_t::FUNC##_func_def) & \ cusolverDn##PREFIX; \ + } \ + \ + template<> \ + typename FUNC##_buf_func_def_t::FUNC##_buf_func_def \ + FUNC##_buf_func() { \ + return (FUNC##_buf_func_def_t::FUNC##_buf_func_def) & \ + cusolverDn##PREFIX##_bufferSize; \ } MQR_FUNC_DEF(mqr) @@ -143,6 +163,13 @@ void qr(Array &q, Array &r, Array &t, const Array &in) { dim4 qdims(M, mn); q = identity(qdims); + CUSOLVER_CHECK(mqr_buf_func()( + solverDnHandle(), CUBLAS_SIDE_LEFT, CUBLAS_OP_N, q.dims()[0], + q.dims()[1], min(M, N), in_copy.get(), in_copy.strides()[1], t.get(), + q.get(), q.strides()[1], &lwork)); + + workspace = memAlloc(lwork); + CUSOLVER_CHECK(mqr_func()( solverDnHandle(), CUBLAS_SIDE_LEFT, CUBLAS_OP_N, q.dims()[0], q.dims()[1], min(M, N), in_copy.get(), in_copy.strides()[1], t.get(), diff --git a/src/backend/cuda/random_engine.cu b/src/backend/cuda/random_engine.cu index a63ead0bf8..26cdbdc23b 100644 --- a/src/backend/cuda/random_engine.cu +++ b/src/backend/cuda/random_engine.cu @@ -143,6 +143,7 @@ INSTANTIATE_UNIFORM(uint) INSTANTIATE_UNIFORM(intl) INSTANTIATE_UNIFORM(uintl) INSTANTIATE_UNIFORM(char) +INSTANTIATE_UNIFORM(schar) INSTANTIATE_UNIFORM(uchar) INSTANTIATE_UNIFORM(short) INSTANTIATE_UNIFORM(ushort) diff --git a/src/backend/cuda/range.cpp b/src/backend/cuda/range.cpp index 55a2553649..f821f283f7 100644 --- a/src/backend/cuda/range.cpp +++ b/src/backend/cuda/range.cpp @@ -48,6 +48,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/reorder.cpp b/src/backend/cuda/reorder.cpp index c81fd02f6a..286dcde6ad 100644 --- a/src/backend/cuda/reorder.cpp +++ b/src/backend/cuda/reorder.cpp @@ -43,6 +43,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/cuda/reshape.cpp b/src/backend/cuda/reshape.cpp index 9d6e57549f..329b7883cb 100644 --- a/src/backend/cuda/reshape.cpp +++ b/src/backend/cuda/reshape.cpp @@ -49,6 +49,8 @@ Array reshape(const Array &in, const dim4 &outDims, dim4 const &, short, double); \ template Array reshape( \ Array const &, dim4 const &, ushort, double); \ + template Array reshape(Array const &, \ + dim4 const &, schar, double); \ template Array reshape(Array const &, \ dim4 const &, uchar, double); \ template Array reshape(Array const &, \ @@ -64,6 +66,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) diff --git a/src/backend/cuda/resize.cpp b/src/backend/cuda/resize.cpp index 97dc8a7da8..dec6f09d26 100644 --- a/src/backend/cuda/resize.cpp +++ b/src/backend/cuda/resize.cpp @@ -41,6 +41,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/rotate.cpp b/src/backend/cuda/rotate.cpp index 2f46894aef..7edb0de7a6 100644 --- a/src/backend/cuda/rotate.cpp +++ b/src/backend/cuda/rotate.cpp @@ -36,6 +36,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/scan.cpp b/src/backend/cuda/scan.cpp index 10002cbbad..cf3f2a0b70 100644 --- a/src/backend/cuda/scan.cpp +++ b/src/backend/cuda/scan.cpp @@ -47,6 +47,7 @@ Array scan(const Array& in, const int dim, bool inclusive_scan) { INSTANTIATE_SCAN(ROp, uintl, uintl) \ INSTANTIATE_SCAN(ROp, char, int) \ INSTANTIATE_SCAN(ROp, char, uint) \ + INSTANTIATE_SCAN(ROp, schar, int) \ INSTANTIATE_SCAN(ROp, uchar, uint) \ INSTANTIATE_SCAN(ROp, short, int) \ INSTANTIATE_SCAN(ROp, ushort, uint) diff --git a/src/backend/cuda/select.cpp b/src/backend/cuda/select.cpp index b13df55bfe..0b78263efd 100644 --- a/src/backend/cuda/select.cpp +++ b/src/backend/cuda/select.cpp @@ -127,6 +127,7 @@ INSTANTIATE(uint); INSTANTIATE(intl); INSTANTIATE(uintl); INSTANTIATE(char); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(short); INSTANTIATE(ushort); diff --git a/src/backend/cuda/set.cu b/src/backend/cuda/set.cu index fbbbc28c0a..d558d6e938 100644 --- a/src/backend/cuda/set.cu +++ b/src/backend/cuda/set.cu @@ -122,6 +122,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/shift.cpp b/src/backend/cuda/shift.cpp index 6f88a38472..f073d3c844 100644 --- a/src/backend/cuda/shift.cpp +++ b/src/backend/cuda/shift.cpp @@ -68,6 +68,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/sobel.cpp b/src/backend/cuda/sobel.cpp index 5200f69a45..1861d0c76c 100644 --- a/src/backend/cuda/sobel.cpp +++ b/src/backend/cuda/sobel.cpp @@ -38,6 +38,7 @@ INSTANTIATE(double, double) INSTANTIATE(int, int) INSTANTIATE(uint, int) INSTANTIATE(char, int) +INSTANTIATE(schar, int) INSTANTIATE(uchar, int) INSTANTIATE(short, int) INSTANTIATE(ushort, int) diff --git a/src/backend/cuda/solve.cu b/src/backend/cuda/solve.cu index 884d7735b1..568e44b136 100644 --- a/src/backend/cuda/solve.cu +++ b/src/backend/cuda/solve.cu @@ -164,6 +164,13 @@ struct mqr_solve_func_def_t { const T *, int, const T *, T *, int, T *, int, int *); }; +template +struct mqr_solve_buf_func_def_t { + typedef cusolverStatus_t (*mqr_solve_buf_func_def)( + cusolverDnHandle_t, cublasSideMode_t, cublasOperation_t, int, int, int, + const T *, int, const T *, T *, int, int *); +}; + #define QR_FUNC_DEF(FUNC) \ template \ static typename FUNC##_solve_func_def_t::FUNC##_solve_func_def \ @@ -195,17 +202,28 @@ QR_FUNC(geqrf, double, D) QR_FUNC(geqrf, cfloat, C) QR_FUNC(geqrf, cdouble, Z) -#define MQR_FUNC_DEF(FUNC) \ - template \ - static typename FUNC##_solve_func_def_t::FUNC##_solve_func_def \ - FUNC##_solve_func(); - -#define MQR_FUNC(FUNC, TYPE, PREFIX) \ - template<> \ - typename FUNC##_solve_func_def_t::FUNC##_solve_func_def \ - FUNC##_solve_func() { \ - return (FUNC##_solve_func_def_t::FUNC##_solve_func_def) & \ - cusolverDn##PREFIX; \ +#define MQR_FUNC_DEF(FUNC) \ + template \ + static typename FUNC##_solve_func_def_t::FUNC##_solve_func_def \ + FUNC##_solve_func(); \ + \ + template \ + static typename FUNC##_solve_buf_func_def_t::FUNC##_solve_buf_func_def \ + FUNC##_solve_buf_func(); + +#define MQR_FUNC(FUNC, TYPE, PREFIX) \ + template<> \ + typename FUNC##_solve_func_def_t::FUNC##_solve_func_def \ + FUNC##_solve_func() { \ + return (FUNC##_solve_func_def_t::FUNC##_solve_func_def) & \ + cusolverDn##PREFIX; \ + } \ + \ + template<> \ + typename FUNC##_solve_buf_func_def_t::FUNC##_solve_buf_func_def \ + FUNC##_solve_buf_func() { \ + return (FUNC##_solve_buf_func_def_t::FUNC##_solve_buf_func_def) & \ + cusolverDn##PREFIX##_bufferSize; \ } MQR_FUNC_DEF(mqr) @@ -393,6 +411,13 @@ Array leastSquares(const Array &a, const Array &b) { B.resetDims(dim4(N, K)); // matmul(Q, Bpad) + CUSOLVER_CHECK(mqr_solve_buf_func()( + solverDnHandle(), CUBLAS_SIDE_LEFT, CUBLAS_OP_N, B.dims()[0], + B.dims()[1], A.dims()[0], A.get(), A.strides()[1], t.get(), B.get(), + B.strides()[1], &lwork)); + + workspace = memAlloc(lwork); + CUSOLVER_CHECK(mqr_solve_func()( solverDnHandle(), CUBLAS_SIDE_LEFT, CUBLAS_OP_N, B.dims()[0], B.dims()[1], A.dims()[0], A.get(), A.strides()[1], t.get(), B.get(), @@ -427,10 +452,17 @@ Array leastSquares(const Array &a, const Array &b) { t.get(), workspace.get(), lwork, info.get())); // matmul(Q1, B) + CUSOLVER_CHECK(mqr_solve_buf_func()( + solverDnHandle(), CUBLAS_SIDE_LEFT, trans(), M, K, N, A.get(), + A.strides()[1], t.get(), B.get(), B.strides()[1], &lwork)); + + workspace = memAlloc(lwork); + CUSOLVER_CHECK(mqr_solve_func()( solverDnHandle(), CUBLAS_SIDE_LEFT, trans(), M, K, N, A.get(), A.strides()[1], t.get(), B.get(), B.strides()[1], workspace.get(), lwork, info.get())); + // tri_solve(R1, Bt) A.resetDims(dim4(N, N)); B.resetDims(dim4(N, K)); diff --git a/src/backend/cuda/sort.cu b/src/backend/cuda/sort.cu index 9970ddd8b2..d56899a87d 100644 --- a/src/backend/cuda/sort.cu +++ b/src/backend/cuda/sort.cu @@ -54,6 +54,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/sort_by_key.cu b/src/backend/cuda/sort_by_key.cu index bd19d16240..21d9efc5b2 100644 --- a/src/backend/cuda/sort_by_key.cu +++ b/src/backend/cuda/sort_by_key.cu @@ -67,6 +67,7 @@ void sort_by_key(Array &okey, Array &oval, const Array &ikey, INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, intl) \ INSTANTIATE(Tk, uintl) @@ -78,6 +79,7 @@ INSTANTIATE1(uint) INSTANTIATE1(short) INSTANTIATE1(ushort) INSTANTIATE1(char) +INSTANTIATE1(schar) INSTANTIATE1(uchar) INSTANTIATE1(intl) INSTANTIATE1(uintl) diff --git a/src/backend/cuda/sort_index.cu b/src/backend/cuda/sort_index.cu index 039e77a147..d923f7c6e9 100644 --- a/src/backend/cuda/sort_index.cu +++ b/src/backend/cuda/sort_index.cu @@ -63,6 +63,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/sum.cu b/src/backend/cuda/sum.cu index 44cfec9449..6a52c2c369 100644 --- a/src/backend/cuda/sum.cu +++ b/src/backend/cuda/sum.cu @@ -29,6 +29,8 @@ INSTANTIATE(af_add_t, uintl, uintl) INSTANTIATE(af_add_t, uintl, double) INSTANTIATE(af_add_t, char, int) INSTANTIATE(af_add_t, char, float) +INSTANTIATE(af_add_t, schar, int) +INSTANTIATE(af_add_t, schar, float) INSTANTIATE(af_add_t, uchar, uint) INSTANTIATE(af_add_t, uchar, float) INSTANTIATE(af_add_t, short, int) diff --git a/src/backend/cuda/surface.cpp b/src/backend/cuda/surface.cpp index bef751239b..61f3457036 100644 --- a/src/backend/cuda/surface.cpp +++ b/src/backend/cuda/surface.cpp @@ -71,6 +71,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace cuda diff --git a/src/backend/cuda/susan.cpp b/src/backend/cuda/susan.cpp index 4d0fcc078c..5f1d07d913 100644 --- a/src/backend/cuda/susan.cpp +++ b/src/backend/cuda/susan.cpp @@ -74,6 +74,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/tile.cpp b/src/backend/cuda/tile.cpp index f93982eb43..edd2a7b686 100644 --- a/src/backend/cuda/tile.cpp +++ b/src/backend/cuda/tile.cpp @@ -48,6 +48,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/transform.cpp b/src/backend/cuda/transform.cpp index baba9b1a04..e0d0509c8d 100644 --- a/src/backend/cuda/transform.cpp +++ b/src/backend/cuda/transform.cpp @@ -37,6 +37,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/transpose.cpp b/src/backend/cuda/transpose.cpp index faa4659b68..03d6f3b91d 100644 --- a/src/backend/cuda/transpose.cpp +++ b/src/backend/cuda/transpose.cpp @@ -45,6 +45,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/cuda/transpose_inplace.cpp b/src/backend/cuda/transpose_inplace.cpp index ff89730d47..dcc8c5664b 100644 --- a/src/backend/cuda/transpose_inplace.cpp +++ b/src/backend/cuda/transpose_inplace.cpp @@ -37,6 +37,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/cuda/triangle.cpp b/src/backend/cuda/triangle.cpp index 4ec0a04e6f..c32e984626 100644 --- a/src/backend/cuda/triangle.cpp +++ b/src/backend/cuda/triangle.cpp @@ -48,6 +48,7 @@ INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/types.hpp b/src/backend/cuda/types.hpp index 34815cba66..2230948f3a 100644 --- a/src/backend/cuda/types.hpp +++ b/src/backend/cuda/types.hpp @@ -35,6 +35,7 @@ namespace cuda { using cdouble = cuDoubleComplex; using cfloat = cuFloatComplex; using intl = long long; +using schar = signed char; using uchar = unsigned char; using uint = unsigned int; using uintl = unsigned long long; @@ -82,6 +83,10 @@ inline const char *shortname(bool caps) { return caps ? "J" : "j"; } template<> +inline const char *shortname(bool caps) { + return caps ? "A" : "a"; // TODO +} +template<> inline const char *shortname(bool caps) { return caps ? "V" : "v"; } @@ -120,6 +125,7 @@ SPECIALIZE(double) SPECIALIZE(cfloat) SPECIALIZE(cdouble) SPECIALIZE(char) +SPECIALIZE(signed char) SPECIALIZE(unsigned char) SPECIALIZE(short) SPECIALIZE(unsigned short) diff --git a/src/backend/cuda/unwrap.cpp b/src/backend/cuda/unwrap.cpp index 6eae7d428b..9d96aec1d9 100644 --- a/src/backend/cuda/unwrap.cpp +++ b/src/backend/cuda/unwrap.cpp @@ -55,6 +55,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/cuda/vector_field.cpp b/src/backend/cuda/vector_field.cpp index 2868979772..a0528cddb1 100644 --- a/src/backend/cuda/vector_field.cpp +++ b/src/backend/cuda/vector_field.cpp @@ -105,6 +105,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace cuda diff --git a/src/backend/cuda/where.cpp b/src/backend/cuda/where.cpp index efd488d26e..862b25fa24 100644 --- a/src/backend/cuda/where.cpp +++ b/src/backend/cuda/where.cpp @@ -36,6 +36,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/cuda/wrap.cpp b/src/backend/cuda/wrap.cpp index d8963cacd9..dd7901cc0e 100644 --- a/src/backend/cuda/wrap.cpp +++ b/src/backend/cuda/wrap.cpp @@ -44,6 +44,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/Array.cpp b/src/backend/oneapi/Array.cpp index f2ef09c044..57c8f111ee 100644 --- a/src/backend/oneapi/Array.cpp +++ b/src/backend/oneapi/Array.cpp @@ -500,10 +500,11 @@ template void writeHostDataArray(Array &arr, const T *const data, const size_t bytes) { if (!arr.isOwner()) { arr = copyArray(arr); } + auto arr_get = arr.get(); getQueue() .submit([&](sycl::handler &h) { auto host_acc = - arr.get()->template get_access( + arr_get->template get_access( h, sycl::range(bytes / sizeof(T)), arr.getOffset()); h.copy(data, host_acc); }) @@ -517,10 +518,11 @@ void writeDeviceDataArray(Array &arr, const void *const data, sycl::buffer *dataptr = static_cast *>(const_cast(data)); + auto arr_get = arr.get(); getQueue().submit([&](sycl::handler &h) { auto src_acc = dataptr->template get_access( h, sycl::range(bytes / sizeof(T))); - auto dst_acc = arr.get()->template get_access( + auto dst_acc = arr_get->template get_access( h, sycl::range(bytes / sizeof(T)), arr.getOffset()); h.copy(src_acc, dst_acc); }); @@ -580,6 +582,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/oneapi/CMakeLists.txt b/src/backend/oneapi/CMakeLists.txt index 9bd7e0850a..a41d3fa3b7 100644 --- a/src/backend/oneapi/CMakeLists.txt +++ b/src/backend/oneapi/CMakeLists.txt @@ -271,6 +271,11 @@ function(set_sycl_language) PROPERTIES LINKER_LANGUAGE SYCL) + get_target_property(target_type ${target} TYPE) + if(NOT (${target_type} STREQUAL "INTERFACE_LIBRARY")) + target_compile_options(${target} PRIVATE ${MSVC_RUNTIME}) + endif() + get_target_property(TGT_SOURCES ${target} SOURCES) if(NOT TGT_SOURCES) get_target_property(TGT_SOURCES ${target} INTERFACE_SOURCES) @@ -341,7 +346,11 @@ target_compile_definitions(afoneapi CL_HPP_TARGET_OPENCL_VERSION=300 CL_HPP_MINIMUM_OPENCL_VERSION=110 CL_HPP_ENABLE_EXCEPTIONS + AF_MKL_INTERFACE_SIZE=${MKL_INTERFACE_INTEGER_SIZE} ) +if(MKL_INTERFACE_INTEGER_SIZE EQUAL 8) + target_compile_definitions(afoneapi PRIVATE MKL_ILP64) +endif() cmake_host_system_information(RESULT NumberOfThreads QUERY NUMBER_OF_LOGICAL_CORES) @@ -355,11 +364,12 @@ target_link_libraries(afoneapi OpenCL::OpenCL OpenCL::cl2hpp -fno-sycl-id-queries-fit-in-int - $<$:-fsycl-link-huge-device-code> + $<$:-flink-huge-device-code> $<$:-fvisibility-inlines-hidden> $<$:-fno-sycl-rdc> + $<$:-Wl,--build-id> -fsycl-max-parallel-link-jobs=${NumberOfThreads} - MKL::MKL_DPCPP + MKL::MKL_SYCL ) set_sycl_language(afcommon_interface oneapi_sort_by_key diff --git a/src/backend/oneapi/all.cpp b/src/backend/oneapi/all.cpp index ad09e4aff1..e4e86232d2 100644 --- a/src/backend/oneapi/all.cpp +++ b/src/backend/oneapi/all.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_and_t, uint, char) INSTANTIATE(af_and_t, intl, char) INSTANTIATE(af_and_t, uintl, char) INSTANTIATE(af_and_t, char, char) +INSTANTIATE(af_and_t, schar, char) INSTANTIATE(af_and_t, uchar, char) INSTANTIATE(af_and_t, short, char) INSTANTIATE(af_and_t, ushort, char) diff --git a/src/backend/oneapi/any.cpp b/src/backend/oneapi/any.cpp index bdf600e9a9..82e242a989 100644 --- a/src/backend/oneapi/any.cpp +++ b/src/backend/oneapi/any.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_or_t, uint, char) INSTANTIATE(af_or_t, intl, char) INSTANTIATE(af_or_t, uintl, char) INSTANTIATE(af_or_t, char, char) +INSTANTIATE(af_or_t, schar, char) INSTANTIATE(af_or_t, uchar, char) INSTANTIATE(af_or_t, short, char) INSTANTIATE(af_or_t, ushort, char) diff --git a/src/backend/oneapi/assign.cpp b/src/backend/oneapi/assign.cpp index def9378d2d..de436495db 100644 --- a/src/backend/oneapi/assign.cpp +++ b/src/backend/oneapi/assign.cpp @@ -80,6 +80,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/bilateral.cpp b/src/backend/oneapi/bilateral.cpp index d7d5dd33b9..6520cf9ffa 100644 --- a/src/backend/oneapi/bilateral.cpp +++ b/src/backend/oneapi/bilateral.cpp @@ -35,6 +35,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/oneapi/blas.cpp b/src/backend/oneapi/blas.cpp index 37495957e9..93ae6559a4 100644 --- a/src/backend/oneapi/blas.cpp +++ b/src/backend/oneapi/blas.cpp @@ -97,9 +97,10 @@ bool isStrideMonotonic(const af::dim4 &dim) { return (dim[0] <= dim[1]) && (dim[1] <= dim[2]) && (dim[2] <= dim[3]); } -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta) { +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta) { const auto lOpts = toBlasTranspose(optLhs); const auto rOpts = toBlasTranspose(optRhs); @@ -120,25 +121,25 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, if (oDims.ndims() <= 2) { // if non-batched if (rhs.dims()[bColDim] == 1) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { // currently no half support for gemv, use gemm instead - gemmDispatch(getQueue(), lOpts, rOpts, M, N, K, alpha, lhs, - lStrides[1], rhs, rStrides[1], beta, out, - oStrides[1]); + gemmDispatch(getQueue(), lOpts, rOpts, M, N, K, alpha, lhs, + lStrides[1], rhs, rStrides[1], beta, out, + oStrides[1]); } else { dim_t incr = (optRhs == AF_MAT_NONE) ? rStrides[0] : rStrides[1]; - gemvDispatch(getQueue(), lOpts, rOpts, lDims[0], lDims[1], - alpha, lhs, lStrides[1], rhs, incr, beta, out, - oStrides[0]); + gemvDispatch(getQueue(), lOpts, rOpts, lDims[0], lDims[1], + alpha, lhs, lStrides[1], rhs, incr, beta, out, + oStrides[0]); } } else { - gemmDispatch(getQueue(), lOpts, rOpts, M, N, K, alpha, lhs, - lStrides[1], rhs, rStrides[1], beta, out, - oStrides[1]); + gemmDispatch(getQueue(), lOpts, rOpts, M, N, K, alpha, lhs, + lStrides[1], rhs, rStrides[1], beta, out, + oStrides[1]); } } else { // if batched - using Dt = arrayfire::oneapi::data_t; + using Dt = arrayfire::oneapi::data_t; int64_t batchSize = static_cast(oDims[2] * oDims[3]); @@ -206,6 +207,14 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, ONEAPI_DEBUG_FINISH(getQueue()); } +template<> +void gemm(Array &out, af_mat_prop optLhs, + af_mat_prop optRhs, const float *alpha, + const Array &lhs, const Array &rhs, + const float *beta) { + TYPE_ERROR(3, af_dtype::s8); +} + template Array dot(const Array &lhs, const Array &rhs, af_mat_prop optLhs, af_mat_prop optRhs) { diff --git a/src/backend/oneapi/blas.hpp b/src/backend/oneapi/blas.hpp index 9e2381c336..af65f56d12 100644 --- a/src/backend/oneapi/blas.hpp +++ b/src/backend/oneapi/blas.hpp @@ -20,9 +20,10 @@ namespace oneapi { void initBlas(); void deInitBlas(); -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta); +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta); template Array matmul(const Array &lhs, const Array &rhs, af_mat_prop optLhs, diff --git a/src/backend/oneapi/cast.hpp b/src/backend/oneapi/cast.hpp index c9b015c4f2..7d4e2be76f 100644 --- a/src/backend/oneapi/cast.hpp +++ b/src/backend/oneapi/cast.hpp @@ -34,6 +34,7 @@ struct CastOp { CAST_FN(int) CAST_FN(uint) +CAST_FN(schar) CAST_FN(uchar) CAST_FN(float) CAST_FN(double) diff --git a/src/backend/oneapi/convolve.cpp b/src/backend/oneapi/convolve.cpp index d2cc41c588..0e443d7b77 100644 --- a/src/backend/oneapi/convolve.cpp +++ b/src/backend/oneapi/convolve.cpp @@ -98,6 +98,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/oneapi/convolve_separable.cpp b/src/backend/oneapi/convolve_separable.cpp index fdf9fc952f..ddf5c27a7e 100644 --- a/src/backend/oneapi/convolve_separable.cpp +++ b/src/backend/oneapi/convolve_separable.cpp @@ -65,6 +65,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(short, float) diff --git a/src/backend/oneapi/copy.cpp b/src/backend/oneapi/copy.cpp index f99f79854e..a89023261e 100644 --- a/src/backend/oneapi/copy.cpp +++ b/src/backend/oneapi/copy.cpp @@ -155,6 +155,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) @@ -184,6 +185,8 @@ INSTANTIATE(half) Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ + template void copyArray(Array & dst, \ + Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ template void copyArray(Array & dst, \ @@ -197,6 +200,7 @@ INSTANTIATE_COPY_ARRAY(int) INSTANTIATE_COPY_ARRAY(uint) INSTANTIATE_COPY_ARRAY(intl) INSTANTIATE_COPY_ARRAY(uintl) +INSTANTIATE_COPY_ARRAY(schar) INSTANTIATE_COPY_ARRAY(uchar) INSTANTIATE_COPY_ARRAY(char) INSTANTIATE_COPY_ARRAY(short) @@ -216,10 +220,11 @@ template T getScalar(const Array &in) { T retVal{}; + auto in_get = in.get(); getQueue() .submit([&](sycl::handler &h) { auto acc_in = - in.get()->template get_access( + in_get->template get_access( h, sycl::range{1}, sycl::id{static_cast(in.getOffset())}); h.copy(acc_in, &retVal); @@ -237,6 +242,7 @@ INSTANTIATE_GETSCALAR(cfloat) INSTANTIATE_GETSCALAR(cdouble) INSTANTIATE_GETSCALAR(int) INSTANTIATE_GETSCALAR(uint) +INSTANTIATE_GETSCALAR(schar) INSTANTIATE_GETSCALAR(uchar) INSTANTIATE_GETSCALAR(char) INSTANTIATE_GETSCALAR(intl) diff --git a/src/backend/oneapi/count.cpp b/src/backend/oneapi/count.cpp index f8ef354169..4ed59eb3b9 100644 --- a/src/backend/oneapi/count.cpp +++ b/src/backend/oneapi/count.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_notzero_t, uint, uint) INSTANTIATE(af_notzero_t, intl, uint) INSTANTIATE(af_notzero_t, uintl, uint) INSTANTIATE(af_notzero_t, char, uint) +INSTANTIATE(af_notzero_t, schar, uint) INSTANTIATE(af_notzero_t, uchar, uint) INSTANTIATE(af_notzero_t, short, uint) INSTANTIATE(af_notzero_t, ushort, uint) diff --git a/src/backend/oneapi/diagonal.cpp b/src/backend/oneapi/diagonal.cpp index a18d024585..900f53ba3c 100644 --- a/src/backend/oneapi/diagonal.cpp +++ b/src/backend/oneapi/diagonal.cpp @@ -54,6 +54,7 @@ INSTANTIATE_DIAGONAL(uint) INSTANTIATE_DIAGONAL(intl) INSTANTIATE_DIAGONAL(uintl) INSTANTIATE_DIAGONAL(char) +INSTANTIATE_DIAGONAL(schar) INSTANTIATE_DIAGONAL(uchar) INSTANTIATE_DIAGONAL(short) INSTANTIATE_DIAGONAL(ushort) diff --git a/src/backend/oneapi/diff.cpp b/src/backend/oneapi/diff.cpp index a3c37f6a4a..01cd18e37e 100644 --- a/src/backend/oneapi/diff.cpp +++ b/src/backend/oneapi/diff.cpp @@ -50,6 +50,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/oneapi/err_oneapi.hpp b/src/backend/oneapi/err_oneapi.hpp index fad7d449c0..4f187b6273 100644 --- a/src/backend/oneapi/err_oneapi.hpp +++ b/src/backend/oneapi/err_oneapi.hpp @@ -13,8 +13,8 @@ #define ONEAPI_NOT_SUPPORTED(message) \ do { \ - throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, message, \ - boost::stacktrace::stacktrace()); \ + throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, "oneAPI",\ + message, boost::stacktrace::stacktrace()); \ } while (0) #define CL_CHECK(call) \ diff --git a/src/backend/oneapi/exampleFunction.cpp b/src/backend/oneapi/exampleFunction.cpp index 6159d9d1d4..9a006febff 100644 --- a/src/backend/oneapi/exampleFunction.cpp +++ b/src/backend/oneapi/exampleFunction.cpp @@ -59,6 +59,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(cfloat) diff --git a/src/backend/oneapi/fast.cpp b/src/backend/oneapi/fast.cpp index cb9ae28d4c..a5b0934f97 100644 --- a/src/backend/oneapi/fast.cpp +++ b/src/backend/oneapi/fast.cpp @@ -38,6 +38,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/fftconvolve.cpp b/src/backend/oneapi/fftconvolve.cpp index de96d94c99..85718f4f4f 100644 --- a/src/backend/oneapi/fftconvolve.cpp +++ b/src/backend/oneapi/fftconvolve.cpp @@ -148,6 +148,7 @@ INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(uint) INSTANTIATE(int) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(uintl) diff --git a/src/backend/oneapi/hist_graphics.cpp b/src/backend/oneapi/hist_graphics.cpp index 3b280592b1..e016337a54 100644 --- a/src/backend/oneapi/hist_graphics.cpp +++ b/src/backend/oneapi/hist_graphics.cpp @@ -28,6 +28,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace oneapi diff --git a/src/backend/oneapi/histogram.cpp b/src/backend/oneapi/histogram.cpp index 4dfece0640..872431f14c 100644 --- a/src/backend/oneapi/histogram.cpp +++ b/src/backend/oneapi/histogram.cpp @@ -41,6 +41,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/identity.cpp b/src/backend/oneapi/identity.cpp index 5a838a4cf0..68a592ab88 100644 --- a/src/backend/oneapi/identity.cpp +++ b/src/backend/oneapi/identity.cpp @@ -37,6 +37,7 @@ INSTANTIATE_IDENTITY(uint) INSTANTIATE_IDENTITY(intl) INSTANTIATE_IDENTITY(uintl) INSTANTIATE_IDENTITY(char) +INSTANTIATE_IDENTITY(schar) INSTANTIATE_IDENTITY(uchar) INSTANTIATE_IDENTITY(short) INSTANTIATE_IDENTITY(ushort) diff --git a/src/backend/oneapi/image.cpp b/src/backend/oneapi/image.cpp index 723c29fb8b..7aa8b4b667 100644 --- a/src/backend/oneapi/image.cpp +++ b/src/backend/oneapi/image.cpp @@ -29,6 +29,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/index.cpp b/src/backend/oneapi/index.cpp index bec65902d8..af204b0820 100644 --- a/src/backend/oneapi/index.cpp +++ b/src/backend/oneapi/index.cpp @@ -44,6 +44,16 @@ Array index(const Array& in, const af_index_t idxrs[]) { p.isSeq[i] = idxrs[i].isSeq; p.offs[i] = iOffs[i]; p.strds[i] = iStrds[i]; + p.steps[i] = 0; + if (idxrs[i].isSeq) { + af_seq seq = idxrs[i].idx.seq; + // The step for af_span used in the kernel must be 1 + if (seq.begin == af_span.begin && seq.end == af_span.end && + seq.step == af_span.step) + p.steps[i] = 1; + else + p.steps[i] = seq.step; + } } std::vector> idxArrs(4, createEmptyArray(dim4(1))); @@ -73,6 +83,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/iota.cpp b/src/backend/oneapi/iota.cpp index 6d511df23f..e775f0dde6 100644 --- a/src/backend/oneapi/iota.cpp +++ b/src/backend/oneapi/iota.cpp @@ -38,6 +38,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/ireduce.cpp b/src/backend/oneapi/ireduce.cpp index c7b4d263ab..c4bfc7604f 100644 --- a/src/backend/oneapi/ireduce.cpp +++ b/src/backend/oneapi/ireduce.cpp @@ -58,6 +58,7 @@ INSTANTIATE(af_min_t, uint) INSTANTIATE(af_min_t, intl) INSTANTIATE(af_min_t, uintl) INSTANTIATE(af_min_t, char) +INSTANTIATE(af_min_t, schar) INSTANTIATE(af_min_t, uchar) INSTANTIATE(af_min_t, short) INSTANTIATE(af_min_t, ushort) @@ -73,6 +74,7 @@ INSTANTIATE(af_max_t, uint) INSTANTIATE(af_max_t, intl) INSTANTIATE(af_max_t, uintl) INSTANTIATE(af_max_t, char) +INSTANTIATE(af_max_t, schar) INSTANTIATE(af_max_t, uchar) INSTANTIATE(af_max_t, short) INSTANTIATE(af_max_t, ushort) diff --git a/src/backend/oneapi/jit.cpp b/src/backend/oneapi/jit.cpp index ecd5bc04b9..2bd34a5dc4 100644 --- a/src/backend/oneapi/jit.cpp +++ b/src/backend/oneapi/jit.cpp @@ -478,8 +478,8 @@ void evalNodes(vector>& outputs, const vector& output_nodes) { full_nodes.clear(); for (Node_ptr& node : node_clones) { full_nodes.push_back(node.get()); } - const string funcName{getFuncName(output_nodes, full_nodes, full_ids, - is_linear, false, false, false, + const string funcName{getFuncName(output_nodes, output_ids, full_nodes, + full_ids, is_linear, false, false, false, outputs[0].info.dims[2] > 1)}; getQueue().submit([&](sycl::handler& h) { @@ -627,6 +627,7 @@ template void evalNodes(Param& out, Node* node); template void evalNodes(Param& out, Node* node); template void evalNodes(Param& out, Node* node); template void evalNodes(Param& out, Node* node); +template void evalNodes(Param& out, Node* node); template void evalNodes(Param& out, Node* node); template void evalNodes(Param& out, Node* node); template void evalNodes(Param& out, Node* node); @@ -648,6 +649,8 @@ template void evalNodes(vector>& out, const vector& node); template void evalNodes(vector>& out, const vector& node); +template void evalNodes(vector>& out, + const vector& node); template void evalNodes(vector>& out, const vector& node); template void evalNodes(vector>& out, diff --git a/src/backend/oneapi/join.cpp b/src/backend/oneapi/join.cpp index 37c7c14fc9..a64e6edb9d 100644 --- a/src/backend/oneapi/join.cpp +++ b/src/backend/oneapi/join.cpp @@ -94,15 +94,17 @@ Array join(const int jdim, const Array &first, const Array &second) { if (first.isReady()) { if (1LL + jdim >= first.ndims() && first.isLinear()) { // first & out are linear + auto first_array = first.get(); + auto out_array = out.get(); getQueue().submit([&](sycl::handler &h) { sycl::range sz(first.elements()); sycl::id src_offset(first.getOffset()); sycl::accessor offset_acc_src = - first.get()->template get_access( + first_array->template get_access( h, sz, src_offset); sycl::id dst_offset(0); sycl::accessor offset_acc_dst = - out.get()->template get_access( + out_array->template get_access( h, sz, dst_offset); h.copy(offset_acc_src, offset_acc_dst); }); @@ -125,16 +127,18 @@ Array join(const int jdim, const Array &first, const Array &second) { if (second.isReady()) { if (1LL + jdim >= second.ndims() && second.isLinear()) { // second & out are linear + auto second_array = second.get(); + auto out_array = out.get(); getQueue().submit([&](sycl::handler &h) { sycl::range sz(second.elements()); sycl::id src_offset(second.getOffset()); sycl::accessor offset_acc_src = - second.get()->template get_access( + second_array->template get_access( h, sz, src_offset); sycl::id dst_offset(fdims.dims[jdim] * out.strides().dims[jdim]); sycl::accessor offset_acc_dst = - out.get()->template get_access( + out_array->template get_access( h, sz, dst_offset); h.copy(offset_acc_src, offset_acc_dst); }); @@ -216,11 +220,12 @@ void join(Array &out, const int jdim, const vector> &inputs) { for (const Array *in : s.ins) { if (in->isReady()) { if (1LL + jdim >= in->ndims() && in->isLinear()) { + auto in_array = in->get(); getQueue().submit([&](sycl::handler &h) { sycl::range sz(in->elements()); sycl::id src_offset(in->getOffset()); sycl::accessor offset_acc_src = - in->get() + in_array ->template get_access< sycl::access_mode::read>(h, sz, src_offset); @@ -267,6 +272,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) @@ -287,6 +293,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) diff --git a/src/backend/oneapi/kernel/assign_kernel_param.hpp b/src/backend/oneapi/kernel/assign_kernel_param.hpp index e2539ed2b3..e2eec56d18 100644 --- a/src/backend/oneapi/kernel/assign_kernel_param.hpp +++ b/src/backend/oneapi/kernel/assign_kernel_param.hpp @@ -19,6 +19,7 @@ namespace oneapi { typedef struct { int offs[4]; int strds[4]; + int steps[4]; bool isSeq[4]; std::array, diff --git a/src/backend/oneapi/kernel/convolve1.hpp b/src/backend/oneapi/kernel/convolve1.hpp index e156308b34..41c6facae6 100644 --- a/src/backend/oneapi/kernel/convolve1.hpp +++ b/src/backend/oneapi/kernel/convolve1.hpp @@ -174,6 +174,7 @@ INSTANTIATE_CONV1(double, double) INSTANTIATE_CONV1(float, float) INSTANTIATE_CONV1(uint, float) INSTANTIATE_CONV1(int, float) +INSTANTIATE_CONV1(schar, float) INSTANTIATE_CONV1(uchar, float) INSTANTIATE_CONV1(char, float) INSTANTIATE_CONV1(ushort, float) diff --git a/src/backend/oneapi/kernel/convolve2.hpp b/src/backend/oneapi/kernel/convolve2.hpp index b216e50917..45bfa6c108 100644 --- a/src/backend/oneapi/kernel/convolve2.hpp +++ b/src/backend/oneapi/kernel/convolve2.hpp @@ -195,4 +195,5 @@ INSTANTIATE_CONV2(intl, float) INSTANTIATE_CONV2(ushort, float) INSTANTIATE_CONV2(uint, float) INSTANTIATE_CONV2(uintl, float) +INSTANTIATE_CONV2(schar, float) INSTANTIATE_CONV2(uchar, float) diff --git a/src/backend/oneapi/kernel/convolve3.hpp b/src/backend/oneapi/kernel/convolve3.hpp index 3ac4a50aa2..bdfcc4eb24 100644 --- a/src/backend/oneapi/kernel/convolve3.hpp +++ b/src/backend/oneapi/kernel/convolve3.hpp @@ -193,6 +193,7 @@ INSTANTIATE_CONV3(double, double) INSTANTIATE_CONV3(float, float) INSTANTIATE_CONV3(uint, float) INSTANTIATE_CONV3(int, float) +INSTANTIATE_CONV3(schar, float) INSTANTIATE_CONV3(uchar, float) INSTANTIATE_CONV3(char, float) INSTANTIATE_CONV3(ushort, float) diff --git a/src/backend/oneapi/kernel/convolve_separable.cpp b/src/backend/oneapi/kernel/convolve_separable.cpp index 45a86efb7a..0f3dfacb30 100644 --- a/src/backend/oneapi/kernel/convolve_separable.cpp +++ b/src/backend/oneapi/kernel/convolve_separable.cpp @@ -200,6 +200,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/oneapi/kernel/index.hpp b/src/backend/oneapi/kernel/index.hpp index 857b299aef..e86c0bd808 100644 --- a/src/backend/oneapi/kernel/index.hpp +++ b/src/backend/oneapi/kernel/index.hpp @@ -88,13 +88,17 @@ class indexKernel { if (gx < odims0 && gy < odims1 && gz < odims2 && gw < odims3) { // calculate pointer offsets for input int i = p.strds[0] * - trimIndex(s0 ? gx + p.offs[0] : ptr0[gx], inp.dims[0]); + trimIndex(s0 ? gx * p.steps[0] + p.offs[0] : ptr0[gx], + inp.dims[0]); int j = p.strds[1] * - trimIndex(s1 ? gy + p.offs[1] : ptr1[gy], inp.dims[1]); + trimIndex(s1 ? gy * p.steps[1] + p.offs[1] : ptr1[gy], + inp.dims[1]); int k = p.strds[2] * - trimIndex(s2 ? gz + p.offs[2] : ptr2[gz], inp.dims[2]); + trimIndex(s2 ? gz * p.steps[2] + p.offs[2] : ptr2[gz], + inp.dims[2]); int l = p.strds[3] * - trimIndex(s3 ? gw + p.offs[3] : ptr3[gw], inp.dims[3]); + trimIndex(s3 ? gw * p.steps[3] + p.offs[3] : ptr3[gw], + inp.dims[3]); // offset input and output pointers const T* src = (const T*)in.get_pointer() + (i + j + k + l); T* dst = (T*)out.get_pointer() + @@ -133,11 +137,14 @@ void index(Param out, Param in, IndexKernelParam& p, blocks[0] *= threads[0]; sycl::nd_range<3> marange(blocks, threads); + sycl::buffer *idxArrs_get[4]; + for (dim_t x = 0; x < 4; ++x) + idxArrs_get[x] = idxArrs[x].get(); getQueue().submit([&](sycl::handler& h) { auto pp = p; for (dim_t x = 0; x < 4; ++x) { pp.ptr[x] = - idxArrs[x].get()->get_access(h); + idxArrs_get[x]->get_access(h); } h.parallel_for( diff --git a/src/backend/oneapi/kernel/ireduce.hpp b/src/backend/oneapi/kernel/ireduce.hpp index 5f8f96bfc8..9ba79ed61b 100644 --- a/src/backend/oneapi/kernel/ireduce.hpp +++ b/src/backend/oneapi/kernel/ireduce.hpp @@ -258,7 +258,7 @@ void ireduce_dim_launcher(Param out, Param oloc, Param in, case 4: h.parallel_for( sycl::nd_range<2>(global, local), - ireduceDimKernelSMEM( + ireduceDimKernelSMEM( out_acc, out.info, oloc_acc, oloc.info, in_acc, in.info, iloc_acc, iloc.info, groups_dim[0], groups_dim[1], groups_dim[dim], rlenValid, rlen_acc, rlen.info, @@ -267,7 +267,7 @@ void ireduce_dim_launcher(Param out, Param oloc, Param in, case 2: h.parallel_for( sycl::nd_range<2>(global, local), - ireduceDimKernelSMEM( + ireduceDimKernelSMEM( out_acc, out.info, oloc_acc, oloc.info, in_acc, in.info, iloc_acc, iloc.info, groups_dim[0], groups_dim[1], groups_dim[dim], rlenValid, rlen_acc, rlen.info, @@ -276,7 +276,7 @@ void ireduce_dim_launcher(Param out, Param oloc, Param in, case 1: h.parallel_for( sycl::nd_range<2>(global, local), - ireduceDimKernelSMEM( + ireduceDimKernelSMEM( out_acc, out.info, oloc_acc, oloc.info, in_acc, in.info, iloc_acc, iloc.info, groups_dim[0], groups_dim[1], groups_dim[dim], rlenValid, rlen_acc, rlen.info, diff --git a/src/backend/oneapi/kernel/mean.hpp b/src/backend/oneapi/kernel/mean.hpp index 695fb7b375..4c8533b1ec 100644 --- a/src/backend/oneapi/kernel/mean.hpp +++ b/src/backend/oneapi/kernel/mean.hpp @@ -609,12 +609,14 @@ T mean_all_weighted(Param in, Param iwt) { blocks_y, threads_x); compute_t val; + auto tmpOut_get = tmpOut.get(); + auto tmpWt_get = tmpWt.get(); getQueue() .submit([&](sycl::handler &h) { auto acc_in = - tmpOut.get()->template get_host_access(h, sycl::read_only); + tmpOut_get->get_host_access(h, sycl::read_only); auto acc_wt = - tmpWt.get()->template get_host_access(h, sycl::read_only); + tmpWt_get->get_host_access(h, sycl::read_only); h.host_task([acc_in, acc_wt, tmp_elements, &val] { val = static_cast>(acc_in[0]); @@ -633,9 +635,9 @@ T mean_all_weighted(Param in, Param iwt) { compute_t val; getQueue() .submit([&](sycl::handler &h) { - auto acc_in = in.data->template get_host_access( + auto acc_in = in.data->get_host_access( h, sycl::range{in_elements}, sycl::read_only); - auto acc_wt = iwt.data->template get_host_access( + auto acc_wt = iwt.data->get_host_access( h, sycl::range{in_elements}, sycl::read_only); h.host_task([acc_in, acc_wt, in_elements, &val]() { @@ -693,12 +695,14 @@ To mean_all(Param in) { uintl tmp_elements = tmpOut.elements(); compute_t val; + auto tmpOut_get = tmpOut.get(); + auto tmpCt_get = tmpCt.get(); getQueue() .submit([&](sycl::handler &h) { auto out = - tmpOut.get()->template get_host_access(h, sycl::read_only); + tmpOut_get->get_host_access(h, sycl::read_only); auto ct = - tmpCt.get()->template get_host_access(h, sycl::read_only); + tmpCt_get->get_host_access(h, sycl::read_only); h.host_task([out, ct, tmp_elements, &val] { val = static_cast>(out[0]); @@ -717,7 +721,7 @@ To mean_all(Param in) { getQueue() .submit([&](sycl::handler &h) { auto acc_in = - in.data->template get_host_access(h, sycl::read_only); + in.data->get_host_access(h, sycl::read_only); h.host_task([acc_in, in_elements, &val]() { common::Transform, af_add_t> transform; compute_t count = static_cast>(1); diff --git a/src/backend/oneapi/kernel/memcopy.hpp b/src/backend/oneapi/kernel/memcopy.hpp index b400d04673..64bd26ba1e 100644 --- a/src/backend/oneapi/kernel/memcopy.hpp +++ b/src/backend/oneapi/kernel/memcopy.hpp @@ -164,6 +164,19 @@ convertType>(char value) { return compute_t(value); } +template<> +signed char inline convertType, signed char>( + compute_t value) { + return (signed char)((short)value); +} + +template<> +inline compute_t +convertType>( + signed char value) { + return compute_t(value); +} + template<> unsigned char inline convertType, unsigned char>( @@ -197,6 +210,7 @@ OTHER_SPECIALIZATIONS(intl) OTHER_SPECIALIZATIONS(uintl) OTHER_SPECIALIZATIONS(short) OTHER_SPECIALIZATIONS(ushort) +OTHER_SPECIALIZATIONS(schar) OTHER_SPECIALIZATIONS(uchar) OTHER_SPECIALIZATIONS(char) OTHER_SPECIALIZATIONS(arrayfire::common::half) diff --git a/src/backend/oneapi/kernel/random_engine_write.hpp b/src/backend/oneapi/kernel/random_engine_write.hpp index dcd20dec13..3ebf0a113e 100644 --- a/src/backend/oneapi/kernel/random_engine_write.hpp +++ b/src/backend/oneapi/kernel/random_engine_write.hpp @@ -303,6 +303,12 @@ static void writeOut128Bytes(uchar *out, const uint &index, const uint groupSz, out[index + 15 * groupSz] = r4 >> 24; } +static void writeOut128Bytes(schar *out, const uint &index, const uint groupSz, + const uint &r1, const uint &r2, const uint &r3, + const uint &r4) { + writeOut128Bytes((uchar *)(out), index, groupSz, r1, r2, r3, r4); +} + static void writeOut128Bytes(char *out, const uint &index, const uint groupSz, const uint &r1, const uint &r2, const uint &r3, const uint &r4) { @@ -505,6 +511,14 @@ static void partialWriteOut128Bytes(uchar *out, const uint &index, } } +static void partialWriteOut128Bytes(schar *out, const uint &index, + const uint groupSz, const uint &r1, + const uint &r2, const uint &r3, + const uint &r4, const uint &elements) { + partialWriteOut128Bytes((uchar *)(out), index, groupSz, r1, r2, r3, r4, + elements); +} + static void partialWriteOut128Bytes(char *out, const uint &index, const uint groupSz, const uint &r1, const uint &r2, const uint &r3, diff --git a/src/backend/oneapi/kernel/reduce_all.hpp b/src/backend/oneapi/kernel/reduce_all.hpp index 4bc3d5254d..7a1e842425 100644 --- a/src/backend/oneapi/kernel/reduce_all.hpp +++ b/src/backend/oneapi/kernel/reduce_all.hpp @@ -249,13 +249,17 @@ void reduce_all_launcher_default(Param out, Param in, "Too many blocks requested (typeof(retirementCount) == unsigned)", AF_ERR_RUNTIME); } - Array tmp = createEmptyArray(tmp_elements); + Array tmp = createEmptyArray(tmp_elements); + auto tmp_get = tmp.get(); + Array retirementCount = createValueArray(1, 0); + auto ret_get = retirementCount.get(); + getQueue().submit([&](sycl::handler &h) { write_accessor out_acc{*out.data, h}; - auto retCount_acc = retirementCount.get()->get_access(h); - auto tmp_acc = tmp.get()->get_access(h); + auto retCount_acc = ret_get->get_access(h); + auto tmp_acc = tmp_get->get_access(h); read_accessor in_acc{*in.data, h}; auto shrdMem = sycl::local_accessor, 1>( diff --git a/src/backend/oneapi/kernel/sort_by_key/CMakeLists.txt b/src/backend/oneapi/kernel/sort_by_key/CMakeLists.txt index 394d593d6e..08b1d35f73 100644 --- a/src/backend/oneapi/kernel/sort_by_key/CMakeLists.txt +++ b/src/backend/oneapi/kernel/sort_by_key/CMakeLists.txt @@ -49,6 +49,7 @@ foreach(SBK_TYPE ${SBK_TYPES}) PRIVATE $<$: -fno-sycl-id-queries-fit-in-int -sycl-std=2020 + ${MSVC_RUNTIME} $<$: -fno-sycl-rdc>>) target_include_directories(oneapi_sort_by_key_${SBK_TYPE} diff --git a/src/backend/oneapi/kernel/sort_by_key/sort_by_key_impl.cpp b/src/backend/oneapi/kernel/sort_by_key/sort_by_key_impl.cpp index 9b04402904..0b0a8fb13f 100644 --- a/src/backend/oneapi/kernel/sort_by_key/sort_by_key_impl.cpp +++ b/src/backend/oneapi/kernel/sort_by_key/sort_by_key_impl.cpp @@ -9,7 +9,7 @@ #include -// SBK_TYPES:float double int uint intl uintl short ushort char uchar half +// SBK_TYPES:float double int uint intl uintl short ushort char schar uchar half namespace arrayfire { namespace oneapi { diff --git a/src/backend/oneapi/kernel/sort_by_key_impl.hpp b/src/backend/oneapi/kernel/sort_by_key_impl.hpp index 5a05eac58c..2e462db4b6 100644 --- a/src/backend/oneapi/kernel/sort_by_key_impl.hpp +++ b/src/backend/oneapi/kernel/sort_by_key_impl.hpp @@ -114,10 +114,11 @@ void sortByKeyBatched(Param pKey, Param pVal, const int dim, auto val_end = val_begin + elements; auto cKey = memAlloc(elements); + auto cKey_get = cKey.get(); getQueue().submit([&](sycl::handler &h) { h.copy(pKey.data->template reinterpret>().get_access( h, elements), - cKey.get()->template reinterpret>().get_access( + cKey_get->template reinterpret>().get_access( h, elements)); }); auto ckey_begin = @@ -150,10 +151,12 @@ void sortByKeyBatched(Param pKey, Param pVal, const int dim, } } + auto Seq_get = Seq.get(); auto cSeq = memAlloc(elements); + auto cSeq_get = cSeq.get(); getQueue().submit([&](sycl::handler &h) { - h.copy(Seq.get()->get_access(h, elements), - cSeq.get()->get_access(h, elements)); + h.copy(Seq_get->get_access(h, elements), + cSeq_get->get_access(h, elements)); }); auto cseq_begin = ::oneapi::dpl::begin(*cSeq.get()); auto cseq_end = cseq_begin + elements; @@ -206,6 +209,7 @@ void sort0ByKey(Param pKey, Param pVal, bool isAscending) { INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, intl) \ INSTANTIATE(Tk, uintl) diff --git a/src/backend/oneapi/kernel/sparse.hpp b/src/backend/oneapi/kernel/sparse.hpp index 70bf051868..24458ed77d 100644 --- a/src/backend/oneapi/kernel/sparse.hpp +++ b/src/backend/oneapi/kernel/sparse.hpp @@ -47,19 +47,16 @@ class coo2DenseCreateKernel { void operator()(sycl::nd_item<2> it) const { sycl::group g = it.get_group(); - const int id = g.get_group_id(0) * g.get_local_range(0) * REPEAT + - it.get_local_id(0); - - if (id >= values_.dims[0]) return; - const int dimSize = g.get_local_range(0); for (int i = it.get_local_id(0); i < REPEAT * dimSize; i += dimSize) { - if (i >= values_.dims[0]) return; + const int id = + g.get_group_id(0) * g.get_local_range(0) * REPEAT + i; + if (id >= values_.dims[0]) return; - T v = vPtr_[i]; - int r = rPtr_[i]; - int c = cPtr_[i]; + T v = vPtr_[id + values_.offset]; + int r = rPtr_[id + rowIdx_.offset]; + int c = cPtr_[id + colIdx_.offset]; int offset = r + c * output_.strides[1]; @@ -83,7 +80,7 @@ void coo2dense(Param out, const Param values, const Param rowIdx, const Param colIdx) { auto local = sycl::range(THREADS_PER_BLOCK, 1); auto global = sycl::range( - divup(out.info.dims[0], local[0] * REPEAT) * THREADS_PER_BLOCK, 1); + divup(values.info.dims[0], local[0] * REPEAT) * THREADS_PER_BLOCK, 1); getQueue().submit([&](auto &h) { sycl::accessor d_rowIdx{*rowIdx.data, h, sycl::read_only}; @@ -104,12 +101,15 @@ class csr2DenseCreateKernel { public: csr2DenseCreateKernel(write_accessor output, read_accessor values, read_accessor rowidx, read_accessor colidx, - const int M) + const int M, const int v_off, const int r_off, const int c_off) : output_(output) , values_(values) , rowidx_(rowidx) , colidx_(colidx) - , M_(M) {} + , M_(M) + , v_off_(v_off) + , r_off_(r_off) + , c_off_(c_off) {} void operator()(sycl::nd_item<2> it) const { sycl::group g = it.get_group(); @@ -117,10 +117,10 @@ class csr2DenseCreateKernel { int lid = it.get_local_id(0); for (int rowId = g.get_group_id(0); rowId < M_; rowId += it.get_group_range(0)) { - int colStart = rowidx_[rowId]; - int colEnd = rowidx_[rowId + 1]; + int colStart = rowidx_[rowId + r_off_]; + int colEnd = rowidx_[rowId + r_off_ + 1]; for (int colId = colStart + lid; colId < colEnd; colId += THREADS) { - output_[rowId + colidx_[colId] * M_] = values_[colId]; + output_[rowId + colidx_[colId + c_off_] * M_] = values_[colId + v_off_]; } } } @@ -131,6 +131,9 @@ class csr2DenseCreateKernel { read_accessor rowidx_; read_accessor colidx_; const int M_; + const int v_off_; + const int r_off_; + const int c_off_; }; template @@ -154,7 +157,10 @@ void csr2dense(Param output, const Param values, const Param rowIdx, sycl::no_init}; h.parallel_for(sycl::nd_range{global, local}, csr2DenseCreateKernel( - d_output, d_values, d_rowIdx, d_colIdx, M)); + d_output, d_values, d_rowIdx, d_colIdx, M, + static_cast(values.info.offset), + static_cast(rowIdx.info.offset), + static_cast(colIdx.info.offset))); }); ONEAPI_DEBUG_FINISH(getQueue()); @@ -185,17 +191,13 @@ class dense2csrCreateKernel { if (gidy >= (unsigned)valinfo_.dims[1]) return; int rowoff = rowptr_[gidx]; - T *svalptr_ptr = svalptr_.get_pointer(); - int *scolptr_ptr = scolptr_.get_pointer(); - svalptr_ptr += rowoff; - scolptr_ptr += rowoff; + auto svalptr_ptr = svalptr_.get_pointer(); + auto scolptr_ptr = scolptr_.get_pointer(); - T *dvalptr_ptr = dvalptr_.get_pointer(); - int *dcolptr_ptr = dcolptr_.get_pointer(); - dvalptr_ptr += valinfo_.offset; - dcolptr_ptr += colinfo_.offset; + auto dvalptr_ptr = dvalptr_.get_pointer(); + auto dcolptr_ptr = dcolptr_.get_pointer(); - T val = dvalptr_ptr[gidx + gidy * (unsigned)valinfo_.strides[1]]; + T val = dvalptr_ptr[gidx + gidy * (unsigned)valinfo_.strides[1] + valinfo_.offset]; if constexpr (std::is_same_v> || std::is_same_v>) { @@ -204,9 +206,9 @@ class dense2csrCreateKernel { if (val == 0) return; } - int oloc = dcolptr_ptr[gidx + gidy * colinfo_.strides[1]]; - svalptr_ptr[oloc - 1] = val; - scolptr_ptr[oloc - 1] = gidy; + int oloc = dcolptr_ptr[gidx + gidy * colinfo_.strides[1] + colinfo_.offset]; + svalptr_ptr[oloc + rowoff - 1] = val; + scolptr_ptr[oloc + rowoff - 1] = gidy; } private: diff --git a/src/backend/oneapi/kernel/sparse_arith.hpp b/src/backend/oneapi/kernel/sparse_arith.hpp index 819af6ffce..b46baa69df 100644 --- a/src/backend/oneapi/kernel/sparse_arith.hpp +++ b/src/backend/oneapi/kernel/sparse_arith.hpp @@ -427,9 +427,10 @@ static void csrCalcOutNNZ(Param outRowIdx, unsigned &nnzC, const uint M, auto global = sycl::range(divup(M, local[0]) * local[0]); Array out = createValueArray(1, 0); + auto out_get = out.get(); getQueue().submit([&](auto &h) { - sycl::accessor d_out{*out.get(), h, sycl::write_only}; + sycl::accessor d_out{*out_get, h, sycl::write_only}; sycl::accessor d_outRowIdx{*outRowIdx.data, h, sycl::write_only}; sycl::accessor d_lRowIdx{*lrowIdx.data, h, sycl::read_only}; sycl::accessor d_lColIdx{*lcolIdx.data, h, sycl::read_only}; diff --git a/src/backend/oneapi/kernel/wrap.hpp b/src/backend/oneapi/kernel/wrap.hpp index b5e5226035..e29403b604 100644 --- a/src/backend/oneapi/kernel/wrap.hpp +++ b/src/backend/oneapi/kernel/wrap.hpp @@ -140,7 +140,7 @@ void wrap(Param out, const Param in, const dim_t wx, const dim_t wy, dim_t groups_y = divup(out.info.dims[1], local[1]); auto global = sycl::range{groups_x * local[0] * out.info.dims[2], - groups_y * local[1]}; + groups_y * local[1] * out.info.dims[3]}; auto Q = getQueue(); Q.submit([&](sycl::handler &h) { diff --git a/src/backend/oneapi/lookup.cpp b/src/backend/oneapi/lookup.cpp index 9c87003375..de0a017c55 100644 --- a/src/backend/oneapi/lookup.cpp +++ b/src/backend/oneapi/lookup.cpp @@ -53,6 +53,8 @@ Array lookup(const Array &input, const Array &indices, const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ + template Array lookup(const Array &, const Array &, \ + const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ template Array lookup(const Array &, const Array &, \ @@ -66,6 +68,7 @@ INSTANTIATE(int); INSTANTIATE(unsigned); INSTANTIATE(intl); INSTANTIATE(uintl); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(char); INSTANTIATE(ushort); diff --git a/src/backend/oneapi/match_template.cpp b/src/backend/oneapi/match_template.cpp index 28794ff2eb..10b84757ac 100644 --- a/src/backend/oneapi/match_template.cpp +++ b/src/backend/oneapi/match_template.cpp @@ -32,6 +32,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/oneapi/math.hpp b/src/backend/oneapi/math.hpp index 4a3c8b41b2..7362874442 100644 --- a/src/backend/oneapi/math.hpp +++ b/src/backend/oneapi/math.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #if defined(__GNUC__) || defined(__GNUG__) diff --git a/src/backend/oneapi/max.cpp b/src/backend/oneapi/max.cpp index 8b6ef71a10..fa21d78c1c 100644 --- a/src/backend/oneapi/max.cpp +++ b/src/backend/oneapi/max.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_max_t, uint, uint) INSTANTIATE(af_max_t, intl, intl) INSTANTIATE(af_max_t, uintl, uintl) INSTANTIATE(af_max_t, char, char) +INSTANTIATE(af_max_t, schar, schar) INSTANTIATE(af_max_t, uchar, uchar) INSTANTIATE(af_max_t, short, short) INSTANTIATE(af_max_t, ushort, ushort) diff --git a/src/backend/oneapi/mean.cpp b/src/backend/oneapi/mean.cpp index 09763bb739..2f94101f56 100644 --- a/src/backend/oneapi/mean.cpp +++ b/src/backend/oneapi/mean.cpp @@ -60,6 +60,7 @@ INSTANTIATE(intl, double, double); INSTANTIATE(uintl, double, double); INSTANTIATE(short, float, float); INSTANTIATE(ushort, float, float); +INSTANTIATE(schar, float, float); INSTANTIATE(uchar, float, float); INSTANTIATE(char, float, float); INSTANTIATE(cfloat, float, cfloat); diff --git a/src/backend/oneapi/meanshift.cpp b/src/backend/oneapi/meanshift.cpp index 1017b9074b..825b26eb88 100644 --- a/src/backend/oneapi/meanshift.cpp +++ b/src/backend/oneapi/meanshift.cpp @@ -38,6 +38,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/medfilt.cpp b/src/backend/oneapi/medfilt.cpp index 3b1ff319c5..50c2cc3dd8 100644 --- a/src/backend/oneapi/medfilt.cpp +++ b/src/backend/oneapi/medfilt.cpp @@ -59,6 +59,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/memory.cpp b/src/backend/oneapi/memory.cpp index f94b6df5a4..3482742b73 100644 --- a/src/backend/oneapi/memory.cpp +++ b/src/backend/oneapi/memory.cpp @@ -152,6 +152,7 @@ INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/oneapi/min.cpp b/src/backend/oneapi/min.cpp index ea9900543c..fe1a5a3fa4 100644 --- a/src/backend/oneapi/min.cpp +++ b/src/backend/oneapi/min.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_min_t, uint, uint) INSTANTIATE(af_min_t, intl, intl) INSTANTIATE(af_min_t, uintl, uintl) INSTANTIATE(af_min_t, char, char) +INSTANTIATE(af_min_t, schar, schar) INSTANTIATE(af_min_t, uchar, uchar) INSTANTIATE(af_min_t, short, short) INSTANTIATE(af_min_t, ushort, ushort) diff --git a/src/backend/oneapi/moments.cpp b/src/backend/oneapi/moments.cpp index 50efe4ccd5..76e385990b 100644 --- a/src/backend/oneapi/moments.cpp +++ b/src/backend/oneapi/moments.cpp @@ -49,6 +49,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/morph.cpp b/src/backend/oneapi/morph.cpp index 44fe6a6529..11f3d3df7a 100644 --- a/src/backend/oneapi/morph.cpp +++ b/src/backend/oneapi/morph.cpp @@ -62,6 +62,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/nearest_neighbour.cpp b/src/backend/oneapi/nearest_neighbour.cpp index 7a34ba0fba..bec80b5cce 100644 --- a/src/backend/oneapi/nearest_neighbour.cpp +++ b/src/backend/oneapi/nearest_neighbour.cpp @@ -82,6 +82,7 @@ INSTANTIATE(intl, intl) INSTANTIATE(uintl, uintl) INSTANTIATE(short, int) INSTANTIATE(ushort, uint) +INSTANTIATE(schar, int) INSTANTIATE(uchar, uint) INSTANTIATE(uintl, uint) // For Hamming diff --git a/src/backend/oneapi/platform.cpp b/src/backend/oneapi/platform.cpp index 91e307d56c..3994a907a5 100644 --- a/src/backend/oneapi/platform.cpp +++ b/src/backend/oneapi/platform.cpp @@ -164,7 +164,9 @@ string getDeviceInfo() noexcept { << ", " << msize / 1048576 << " MB"; info << " ("; if (device->has(aspect::fp64)) { info << "fp64 "; } - if (device->has(aspect::fp16)) { info << "fp16 "; } + if (device->has(aspect::fp16) && + device->get_info() != 0) + { info << "fp16 "; } info << "\b)"; #ifndef NDEBUG info << " -- "; @@ -386,7 +388,8 @@ bool isHalfSupported(unsigned device) { DeviceManager& devMngr = DeviceManager::getInstance(); common::lock_guard_t lock(devMngr.deviceMutex); - return devMngr.mDevices[device]->has(sycl::aspect::fp16); + return devMngr.mDevices[device]->has(sycl::aspect::fp16) && + devMngr.mDevices[device]->get_info() != 0; } void devprop(char* d_name, char* d_platform, char* d_toolkit, char* d_compute) { diff --git a/src/backend/oneapi/plot.cpp b/src/backend/oneapi/plot.cpp index d2fa041291..3bd287fbd6 100644 --- a/src/backend/oneapi/plot.cpp +++ b/src/backend/oneapi/plot.cpp @@ -78,6 +78,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace oneapi diff --git a/src/backend/oneapi/product.cpp b/src/backend/oneapi/product.cpp index bc3f9421ae..4aa9cb61dd 100644 --- a/src/backend/oneapi/product.cpp +++ b/src/backend/oneapi/product.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_mul_t, uint, uint) INSTANTIATE(af_mul_t, intl, intl) INSTANTIATE(af_mul_t, uintl, uintl) INSTANTIATE(af_mul_t, char, int) +INSTANTIATE(af_mul_t, schar, int) INSTANTIATE(af_mul_t, uchar, uint) INSTANTIATE(af_mul_t, short, int) INSTANTIATE(af_mul_t, ushort, uint) diff --git a/src/backend/oneapi/random_engine.cpp b/src/backend/oneapi/random_engine.cpp index 7045dcc8cc..e3eac5da0b 100644 --- a/src/backend/oneapi/random_engine.cpp +++ b/src/backend/oneapi/random_engine.cpp @@ -92,6 +92,7 @@ INSTANTIATE_UNIFORM(uint) INSTANTIATE_UNIFORM(intl) INSTANTIATE_UNIFORM(uintl) INSTANTIATE_UNIFORM(char) +INSTANTIATE_UNIFORM(schar) INSTANTIATE_UNIFORM(uchar) INSTANTIATE_UNIFORM(short) INSTANTIATE_UNIFORM(ushort) diff --git a/src/backend/oneapi/range.cpp b/src/backend/oneapi/range.cpp index caa8ed48bc..c08a7bea91 100644 --- a/src/backend/oneapi/range.cpp +++ b/src/backend/oneapi/range.cpp @@ -48,6 +48,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/reduce_impl.hpp b/src/backend/oneapi/reduce_impl.hpp index 698f2f1831..b2c478c71f 100644 --- a/src/backend/oneapi/reduce_impl.hpp +++ b/src/backend/oneapi/reduce_impl.hpp @@ -58,12 +58,16 @@ void reduceBlocksByKey(sycl::buffer &reduced_block_sizes, sycl::range<3> global(local[0] * numBlocks, vals_out.dims()[1], vals_out.dims()[2] * vals_out.dims()[3]); + auto keys_out_get = keys_out.get(); + auto vals_out_get = vals_out.get(); + auto keys_get = keys.get(); + auto vals_get = vals.get(); getQueue().submit([&](sycl::handler &h) { sycl::accessor reduced_block_sizes_acc{reduced_block_sizes, h}; - write_accessor keys_out_acc{*keys_out.get(), h}; - write_accessor vals_out_acc{*vals_out.get(), h}; - read_accessor keys_acc{*keys.get(), h}; - read_accessor vals_acc{*vals.get(), h}; + write_accessor keys_out_acc{*keys_out_get, h}; + write_accessor vals_out_acc{*vals_out_get, h}; + read_accessor keys_acc{*keys_get, h}; + read_accessor vals_acc{*vals_get, h}; auto l_keys = sycl::local_accessor(threads_x, h); auto l_vals = sycl::local_accessor>(threads_x, h); @@ -100,12 +104,16 @@ void reduceBlocksByKeyDim(sycl::buffer &reduced_block_sizes, local[0] * numBlocks, vals_out.dims()[dim_ordering[1]], vals_out.dims()[dim_ordering[2]] * vals_out.dims()[dim_ordering[3]]); + auto keys_out_get = keys_out.get(); + auto vals_out_get = vals_out.get(); + auto keys_get = keys.get(); + auto vals_get = vals.get(); getQueue().submit([&](sycl::handler &h) { sycl::accessor reduced_block_sizes_acc{reduced_block_sizes, h}; - write_accessor keys_out_acc{*keys_out.get(), h}; - write_accessor vals_out_acc{*vals_out.get(), h}; - read_accessor keys_acc{*keys.get(), h}; - read_accessor vals_acc{*vals.get(), h}; + write_accessor keys_out_acc{*keys_out_get, h}; + write_accessor vals_out_acc{*vals_out_get, h}; + read_accessor keys_acc{*keys_get, h}; + read_accessor vals_acc{*vals_get, h}; auto l_keys = sycl::local_accessor(threads_x, h); auto l_vals = sycl::local_accessor>(threads_x, h); @@ -135,10 +143,12 @@ void finalBoundaryReduce(sycl::buffer &reduced_block_sizes, Array keys, sycl::range<1> local(threads_x); sycl::range<1> global(local[0] * numBlocks); + auto vals_out_get = vals_out.get(); + auto keys_get = keys.get(); getQueue().submit([&](sycl::handler &h) { write_accessor reduced_block_sizes_acc{reduced_block_sizes, h}; - read_accessor keys_acc{*keys.get(), h}; - sycl::accessor vals_out_acc{*vals_out.get(), h}; + read_accessor keys_acc{*keys_get, h}; + sycl::accessor vals_out_acc{*vals_out_get, h}; h.parallel_for(sycl::nd_range<1>(global, local), kernel::finalBoundaryReduceKernel( @@ -158,10 +168,12 @@ void finalBoundaryReduceDim(sycl::buffer &reduced_block_sizes, local[0] * numBlocks, vals_out.dims()[dim_ordering[1]], vals_out.dims()[dim_ordering[2]] * vals_out.dims()[dim_ordering[3]]); + auto vals_out_get = vals_out.get(); + auto keys_get = keys.get(); getQueue().submit([&](sycl::handler &h) { write_accessor reduced_block_sizes_acc{reduced_block_sizes, h}; - read_accessor keys_acc{*keys.get(), h}; - sycl::accessor vals_out_acc{*vals_out.get(), h}; + read_accessor keys_acc{*keys_get, h}; + sycl::accessor vals_out_acc{*vals_out_get, h}; // TODO: fold 3,4 dimensions h.parallel_for( @@ -181,12 +193,16 @@ void compact(sycl::buffer reduced_block_sizes, Array &keys_out, sycl::range<3> global(local[0] * numBlocks, vals_out.dims()[1], vals_out.dims()[2] * vals_out.dims()[3]); + auto keys_out_get = keys_out.get(); + auto vals_out_get = vals_out.get(); + auto keys_get = keys.get(); + auto vals_get = vals.get(); getQueue().submit([&](sycl::handler &h) { read_accessor reduced_block_sizes_acc{reduced_block_sizes, h}; - write_accessor keys_out_acc{*keys_out.get(), h}; - write_accessor vals_out_acc{*vals_out.get(), h}; - read_accessor keys_acc{*keys.get(), h}; - read_accessor vals_acc{*vals.get(), h}; + write_accessor keys_out_acc{*keys_out_get, h}; + write_accessor vals_out_acc{*vals_out_get, h}; + read_accessor keys_acc{*keys_get, h}; + read_accessor vals_acc{*vals_get, h}; h.parallel_for(sycl::nd_range<3>(global, local), kernel::compactKernel( @@ -207,12 +223,16 @@ void compactDim(sycl::buffer &reduced_block_sizes, Array &keys_out, local[0] * numBlocks, vals_out.dims()[dim_ordering[1]], vals_out.dims()[dim_ordering[2]] * vals_out.dims()[dim_ordering[3]]); + auto keys_out_get = keys_out.get(); + auto vals_out_get = vals_out.get(); + auto keys_get = keys.get(); + auto vals_get = vals.get(); getQueue().submit([&](sycl::handler &h) { read_accessor reduced_block_sizes_acc{reduced_block_sizes, h}; - write_accessor keys_out_acc{*keys_out.get(), h}; - write_accessor vals_out_acc{*vals_out.get(), h}; - read_accessor keys_acc{*keys.get(), h}; - read_accessor vals_acc{*vals.get(), h}; + write_accessor keys_out_acc{*keys_out_get, h}; + write_accessor vals_out_acc{*vals_out_get, h}; + read_accessor keys_acc{*keys_get, h}; + read_accessor vals_acc{*vals_get, h}; h.parallel_for( sycl::nd_range<3>(global, local), @@ -231,10 +251,11 @@ void testNeedsReduction(sycl::buffer needs_reduction, sycl::range<1> local(threads_x); sycl::range<1> global(local[0] * numBlocks); + auto keys_get = keys.get(); getQueue().submit([&](sycl::handler &h) { sycl::accessor needs_reduction_acc{needs_reduction, h}; sycl::accessor needs_boundary_acc{needs_boundary, h}; - read_accessor keys_acc{*keys.get(), h}; + read_accessor keys_acc{*keys_get, h}; auto l_keys = sycl::local_accessor(threads_x, h); h.parallel_for(sycl::nd_range<1>(global, local), diff --git a/src/backend/oneapi/reorder.cpp b/src/backend/oneapi/reorder.cpp index d62db984e9..d9e264f70c 100644 --- a/src/backend/oneapi/reorder.cpp +++ b/src/backend/oneapi/reorder.cpp @@ -40,6 +40,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/oneapi/reshape.cpp b/src/backend/oneapi/reshape.cpp index 8f1b6f0ecb..2b15f686e9 100644 --- a/src/backend/oneapi/reshape.cpp +++ b/src/backend/oneapi/reshape.cpp @@ -50,6 +50,8 @@ Array reshape(const Array &in, const dim4 &outDims, dim4 const &, short, double); \ template Array reshape( \ Array const &, dim4 const &, ushort, double); \ + template Array reshape(Array const &, \ + dim4 const &, schar, double); \ template Array reshape(Array const &, \ dim4 const &, uchar, double); \ template Array reshape(Array const &, \ @@ -65,6 +67,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) diff --git a/src/backend/oneapi/resize.cpp b/src/backend/oneapi/resize.cpp index 005faf6b2b..b73f42eabb 100644 --- a/src/backend/oneapi/resize.cpp +++ b/src/backend/oneapi/resize.cpp @@ -40,6 +40,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/rotate.cpp b/src/backend/oneapi/rotate.cpp index 10f1f93480..bcd7b5810a 100644 --- a/src/backend/oneapi/rotate.cpp +++ b/src/backend/oneapi/rotate.cpp @@ -50,6 +50,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/scan.cpp b/src/backend/oneapi/scan.cpp index f7151ce076..9aaae59b49 100644 --- a/src/backend/oneapi/scan.cpp +++ b/src/backend/oneapi/scan.cpp @@ -45,6 +45,7 @@ Array scan(const Array& in, const int dim, bool inclusiveScan) { INSTANTIATE_SCAN(ROp, intl, intl) \ INSTANTIATE_SCAN(ROp, uintl, uintl) \ INSTANTIATE_SCAN(ROp, char, uint) \ + INSTANTIATE_SCAN(ROp, schar, int) \ INSTANTIATE_SCAN(ROp, uchar, uint) \ INSTANTIATE_SCAN(ROp, short, int) \ INSTANTIATE_SCAN(ROp, ushort, uint) diff --git a/src/backend/oneapi/select.cpp b/src/backend/oneapi/select.cpp index 8cb80c919d..b24b1fa340 100644 --- a/src/backend/oneapi/select.cpp +++ b/src/backend/oneapi/select.cpp @@ -128,6 +128,7 @@ INSTANTIATE(uint); INSTANTIATE(intl); INSTANTIATE(uintl); INSTANTIATE(char); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(short); INSTANTIATE(ushort); diff --git a/src/backend/oneapi/set.cpp b/src/backend/oneapi/set.cpp index 416efb4040..4c4b68e4b0 100644 --- a/src/backend/oneapi/set.cpp +++ b/src/backend/oneapi/set.cpp @@ -127,6 +127,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/shift.cpp b/src/backend/oneapi/shift.cpp index 8a12eb81a8..7e5e31bf37 100644 --- a/src/backend/oneapi/shift.cpp +++ b/src/backend/oneapi/shift.cpp @@ -64,6 +64,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/sobel.cpp b/src/backend/oneapi/sobel.cpp index 54ba117be7..e919a37b77 100644 --- a/src/backend/oneapi/sobel.cpp +++ b/src/backend/oneapi/sobel.cpp @@ -42,6 +42,7 @@ INSTANTIATE(double, double) INSTANTIATE(int, int) INSTANTIATE(uint, int) INSTANTIATE(char, int) +INSTANTIATE(schar, int) INSTANTIATE(uchar, int) INSTANTIATE(short, int) INSTANTIATE(ushort, int) diff --git a/src/backend/oneapi/sort.cpp b/src/backend/oneapi/sort.cpp index 4dc65a621c..9bfbeb9094 100644 --- a/src/backend/oneapi/sort.cpp +++ b/src/backend/oneapi/sort.cpp @@ -63,6 +63,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/sort_by_key.cpp b/src/backend/oneapi/sort_by_key.cpp index 9ec60130cd..ba24249955 100644 --- a/src/backend/oneapi/sort_by_key.cpp +++ b/src/backend/oneapi/sort_by_key.cpp @@ -67,6 +67,7 @@ void sort_by_key(Array &okey, Array &oval, const Array &ikey, INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, intl) \ INSTANTIATE(Tk, uintl) @@ -78,6 +79,7 @@ INSTANTIATE1(uint) INSTANTIATE1(short) INSTANTIATE1(ushort) INSTANTIATE1(char) +INSTANTIATE1(schar) INSTANTIATE1(uchar) INSTANTIATE1(intl) INSTANTIATE1(uintl) diff --git a/src/backend/oneapi/sort_index.cpp b/src/backend/oneapi/sort_index.cpp index 17de33fbad..a8c547f8a1 100644 --- a/src/backend/oneapi/sort_index.cpp +++ b/src/backend/oneapi/sort_index.cpp @@ -68,6 +68,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/sum.cpp b/src/backend/oneapi/sum.cpp index fb20ce6121..990979ba25 100644 --- a/src/backend/oneapi/sum.cpp +++ b/src/backend/oneapi/sum.cpp @@ -29,6 +29,8 @@ INSTANTIATE(af_add_t, uintl, uintl) INSTANTIATE(af_add_t, uintl, double) INSTANTIATE(af_add_t, char, int) INSTANTIATE(af_add_t, char, float) +INSTANTIATE(af_add_t, schar, int) +INSTANTIATE(af_add_t, schar, float) INSTANTIATE(af_add_t, uchar, uint) INSTANTIATE(af_add_t, uchar, float) INSTANTIATE(af_add_t, short, int) diff --git a/src/backend/oneapi/surface.cpp b/src/backend/oneapi/surface.cpp index 2a8d604772..ac50627938 100644 --- a/src/backend/oneapi/surface.cpp +++ b/src/backend/oneapi/surface.cpp @@ -80,6 +80,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace oneapi diff --git a/src/backend/oneapi/susan.cpp b/src/backend/oneapi/susan.cpp index 437259681c..b51acf13df 100644 --- a/src/backend/oneapi/susan.cpp +++ b/src/backend/oneapi/susan.cpp @@ -70,6 +70,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/tile.cpp b/src/backend/oneapi/tile.cpp index aca96e4ec6..928d0e2b19 100644 --- a/src/backend/oneapi/tile.cpp +++ b/src/backend/oneapi/tile.cpp @@ -42,6 +42,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/transform.cpp b/src/backend/oneapi/transform.cpp index 54b328f7fd..a277df9661 100644 --- a/src/backend/oneapi/transform.cpp +++ b/src/backend/oneapi/transform.cpp @@ -50,6 +50,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/transpose.cpp b/src/backend/oneapi/transpose.cpp index 580573125f..1f41e96cde 100644 --- a/src/backend/oneapi/transpose.cpp +++ b/src/backend/oneapi/transpose.cpp @@ -43,6 +43,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/oneapi/transpose_inplace.cpp b/src/backend/oneapi/transpose_inplace.cpp index ddbb14e419..013027f780 100644 --- a/src/backend/oneapi/transpose_inplace.cpp +++ b/src/backend/oneapi/transpose_inplace.cpp @@ -40,6 +40,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/oneapi/triangle.cpp b/src/backend/oneapi/triangle.cpp index e418c15b93..c8ab5e2b16 100644 --- a/src/backend/oneapi/triangle.cpp +++ b/src/backend/oneapi/triangle.cpp @@ -49,6 +49,7 @@ INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/types.hpp b/src/backend/oneapi/types.hpp index 4537f27987..395687396c 100644 --- a/src/backend/oneapi/types.hpp +++ b/src/backend/oneapi/types.hpp @@ -43,6 +43,7 @@ namespace oneapi { using cdouble = std::complex; using cfloat = std::complex; using intl = long long; +using schar = signed char; using uchar = unsigned char; using uint = unsigned int; using uintl = unsigned long long; @@ -95,6 +96,10 @@ inline const char *shortname(bool caps) { return caps ? "J" : "j"; } template<> +inline const char *shortname(bool caps) { + return caps ? "A" : "a"; // TODO +} +template<> inline const char *shortname(bool caps) { return caps ? "V" : "v"; } @@ -120,6 +125,11 @@ inline const char *getFullName() { return af::dtype_traits::getName(); } +template<> +inline const char *getFullName() { + return "signed char"; +} + template<> inline const char *getFullName() { return "float2"; diff --git a/src/backend/oneapi/unwrap.cpp b/src/backend/oneapi/unwrap.cpp index 15d60afe5d..bfc95e0f18 100644 --- a/src/backend/oneapi/unwrap.cpp +++ b/src/backend/oneapi/unwrap.cpp @@ -53,6 +53,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/oneapi/vector_field.cpp b/src/backend/oneapi/vector_field.cpp index 92f310698a..d67fa73c51 100644 --- a/src/backend/oneapi/vector_field.cpp +++ b/src/backend/oneapi/vector_field.cpp @@ -31,6 +31,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace oneapi diff --git a/src/backend/oneapi/where.cpp b/src/backend/oneapi/where.cpp index bc9e45a515..fd08b975b8 100644 --- a/src/backend/oneapi/where.cpp +++ b/src/backend/oneapi/where.cpp @@ -36,6 +36,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/oneapi/wrap.cpp b/src/backend/oneapi/wrap.cpp index 19e8c0260e..21c47ac007 100644 --- a/src/backend/oneapi/wrap.cpp +++ b/src/backend/oneapi/wrap.cpp @@ -44,6 +44,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/Array.cpp b/src/backend/opencl/Array.cpp index 21dec5166c..38fbfc4d84 100644 --- a/src/backend/opencl/Array.cpp +++ b/src/backend/opencl/Array.cpp @@ -201,10 +201,12 @@ void checkAndMigrate(Array &arr) { AF_TRACE("Migrating array from {} to {}.", arr_id, cur_id); auto migrated_data = memAlloc(arr.elements()); void *mapped_migrated_buffer = getQueue().enqueueMapBuffer( - *migrated_data, CL_TRUE, CL_MAP_READ, 0, arr.elements()); + *migrated_data, CL_TRUE, CL_MAP_WRITE_INVALIDATE_REGION, 0, + sizeof(T) * arr.elements()); setDevice(arr_id); Buffer &buf = *arr.get(); - getQueue().enqueueReadBuffer(buf, CL_TRUE, 0, arr.elements(), + getQueue().enqueueReadBuffer(buf, CL_TRUE, 0, + sizeof(T) * arr.elements(), mapped_migrated_buffer); setDevice(cur_id); getQueue().enqueueUnmapMemObject(*migrated_data, @@ -583,6 +585,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/opencl/CMakeLists.txt b/src/backend/opencl/CMakeLists.txt index 5c920f44f8..23bedeedab 100644 --- a/src/backend/opencl/CMakeLists.txt +++ b/src/backend/opencl/CMakeLists.txt @@ -7,6 +7,10 @@ dependency_check(OpenCL_FOUND "OpenCL not found.") +# OpenCL back end needs to use MKL LP64 interface +set(MKL_INTERFACE_INTEGER_SIZE 4) +set(MKL_INTERFACE "lp64") + include(InternalUtils) include(build_cl2hpp) include(build_CLBlast) @@ -454,6 +458,7 @@ target_sources(afopencl kernel/convolve/conv2_f32.cpp kernel/convolve/conv2_f64.cpp kernel/convolve/conv2_impl.hpp + kernel/convolve/conv2_s8.cpp kernel/convolve/conv2_s16.cpp kernel/convolve/conv2_s32.cpp kernel/convolve/conv2_s64.cpp @@ -577,6 +582,7 @@ if(LAPACK_FOUND OR BUILD_WITH_MKL) if(BUILD_WITH_MKL) target_compile_definitions(afopencl PRIVATE USE_MKL) + target_compile_definitions(afopencl PRIVATE AF_MKL_INTERFACE_SIZE=${MKL_INTERFACE_INTEGER_SIZE}) if(MKL_BATCH) target_compile_definitions(afopencl PRIVATE AF_USE_MKL_BATCH) endif() diff --git a/src/backend/opencl/all.cpp b/src/backend/opencl/all.cpp index 2d2a1d4717..d81d9def34 100644 --- a/src/backend/opencl/all.cpp +++ b/src/backend/opencl/all.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_and_t, uint, char) INSTANTIATE(af_and_t, intl, char) INSTANTIATE(af_and_t, uintl, char) INSTANTIATE(af_and_t, char, char) +INSTANTIATE(af_and_t, schar, char) INSTANTIATE(af_and_t, uchar, char) INSTANTIATE(af_and_t, short, char) INSTANTIATE(af_and_t, ushort, char) diff --git a/src/backend/opencl/any.cpp b/src/backend/opencl/any.cpp index ce36f8ed90..ee2d16ab63 100644 --- a/src/backend/opencl/any.cpp +++ b/src/backend/opencl/any.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_or_t, uint, char) INSTANTIATE(af_or_t, intl, char) INSTANTIATE(af_or_t, uintl, char) INSTANTIATE(af_or_t, char, char) +INSTANTIATE(af_or_t, schar, char) INSTANTIATE(af_or_t, uchar, char) INSTANTIATE(af_or_t, short, char) INSTANTIATE(af_or_t, ushort, char) diff --git a/src/backend/opencl/assign.cpp b/src/backend/opencl/assign.cpp index 57ceeaab2d..fbe0370dde 100644 --- a/src/backend/opencl/assign.cpp +++ b/src/backend/opencl/assign.cpp @@ -104,6 +104,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/bilateral.cpp b/src/backend/opencl/bilateral.cpp index 21ec82e2b6..6475377e75 100644 --- a/src/backend/opencl/bilateral.cpp +++ b/src/backend/opencl/bilateral.cpp @@ -34,6 +34,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/opencl/binary.hpp b/src/backend/opencl/binary.hpp index 02291d566a..39f340942a 100644 --- a/src/backend/opencl/binary.hpp +++ b/src/backend/opencl/binary.hpp @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -80,6 +80,11 @@ BINARY_TYPE_2(max) BINARY_TYPE_2(rem) BINARY_TYPE_2(mod) +template<> +struct BinOp { + const char *name() { return "fmod"; } +}; + template struct BinOp { const char *name() { return "__pow"; } diff --git a/src/backend/opencl/blas.cpp b/src/backend/opencl/blas.cpp index 45b4149599..8010fe555d 100644 --- a/src/backend/opencl/blas.cpp +++ b/src/backend/opencl/blas.cpp @@ -62,13 +62,14 @@ void gemm_fallback(Array & /*out*/, af_mat_prop /*optLhs*/, assert(false && "CPU fallback not implemented for f16"); } -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta) { +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta) { #if defined(WITH_LINEAR_ALGEBRA) // Do not force offload gemm on OSX Intel devices if (OpenCLCPUOffload(false) && - static_cast(dtype_traits::af_type) != f16) { + static_cast(dtype_traits::af_type) != f16) { gemm_fallback(out, optLhs, optRhs, alpha, lhs, rhs, beta); return; } @@ -114,14 +115,14 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, cl::Event event; if (rDims[bColDim] == 1) { dim_t incr = (optRhs == AF_MAT_NONE) ? rStrides[0] : rStrides[1]; - gpu_blas_gemv_func gemv; + gpu_blas_gemv_func gemv; OPENCL_BLAS_CHECK(gemv(lOpts, lDims[0], lDims[1], *alpha, (*lhs.get())(), lOffset, lStrides[1], (*rhs.get())(), rOffset, incr, *beta, (*out.get())(), oOffset, oStrides[0], 1, &getQueue()(), 0, nullptr, &event())); } else { - gpu_blas_gemm_func gemm; + gpu_blas_gemm_func gemm; OPENCL_BLAS_CHECK(gemm(lOpts, rOpts, M, N, K, *alpha, (*lhs.get())(), lOffset, lStrides[1], (*rhs.get())(), rOffset, rStrides[1], *beta, @@ -131,6 +132,14 @@ void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, } } +template<> +void gemm(Array &out, af_mat_prop optLhs, + af_mat_prop optRhs, const float *alpha, + const Array &lhs, const Array &rhs, + const float *beta) { + TYPE_ERROR(3, af_dtype::s8); +} + template Array dot(const Array &lhs, const Array &rhs, af_mat_prop optLhs, af_mat_prop optRhs) { diff --git a/src/backend/opencl/blas.hpp b/src/backend/opencl/blas.hpp index 4416960f46..fc4571d4b5 100644 --- a/src/backend/opencl/blas.hpp +++ b/src/backend/opencl/blas.hpp @@ -20,9 +20,10 @@ namespace opencl { void initBlas(); void deInitBlas(); -template -void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, const T *alpha, - const Array &lhs, const Array &rhs, const T *beta); +template +void gemm(Array &out, af_mat_prop optLhs, af_mat_prop optRhs, + const To *alpha, const Array &lhs, const Array &rhs, + const To *beta); template Array matmul(const Array &lhs, const Array &rhs, af_mat_prop optLhs, diff --git a/src/backend/opencl/cast.hpp b/src/backend/opencl/cast.hpp index 999d6188d9..cef1d76c0e 100644 --- a/src/backend/opencl/cast.hpp +++ b/src/backend/opencl/cast.hpp @@ -38,6 +38,11 @@ CAST_FN(uchar) CAST_FN(float) CAST_FN(double) +template +struct CastOp { + const char *name() { return "convert_char"; } +}; + #define CAST_CFN(TYPE) \ template \ struct CastOp { \ diff --git a/src/backend/opencl/compile_module.cpp b/src/backend/opencl/compile_module.cpp index 89d382c9c0..f0244b3b0d 100644 --- a/src/backend/opencl/compile_module.cpp +++ b/src/backend/opencl/compile_module.cpp @@ -81,6 +81,9 @@ const static string DEFAULT_MACROS_STR( #else\n \ #define half short\n \ #endif\n \ + #ifndef schar\n \ + #define schar char\n \ + #endif\n \ #ifndef M_PI\n \ #define M_PI 3.1415926535897932384626433832795028841971693993751058209749445923078164\n \ #endif\n \ diff --git a/src/backend/opencl/convolve.cpp b/src/backend/opencl/convolve.cpp index f826102caf..34aa93b642 100644 --- a/src/backend/opencl/convolve.cpp +++ b/src/backend/opencl/convolve.cpp @@ -98,6 +98,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/opencl/convolve_separable.cpp b/src/backend/opencl/convolve_separable.cpp index 03da468ac4..41b88b6ba8 100644 --- a/src/backend/opencl/convolve_separable.cpp +++ b/src/backend/opencl/convolve_separable.cpp @@ -65,6 +65,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(short, float) diff --git a/src/backend/opencl/copy.cpp b/src/backend/opencl/copy.cpp index 970deae518..97d54d432c 100644 --- a/src/backend/opencl/copy.cpp +++ b/src/backend/opencl/copy.cpp @@ -128,6 +128,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) @@ -157,6 +158,8 @@ INSTANTIATE(half) Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ + template void copyArray(Array & dst, \ + Array const &src); \ template void copyArray(Array & dst, \ Array const &src); \ template void copyArray(Array & dst, \ @@ -170,6 +173,7 @@ INSTANTIATE_COPY_ARRAY(int) INSTANTIATE_COPY_ARRAY(uint) INSTANTIATE_COPY_ARRAY(intl) INSTANTIATE_COPY_ARRAY(uintl) +INSTANTIATE_COPY_ARRAY(schar) INSTANTIATE_COPY_ARRAY(uchar) INSTANTIATE_COPY_ARRAY(char) INSTANTIATE_COPY_ARRAY(short) @@ -201,6 +205,7 @@ INSTANTIATE_GETSCALAR(cfloat) INSTANTIATE_GETSCALAR(cdouble) INSTANTIATE_GETSCALAR(int) INSTANTIATE_GETSCALAR(uint) +INSTANTIATE_GETSCALAR(schar) INSTANTIATE_GETSCALAR(uchar) INSTANTIATE_GETSCALAR(char) INSTANTIATE_GETSCALAR(intl) diff --git a/src/backend/opencl/count.cpp b/src/backend/opencl/count.cpp index 80f12e68cd..fe1b588f89 100644 --- a/src/backend/opencl/count.cpp +++ b/src/backend/opencl/count.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_notzero_t, uint, uint) INSTANTIATE(af_notzero_t, intl, uint) INSTANTIATE(af_notzero_t, uintl, uint) INSTANTIATE(af_notzero_t, char, uint) +INSTANTIATE(af_notzero_t, schar, uint) INSTANTIATE(af_notzero_t, uchar, uint) INSTANTIATE(af_notzero_t, short, uint) INSTANTIATE(af_notzero_t, ushort, uint) diff --git a/src/backend/opencl/device_manager.cpp b/src/backend/opencl/device_manager.cpp index 1e628af521..62c06a21a5 100644 --- a/src/backend/opencl/device_manager.cpp +++ b/src/backend/opencl/device_manager.cpp @@ -261,8 +261,11 @@ DeviceManager::DeviceManager() // Create contexts and queues once the sort is done for (int i = 0; i < nDevices; i++) { - cl_platform_id device_platform = - devices[i]->getInfo(); + // For OpenCL-HPP >= v2023.12.14 type is cl::Platform instead of + // cl_platform_id + cl::Platform device_platform; + device_platform = devices[i]->getInfo(); + try { mContexts.emplace_back( make_unique(mDeviceContextMap[*devices[i]])); @@ -272,7 +275,7 @@ DeviceManager::DeviceManager() mDeviceTypes.push_back(getDeviceTypeEnum(*devices[i])); mPlatforms.push_back( std::make_pair, afcl_platform>( - make_unique(device_platform, true), + make_unique(device_platform(), true), getPlatformEnum(*devices[i]))); mDevices.emplace_back(std::move(devices[i])); diff --git a/src/backend/opencl/diagonal.cpp b/src/backend/opencl/diagonal.cpp index 094906a77a..2d21b5f461 100644 --- a/src/backend/opencl/diagonal.cpp +++ b/src/backend/opencl/diagonal.cpp @@ -54,6 +54,7 @@ INSTANTIATE_DIAGONAL(uint) INSTANTIATE_DIAGONAL(intl) INSTANTIATE_DIAGONAL(uintl) INSTANTIATE_DIAGONAL(char) +INSTANTIATE_DIAGONAL(schar) INSTANTIATE_DIAGONAL(uchar) INSTANTIATE_DIAGONAL(short) INSTANTIATE_DIAGONAL(ushort) diff --git a/src/backend/opencl/diff.cpp b/src/backend/opencl/diff.cpp index 020365d24c..e152301f0d 100644 --- a/src/backend/opencl/diff.cpp +++ b/src/backend/opencl/diff.cpp @@ -50,6 +50,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/opencl/err_opencl.hpp b/src/backend/opencl/err_opencl.hpp index 2c1187c569..9a24bc2789 100644 --- a/src/backend/opencl/err_opencl.hpp +++ b/src/backend/opencl/err_opencl.hpp @@ -27,6 +27,6 @@ std::string getProgramBuildLog(const cl::Program &prog); #define OPENCL_NOT_SUPPORTED(message) \ do { \ - throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, message, \ - boost::stacktrace::stacktrace()); \ + throw SupportError(__AF_FUNC__, __AF_FILENAME__, __LINE__, "OpenCL",\ + message, boost::stacktrace::stacktrace()); \ } while (0) diff --git a/src/backend/opencl/exampleFunction.cpp b/src/backend/opencl/exampleFunction.cpp index 10af977382..87306e329c 100644 --- a/src/backend/opencl/exampleFunction.cpp +++ b/src/backend/opencl/exampleFunction.cpp @@ -57,6 +57,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(cfloat) diff --git a/src/backend/opencl/fast.cpp b/src/backend/opencl/fast.cpp index bfe6c84177..4198cf82ba 100644 --- a/src/backend/opencl/fast.cpp +++ b/src/backend/opencl/fast.cpp @@ -53,6 +53,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/fftconvolve.cpp b/src/backend/opencl/fftconvolve.cpp index f6b243baac..f5a875f41c 100644 --- a/src/backend/opencl/fftconvolve.cpp +++ b/src/backend/opencl/fftconvolve.cpp @@ -137,6 +137,7 @@ INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(uint) INSTANTIATE(int) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(uintl) diff --git a/src/backend/opencl/flood_fill.cpp b/src/backend/opencl/flood_fill.cpp index b57de824bd..4a759e095d 100644 --- a/src/backend/opencl/flood_fill.cpp +++ b/src/backend/opencl/flood_fill.cpp @@ -34,6 +34,7 @@ Array floodFill(const Array& image, const Array& seedsX, INSTANTIATE(float) INSTANTIATE(uint) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace opencl diff --git a/src/backend/opencl/hist_graphics.cpp b/src/backend/opencl/hist_graphics.cpp index 6c2a06e0b1..a20daeb700 100644 --- a/src/backend/opencl/hist_graphics.cpp +++ b/src/backend/opencl/hist_graphics.cpp @@ -74,6 +74,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace opencl diff --git a/src/backend/opencl/histogram.cpp b/src/backend/opencl/histogram.cpp index 7c3d432228..bbf7e9082e 100644 --- a/src/backend/opencl/histogram.cpp +++ b/src/backend/opencl/histogram.cpp @@ -41,6 +41,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/identity.cpp b/src/backend/opencl/identity.cpp index 9d9ae55718..9aa72fc433 100644 --- a/src/backend/opencl/identity.cpp +++ b/src/backend/opencl/identity.cpp @@ -37,6 +37,7 @@ INSTANTIATE_IDENTITY(uint) INSTANTIATE_IDENTITY(intl) INSTANTIATE_IDENTITY(uintl) INSTANTIATE_IDENTITY(char) +INSTANTIATE_IDENTITY(schar) INSTANTIATE_IDENTITY(uchar) INSTANTIATE_IDENTITY(short) INSTANTIATE_IDENTITY(ushort) diff --git a/src/backend/opencl/image.cpp b/src/backend/opencl/image.cpp index cffc2b8194..663fc63c24 100644 --- a/src/backend/opencl/image.cpp +++ b/src/backend/opencl/image.cpp @@ -78,6 +78,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/opencl/index.cpp b/src/backend/opencl/index.cpp index 0911229936..b1cb238968 100644 --- a/src/backend/opencl/index.cpp +++ b/src/backend/opencl/index.cpp @@ -42,6 +42,16 @@ Array index(const Array& in, const af_index_t idxrs[]) { p.isSeq[i] = idxrs[i].isSeq ? 1 : 0; p.offs[i] = iOffs[i]; p.strds[i] = iStrds[i]; + p.steps[i] = 0; + if (idxrs[i].isSeq) { + af_seq seq = idxrs[i].idx.seq; + // The step for af_span used in the kernel must be 1 + if (seq.begin == af_span.begin && seq.end == af_span.end && + seq.step == af_span.step) + p.steps[i] = 1; + else + p.steps[i] = seq.step; + } } cl::Buffer* bPtrs[4]; @@ -81,6 +91,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/iota.cpp b/src/backend/opencl/iota.cpp index de69ca6595..87c840b419 100644 --- a/src/backend/opencl/iota.cpp +++ b/src/backend/opencl/iota.cpp @@ -39,6 +39,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/ireduce.cpp b/src/backend/opencl/ireduce.cpp index ca4c916f63..d4b080389c 100644 --- a/src/backend/opencl/ireduce.cpp +++ b/src/backend/opencl/ireduce.cpp @@ -58,6 +58,7 @@ INSTANTIATE(af_min_t, uint) INSTANTIATE(af_min_t, intl) INSTANTIATE(af_min_t, uintl) INSTANTIATE(af_min_t, char) +INSTANTIATE(af_min_t, schar) INSTANTIATE(af_min_t, uchar) INSTANTIATE(af_min_t, short) INSTANTIATE(af_min_t, ushort) @@ -73,6 +74,7 @@ INSTANTIATE(af_max_t, uint) INSTANTIATE(af_max_t, intl) INSTANTIATE(af_max_t, uintl) INSTANTIATE(af_max_t, char) +INSTANTIATE(af_max_t, schar) INSTANTIATE(af_max_t, uchar) INSTANTIATE(af_max_t, short) INSTANTIATE(af_max_t, ushort) diff --git a/src/backend/opencl/jit.cpp b/src/backend/opencl/jit.cpp index 7ace33cd96..c0858c3cc5 100644 --- a/src/backend/opencl/jit.cpp +++ b/src/backend/opencl/jit.cpp @@ -188,62 +188,77 @@ __kernel void )JIT"; thread_local stringstream outOffsetStream; thread_local stringstream inOffsetsStream; thread_local stringstream opsStream; + thread_local stringstream kerStream; - int oid{0}; - for (size_t i{0}; i < full_nodes.size(); i++) { - const auto& node{full_nodes[i]}; - const auto& ids_curr{full_ids[i]}; - // Generate input parameters, only needs current id - node->genParams(inParamStream, ids_curr.id, is_linear); - // Generate input offsets, only needs current id - node->genOffsets(inOffsetsStream, ids_curr.id, is_linear); - // Generate the core function body, needs children ids as well - node->genFuncs(opsStream, ids_curr); - for (auto outIt{begin(output_ids)}, endIt{end(output_ids)}; - (outIt = find(outIt, endIt, ids_curr.id)) != endIt; ++outIt) { - // Generate also output parameters - outParamStream << "__global " - << full_nodes[ids_curr.id]->getTypeStr() << " *out" - << oid << ", int offset" << oid << ",\n"; - // Apply output offset - outOffsetStream << "\nout" << oid << " += offset" << oid << ';'; - // Generate code to write the output - opsStream << "out" << oid << "[idx] = val" << ids_curr.id << ";\n"; - ++oid; + string ret; + try { + int oid{0}; + for (size_t i{0}; i < full_nodes.size(); i++) { + const auto& node{full_nodes[i]}; + const auto& ids_curr{full_ids[i]}; + // Generate input parameters, only needs current id + node->genParams(inParamStream, ids_curr.id, is_linear); + // Generate input offsets, only needs current id + node->genOffsets(inOffsetsStream, ids_curr.id, is_linear); + // Generate the core function body, needs children ids as well + node->genFuncs(opsStream, ids_curr); + for (size_t output_idx{0}; output_idx < output_ids.size(); + ++output_idx) { + if (output_ids[output_idx] == ids_curr.id) { + outParamStream + << "__global " << full_nodes[ids_curr.id]->getTypeStr() + << " *out" << oid << ", int offset" << oid << ",\n"; + // Apply output offset + outOffsetStream << "\nout" << oid << " += offset" << oid + << ';'; + // Generate code to write the output + opsStream << "out" << output_idx << "[idx] = val" + << ids_curr.id << ";\n"; + ++oid; + } + } } - } - thread_local stringstream kerStream; - kerStream << kernelVoid << funcName << "(\n" - << inParamStream.str() << outParamStream.str() << dimParams << ")" - << blockStart; - if (is_linear) { - kerStream << linearInit << inOffsetsStream.str() - << outOffsetStream.str() << '\n'; - if (loop0) kerStream << linearLoop0Start; - kerStream << "\n\n" << opsStream.str(); - if (loop0) kerStream << linearLoop0End; - kerStream << linearEnd; - } else { - if (loop0) { - kerStream << stridedLoop0Init << outOffsetStream.str() << '\n' - << stridedLoop0Start; + kerStream << kernelVoid << funcName << "(\n" + << inParamStream.str() << outParamStream.str() << dimParams + << ")" << blockStart; + if (is_linear) { + kerStream << linearInit << inOffsetsStream.str() + << outOffsetStream.str() << '\n'; + if (loop0) kerStream << linearLoop0Start; + kerStream << "\n\n" << opsStream.str(); + if (loop0) kerStream << linearLoop0End; + kerStream << linearEnd; } else { - kerStream << stridedLoopNInit << outOffsetStream.str() << '\n'; - if (loop3) kerStream << stridedLoop3Init; - if (loop1) kerStream << stridedLoop1Init << stridedLoop1Start; - if (loop3) kerStream << stridedLoop3Start; + if (loop0) { + kerStream << stridedLoop0Init << outOffsetStream.str() << '\n' + << stridedLoop0Start; + } else { + kerStream << stridedLoopNInit << outOffsetStream.str() << '\n'; + if (loop3) kerStream << stridedLoop3Init; + if (loop1) kerStream << stridedLoop1Init << stridedLoop1Start; + if (loop3) kerStream << stridedLoop3Start; + } + kerStream << "\n\n" << inOffsetsStream.str() << opsStream.str(); + if (loop3) kerStream << stridedLoop3End; + if (loop1) kerStream << stridedLoop1End; + if (loop0) kerStream << stridedLoop0End; + kerStream << stridedEnd; } - kerStream << "\n\n" << inOffsetsStream.str() << opsStream.str(); - if (loop3) kerStream << stridedLoop3End; - if (loop1) kerStream << stridedLoop1End; - if (loop0) kerStream << stridedLoop0End; - kerStream << stridedEnd; + kerStream << blockEnd; + ret = kerStream.str(); + } catch (...) { + // Prepare for next round + inParamStream.str(""); + outParamStream.str(""); + inOffsetsStream.str(""); + outOffsetStream.str(""); + opsStream.str(""); + kerStream.str(""); + throw; } - kerStream << blockEnd; - const string ret{kerStream.str()}; - // Prepare for next round, limit memory + // Prepare for next round inParamStream.str(""); outParamStream.str(""); inOffsetsStream.str(""); @@ -259,8 +274,9 @@ cl::Kernel getKernel(const vector& output_nodes, const vector& full_nodes, const vector& full_ids, const bool is_linear, const bool loop0, const bool loop1, const bool loop3) { - const string funcName{getFuncName(output_nodes, full_nodes, full_ids, - is_linear, loop0, loop1, false, loop3)}; + const string funcName{getFuncName(output_nodes, output_ids, full_nodes, + full_ids, is_linear, loop0, loop1, false, + loop3)}; // A forward lookup in module cache helps avoid recompiling the JIT // source generated from identical JIT-trees. const auto entry{ diff --git a/src/backend/opencl/join.cpp b/src/backend/opencl/join.cpp index 22875d0e61..7975ecfb5a 100644 --- a/src/backend/opencl/join.cpp +++ b/src/backend/opencl/join.cpp @@ -227,6 +227,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) @@ -247,6 +248,7 @@ INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(half) diff --git a/src/backend/opencl/kernel/KParam.hpp b/src/backend/opencl/kernel/KParam.hpp index 165bec9b02..1f4f1d5ba4 100644 --- a/src/backend/opencl/kernel/KParam.hpp +++ b/src/backend/opencl/kernel/KParam.hpp @@ -17,7 +17,7 @@ #endif // Defines the size and shape of the data in the OpenCL buffer -typedef struct { +typedef struct KParam_t { dim_t dims[4]; dim_t strides[4]; dim_t offset; diff --git a/src/backend/opencl/kernel/convolve/conv1.cpp b/src/backend/opencl/kernel/convolve/conv1.cpp index 10ae600888..5bfa9668d6 100644 --- a/src/backend/opencl/kernel/convolve/conv1.cpp +++ b/src/backend/opencl/kernel/convolve/conv1.cpp @@ -58,6 +58,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/opencl/kernel/convolve/conv2_s8.cpp b/src/backend/opencl/kernel/convolve/conv2_s8.cpp new file mode 100644 index 0000000000..b4b39b3f28 --- /dev/null +++ b/src/backend/opencl/kernel/convolve/conv2_s8.cpp @@ -0,0 +1,20 @@ +/******************************************************* + * Copyright (c) 2023, ArrayFire + * All rights reserved. + * + * This file is distributed under 3-clause BSD license. + * The complete license agreement can be obtained at: + * http://arrayfire.com/licenses/BSD-3-Clause + ********************************************************/ + +#include + +namespace arrayfire { +namespace opencl { +namespace kernel { + +INSTANTIATE(schar, float) + +} // namespace kernel +} // namespace opencl +} // namespace arrayfire diff --git a/src/backend/opencl/kernel/convolve/conv3.cpp b/src/backend/opencl/kernel/convolve/conv3.cpp index 9a1baf9c6b..1383e8f443 100644 --- a/src/backend/opencl/kernel/convolve/conv3.cpp +++ b/src/backend/opencl/kernel/convolve/conv3.cpp @@ -45,6 +45,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/opencl/kernel/convolve_separable.cpp b/src/backend/opencl/kernel/convolve_separable.cpp index 41bfa55dde..83a9116d72 100644 --- a/src/backend/opencl/kernel/convolve_separable.cpp +++ b/src/backend/opencl/kernel/convolve_separable.cpp @@ -95,6 +95,7 @@ INSTANTIATE(double, double) INSTANTIATE(float, float) INSTANTIATE(uint, float) INSTANTIATE(int, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(char, float) INSTANTIATE(ushort, float) diff --git a/src/backend/opencl/kernel/coo2dense.cl b/src/backend/opencl/kernel/coo2dense.cl index f86c073621..85afbfcd4b 100644 --- a/src/backend/opencl/kernel/coo2dense.cl +++ b/src/backend/opencl/kernel/coo2dense.cl @@ -11,18 +11,15 @@ kernel void coo2Dense(global T *oPtr, const KParam output, global const T *vPtr, const KParam values, global const int *rPtr, const KParam rowIdx, global const int *cPtr, const KParam colIdx) { - const int id = get_group_id(0) * get_local_size(0) * reps + get_local_id(0); - - if (id >= values.dims[0]) return; - const int dimSize = get_local_size(0); for (int i = get_local_id(0); i < reps * dimSize; i += dimSize) { - if (i >= values.dims[0]) return; + const int id = i + get_group_id(0) * dimSize * reps; + if (id >= values.dims[0]) return; - T v = vPtr[i]; - int r = rPtr[i]; - int c = cPtr[i]; + T v = vPtr[id + values.offset]; + int r = rPtr[id + rowIdx.offset]; + int c = cPtr[id + colIdx.offset]; int offset = r + c * output.strides[1]; diff --git a/src/backend/opencl/kernel/cscmv.cl b/src/backend/opencl/kernel/cscmv.cl index fab18301a1..bc56f57e46 100644 --- a/src/backend/opencl/kernel/cscmv.cl +++ b/src/backend/opencl/kernel/cscmv.cl @@ -7,6 +7,10 @@ * http://arrayfire.com/licenses/BSD-3-Clause ********************************************************/ +#if IS_DBL || IS_LONG +#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable +#endif + #if IS_CPLX T __cmul(T lhs, T rhs) { T out; @@ -35,100 +39,70 @@ T __ccmul(T lhs, T rhs) { #define CMUL(a, b) (a) * (b) #endif -int binary_search(global const int *ptr, int len, int val) { - int start = 0; - int end = len; - while (end > start) { - int mid = start + (end - start) / 2; - if (val < ptr[mid]) { - end = mid; - } else if (val > ptr[mid]) { - start = mid + 1; - } else { - return mid; - } - } - return start; +#if IS_DBL || IS_LONG +#define U ulong +#define ATOMIC_FN atom_cmpxchg +#else +#define U unsigned +#define ATOMIC_FN atomic_cmpxchg +#endif + +#if IS_CPLX +inline void atomicAdd(volatile __global T *ptr, T val) { + union { + U u[2]; + T t; + } next, expected, current; + current.t = *ptr; + + do { + expected.t.x = current.t.x; + next.t.x = expected.t.x + val.x; + current.u[0] = ATOMIC_FN((volatile __global U *) ptr, expected.u[0], next.u[0]); + } while(current.u[0] != expected.u[0]); + do { + expected.t.y = current.t.y; + next.t.y = expected.t.y + val.y; + current.u[1] = ATOMIC_FN(((volatile __global U *) ptr) + 1, expected.u[1], next.u[1]); + } while(current.u[1] != expected.u[1]); +} +#else +inline void atomicAdd(volatile __global T *ptr, T val) { + union { + U u; + T t; + } next, expected, current; + current.t = *ptr; + + do { + expected.t = current.t; + next.t = expected.t + val; + current.u = ATOMIC_FN((volatile __global U *) ptr, expected.u, next.u); + } while(current.u != expected.u); +} +#endif + +kernel void cscmv_beta(global T *output, const int M, const T beta) { + for(unsigned j = get_global_id(0); j < M; j += THREADS * get_num_groups(0)) + output[j] *= beta; } -// Each thread performs Matrix Vector multiplications for ROWS_PER_GROUP rows -// and (K / THREAD) columns. This generates a local output buffer of size -// ROWS_PER_THREAD for each thread. The outputs from each thread are added up to -// generate the final result. -kernel void cscmv_block( - global T *output, __global const T *values, - global const int *colidx, // rowidx from csr is colidx in csc - global const int *rowidx, // colidx from csr is rowidx in csc - const int M, // K from csr is M in csc +kernel void cscmv_atomic( + global T *output, __global T *values, + global int *colidx, // rowidx from csr is colidx in csc + global int *rowidx, // colidx from csr is rowidx in csc const int K, // M from csr is K in csc - global const T *rhs, const KParam rinfo, const T alpha, const T beta) { - int lid = get_local_id(0); + global const T *rhs, const KParam rinfo, const T alpha) { - // Get the row offset for the current group in the uncompressed matrix - int rowOff = get_group_id(0) * ROWS_PER_GROUP; - int rowLim = min(ROWS_PER_GROUP, M - rowOff); rhs += rinfo.offset; - T l_outvals[ROWS_PER_GROUP]; - for (int i = 0; i < rowLim; i++) { l_outvals[i] = 0; } - - for (int colId = lid; colId < K; colId += THREADS) { - int rowStart = colidx[colId]; - int rowEnd = colidx[colId + 1]; - int nonZeroCount = rowEnd - rowStart; - - // Find the location of the next non zero element after rowOff - int rowPos = binary_search(rowidx + rowStart, nonZeroCount, rowOff); - T rhsval = rhs[colId]; - - // Traversing through nonzero elements in the current chunk - for (int id = rowPos + rowStart; id < rowEnd; id++) { - int rowId = rowidx[id]; - - // Exit if moving past current chunk - if (rowId >= rowOff + ROWS_PER_GROUP) break; - - l_outvals[rowId - rowOff] += CMUL(values[id], rhsval); - } - } - - // s_outvals is used for reduction - local T s_outvals[THREADS]; - - // s_output is used to store the final output into local memory - local T s_output[ROWS_PER_GROUP]; - - // For each row of output, copy registers to local memory, add results, - // write to output. - for (int i = 0; i < rowLim; i++) { - // Copying to local memory - s_outvals[lid] = l_outvals[i]; - barrier(CLK_LOCAL_MEM_FENCE); - - // Adding the results through reduction - for (int n = THREADS / 2; n > 0; n /= 2) { - if (lid < n) s_outvals[lid] += s_outvals[lid + n]; - barrier(CLK_LOCAL_MEM_FENCE); - } - - // Store to another local buffer so it can be written in a coalesced - // manner later - if (lid == 0) { s_output[i] = s_outvals[0]; } - } - barrier(CLK_LOCAL_MEM_FENCE); - - // For each row in output, write output in coalesced manner - for (int i = lid; i < ROWS_PER_GROUP; i += THREADS) { - T outval = s_output[i]; - + for(unsigned j = get_group_id(0); j < K; j += get_num_groups(0)) { + for(unsigned i = get_local_id(0) + colidx[j]; i < colidx[j + 1]; i += THREADS) { + T outval = CMUL(values[i], rhs[j]); #if USE_ALPHA - outval = MUL(alpha, outval); -#endif - -#if USE_BETA - output[rowOff + i] = outval + MUL(beta, output[j * M + rowOff + i]); -#else - output[rowOff + i] = outval; + outval = MUL(alpha, outval); #endif + atomicAdd(output + rowidx[i], outval); + } } } diff --git a/src/backend/opencl/kernel/cscmv.hpp b/src/backend/opencl/kernel/cscmv.hpp index 88008480f8..2ab88b202c 100644 --- a/src/backend/opencl/kernel/cscmv.hpp +++ b/src/backend/opencl/kernel/cscmv.hpp @@ -32,39 +32,64 @@ void cscmv(Param out, const Param &values, const Param &colIdx, bool is_conj) { // TODO: rows_per_group limited by register pressure. Find better way to // handle this. + constexpr int threads_per_g = 64; constexpr int rows_per_group = 64; const bool use_alpha = (alpha != scalar(1.0)); const bool use_beta = (beta != scalar(0.0)); - cl::NDRange local(THREADS_PER_GROUP); + cl::NDRange local(threads_per_g); - std::array targs = { + int K = colIdx.info.dims[0] - 1; + int M = out.info.dims[0]; + + std::array targs = { TemplateTypename(), TemplateArg(use_alpha), - TemplateArg(use_beta), TemplateArg(is_conj), - TemplateArg(rows_per_group), TemplateArg(local[0]), + TemplateArg(is_conj), TemplateArg(rows_per_group), + TemplateArg(local[0]), }; - std::array options = { + std::array options = { DefineKeyValue(T, dtype_traits::getName()), DefineKeyValue(USE_ALPHA, use_alpha), - DefineKeyValue(USE_BETA, use_beta), DefineKeyValue(IS_CONJ, is_conj), DefineKeyValue(THREADS, local[0]), DefineKeyValue(ROWS_PER_GROUP, rows_per_group), DefineKeyValue(IS_CPLX, (iscplx() ? 1 : 0)), + DefineKeyValue(IS_DBL, (isdbl() ? 1 : 0)), + DefineKeyValue(IS_LONG, (islong() ? 1 : 0)), getTypeBuildDefinition()}; - auto cscmvBlock = - common::getKernel("cscmv_block", {{cscmv_cl_src}}, targs, options); + if(use_beta) { + std::array targs_beta = { + TemplateTypename(), TemplateArg(is_conj), + TemplateArg(rows_per_group), TemplateArg(local[0])}; + std::array options_beta = { + DefineKeyValue(T, dtype_traits::getName()), + DefineKeyValue(IS_CONJ, is_conj), + DefineKeyValue(THREADS, local[0]), + DefineKeyValue(ROWS_PER_GROUP, rows_per_group), + DefineKeyValue(IS_CPLX, (iscplx() ? 1 : 0)), + DefineKeyValue(IS_DBL, (isdbl() ? 1 : 0)), + DefineKeyValue(IS_LONG, (islong() ? 1 : 0)), + getTypeBuildDefinition()}; + + int groups_x = divup(M, rows_per_group * threads_per_g); + cl::NDRange global(local[0] * groups_x, 1); + auto cscmvBeta = common::getKernel("cscmv_beta", {{cscmv_cl_src}}, targs_beta, options_beta); + cscmvBeta(cl::EnqueueArgs(getQueue(), global, local), *out.data, M, beta); + + } else { + getQueue().enqueueFillBuffer(*out.data, 0, 0, M * sizeof(T)); + } - int K = colIdx.info.dims[0] - 1; - int M = out.info.dims[0]; int groups_x = divup(M, rows_per_group); cl::NDRange global(local[0] * groups_x, 1); - cscmvBlock(cl::EnqueueArgs(getQueue(), global, local), *out.data, - *values.data, *colIdx.data, *rowIdx.data, M, K, *rhs.data, - rhs.info, alpha, beta); + auto cscmvAtomic = + common::getKernel("cscmv_atomic", {{cscmv_cl_src}}, targs, options); + cscmvAtomic(cl::EnqueueArgs(getQueue(), global, local), *out.data, + *values.data, *colIdx.data, *rowIdx.data, K, *rhs.data, + rhs.info, alpha); CL_DEBUG_FINISH(getQueue()); } } // namespace kernel diff --git a/src/backend/opencl/kernel/csr2dense.cl b/src/backend/opencl/kernel/csr2dense.cl index 15a7c0c60d..e15ef014f3 100644 --- a/src/backend/opencl/kernel/csr2dense.cl +++ b/src/backend/opencl/kernel/csr2dense.cl @@ -9,13 +9,16 @@ kernel void csr2Dense(global T *output, global const T *values, global const int *rowidx, global const int *colidx, - const int M) { + const int M, const int v_off, const int r_off, const int c_off) { + T *v = values + v_off; + int *r = rowidx + r_off; + int *c = colidx + c_off; int lid = get_local_id(0); for (int rowId = get_group_id(0); rowId < M; rowId += get_num_groups(0)) { - int colStart = rowidx[rowId]; - int colEnd = rowidx[rowId + 1]; + int colStart = r[rowId]; + int colEnd = r[rowId + 1]; for (int colId = colStart + lid; colId < colEnd; colId += THREADS) { - output[rowId + colidx[colId] * M] = values[colId]; + output[rowId + c[colId] * M] = v[colId]; } } } diff --git a/src/backend/opencl/kernel/flood_fill.cl b/src/backend/opencl/kernel/flood_fill.cl index 0a7916fd49..ba8f8e109a 100644 --- a/src/backend/opencl/kernel/flood_fill.cl +++ b/src/backend/opencl/kernel/flood_fill.cl @@ -42,13 +42,7 @@ int barrierOR(local int *predicates) { barrier(CLK_LOCAL_MEM_FENCE); } int retVal = predicates[0]; -#if AF_IS_PLATFORM_NVIDIA - // Without the extra barrier sync after reading the reduction result, - // the caller's loop is going into infinite loop occasionally which is - // in turn randoms hangs. This doesn't seem to be an issue on non-nvidia - // hardware. Hence, the check. barrier(CLK_LOCAL_MEM_FENCE); -#endif return retVal; } diff --git a/src/backend/opencl/kernel/flood_fill.hpp b/src/backend/opencl/kernel/flood_fill.hpp index 793ae5adcd..8035a61fd6 100644 --- a/src/backend/opencl/kernel/flood_fill.hpp +++ b/src/backend/opencl/kernel/flood_fill.hpp @@ -84,8 +84,6 @@ void floodFill(Param out, const Param image, const Param seedsx, DefineKeyValue(LMEM_WIDTH, (THREADS_X + 2 * RADIUS)), DefineKeyValue(LMEM_HEIGHT, (THREADS_Y + 2 * RADIUS)), DefineKeyValue(GROUP_SIZE, (THREADS_Y * THREADS_X)), - DefineKeyValue(AF_IS_PLATFORM_NVIDIA, (int)(AFCL_PLATFORM_NVIDIA == - getActivePlatformVendor())), getTypeBuildDefinition()}; auto floodStep = diff --git a/src/backend/opencl/kernel/index.cl b/src/backend/opencl/kernel/index.cl index 85e6e10cc0..2cc3cb57fe 100644 --- a/src/backend/opencl/kernel/index.cl +++ b/src/backend/opencl/kernel/index.cl @@ -10,6 +10,7 @@ typedef struct { int offs[4]; int strds[4]; + int steps[4]; char isSeq[4]; } IndexKernelParam_t; @@ -47,14 +48,18 @@ kernel void indexKernel(global T* optr, KParam oInfo, global const T* iptr, if (gx < oInfo.dims[0] && gy < oInfo.dims[1] && gz < oInfo.dims[2] && gw < oInfo.dims[3]) { // calculate pointer offsets for input - int i = p.strds[0] * - trimIndex(s0 ? gx + p.offs[0] : ptr0[gx], iInfo.dims[0]); - int j = p.strds[1] * - trimIndex(s1 ? gy + p.offs[1] : ptr1[gy], iInfo.dims[1]); - int k = p.strds[2] * - trimIndex(s2 ? gz + p.offs[2] : ptr2[gz], iInfo.dims[2]); - int l = p.strds[3] * - trimIndex(s3 ? gw + p.offs[3] : ptr3[gw], iInfo.dims[3]); + int i = + p.strds[0] * trimIndex(s0 ? gx * p.steps[0] + p.offs[0] : ptr0[gx], + iInfo.dims[0]); + int j = + p.strds[1] * trimIndex(s1 ? gy * p.steps[1] + p.offs[1] : ptr1[gy], + iInfo.dims[1]); + int k = + p.strds[2] * trimIndex(s2 ? gz * p.steps[2] + p.offs[2] : ptr2[gz], + iInfo.dims[2]); + int l = + p.strds[3] * trimIndex(s3 ? gw * p.steps[3] + p.offs[3] : ptr3[gw], + iInfo.dims[3]); // offset input and output pointers global const T* src = iptr + (i + j + k + l) + iInfo.offset; global T* dst = optr + (gx * oInfo.strides[0] + gy * oInfo.strides[1] + diff --git a/src/backend/opencl/kernel/index.hpp b/src/backend/opencl/kernel/index.hpp index 9433893b96..5362a8e78b 100644 --- a/src/backend/opencl/kernel/index.hpp +++ b/src/backend/opencl/kernel/index.hpp @@ -26,6 +26,7 @@ namespace kernel { typedef struct { int offs[4]; int strds[4]; + int steps[4]; char isSeq[4]; } IndexKernelParam_t; diff --git a/src/backend/opencl/kernel/lookup.cl b/src/backend/opencl/kernel/lookup.cl index 622a47e8f6..7ed4bc1cfa 100644 --- a/src/backend/opencl/kernel/lookup.cl +++ b/src/backend/opencl/kernel/lookup.cl @@ -31,7 +31,7 @@ kernel void lookupND(global in_t *out, KParam oInfo, global const in_t *in, int gx = get_local_size(0) * (get_group_id(0) - gz * nBBS0) + lx; int gy = get_local_size(1) * (get_group_id(1) - gw * nBBS1) + ly; - global const idx_t *idxPtr = indices; + global const idx_t *idxPtr = indices + idxInfo.offset; int i = iInfo.strides[0] * (DIM == 0 ? trimIndex((int)idxPtr[gx], iInfo.dims[0]) : gx); diff --git a/src/backend/opencl/kernel/random_engine_write.cl b/src/backend/opencl/kernel/random_engine_write.cl index 8711987e44..c36c5f1d6d 100644 --- a/src/backend/opencl/kernel/random_engine_write.cl +++ b/src/backend/opencl/kernel/random_engine_write.cl @@ -27,6 +27,26 @@ float getFloatNegative11(uint num) { // Writes without boundary checking +void writeOut128Bytes_schar(global char *out, uint index, uint r1, uint r2, + uint r3, uint r4) { + out[index] = r1; + out[index + THREADS] = r1 >> 8; + out[index + 2 * THREADS] = r1 >> 16; + out[index + 3 * THREADS] = r1 >> 24; + out[index + 4 * THREADS] = r2; + out[index + 5 * THREADS] = r2 >> 8; + out[index + 6 * THREADS] = r2 >> 16; + out[index + 7 * THREADS] = r2 >> 24; + out[index + 8 * THREADS] = r3; + out[index + 9 * THREADS] = r3 >> 8; + out[index + 10 * THREADS] = r3 >> 16; + out[index + 11 * THREADS] = r3 >> 24; + out[index + 12 * THREADS] = r4; + out[index + 13 * THREADS] = r4 >> 8; + out[index + 14 * THREADS] = r4 >> 16; + out[index + 15 * THREADS] = r4 >> 24; +} + void writeOut128Bytes_uchar(global uchar *out, uint index, uint r1, uint r2, uint r3, uint r4) { out[index] = r1; @@ -154,6 +174,36 @@ void boxMullerTransform(T *const out1, T *const out2, T r1, T r2) { // Writes with boundary checking +void partialWriteOut128Bytes_schar(global char *out, uint index, uint r1, + uint r2, uint r3, uint r4, uint elements) { + if (index < elements) { out[index] = r1; } + if (index + THREADS < elements) { out[index + THREADS] = r1 >> 8; } + if (index + 2 * THREADS < elements) { out[index + 2 * THREADS] = r1 >> 16; } + if (index + 3 * THREADS < elements) { out[index + 3 * THREADS] = r1 >> 24; } + if (index + 4 * THREADS < elements) { out[index + 4 * THREADS] = r2; } + if (index + 5 * THREADS < elements) { out[index + 5 * THREADS] = r2 >> 8; } + if (index + 6 * THREADS < elements) { out[index + 6 * THREADS] = r2 >> 16; } + if (index + 7 * THREADS < elements) { out[index + 7 * THREADS] = r2 >> 24; } + if (index + 8 * THREADS < elements) { out[index + 8 * THREADS] = r3; } + if (index + 9 * THREADS < elements) { out[index + 9 * THREADS] = r3 >> 8; } + if (index + 10 * THREADS < elements) { + out[index + 10 * THREADS] = r3 >> 16; + } + if (index + 11 * THREADS < elements) { + out[index + 11 * THREADS] = r3 >> 24; + } + if (index + 12 * THREADS < elements) { out[index + 12 * THREADS] = r4; } + if (index + 13 * THREADS < elements) { + out[index + 13 * THREADS] = r4 >> 8; + } + if (index + 14 * THREADS < elements) { + out[index + 14 * THREADS] = r4 >> 16; + } + if (index + 15 * THREADS < elements) { + out[index + 15 * THREADS] = r4 >> 24; + } +} + void partialWriteOut128Bytes_uchar(global uchar *out, uint index, uint r1, uint r2, uint r3, uint r4, uint elements) { if (index < elements) { out[index] = r1; } diff --git a/src/backend/opencl/kernel/sort_by_key/sort_by_key_impl.cpp b/src/backend/opencl/kernel/sort_by_key/sort_by_key_impl.cpp index dd74cccc7e..dd14eee6c5 100644 --- a/src/backend/opencl/kernel/sort_by_key/sort_by_key_impl.cpp +++ b/src/backend/opencl/kernel/sort_by_key/sort_by_key_impl.cpp @@ -9,7 +9,7 @@ #include -// SBK_TYPES:float double int uint intl uintl short ushort char uchar half +// SBK_TYPES:float double int uint intl uintl short ushort char schar uchar half namespace arrayfire { namespace opencl { diff --git a/src/backend/opencl/kernel/sort_by_key_impl.hpp b/src/backend/opencl/kernel/sort_by_key_impl.hpp index a070a60c67..f03721d01e 100644 --- a/src/backend/opencl/kernel/sort_by_key_impl.hpp +++ b/src/backend/opencl/kernel/sort_by_key_impl.hpp @@ -248,6 +248,7 @@ void sort0ByKey(Param pKey, Param pVal, bool isAscending) { INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, intl) \ INSTANTIATE(Tk, uintl) \ diff --git a/src/backend/opencl/kernel/sparse.hpp b/src/backend/opencl/kernel/sparse.hpp index e1b29c986c..4d3a33d14a 100644 --- a/src/backend/opencl/kernel/sparse.hpp +++ b/src/backend/opencl/kernel/sparse.hpp @@ -39,7 +39,7 @@ void coo2dense(Param out, const Param values, const Param rowIdx, }; std::vector compileOpts = { DefineKeyValue(T, dtype_traits::getName()), - DefineKeyValue(resp, REPEAT), + DefineKeyValue(reps, REPEAT), }; compileOpts.emplace_back(getTypeBuildDefinition()); @@ -49,7 +49,8 @@ void coo2dense(Param out, const Param values, const Param rowIdx, cl::NDRange local(THREADS_PER_GROUP, 1, 1); cl::NDRange global( - divup(out.info.dims[0], local[0] * REPEAT) * THREADS_PER_GROUP, 1, 1); + divup(values.info.dims[0], local[0] * REPEAT) * THREADS_PER_GROUP, 1, + 1); coo2dense(cl::EnqueueArgs(getQueue(), global, local), *out.data, out.info, *values.data, values.info, *rowIdx.data, rowIdx.info, @@ -84,7 +85,10 @@ void csr2dense(Param output, const Param values, const Param rowIdx, cl::NDRange global(local[0] * groups_x, 1); csr2dense(cl::EnqueueArgs(getQueue(), global, local), *output.data, - *values.data, *rowIdx.data, *colIdx.data, M); + *values.data, *rowIdx.data, *colIdx.data, M, + static_cast(values.info.offset), + static_cast(rowIdx.info.offset), + static_cast(colIdx.info.offset)); CL_DEBUG_FINISH(getQueue()); } diff --git a/src/backend/opencl/lookup.cpp b/src/backend/opencl/lookup.cpp index 2fee6f6ae0..83bca0ac44 100644 --- a/src/backend/opencl/lookup.cpp +++ b/src/backend/opencl/lookup.cpp @@ -25,8 +25,8 @@ Array lookup(const Array &input, const Array &indices, const dim4 &iDims = input.dims(); dim4 oDims(1); - for (int d = 0; d < 4; ++d) { - oDims[d] = (d == int(dim) ? indices.elements() : iDims[d]); + for (dim_t d = 0; d < 4; ++d) { + oDims[d] = (d == dim ? indices.elements() : iDims[d]); } Array out = createEmptyArray(oDims); @@ -53,6 +53,8 @@ Array lookup(const Array &input, const Array &indices, const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ + template Array lookup(const Array &, const Array &, \ + const unsigned); \ template Array lookup(const Array &, const Array &, \ const unsigned); \ template Array lookup(const Array &, const Array &, \ @@ -66,6 +68,7 @@ INSTANTIATE(int); INSTANTIATE(unsigned); INSTANTIATE(intl); INSTANTIATE(uintl); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(char); INSTANTIATE(ushort); diff --git a/src/backend/opencl/match_template.cpp b/src/backend/opencl/match_template.cpp index f97bc6d353..7f02d886b3 100644 --- a/src/backend/opencl/match_template.cpp +++ b/src/backend/opencl/match_template.cpp @@ -37,6 +37,7 @@ INSTANTIATE(float, float) INSTANTIATE(char, float) INSTANTIATE(int, float) INSTANTIATE(uint, float) +INSTANTIATE(schar, float) INSTANTIATE(uchar, float) INSTANTIATE(short, float) INSTANTIATE(ushort, float) diff --git a/src/backend/opencl/math.hpp b/src/backend/opencl/math.hpp index e4745d9e92..f164c3002c 100644 --- a/src/backend/opencl/math.hpp +++ b/src/backend/opencl/math.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #if defined(__GNUC__) || defined(__GNUG__) diff --git a/src/backend/opencl/max.cpp b/src/backend/opencl/max.cpp index b2a2cdfdf0..695415517d 100644 --- a/src/backend/opencl/max.cpp +++ b/src/backend/opencl/max.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_max_t, uint, uint) INSTANTIATE(af_max_t, intl, intl) INSTANTIATE(af_max_t, uintl, uintl) INSTANTIATE(af_max_t, char, char) +INSTANTIATE(af_max_t, schar, schar) INSTANTIATE(af_max_t, uchar, uchar) INSTANTIATE(af_max_t, short, short) INSTANTIATE(af_max_t, ushort, ushort) diff --git a/src/backend/opencl/mean.cpp b/src/backend/opencl/mean.cpp index 7bd586e587..428c2812c3 100644 --- a/src/backend/opencl/mean.cpp +++ b/src/backend/opencl/mean.cpp @@ -59,6 +59,7 @@ INSTANTIATE(intl, double, double); INSTANTIATE(uintl, double, double); INSTANTIATE(short, float, float); INSTANTIATE(ushort, float, float); +INSTANTIATE(schar, float, float); INSTANTIATE(uchar, float, float); INSTANTIATE(char, float, float); INSTANTIATE(cfloat, float, cfloat); diff --git a/src/backend/opencl/meanshift.cpp b/src/backend/opencl/meanshift.cpp index 3c6f140c98..9eaec9db9d 100644 --- a/src/backend/opencl/meanshift.cpp +++ b/src/backend/opencl/meanshift.cpp @@ -38,6 +38,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/medfilt.cpp b/src/backend/opencl/medfilt.cpp index 66a4c6969e..d3025a50b9 100644 --- a/src/backend/opencl/medfilt.cpp +++ b/src/backend/opencl/medfilt.cpp @@ -55,6 +55,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/memory.cpp b/src/backend/opencl/memory.cpp index d2e0190431..7c69b33e24 100644 --- a/src/backend/opencl/memory.cpp +++ b/src/backend/opencl/memory.cpp @@ -162,6 +162,7 @@ INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/opencl/min.cpp b/src/backend/opencl/min.cpp index 9cc6a09272..75c117caa8 100644 --- a/src/backend/opencl/min.cpp +++ b/src/backend/opencl/min.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_min_t, uint, uint) INSTANTIATE(af_min_t, intl, intl) INSTANTIATE(af_min_t, uintl, uintl) INSTANTIATE(af_min_t, char, char) +INSTANTIATE(af_min_t, schar, schar) INSTANTIATE(af_min_t, uchar, uchar) INSTANTIATE(af_min_t, short, short) INSTANTIATE(af_min_t, ushort, ushort) diff --git a/src/backend/opencl/moments.cpp b/src/backend/opencl/moments.cpp index 0b03d203c9..80afc2ece1 100644 --- a/src/backend/opencl/moments.cpp +++ b/src/backend/opencl/moments.cpp @@ -47,6 +47,7 @@ INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(ushort) diff --git a/src/backend/opencl/morph.cpp b/src/backend/opencl/morph.cpp index e77b7a063c..a1cb86aa03 100644 --- a/src/backend/opencl/morph.cpp +++ b/src/backend/opencl/morph.cpp @@ -57,6 +57,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/nearest_neighbour.cpp b/src/backend/opencl/nearest_neighbour.cpp index 535be4083f..615165a8e5 100644 --- a/src/backend/opencl/nearest_neighbour.cpp +++ b/src/backend/opencl/nearest_neighbour.cpp @@ -80,6 +80,7 @@ INSTANTIATE(intl, intl) INSTANTIATE(uintl, uintl) INSTANTIATE(short, int) INSTANTIATE(ushort, uint) +INSTANTIATE(schar, int) INSTANTIATE(uchar, uint) INSTANTIATE(uintl, uint) // For Hamming diff --git a/src/backend/opencl/platform.cpp b/src/backend/opencl/platform.cpp index d6406a32e1..b6886c97bb 100644 --- a/src/backend/opencl/platform.cpp +++ b/src/backend/opencl/platform.cpp @@ -337,7 +337,11 @@ const std::string& getActiveDeviceBaseBuildFlags() { } vector getOpenCLCDeviceVersion(const Device& device) { - Platform device_platform(device.getInfo(), false); + // For OpenCL-HPP >= v2023.12.14 type is cl::Platform instead of + // cl_platform_id + Platform device_platform; + device_platform = device.getInfo(); + auto platform_version = device_platform.getInfo(); vector out; @@ -540,10 +544,13 @@ void addDeviceContext(cl_device_id dev, cl_context ctx, cl_command_queue que) { devMngr.mDeviceTypes.push_back( static_cast(tDevice.getInfo())); - auto device_platform = tDevice.getInfo(); + // For OpenCL-HPP >= v2023.12.14 type is cl::Platform instead of + // cl_platform_id + cl::Platform device_platform; + device_platform = tDevice.getInfo(); devMngr.mPlatforms.push_back( std::make_pair, afcl_platform>( - make_unique(device_platform, true), + make_unique(device_platform(), true), getPlatformEnum(tDevice))); devMngr.mDevices.emplace_back(make_unique(move(tDevice))); diff --git a/src/backend/opencl/plot.cpp b/src/backend/opencl/plot.cpp index cc7f93262e..5b7dfa69cb 100644 --- a/src/backend/opencl/plot.cpp +++ b/src/backend/opencl/plot.cpp @@ -75,6 +75,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace opencl diff --git a/src/backend/opencl/product.cpp b/src/backend/opencl/product.cpp index f13a9b9ae3..a949f87345 100644 --- a/src/backend/opencl/product.cpp +++ b/src/backend/opencl/product.cpp @@ -24,6 +24,7 @@ INSTANTIATE(af_mul_t, uint, uint) INSTANTIATE(af_mul_t, intl, intl) INSTANTIATE(af_mul_t, uintl, uintl) INSTANTIATE(af_mul_t, char, int) +INSTANTIATE(af_mul_t, schar, int) INSTANTIATE(af_mul_t, uchar, uint) INSTANTIATE(af_mul_t, short, int) INSTANTIATE(af_mul_t, ushort, uint) diff --git a/src/backend/opencl/random_engine.cpp b/src/backend/opencl/random_engine.cpp index f2110c8be0..d307e54c2b 100644 --- a/src/backend/opencl/random_engine.cpp +++ b/src/backend/opencl/random_engine.cpp @@ -138,6 +138,7 @@ INSTANTIATE_UNIFORM(uint) INSTANTIATE_UNIFORM(intl) INSTANTIATE_UNIFORM(uintl) INSTANTIATE_UNIFORM(char) +INSTANTIATE_UNIFORM(schar) INSTANTIATE_UNIFORM(uchar) INSTANTIATE_UNIFORM(short) INSTANTIATE_UNIFORM(ushort) diff --git a/src/backend/opencl/range.cpp b/src/backend/opencl/range.cpp index 92340d34eb..a49ba931c8 100644 --- a/src/backend/opencl/range.cpp +++ b/src/backend/opencl/range.cpp @@ -47,6 +47,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/reorder.cpp b/src/backend/opencl/reorder.cpp index da485911e6..ecacccd677 100644 --- a/src/backend/opencl/reorder.cpp +++ b/src/backend/opencl/reorder.cpp @@ -40,6 +40,7 @@ INSTANTIATE(cfloat) INSTANTIATE(cdouble) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(intl) diff --git a/src/backend/opencl/resize.cpp b/src/backend/opencl/resize.cpp index ee7776b82f..bf3a8497b2 100644 --- a/src/backend/opencl/resize.cpp +++ b/src/backend/opencl/resize.cpp @@ -38,6 +38,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/rotate.cpp b/src/backend/opencl/rotate.cpp index 46caa65c88..eab0c1da26 100644 --- a/src/backend/opencl/rotate.cpp +++ b/src/backend/opencl/rotate.cpp @@ -49,6 +49,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/scan.cpp b/src/backend/opencl/scan.cpp index 0fc36366ef..649789ef91 100644 --- a/src/backend/opencl/scan.cpp +++ b/src/backend/opencl/scan.cpp @@ -43,6 +43,7 @@ Array scan(const Array& in, const int dim, bool inclusiveScan) { INSTANTIATE_SCAN(ROp, intl, intl) \ INSTANTIATE_SCAN(ROp, uintl, uintl) \ INSTANTIATE_SCAN(ROp, char, uint) \ + INSTANTIATE_SCAN(ROp, schar, int) \ INSTANTIATE_SCAN(ROp, uchar, uint) \ INSTANTIATE_SCAN(ROp, short, int) \ INSTANTIATE_SCAN(ROp, ushort, uint) diff --git a/src/backend/opencl/select.cpp b/src/backend/opencl/select.cpp index bbafbe989c..20c900007a 100644 --- a/src/backend/opencl/select.cpp +++ b/src/backend/opencl/select.cpp @@ -127,6 +127,7 @@ INSTANTIATE(uint); INSTANTIATE(intl); INSTANTIATE(uintl); INSTANTIATE(char); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(short); INSTANTIATE(ushort); diff --git a/src/backend/opencl/set.cpp b/src/backend/opencl/set.cpp index 195cf23047..1c1b74396c 100644 --- a/src/backend/opencl/set.cpp +++ b/src/backend/opencl/set.cpp @@ -147,6 +147,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/shift.cpp b/src/backend/opencl/shift.cpp index 8b257f2c97..19e37286d3 100644 --- a/src/backend/opencl/shift.cpp +++ b/src/backend/opencl/shift.cpp @@ -64,6 +64,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/sobel.cpp b/src/backend/opencl/sobel.cpp index e718021b42..a7651de07d 100644 --- a/src/backend/opencl/sobel.cpp +++ b/src/backend/opencl/sobel.cpp @@ -40,6 +40,7 @@ INSTANTIATE(double, double) INSTANTIATE(int, int) INSTANTIATE(uint, int) INSTANTIATE(char, int) +INSTANTIATE(schar, int) INSTANTIATE(uchar, int) INSTANTIATE(short, int) INSTANTIATE(ushort, int) diff --git a/src/backend/opencl/sort.cpp b/src/backend/opencl/sort.cpp index 8b977316f1..e2bfcaa057 100644 --- a/src/backend/opencl/sort.cpp +++ b/src/backend/opencl/sort.cpp @@ -56,6 +56,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/sort_by_key.cpp b/src/backend/opencl/sort_by_key.cpp index 2e4b2dd616..f1a89aef4d 100644 --- a/src/backend/opencl/sort_by_key.cpp +++ b/src/backend/opencl/sort_by_key.cpp @@ -69,6 +69,7 @@ void sort_by_key(Array &okey, Array &oval, const Array &ikey, INSTANTIATE(Tk, short) \ INSTANTIATE(Tk, ushort) \ INSTANTIATE(Tk, char) \ + INSTANTIATE(Tk, schar) \ INSTANTIATE(Tk, uchar) \ INSTANTIATE(Tk, intl) \ INSTANTIATE(Tk, uintl) @@ -80,6 +81,7 @@ INSTANTIATE1(uint) INSTANTIATE1(short) INSTANTIATE1(ushort) INSTANTIATE1(char) +INSTANTIATE1(schar) INSTANTIATE1(uchar) INSTANTIATE1(intl) INSTANTIATE1(uintl) diff --git a/src/backend/opencl/sort_index.cpp b/src/backend/opencl/sort_index.cpp index 9c92f8406c..4840c24277 100644 --- a/src/backend/opencl/sort_index.cpp +++ b/src/backend/opencl/sort_index.cpp @@ -70,6 +70,7 @@ INSTANTIATE(double) INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/sum.cpp b/src/backend/opencl/sum.cpp index 890280ba92..1ef26bdb89 100644 --- a/src/backend/opencl/sum.cpp +++ b/src/backend/opencl/sum.cpp @@ -29,6 +29,8 @@ INSTANTIATE(af_add_t, uintl, uintl) INSTANTIATE(af_add_t, uintl, double) INSTANTIATE(af_add_t, char, int) INSTANTIATE(af_add_t, char, float) +INSTANTIATE(af_add_t, schar, int) +INSTANTIATE(af_add_t, schar, float) INSTANTIATE(af_add_t, uchar, uint) INSTANTIATE(af_add_t, uchar, float) INSTANTIATE(af_add_t, short, int) diff --git a/src/backend/opencl/surface.cpp b/src/backend/opencl/surface.cpp index a0de95fb19..7a2e15276b 100644 --- a/src/backend/opencl/surface.cpp +++ b/src/backend/opencl/surface.cpp @@ -78,6 +78,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace opencl diff --git a/src/backend/opencl/susan.cpp b/src/backend/opencl/susan.cpp index 6bd78e2540..91b011120b 100644 --- a/src/backend/opencl/susan.cpp +++ b/src/backend/opencl/susan.cpp @@ -66,6 +66,7 @@ INSTANTIATE(double) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/tile.cpp b/src/backend/opencl/tile.cpp index 14e2d5beac..98c7eb2bfb 100644 --- a/src/backend/opencl/tile.cpp +++ b/src/backend/opencl/tile.cpp @@ -41,6 +41,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/traits.hpp b/src/backend/opencl/traits.hpp index 00af1d17b0..2af7257b76 100644 --- a/src/backend/opencl/traits.hpp +++ b/src/backend/opencl/traits.hpp @@ -49,6 +49,36 @@ inline bool iscplx() { return true; } +template +static bool isdbl() { + return false; +} + +template<> +inline bool isdbl() { + return true; +} + +template<> +inline bool isdbl() { + return true; +} + +template +static bool islong() { + return false; +} + +template<> +inline bool islong() { + return true; +} + +template<> +inline bool islong() { + return true; +} + template inline std::string scalar_to_option(const T &val) { using namespace arrayfire::common; diff --git a/src/backend/opencl/transform.cpp b/src/backend/opencl/transform.cpp index 14ee03c962..78428ed3a7 100644 --- a/src/backend/opencl/transform.cpp +++ b/src/backend/opencl/transform.cpp @@ -49,6 +49,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/transpose.cpp b/src/backend/opencl/transpose.cpp index a25fa9be28..248de43017 100644 --- a/src/backend/opencl/transpose.cpp +++ b/src/backend/opencl/transpose.cpp @@ -43,6 +43,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/opencl/transpose_inplace.cpp b/src/backend/opencl/transpose_inplace.cpp index dc23873814..d6b783e5b2 100644 --- a/src/backend/opencl/transpose_inplace.cpp +++ b/src/backend/opencl/transpose_inplace.cpp @@ -39,6 +39,7 @@ INSTANTIATE(cdouble) INSTANTIATE(char) INSTANTIATE(int) INSTANTIATE(uint) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(intl) INSTANTIATE(uintl) diff --git a/src/backend/opencl/triangle.cpp b/src/backend/opencl/triangle.cpp index cb781eeef4..346f8d1af7 100644 --- a/src/backend/opencl/triangle.cpp +++ b/src/backend/opencl/triangle.cpp @@ -47,6 +47,7 @@ INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) INSTANTIATE(char) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/types.cpp b/src/backend/opencl/types.cpp index 35c2b5745a..90393de3f9 100644 --- a/src/backend/opencl/types.cpp +++ b/src/backend/opencl/types.cpp @@ -95,6 +95,7 @@ INSTANTIATE(int); INSTANTIATE(uint); INSTANTIATE(intl); INSTANTIATE(uintl); +INSTANTIATE(schar); INSTANTIATE(uchar); INSTANTIATE(char); INSTANTIATE(half); diff --git a/src/backend/opencl/types.hpp b/src/backend/opencl/types.hpp index 620ab74ca9..48985ab837 100644 --- a/src/backend/opencl/types.hpp +++ b/src/backend/opencl/types.hpp @@ -40,6 +40,7 @@ namespace opencl { using cdouble = cl_double2; using cfloat = cl_float2; using intl = long long; +using schar = cl_char; using uchar = cl_uchar; using uint = cl_uint; using uintl = unsigned long long; @@ -93,6 +94,10 @@ inline const char *shortname(bool caps) { return caps ? "J" : "j"; } template<> +inline const char *shortname(bool caps) { + return caps ? "A" : "a"; // TODO +} +template<> inline const char *shortname(bool caps) { return caps ? "V" : "v"; } @@ -118,6 +123,11 @@ inline const char *getFullName() { return af::dtype_traits::getName(); } +template<> +inline const char *getFullName() { + return "char"; +} + template<> inline const char *getFullName() { return "float2"; diff --git a/src/backend/opencl/unwrap.cpp b/src/backend/opencl/unwrap.cpp index c6c7a12d4f..3fb0d9a14c 100644 --- a/src/backend/opencl/unwrap.cpp +++ b/src/backend/opencl/unwrap.cpp @@ -53,6 +53,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/src/backend/opencl/vector_field.cpp b/src/backend/opencl/vector_field.cpp index e470f73c9a..4d85032602 100644 --- a/src/backend/opencl/vector_field.cpp +++ b/src/backend/opencl/vector_field.cpp @@ -101,6 +101,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(short) INSTANTIATE(ushort) +INSTANTIATE(schar) INSTANTIATE(uchar) } // namespace opencl diff --git a/src/backend/opencl/where.cpp b/src/backend/opencl/where.cpp index c3ac797454..ae86cd8521 100644 --- a/src/backend/opencl/where.cpp +++ b/src/backend/opencl/where.cpp @@ -35,6 +35,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(short) INSTANTIATE(ushort) diff --git a/src/backend/opencl/wrap.cpp b/src/backend/opencl/wrap.cpp index 42d684857a..418dc9bc1f 100644 --- a/src/backend/opencl/wrap.cpp +++ b/src/backend/opencl/wrap.cpp @@ -42,6 +42,7 @@ INSTANTIATE(int) INSTANTIATE(uint) INSTANTIATE(intl) INSTANTIATE(uintl) +INSTANTIATE(schar) INSTANTIATE(uchar) INSTANTIATE(char) INSTANTIATE(short) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cf7e66255f..64e1feb777 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2020, ArrayFire +# Copyright (c) 2025, ArrayFire # All rights reserved. # # This file is distributed under 3-clause BSD license. @@ -20,11 +20,11 @@ if(AF_TEST_WITH_MTX_FILES) endif() if(AF_WITH_EXTERNAL_PACKAGES_ONLY) - dependency_check(GTest_FOUND) + dependency_check(GTest_FOUND "Google Tests not found.") elseif(NOT TARGET GTest::gtest) af_dep_check_and_populate(${gtest_prefix} URI https://github.com/google/googletest.git - REF release-1.12.1 + REF v1.16.0 ) if(WIN32) set(gtest_force_shared_crt ON @@ -99,8 +99,8 @@ if(${AF_USE_RELATIVE_TEST_DIR}) else(${AF_USE_RELATIVE_TEST_DIR}) af_dep_check_and_populate(${testdata_prefix} URI https://github.com/arrayfire/arrayfire-data.git - #pinv large data set update change - REF 0144a599f913cc67c76c9227031b4100156abc25 + #Add test file for SSAS_LinearSteps + REF 05703a4897c8b89b7a0ece1dbe21ede33d226f44 ) set(TESTDATA_SOURCE_DIR "${${testdata_prefix}_SOURCE_DIR}") endif(${AF_USE_RELATIVE_TEST_DIR}) @@ -259,6 +259,11 @@ function(make_test) MTX_TEST_DIR="${ArrayFire_BINARY_DIR}/extern/matrixmarket/" ) endif() + if(AF_SKIP_UNSUPPORTED_TESTS) + target_compile_definitions(${target} + PRIVATE + SKIP_UNSUPPORTED_TESTS) + endif() if(WIN32) target_compile_definitions(${target} PRIVATE @@ -354,6 +359,7 @@ make_test(SRC moments.cpp) make_test(SRC morph.cpp) make_test(SRC nearest_neighbour.cpp CXX11) make_test(SRC nodevice.cpp CXX11) +make_test(SRC norm.cpp CXX11) if(OpenCL_FOUND) make_test(SRC ocl_ext_context.cpp @@ -372,51 +378,53 @@ if(OpenCL_FOUND) CXX11) endif() -if(CUDA_FOUND) - include(AFcuda_helpers) - foreach(backend ${enabled_backends}) - set(cuda_test_backends "cuda" "unified") - if(${backend} IN_LIST cuda_test_backends) - set(target test_cuda_${backend}) - add_executable(${target} cuda.cu) - target_include_directories(${target} - PRIVATE - ${CMAKE_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}) - target_include_directories(${target} - SYSTEM PRIVATE - ${ArrayFire_SOURCE_DIR}/extern/half/include) - if(${backend} STREQUAL "unified") - target_link_libraries(${target} - ArrayFire::af) - else() +if(AF_BUILD_CUDA) + if(CUDA_FOUND) + include(AFcuda_helpers) + foreach(backend ${enabled_backends}) + set(cuda_test_backends "cuda" "unified") + if(${backend} IN_LIST cuda_test_backends) + set(target test_cuda_${backend}) + add_executable(${target} cuda.cu) + target_include_directories(${target} + PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(${target} + SYSTEM PRIVATE + ${ArrayFire_SOURCE_DIR}/extern/half/include) + if(${backend} STREQUAL "unified") + target_link_libraries(${target} + ArrayFire::af) + else() + target_link_libraries(${target} + ArrayFire::af${backend}) + endif() target_link_libraries(${target} - ArrayFire::af${backend}) - endif() - target_link_libraries(${target} - mmio - arrayfire_test) - - # Couldn't get Threads::Threads to work with this cuda binary. The import - # target would not add the -pthread flag which is required for this - # executable (on Ubuntu 18.04 anyway) - check_cxx_compiler_flag(-pthread pthread_flag) - if(pthread_flag) - target_link_libraries(${target} -pthread) - endif() - - af_detect_and_set_cuda_architectures(${target}) - - set_target_properties(${target} - PROPERTIES - FOLDER "Tests" - OUTPUT_NAME "cuda_${backend}") - - if(NOT ${backend} STREQUAL "unified") - af_add_test(${target} ${backend} ON) + mmio + arrayfire_test) + + # Couldn't get Threads::Threads to work with this cuda binary. The import + # target would not add the -pthread flag which is required for this + # executable (on Ubuntu 18.04 anyway) + check_cxx_compiler_flag(-pthread pthread_flag) + if(pthread_flag) + target_link_libraries(${target} -pthread) + endif() + + af_detect_and_set_cuda_architectures(${target}) + + set_target_properties(${target} + PROPERTIES + FOLDER "Tests" + OUTPUT_NAME "cuda_${backend}") + + if(NOT ${backend} STREQUAL "unified") + af_add_test(${target} ${backend} ON) + endif() endif() - endif() - endforeach() + endforeach() + endif() endif() diff --git a/test/anisotropic_diffusion.cpp b/test/anisotropic_diffusion.cpp index afeda45d52..a498d4cdd8 100644 --- a/test/anisotropic_diffusion.cpp +++ b/test/anisotropic_diffusion.cpp @@ -29,7 +29,7 @@ using std::vector; template class AnisotropicDiffusion : public ::testing::Test {}; -typedef ::testing::Types +typedef ::testing::Types TestTypes; TYPED_TEST_SUITE(AnisotropicDiffusion, TestTypes); @@ -98,12 +98,12 @@ void imageTest(string pTestFile, const float dt, const float K, if (isCurvatureDiffusion) { ASSERT_SUCCESS(af_anisotropic_diffusion(&_outArray, inArray, dt, K, - iters, fluxKind, - AF_DIFFUSION_MCDE)); + iters, fluxKind, + AF_DIFFUSION_MCDE)); } else { ASSERT_SUCCESS(af_anisotropic_diffusion(&_outArray, inArray, dt, K, - iters, fluxKind, - AF_DIFFUSION_GRAD)); + iters, fluxKind, + AF_DIFFUSION_GRAD)); } double maxima, minima, imag; @@ -142,6 +142,7 @@ void imageTest(string pTestFile, const float dt, const float K, } TYPED_TEST(AnisotropicDiffusion, GradientGrayscale) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); // Numeric values separated by underscore are arguments to fn being tested. // Divide first value by 1000 to get time step `dt` // Divide second value by 100 to get time step `K` @@ -153,6 +154,7 @@ TYPED_TEST(AnisotropicDiffusion, GradientGrayscale) { } TYPED_TEST(AnisotropicDiffusion, GradientColorImage) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); imageTest( string(TEST_DIR "/gradient_diffusion/color_00125_100_2_exp.test"), 0.125f, 1.0, 2, AF_FLUX_EXPONENTIAL); @@ -166,6 +168,7 @@ TEST(AnisotropicDiffusion, GradientInvalidInputArray) { } TYPED_TEST(AnisotropicDiffusion, CurvatureGrayscale) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); // Numeric values separated by underscore are arguments to fn being tested. // Divide first value by 1000 to get time step `dt` // Divide second value by 100 to get time step `K` @@ -177,6 +180,7 @@ TYPED_TEST(AnisotropicDiffusion, CurvatureGrayscale) { } TYPED_TEST(AnisotropicDiffusion, CurvatureColorImage) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); imageTest( string(TEST_DIR "/curvature_diffusion/color_00125_100_2_mcde.test"), 0.125f, 1.0, 2, AF_FLUX_EXPONENTIAL, true); diff --git a/test/array.cpp b/test/array.cpp index bcf6fa997e..c5befe1fdb 100644 --- a/test/array.cpp +++ b/test/array.cpp @@ -21,8 +21,8 @@ using std::vector; template class Array : public ::testing::Test {}; -typedef ::testing::Types TestTypes; @@ -302,6 +302,17 @@ TYPED_TEST(Array, TypeAttributes) { EXPECT_FALSE(one.isbool()); EXPECT_FALSE(one.ishalf()); break; + case s8: + EXPECT_FALSE(one.isfloating()); + EXPECT_FALSE(one.isdouble()); + EXPECT_FALSE(one.issingle()); + EXPECT_FALSE(one.isrealfloating()); + EXPECT_TRUE(one.isinteger()); + EXPECT_TRUE(one.isreal()); + EXPECT_FALSE(one.iscomplex()); + EXPECT_FALSE(one.isbool()); + EXPECT_FALSE(one.ishalf()); + break; case u8: EXPECT_FALSE(one.isfloating()); EXPECT_FALSE(one.isdouble()); @@ -501,6 +512,29 @@ TEST(DeviceId, Different) { deviceGC(); } +TEST(Device, MigrateAllDevicesToAllDevices) { + int ndevices = getDeviceCount(); + if (ndevices < 2) GTEST_SKIP() << "Skipping mult-GPU test"; + + for (int i = 0; i < ndevices; i++) { + for (int j = 0; j < ndevices; j++) { + setDevice(i); + array a = constant(i * 255, 10, 10); + a.eval(); + + setDevice(j); + array b = constant(j * 256, 10, 10); + b.eval(); + + array c = a + b; + + std::vector gold(10 * 10, i * 255 + j * 256); + + ASSERT_VEC_ARRAY_EQ(gold, dim4(10, 10), c); + } + } +} + TEST(Device, empty) { array a = array(); ASSERT_EQ(a.device(), nullptr); diff --git a/test/arrayfire_test.cpp b/test/arrayfire_test.cpp index 4c6e966220..dedaedbf75 100644 --- a/test/arrayfire_test.cpp +++ b/test/arrayfire_test.cpp @@ -77,6 +77,7 @@ std::ostream &operator<<(std::ostream &os, af::dtype type) { case b8: name = "b8"; break; case s32: name = "s32"; break; case u32: name = "u32"; break; + case s8: name = "s8"; break; case u8: name = "u8"; break; case s64: name = "s64"; break; case u64: name = "u64"; break; @@ -102,14 +103,20 @@ std::string readNextNonEmptyLine(std::ifstream &file) { return result; } -std::string getBackendName() { +std::string getBackendName(bool lower) { af::Backend backend = af::getActiveBackend(); - if (backend == AF_BACKEND_OPENCL) - return std::string("opencl"); - else if (backend == AF_BACKEND_CUDA) - return std::string("cuda"); - - return std::string("cpu"); + switch(backend) { + case AF_BACKEND_CPU: + return lower ? std::string("cpu") : std::string("CPU"); + case AF_BACKEND_CUDA: + return lower ? std::string("cuda") : std::string("CUDA"); + case AF_BACKEND_OPENCL: + return lower ? std::string("opencl") : std::string("OpenCL"); + case AF_BACKEND_ONEAPI: + return lower ? std::string("oneapi") : std::string("oneAPI"); + default: + return lower ? std::string("unknown") : std::string("Unknown"); + } } std::string getTestName() { @@ -162,6 +169,9 @@ ::testing::AssertionResult assertArrayEq(std::string aName, std::string bName, case u32: return elemWiseEq(aName, bName, a, b, maxAbsDiff); break; + case s8: + return elemWiseEq(aName, bName, a, b, maxAbsDiff); + break; case u8: return elemWiseEq(aName, bName, a, b, maxAbsDiff); break; @@ -258,6 +268,7 @@ ::testing::AssertionResult assertImageEq(std::string aName, std::string bName, << "Expected: " << aName << "([" << a.dims() << "])"; switch (arrDtype) { + case s8: return imageEq(aName, bName, a, b, maxAbsDiff); case u8: return imageEq(aName, bName, a, b, maxAbsDiff); case b8: return imageEq(aName, bName, a, b, maxAbsDiff); case s32: return imageEq(aName, bName, a, b, maxAbsDiff); @@ -344,6 +355,7 @@ INSTANTIATE(double, float, int); INSTANTIATE(int, float, int); INSTANTIATE(unsigned int, float, int); INSTANTIATE(char, float, int); +INSTANTIATE(signed char, float, int); INSTANTIATE(unsigned char, float, int); INSTANTIATE(short, float, int); INSTANTIATE(unsigned short, float, int); @@ -358,6 +370,7 @@ INSTANTIATE(unsigned int, unsigned int, unsigned int); INSTANTIATE(long long, long long, int); INSTANTIATE(unsigned long long, unsigned long long, int); INSTANTIATE(char, char, int); +INSTANTIATE(signed char, signed char, int); INSTANTIATE(unsigned char, unsigned char, int); INSTANTIATE(short, short, int); INSTANTIATE(unsigned short, unsigned short, int); @@ -366,12 +379,19 @@ INSTANTIATE(af_half, af_half, int); INSTANTIATE(float, int, int); INSTANTIATE(unsigned int, int, int); INSTANTIATE(char, int, int); +INSTANTIATE(signed char, int, int); INSTANTIATE(unsigned char, int, int); INSTANTIATE(short, int, int); INSTANTIATE(unsigned short, int, int); +INSTANTIATE(signed char, unsigned short, int); +INSTANTIATE(signed char, short, int); +INSTANTIATE(signed char, unsigned char, int); +INSTANTIATE(signed char, double, int); + INSTANTIATE(unsigned char, unsigned short, int); INSTANTIATE(unsigned char, short, int); +INSTANTIATE(unsigned char, signed char, int); INSTANTIATE(unsigned char, double, int); INSTANTIATE(long long, unsigned int, unsigned int); @@ -380,6 +400,7 @@ INSTANTIATE(int, unsigned int, unsigned int); INSTANTIATE(short, unsigned int, unsigned int); INSTANTIATE(unsigned short, unsigned int, unsigned int); INSTANTIATE(char, unsigned int, unsigned int); +INSTANTIATE(signed char, unsigned int, unsigned int); INSTANTIATE(unsigned char, unsigned int, unsigned int); INSTANTIATE(float, unsigned int, unsigned int); INSTANTIATE(double, unsigned int, unsigned int); @@ -390,12 +411,14 @@ INSTANTIATE(int, unsigned int, int); INSTANTIATE(long long, unsigned int, int); INSTANTIATE(unsigned long long, unsigned int, int); INSTANTIATE(char, unsigned int, int); +INSTANTIATE(signed char, unsigned int, int); INSTANTIATE(unsigned char, unsigned int, int); INSTANTIATE(short, unsigned int, int); INSTANTIATE(unsigned short, unsigned int, int); INSTANTIATE(float, char, int); INSTANTIATE(double, char, int); +INSTANTIATE(signed char, char, int); INSTANTIATE(unsigned char, char, int); INSTANTIATE(short, char, int); INSTANTIATE(unsigned short, char, int); @@ -406,6 +429,7 @@ INSTANTIATE(char, float, float); INSTANTIATE(int, float, float); INSTANTIATE(unsigned int, float, float); INSTANTIATE(short, float, float); +INSTANTIATE(signed char, float, float); INSTANTIATE(unsigned char, float, float); INSTANTIATE(unsigned short, float, float); INSTANTIATE(double, float, float); @@ -426,6 +450,7 @@ INSTANTIATE(unsigned int, unsigned int, float); INSTANTIATE(long long, long long, float); INSTANTIATE(unsigned long long, unsigned long long, float); INSTANTIATE(char, char, float); +INSTANTIATE(signed char, signed char, float); INSTANTIATE(unsigned char, unsigned char, float); INSTANTIATE(short, short, float); INSTANTIATE(unsigned short, unsigned short, float); @@ -442,6 +467,7 @@ INSTANTIATE(unsigned int, float, double); INSTANTIATE(short, float, double); INSTANTIATE(unsigned short, float, double); INSTANTIATE(char, float, double); +INSTANTIATE(signed char, float, double); INSTANTIATE(unsigned char, float, double); INSTANTIATE(long long, double, double); INSTANTIATE(unsigned long long, double, double); @@ -1332,10 +1358,17 @@ af_err conv_image(af_array *out, af_array in) { T *out_data = new T[nElems]; - for (int i = 0; i < (int)nElems; i++) out_data[i] = (T)in_data[i]; + af_dtype out_type = (af_dtype)af::dtype_traits::af_type; + for (int i = 0; i < (int)nElems; i++) { + if (out_type == s8) { + // shift to avoid overflow + out_data[i] = (T)(std::trunc(in_data[i]) - 128.f); + } else { + out_data[i] = (T)in_data[i]; + } + } - af_create_array(&outArray, out_data, idims.ndims(), idims.get(), - (af_dtype)af::dtype_traits::af_type); + af_create_array(&outArray, out_data, idims.ndims(), idims.get(), out_type); std::swap(*out, outArray); @@ -1350,6 +1383,7 @@ af_err conv_image(af_array *out, af_array in) { INSTANTIATE(float); INSTANTIATE(double); +INSTANTIATE(signed char); INSTANTIATE(unsigned char); INSTANTIATE(half_float::half); INSTANTIATE(unsigned int); @@ -1387,6 +1421,7 @@ af::array cpu_randu(const af::dim4 dims) { #define INSTANTIATE(To) template af::array cpu_randu(const af::dim4 dims) INSTANTIATE(float); INSTANTIATE(double); +INSTANTIATE(signed char); INSTANTIATE(unsigned char); INSTANTIATE(half_float::half); INSTANTIATE(unsigned int); @@ -1995,6 +2030,7 @@ ::testing::AssertionResult assertRefEq(std::string hA_name, INSTANTIATE(float); INSTANTIATE(double); +INSTANTIATE(signed char); INSTANTIATE(unsigned char); INSTANTIATE(half_float::half); INSTANTIATE(unsigned int); diff --git a/test/arrayio.cpp b/test/arrayio.cpp index 00d907a568..ea15165ac4 100644 --- a/test/arrayio.cpp +++ b/test/arrayio.cpp @@ -51,7 +51,8 @@ INSTANTIATE_TEST_SUITE_P( type_params("s32", s32, 11), type_params("u32", u32, 12), type_params("u8", u8, 13), type_params("b8", b8, 1), type_params("s64", s64, 15), type_params("u64", u64, 16), - type_params("s16", s16, 17), type_params("u16", u16, 18)), + type_params("s16", s16, 17), type_params("u16", u16, 18), + type_params("s8", s8, 19)), getTypeName); TEST_P(ArrayIOType, ReadType) { @@ -103,6 +104,7 @@ TEST_P(ArrayIOType, ReadContent) { case c64: checkVals(arr, p.real, p.imag, p.type); break; case s32: checkVals(arr, p.real, p.imag, p.type); break; case u32: checkVals(arr, p.real, p.imag, p.type); break; + case s8: checkVals(arr, p.real, p.imag, p.type); break; case u8: checkVals(arr, p.real, p.imag, p.type); break; case b8: checkVals(arr, p.real, p.imag, p.type); break; case s64: checkVals(arr, p.real, p.imag, p.type); break; diff --git a/test/assign.cpp b/test/assign.cpp index cbfe6359b1..7b94bfa608 100644 --- a/test/assign.cpp +++ b/test/assign.cpp @@ -94,8 +94,8 @@ class ArrayAssign : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/bilateral.cpp b/test/bilateral.cpp index f4ff949b55..12b27fc33f 100644 --- a/test/bilateral.cpp +++ b/test/bilateral.cpp @@ -73,7 +73,8 @@ TEST(BilateralOnImage, Color) { template class BilateralOnData : public ::testing::Test {}; -typedef ::testing::Types +typedef ::testing::Types DataTestTypes; // register the type list diff --git a/test/binary.cpp b/test/binary.cpp index dafc3b8bff..7fd47bcfbd 100644 --- a/test/binary.cpp +++ b/test/binary.cpp @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -14,6 +14,8 @@ #include #include #include +#include +#include "half.hpp" //note: NOT common. From extern/half/include/half.hpp #include #include @@ -21,6 +23,8 @@ using namespace std; using namespace af; +using half_float_half = half_float::half; + const int num = 10000; #define add(left, right) (left) + (right) @@ -36,6 +40,11 @@ T mod(T a, T b) { return std::fmod(a, b); } +template +T rem(T x, T y) { + return remainder(x, y); +} + af::array randgen(const int num, dtype ty) { af::array tmp = round(1 + 2 * af::randu(num, f32)).as(ty); tmp.eval(); @@ -122,7 +131,7 @@ af::array randgen(const int num, dtype ty) { \ af_dtype ta = (af_dtype)dtype_traits::af_type; \ af::array a = randgen(num, ta); \ - Tb h_b = 0.3; \ + Tb h_b = (Tb)0.3; \ af::array c = func(a, h_b); \ Ta *h_a = a.host(); \ Td *h_d = c.host(); \ @@ -139,7 +148,7 @@ af::array randgen(const int num, dtype ty) { SUPPORTED_TYPE_CHECK(Tc); \ \ af_dtype tb = (af_dtype)dtype_traits::af_type; \ - Ta h_a = 0.3; \ + Ta h_a = (Ta)0.3; \ af::array b = randgen(num, tb); \ af::array c = func(h_a, b); \ Tb *h_b = b.host(); \ @@ -163,6 +172,8 @@ af::array randgen(const int num, dtype ty) { #define BINARY_TESTS_UINT(func) BINARY_TESTS(uint, uint, uint, func) #define BINARY_TESTS_INTL(func) BINARY_TESTS(intl, intl, intl, func) #define BINARY_TESTS_UINTL(func) BINARY_TESTS(uintl, uintl, uintl, func) +#define BINARY_TESTS_NEAR_HALF(func) \ + BINARY_TESTS_NEAR(half_float_half, half_float_half, half_float_half, func, 1e-3) #define BINARY_TESTS_NEAR_FLOAT(func) \ BINARY_TESTS_NEAR(float, float, float, func, 1e-5) #define BINARY_TESTS_NEAR_DOUBLE(func) \ @@ -175,6 +186,7 @@ BINARY_TESTS_NEAR(float, float, float, div, 1e-3) // FIXME BINARY_TESTS_FLOAT(min) BINARY_TESTS_FLOAT(max) BINARY_TESTS_NEAR(float, float, float, mod, 1e-5) // FIXME +BINARY_TESTS_FLOAT(rem) BINARY_TESTS_DOUBLE(add) BINARY_TESTS_DOUBLE(sub) @@ -183,11 +195,16 @@ BINARY_TESTS_DOUBLE(div) BINARY_TESTS_DOUBLE(min) BINARY_TESTS_DOUBLE(max) BINARY_TESTS_DOUBLE(mod) +BINARY_TESTS_DOUBLE(rem) BINARY_TESTS_NEAR_FLOAT(atan2) BINARY_TESTS_NEAR_FLOAT(pow) BINARY_TESTS_NEAR_FLOAT(hypot) +BINARY_TESTS_NEAR_HALF(atan2) +BINARY_TESTS_NEAR_HALF(pow) +BINARY_TESTS_NEAR_HALF(hypot) + BINARY_TESTS_NEAR_DOUBLE(atan2) BINARY_TESTS_NEAR_DOUBLE(pow) BINARY_TESTS_NEAR_DOUBLE(hypot) @@ -195,18 +212,26 @@ BINARY_TESTS_NEAR_DOUBLE(hypot) BINARY_TESTS_INT(add) BINARY_TESTS_INT(sub) BINARY_TESTS_INT(mul) +BINARY_TESTS_INT(div) +BINARY_TESTS_INT(pow) BINARY_TESTS_UINT(add) BINARY_TESTS_UINT(sub) BINARY_TESTS_UINT(mul) +BINARY_TESTS_UINT(div) +BINARY_TESTS_UINT(pow) BINARY_TESTS_INTL(add) BINARY_TESTS_INTL(sub) BINARY_TESTS_INTL(mul) +BINARY_TESTS_INTL(div) +BINARY_TESTS_INTL(pow) BINARY_TESTS_UINTL(add) BINARY_TESTS_UINTL(sub) BINARY_TESTS_UINTL(mul) +BINARY_TESTS_UINTL(div) +BINARY_TESTS_UINTL(pow) BINARY_TESTS_CFLOAT(add) BINARY_TESTS_CFLOAT(sub) @@ -299,6 +324,7 @@ UBITOP(bitnot, int) UBITOP(bitnot, uint) UBITOP(bitnot, intl) UBITOP(bitnot, uintl) +UBITOP(bitnot, schar) UBITOP(bitnot, uchar) UBITOP(bitnot, short) UBITOP(bitnot, ushort) @@ -389,6 +415,7 @@ DEF_TEST(Int, int) DEF_TEST(UShort, unsigned short) DEF_TEST(Short, short) DEF_TEST(UChar, unsigned char) +DEF_TEST(SChar, signed char) #undef DEF_TEST @@ -406,6 +433,8 @@ INSTANTIATE_TEST_SUITE_P(PositiveValues, PowPrecisionTestShort, testing::Range(1, 180, 50)); INSTANTIATE_TEST_SUITE_P(PositiveValues, PowPrecisionTestUChar, testing::Range(1, 12, 5)); +INSTANTIATE_TEST_SUITE_P(PositiveValues, PowPrecisionTestSChar, + testing::Range(1, 9, 3)); INSTANTIATE_TEST_SUITE_P(NegativeValues, PowPrecisionTestLong, testing::Range(-1e7, 0, 1e6)); @@ -413,6 +442,8 @@ INSTANTIATE_TEST_SUITE_P(NegativeValues, PowPrecisionTestInt, testing::Range(-46340, 0, 10e3)); INSTANTIATE_TEST_SUITE_P(NegativeValues, PowPrecisionTestShort, testing::Range(-180, 0, 50)); +INSTANTIATE_TEST_SUITE_P(NegativeValues, PowPrecisionTestSChar, + testing::Range(-9, 0, 3)); struct result_type_param { af_dtype result_; @@ -471,6 +502,7 @@ INSTANTIATE_TEST_SUITE_P( result_type_param(b8), result_type_param(s32), result_type_param(u32), + result_type_param(s8), result_type_param(u8), result_type_param(s64), result_type_param(u64), @@ -490,6 +522,7 @@ INSTANTIATE_TEST_SUITE_P( result_type_param(f32, b8, f32), result_type_param(f32, s32, f32), result_type_param(f32, u32, f32), + result_type_param(f32, s8, f32), result_type_param(f32, u8, f32), result_type_param(f32, s64, f32), result_type_param(f32, u64, f32), @@ -510,6 +543,7 @@ INSTANTIATE_TEST_SUITE_P( result_type_param(f64, b8, f64), result_type_param(f64, s32, f64), result_type_param(f64, u32, f64), + result_type_param(f64, s8, f64), result_type_param(f64, u8, f64), result_type_param(f64, s64, f64), result_type_param(f64, u64, f64), @@ -542,7 +576,8 @@ class ResultTypeScalar : public ::testing::Test { }; typedef ::testing::Types + unsigned short, char, signed char, unsigned char, + half_float::half> TestTypes; TYPED_TEST_SUITE(ResultTypeScalar, TestTypes); diff --git a/test/blas.cpp b/test/blas.cpp index 6b0590d73b..6f77c10160 100644 --- a/test/blas.cpp +++ b/test/blas.cpp @@ -492,6 +492,36 @@ TEST(MatrixMultiply, half) { } } +TEST(MatrixMultiply, schar) { + array A8 = array(3, 3, h_lhs).as(s8); + array B8 = array(3, 3, h_rhs).as(s8); + array expected32 = array(3, 3, h_gold).as(f32); + + { + af_array C32 = 0; + const float alpha32(1.0f); + const float beta32(0.0f); + af_backend backend; + af_get_active_backend(&backend); + if (backend == AF_BACKEND_CUDA) { + ASSERT_SUCCESS(af_gemm(&C32, AF_MAT_NONE, AF_MAT_NONE, &alpha32, + A8.get(), B8.get(), &beta32)); + } else { + ASSERT_EQ(AF_ERR_TYPE, + af_gemm(&C32, AF_MAT_NONE, AF_MAT_NONE, &alpha32, + A8.get(), B8.get(), &beta32)); + SUCCEED(); + return; + } + af::array C(C32); + ASSERT_ARRAYS_NEAR(expected32, C, 0.00001); + } + { + array C32 = matmul(A8, B8); + ASSERT_ARRAYS_NEAR(expected32, C32, 0.00001); + } +} + struct test_params { af_mat_prop opt_lhs; af_mat_prop opt_rhs; diff --git a/test/canny.cpp b/test/canny.cpp index 7f2fa2918c..0a0fdbc08c 100644 --- a/test/canny.cpp +++ b/test/canny.cpp @@ -28,7 +28,7 @@ class CannyEdgeDetector : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -53,7 +53,7 @@ void cannyTest(string pTestFile) { (af_dtype)dtype_traits::af_type)); ASSERT_SUCCESS(af_canny(&outArray, sArray, AF_CANNY_THRESHOLD_MANUAL, - 0.4147f, 0.8454f, 3, true)); + 0.4147f, 0.8454f, 3, true)); vector outData(sDims.elements()); @@ -72,10 +72,12 @@ void cannyTest(string pTestFile) { } TYPED_TEST(CannyEdgeDetector, ArraySizeLessThanBlockSize10x10) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); cannyTest(string(TEST_DIR "/CannyEdgeDetector/fast10x10.test")); } TYPED_TEST(CannyEdgeDetector, ArraySizeEqualBlockSize16x16) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); cannyTest(string(TEST_DIR "/CannyEdgeDetector/fast16x16.test")); } @@ -129,8 +131,9 @@ void cannyImageOtsuTest(string pTestFile, bool isColor) { af_load_image_native(&goldArray, outFiles[testId].c_str())); ASSERT_SUCCESS(af_canny(&_outArray, inArray, - AF_CANNY_THRESHOLD_AUTO_OTSU, 0.08, 0.32, 3, - false)); + AF_CANNY_THRESHOLD_AUTO_OTSU, + 0.08, 0.32, 3, false)); + unsigned ndims = 0; dim_t dims[4]; @@ -156,6 +159,7 @@ void cannyImageOtsuTest(string pTestFile, bool isColor) { } TEST(CannyEdgeDetector, OtsuThreshold) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); cannyImageOtsuTest(string(TEST_DIR "/CannyEdgeDetector/gray.test"), false); } @@ -248,7 +252,7 @@ void cannyImageOtsuBatchTest(string pTestFile, const dim_t targetBatchCount) { array inputIm = tile(readImg, 1, 1, targetBatchCount); array outIm = - canny(inputIm, AF_CANNY_THRESHOLD_AUTO_OTSU, 0.08, 0.32, 3, false); + canny(inputIm, AF_CANNY_THRESHOLD_AUTO_OTSU, 0.08, 0.32, 3, false); outIm *= 255.0; ASSERT_IMAGES_NEAR(goldIm, outIm.as(u8), 1.0e-3); @@ -256,6 +260,7 @@ void cannyImageOtsuBatchTest(string pTestFile, const dim_t targetBatchCount) { } TEST(CannyEdgeDetector, BatchofImagesUsingCPPAPI) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); // DO NOT INCREASE BATCH COUNT BEYOND 4 // This is a limitation on the test assert macro that is saving // images to disk which can't handle a batch of images. diff --git a/test/cast.cpp b/test/cast.cpp index cb1f4e3f42..d2b4f95250 100644 --- a/test/cast.cpp +++ b/test/cast.cpp @@ -52,6 +52,7 @@ void cast_test() { REAL_TO_TESTS(Ti, char); \ REAL_TO_TESTS(Ti, int); \ REAL_TO_TESTS(Ti, unsigned); \ + REAL_TO_TESTS(Ti, schar); \ REAL_TO_TESTS(Ti, uchar); \ REAL_TO_TESTS(Ti, intl); \ REAL_TO_TESTS(Ti, uintl); \ @@ -67,6 +68,7 @@ REAL_TEST_INVOKE(double) REAL_TEST_INVOKE(char) REAL_TEST_INVOKE(int) REAL_TEST_INVOKE(unsigned) +REAL_TEST_INVOKE(schar) REAL_TEST_INVOKE(uchar) REAL_TEST_INVOKE(intl) REAL_TEST_INVOKE(uintl) diff --git a/test/clamp.cpp b/test/clamp.cpp index 1e0b04b7c2..c830b06b2b 100644 --- a/test/clamp.cpp +++ b/test/clamp.cpp @@ -125,6 +125,7 @@ INSTANTIATE_TEST_SUITE_P( clamp_params(dim4(10), f16, f16, f16, f16), clamp_params(dim4(10), s32, f32, f32, f32), clamp_params(dim4(10), u32, f32, f32, f32), + clamp_params(dim4(10), s8, f32, f32, f32), clamp_params(dim4(10), u8, f32, f32, f32), clamp_params(dim4(10), b8, f32, f32, f32), clamp_params(dim4(10), s64, f32, f32, f32), diff --git a/test/compare.cpp b/test/compare.cpp index 66d9778039..877c08275f 100644 --- a/test/compare.cpp +++ b/test/compare.cpp @@ -23,8 +23,8 @@ using std::vector; template class Compare : public ::testing::Test {}; -typedef ::testing::Types +typedef ::testing::Types TestTypes; TYPED_TEST_SUITE(Compare, TestTypes); diff --git a/test/confidence_connected.cpp b/test/confidence_connected.cpp index ac5b0bf2bc..22254e5532 100644 --- a/test/confidence_connected.cpp +++ b/test/confidence_connected.cpp @@ -41,17 +41,6 @@ struct CCCTestParams { double replace; }; -void apiWrapper(af_array *out, const af_array in, const af_array seedx, - const af_array seedy, const CCCTestParams params) { - ASSERT_SUCCESS(af_confidence_cc(out, in, seedx, seedy, params.radius, - params.multiplier, params.iterations, - params.replace)); - - int device = 0; - ASSERT_SUCCESS(af_get_device(&device)); - ASSERT_SUCCESS(af_sync(device)); -} - template void testImage(const std::string pTestFile, const size_t numSeeds, const unsigned *seedx, const unsigned *seedy, @@ -103,7 +92,12 @@ void testImage(const std::string pTestFile, const size_t numSeeds, params.iterations = iter; params.replace = 255.0; - apiWrapper(&outArray, inArray, seedxArr, seedyArr, params); + ASSERT_SUCCESS(af_confidence_cc(&outArray, inArray, seedxArr, seedyArr, params.radius, + params.multiplier, params.iterations, + params.replace)); + int device = 0; + ASSERT_SUCCESS(af_get_device(&device)); + ASSERT_SUCCESS(af_sync(device)); ASSERT_ARRAYS_EQ(outArray, goldArray); @@ -147,7 +141,12 @@ void testData(CCCTestParams params) { (af_dtype)af::dtype_traits::af_type)); af_array outArray = 0; - apiWrapper(&outArray, inArray, seedxArr, seedyArr, params); + ASSERT_SUCCESS(af_confidence_cc(&outArray, inArray, seedxArr, seedyArr, params.radius, + params.multiplier, params.iterations, + params.replace)); + int device = 0; + ASSERT_SUCCESS(af_get_device(&device)); + ASSERT_SUCCESS(af_sync(device)); ASSERT_VEC_ARRAY_EQ(tests[0], dims, outArray); @@ -161,6 +160,7 @@ class ConfidenceConnectedDataTest : public testing::TestWithParam {}; TYPED_TEST(ConfidenceConnectedImageTest, DonutBackgroundExtraction) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const unsigned seedx = 10; const unsigned seedy = 10; testImage(std::string("donut_background.test"), 1, &seedx, @@ -168,6 +168,7 @@ TYPED_TEST(ConfidenceConnectedImageTest, DonutBackgroundExtraction) { } TYPED_TEST(ConfidenceConnectedImageTest, DonutRingExtraction) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const unsigned seedx = 132; const unsigned seedy = 132; testImage(std::string("donut_ring.test"), 1, &seedx, &seedy, 3, @@ -175,6 +176,7 @@ TYPED_TEST(ConfidenceConnectedImageTest, DonutRingExtraction) { } TYPED_TEST(ConfidenceConnectedImageTest, DonutKernelExtraction) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const unsigned seedx = 150; const unsigned seedy = 150; testImage(std::string("donut_core.test"), 1, &seedx, &seedy, 3, @@ -182,6 +184,7 @@ TYPED_TEST(ConfidenceConnectedImageTest, DonutKernelExtraction) { } TEST_P(ConfidenceConnectedDataTest, SegmentARegion) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); testData(GetParam()); } diff --git a/test/constant.cpp b/test/constant.cpp index 0a75e3d974..b1d3e0a5af 100644 --- a/test/constant.cpp +++ b/test/constant.cpp @@ -31,7 +31,8 @@ template class Constant : public ::testing::Test {}; typedef ::testing::Types + schar, uchar, uintl, intl, short, ushort, + half_float::half> TestTypes; TYPED_TEST_SUITE(Constant, TestTypes); diff --git a/test/convolve.cpp b/test/convolve.cpp index 8adeb40fd8..5df8961e1b 100644 --- a/test/convolve.cpp +++ b/test/convolve.cpp @@ -33,8 +33,8 @@ class Convolve : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -898,7 +898,7 @@ float tolerance(); template<> float tolerance() { - return 2e-3; + return 4e-3; } template<> @@ -1176,4 +1176,10 @@ TEST(ConvolveNN, ZeroPadding_Issue2817) { array convolved = convolve2NN(signal, filter, strides, padding, dilation); ASSERT_EQ(sum(abs(signal(seq(1, 3), seq(1, 3)) - convolved)) < 1E-5, true); + + array incoming_gradient = constant(1 / 9.f, 3, 3); + array convolved_grad = convolve2GradientNN(incoming_gradient, signal, filter, + convolved, strides, padding, dilation, + AF_CONV_GRADIENT_FILTER); + ASSERT_EQ(sum(abs(convolved - convolved_grad)) < 1E-5, true); } diff --git a/test/corrcoef.cpp b/test/corrcoef.cpp index 213a8de092..e9bc5a5616 100644 --- a/test/corrcoef.cpp +++ b/test/corrcoef.cpp @@ -31,7 +31,8 @@ class CorrelationCoefficient : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -61,9 +62,9 @@ template struct ccOutType { typedef typename cond_type< is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value, + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value, float, typename elseType::type>::type type; }; diff --git a/test/covariance.cpp b/test/covariance.cpp index 4d4e4877f1..f149fbd095 100644 --- a/test/covariance.cpp +++ b/test/covariance.cpp @@ -34,8 +34,8 @@ class Covariance : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -65,9 +65,9 @@ template struct covOutType { typedef typename cond_type< is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value, + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value, float, typename elseType::type>::type type; }; diff --git a/test/diagonal.cpp b/test/diagonal.cpp index 1eecb883ae..e3031f731c 100644 --- a/test/diagonal.cpp +++ b/test/diagonal.cpp @@ -31,8 +31,8 @@ using std::vector; template class Diagonal : public ::testing::Test {}; -typedef ::testing::Types +typedef ::testing::Types TestTypes; TYPED_TEST_SUITE(Diagonal, TestTypes); diff --git a/test/diff1.cpp b/test/diff1.cpp index a7456fd0a2..9fdf11a91a 100644 --- a/test/diff1.cpp +++ b/test/diff1.cpp @@ -46,7 +46,7 @@ class Diff1 : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + uintl, char, signed char, unsigned char, short, ushort> TestTypes; // register the type list diff --git a/test/diff2.cpp b/test/diff2.cpp index c7c17f333f..cdc2b9909e 100644 --- a/test/diff2.cpp +++ b/test/diff2.cpp @@ -51,7 +51,7 @@ class Diff2 : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + uintl, char, signed char, unsigned char, short, ushort> TestTypes; // register the type list diff --git a/test/dog.cpp b/test/dog.cpp index 0b764f2c06..af76c23f59 100644 --- a/test/dog.cpp +++ b/test/dog.cpp @@ -33,7 +33,8 @@ class DOG : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/fast.cpp b/test/fast.cpp index 1d494641ff..c5e3225d0e 100644 --- a/test/fast.cpp +++ b/test/fast.cpp @@ -61,7 +61,7 @@ class FixedFAST : public ::testing::Test { }; typedef ::testing::Types FloatTestTypes; -typedef ::testing::Types FixedTestTypes; +typedef ::testing::Types FixedTestTypes; TYPED_TEST_SUITE(FloatFAST, FloatTestTypes); TYPED_TEST_SUITE(FixedFAST, FixedTestTypes); @@ -158,12 +158,14 @@ void fastTest(string pTestFile, bool nonmax) { #define FLOAT_FAST_INIT(desc, image, nonmax) \ TYPED_TEST(FloatFAST, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ fastTest(string(TEST_DIR "/fast/" #image "_float.test"), \ nonmax); \ } #define FIXED_FAST_INIT(desc, image, nonmax) \ TYPED_TEST(FixedFAST, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ fastTest(string(TEST_DIR "/fast/" #image "_fixed.test"), \ nonmax); \ } @@ -180,6 +182,7 @@ using af::features; using af::loadImage; TEST(FloatFAST, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); IMAGEIO_ENABLED_CHECK(); vector inDims; diff --git a/test/fftconvolve.cpp b/test/fftconvolve.cpp index 57d9398a04..a8f63e2f45 100644 --- a/test/fftconvolve.cpp +++ b/test/fftconvolve.cpp @@ -39,8 +39,8 @@ class FFTConvolveLarge : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; typedef ::testing::Types TestTypesLarge; diff --git a/test/gen_assign.cpp b/test/gen_assign.cpp index 7cfd78ae62..07685108c4 100644 --- a/test/gen_assign.cpp +++ b/test/gen_assign.cpp @@ -455,3 +455,46 @@ TEST(GeneralAssign, CPP_AANN) { freeHost(hIdx0); freeHost(hIdx1); } + +TEST(GeneralAssign, NDimsDoesNotMatchLDims) { + af_err err; + af_array zeros, l1, l2, sevens; + dim_t sevens_size[3] = {5, 1, 1}; + short hsevens[5] = {7, 7, 7, 7, 7}; + + dim_t zeros_size[3] = {5, 6, 1}; + short hzeros[5 * 6] = {0}; + + dim_t hone[1] = {1}; + + ASSERT_SUCCESS(af_create_array(&zeros, hzeros, 3, zeros_size, s16)); + ASSERT_SUCCESS(af_create_array(&sevens, hsevens, 3, sevens_size, s16)); + ASSERT_SUCCESS(af_create_array(&l2, hone, 1, hone, s64)); + + af_index_t *ix; + ASSERT_SUCCESS(af_create_indexers(&ix)); + ASSERT_SUCCESS(af_set_array_indexer(ix, l2, 1)); + + // clang-format off + vector gold = { + 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + }; + // clang-format on + for (int number_of_indices = 2; number_of_indices < 4; + number_of_indices++) { + af_array result = 0; + ASSERT_SUCCESS( + af_assign_gen(&result, zeros, number_of_indices, ix, sevens)); + + ASSERT_VEC_ARRAY_EQ(gold, dim4(3, zeros_size), af::array(result)); + } + ASSERT_SUCCESS(af_release_array(zeros)); + ASSERT_SUCCESS(af_release_array(sevens)); + ASSERT_SUCCESS(af_release_array(l2)); + ASSERT_SUCCESS(af_release_indexers(ix)); +} diff --git a/test/gen_index.cpp b/test/gen_index.cpp index e65d4e48e5..fe684ebd27 100644 --- a/test/gen_index.cpp +++ b/test/gen_index.cpp @@ -108,8 +108,9 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Combine( ::testing::Values(index_test( string(TEST_DIR "/gen_index/s0_3s0_1s1_2a.test"), dim4(4, 2, 2))), - ::testing::Values(f32, f64, c32, c64, u64, s64, u16, s16, u8, b8, f16), - ::testing::Values(f32, f64, u64, s64, u16, s16, u8, f16)), + ::testing::Values(f32, f64, c32, c64, u64, s64, u16, s16, s8, u8, b8, + f16), + ::testing::Values(f32, f64, u64, s64, u16, s16, s8, u8, f16)), testNameGenerator); TEST_P(IndexGeneralizedLegacy, SSSA) { @@ -253,6 +254,56 @@ TEST(GeneralIndex, AASS) { ASSERT_SUCCESS(af_release_array(outArray)); } +TEST(GeneralIndex, SSAS_LinearSteps) { + vector numDims; + vector> in; + vector> tests; // Read tests from file + + readTestsFromFile( + TEST_DIR "/gen_index/s29_9__3s0_9_2as0_n.test", numDims, in, tests); + + af_array outArray = 0; + af_array inArray = 0; + af_array idxArray0 = 0; + dim4 dims0 = numDims[0]; + dim4 dims1 = numDims[1]; + + ASSERT_SUCCESS(af_create_array(&inArray, &(in[0].front()), dims0.ndims(), + dims0.get(), + (af_dtype)dtype_traits::af_type)); + + ASSERT_SUCCESS(af_create_array(&idxArray0, &(in[1].front()), dims1.ndims(), + dims1.get(), + (af_dtype)dtype_traits::af_type)); + + af_index_t indexs[4]; + indexs[0].idx.seq = af_make_seq(29, 9, -3); + indexs[1].idx.seq = af_make_seq(0, 9, 2); + indexs[2].idx.arr = idxArray0; + indexs[3].idx.seq = af_span; + + indexs[0].isSeq = true; + indexs[1].isSeq = true; + indexs[2].isSeq = false; + indexs[3].isSeq = true; + + ASSERT_SUCCESS(af_index_gen(&outArray, inArray, 4, indexs)); + + vector currGoldBar = tests[0]; + size_t nElems = currGoldBar.size(); + vector outData(nElems); + + ASSERT_SUCCESS(af_get_data_ptr((void *)outData.data(), outArray)); + + for (size_t elIter = 0; elIter < nElems; ++elIter) { + ASSERT_EQ(currGoldBar[elIter], outData[elIter]) + << "at: " << elIter << endl; + } + + ASSERT_SUCCESS(af_release_array(inArray)); + ASSERT_SUCCESS(af_release_array(outArray)); +} + using af::array; using af::freeHost; using af::randu; diff --git a/test/gloh.cpp b/test/gloh.cpp index b360ac6a18..4ce2fa547b 100644 --- a/test/gloh.cpp +++ b/test/gloh.cpp @@ -161,8 +161,9 @@ void glohTest(string pTestFile) { af_load_image(&inArray_f32, inFiles[testId].c_str(), false)); ASSERT_SUCCESS(conv_image(&inArray, inArray_f32)); - ASSERT_SUCCESS(af_gloh(&feat, &desc, inArray, 3, 0.04f, 10.0f, 1.6f, - true, 1.f / 256.f, 0.05f)); + ASSERT_SUCCESS(af_gloh(&feat, &desc, inArray, 3, + 0.04f, 10.0f, 1.6f, + true, 1.f / 256.f, 0.05f)); dim_t n = 0; af_array x, y, score, orientation, size; @@ -253,6 +254,7 @@ void glohTest(string pTestFile) { #define GLOH_INIT(desc, image) \ TYPED_TEST(GLOH, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ glohTest(string(TEST_DIR "/gloh/" #image ".test")); \ } @@ -261,6 +263,7 @@ GLOH_INIT(man, man); ///////////////////////////////////// CPP //////////////////////////////// // TEST(GLOH, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); IMAGEIO_ENABLED_CHECK(); vector inDims; diff --git a/test/half.cpp b/test/half.cpp index 7f85950170..8afb6d5f4d 100644 --- a/test/half.cpp +++ b/test/half.cpp @@ -41,6 +41,7 @@ INSTANTIATE_TEST_SUITE_P(ToF16, HalfConvert, convert_params(f64, f16, 10), convert_params(s32, f16, 10), convert_params(u32, f16, 10), + convert_params(s8, f16, 10), convert_params(u8, f16, 10), convert_params(s64, f16, 10), convert_params(u64, f16, 10), @@ -53,6 +54,7 @@ INSTANTIATE_TEST_SUITE_P(FromF16, HalfConvert, convert_params(f16, f64, 10), convert_params(f16, s32, 10), convert_params(f16, u32, 10), + convert_params(f16, s8, 10), convert_params(f16, u8, 10), convert_params(f16, s64, 10), convert_params(f16, u64, 10), diff --git a/test/hamming.cpp b/test/hamming.cpp index b14a33db0a..b8394e36b5 100644 --- a/test/hamming.cpp +++ b/test/hamming.cpp @@ -95,21 +95,25 @@ void hammingMatcherTest(string pTestFile, int feat_dim) { } TYPED_TEST(HammingMatcher8, Hamming_500_5000_Dim0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); hammingMatcherTest( string(TEST_DIR "/hamming/hamming_500_5000_dim0_u8.test"), 0); } TYPED_TEST(HammingMatcher8, Hamming_500_5000_Dim1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); hammingMatcherTest( string(TEST_DIR "/hamming/hamming_500_5000_dim1_u8.test"), 1); } TYPED_TEST(HammingMatcher32, Hamming_500_5000_Dim0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); hammingMatcherTest( string(TEST_DIR "/hamming/hamming_500_5000_dim0_u32.test"), 0); } TYPED_TEST(HammingMatcher32, Hamming_500_5000_Dim1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); hammingMatcherTest( string(TEST_DIR "/hamming/hamming_500_5000_dim1_u32.test"), 1); } @@ -117,6 +121,7 @@ TYPED_TEST(HammingMatcher32, Hamming_500_5000_Dim1) { ///////////////////////////////////// CPP //////////////////////////////// // TEST(HammingMatcher, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); using af::array; using af::dim4; @@ -155,6 +160,7 @@ TEST(HammingMatcher, CPP) { } TEST(HammingMatcher64bit, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); using af::array; using af::dim4; diff --git a/test/harris.cpp b/test/harris.cpp index 43c0bb6433..f2fd27d47a 100644 --- a/test/harris.cpp +++ b/test/harris.cpp @@ -145,6 +145,7 @@ void harrisTest(string pTestFile, float sigma, unsigned block_size) { #define HARRIS_INIT(desc, image, sigma, block_size) \ TYPED_TEST(Harris, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ harrisTest(string(TEST_DIR "/harris/" #image "_" #sigma \ "_" #block_size ".test"), \ sigma, block_size); \ @@ -167,6 +168,7 @@ using af::harris; using af::loadImage; TEST(FloatHarris, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); IMAGEIO_ENABLED_CHECK(); vector inDims; diff --git a/test/histogram.cpp b/test/histogram.cpp index ca3df72f74..ea9431485c 100644 --- a/test/histogram.cpp +++ b/test/histogram.cpp @@ -33,7 +33,7 @@ class Histogram : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + schar, uchar, short, ushort, intl, uintl> TestTypes; // register the type list diff --git a/test/homography.cpp b/test/homography.cpp index f4c1c75259..bd4809d428 100644 --- a/test/homography.cpp +++ b/test/homography.cpp @@ -69,8 +69,8 @@ void homographyTest(string pTestFile, const af_homography_type htype, ASSERT_SUCCESS(af_load_image(&trainArray_f32, inFiles[0].c_str(), false)); ASSERT_SUCCESS(conv_image(&trainArray, trainArray_f32)); - ASSERT_SUCCESS(af_orb(&train_feat, &train_desc, trainArray, 20.0f, 2000, - 1.2f, 8, true)); + ASSERT_SUCCESS(af_orb(&train_feat, &train_desc, trainArray, + 20.0f, 2000, 1.2f, 8, true)); ASSERT_SUCCESS(af_get_features_xpos(&train_feat_x, train_feat)); ASSERT_SUCCESS(af_get_features_ypos(&train_feat_y, train_feat)); @@ -96,15 +96,16 @@ void homographyTest(string pTestFile, const af_homography_type htype, const dim_t test_d0 = inDims[0][0] * size_ratio; const dim_t test_d1 = inDims[0][1] * size_ratio; const dim_t tDims[] = {test_d0, test_d1}; - if (rotate) + if (rotate) { ASSERT_SUCCESS(af_rotate(&queryArray, trainArray, theta, false, AF_INTERP_NEAREST)); - else + } else { ASSERT_SUCCESS(af_resize(&queryArray, trainArray, test_d0, test_d1, AF_INTERP_BILINEAR)); + } - ASSERT_SUCCESS(af_orb(&query_feat, &query_desc, queryArray, 20.0f, 2000, - 1.2f, 8, true)); + ASSERT_SUCCESS(af_orb(&query_feat, &query_desc, queryArray, + 20.0f, 2000, 1.2f, 8, true)); ASSERT_SUCCESS( af_hamming_matcher(&idx, &dist, train_desc, query_desc, 0, 1)); @@ -144,9 +145,9 @@ void homographyTest(string pTestFile, const af_homography_type htype, int inliers = 0; ASSERT_SUCCESS(af_homography(&H, &inliers, train_feat_x_idx, - train_feat_y_idx, query_feat_x_idx, - query_feat_y_idx, htype, 3.0f, 1000, - (af_dtype)dtype_traits::af_type)); + train_feat_y_idx, query_feat_x_idx, + query_feat_y_idx, htype, 3.0f, 1000, + (af_dtype)dtype_traits::af_type)); array HH(H); @@ -201,6 +202,7 @@ void homographyTest(string pTestFile, const af_homography_type htype, #define HOMOGRAPHY_INIT(desc, image, htype, rotate, size_ratio) \ TYPED_TEST(Homography, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ homographyTest( \ string(TEST_DIR "/homography/" #image ".test"), htype, rotate, \ size_ratio); \ @@ -220,6 +222,7 @@ using af::features; using af::loadImage; TEST(Homography, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); IMAGEIO_ENABLED_CHECK(); vector inDims; @@ -262,7 +265,7 @@ TEST(Homography, CPP) { array H; int inliers = 0; homography(H, inliers, feat_train_x, feat_train_y, feat_query_x, - feat_query_y, AF_HOMOGRAPHY_RANSAC, 3.0f, 1000, f32); + feat_query_y, AF_HOMOGRAPHY_RANSAC, 3.0f, 1000, f32); float* gold_t = new float[8]; for (int i = 0; i < 8; i++) gold_t[i] = 0.f; diff --git a/test/hsv_rgb.cpp b/test/hsv_rgb.cpp index 423fc5fad5..134e56c6c3 100644 --- a/test/hsv_rgb.cpp +++ b/test/hsv_rgb.cpp @@ -38,6 +38,7 @@ TEST(hsv_rgb, InvalidArray) { } TEST(hsv2rgb, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; @@ -54,6 +55,7 @@ TEST(hsv2rgb, CPP) { } TEST(rgb2hsv, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; @@ -70,6 +72,7 @@ TEST(rgb2hsv, CPP) { } TEST(rgb2hsv, MaxDim) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; @@ -108,6 +111,7 @@ TEST(rgb2hsv, MaxDim) { } TEST(hsv2rgb, MaxDim) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; diff --git a/test/imageio.cpp b/test/imageio.cpp index 00834fb693..16cead852c 100644 --- a/test/imageio.cpp +++ b/test/imageio.cpp @@ -160,7 +160,7 @@ TEST(ImageIO, SavePNGCPP) { input(9, 0, 2) = 255; input(9, 9, span) = 255; - std::string testname = getTestName() + "_" + getBackendName(); + std::string testname = getTestName() + "_" + getBackendName(true); std::string imagename = "SaveCPP_" + testname + ".png"; saveImage(imagename.c_str(), input); @@ -180,7 +180,7 @@ TEST(ImageIO, SaveBMPCPP) { input(9, 0, 2) = 255; input(9, 9, span) = 255; - std::string testname = getTestName() + "_" + getBackendName(); + std::string testname = getTestName() + "_" + getBackendName(true); std::string imagename = "SaveCPP_" + testname + ".bmp"; saveImage(imagename.c_str(), input); @@ -291,7 +291,7 @@ TEST(ImageIO, SaveImage16CPP) { array input = randu(dims, u16); array input_255 = floor(input.as(f32) / 257); - std::string testname = getTestName() + "_" + getBackendName(); + std::string testname = getTestName() + "_" + getBackendName(true); std::string imagename = "saveImage16CPP_" + testname + ".png"; saveImage(imagename.c_str(), input); @@ -366,7 +366,7 @@ void saveLoadImageNativeCPPTest(dim4 dims) { array input = randu(dims, (af_dtype)dtype_traits::af_type); - std::string imagename = getTestName() + "_" + getBackendName() + ".png"; + std::string imagename = getTestName() + "_" + getBackendName(true) + ".png"; saveImageNative(imagename.c_str(), input); diff --git a/test/index.cpp b/test/index.cpp index c8e1a7ffb9..d5d010ffb1 100644 --- a/test/index.cpp +++ b/test/index.cpp @@ -138,7 +138,7 @@ class Indexing1D : public ::testing::Test { }; typedef ::testing::Types AllTypes; TYPED_TEST_SUITE(Indexing1D, AllTypes); @@ -710,8 +710,9 @@ class lookup : public ::testing::Test { virtual void SetUp() {} }; -typedef ::testing::Types +typedef ::testing::Types ArrIdxTestTypes; TYPED_TEST_SUITE(lookup, ArrIdxTestTypes); @@ -808,6 +809,127 @@ TEST(lookup, Issue2009) { ASSERT_ARRAYS_EQ(a, b); } +TEST(lookup, Issue3613_FirstDimLookupWithOffset) { + dim4 dims(1); + const int selected_dim = 0; // selected span dimension + dims[selected_dim] = 125; // input size + + array a = iota(dims); + array idxs = iota(dim4(5, 4, 3, 2)); + array selected_idx = idxs(af::span, 3, 2, 1); // Offsets in second, third, & fourth dimension + + array expected_selected_idx = range(dim4(5)) * 1 + 3 * 5 + 2 * (5 * 4) + 1 * (5 * 4 * 3); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx, selected_dim); + dim4 output_dims(1); + output_dims[selected_dim] = 5; // output size + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, output_dims), b); // lookup output should be the same as looked up indices +} + +TEST(lookup, Issue3613_SecondDimLookupWithOffset) { + dim4 dims(1); + const int selected_dim = 1; // selected span dimension + dims[selected_dim] = 125; // input size + + array a = iota(dims); + array idxs = iota(dim4(5, 4, 3, 2)); + array selected_idx = idxs(af::span, 3, 2, 1); // Offsets in second, third, & fourth dimension + + array expected_selected_idx = range(dim4(5)) * 1 + 3 * 5 + 2 * (5 * 4) + 1 * (5 * 4 * 3); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx, selected_dim); + dim4 output_dims(1); + output_dims[selected_dim] = 5; // output size + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, output_dims), b); // lookup output should be the same as looked up indices +} + + +TEST(lookup, Issue3613_ThirdDimLookupWithOffset) { + dim4 dims(1); + const int selected_dim = 2; // selected span dimension + dims[selected_dim] = 125; // input size + + array a = iota(dims); + array idxs = iota(dim4(5, 4, 3, 2)); + array selected_idx = idxs(af::span, 3, 2, 1); // Offsets in second, third, & fourth dimension + + array expected_selected_idx = range(dim4(5)) * 1 + 3 * 5 + 2 * (5 * 4) + 1 * (5 * 4 * 3); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx, selected_dim); + dim4 output_dims(1); + output_dims[selected_dim] = 5; // output size + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, output_dims), b); // lookup output should be the same as looked up indices +} + +TEST(lookup, Issue3613_FourthDimLookupWithOffset) { + dim4 dims(1); + const int selected_dim = 3; // selected span dimension + dims[selected_dim] = 125; // input size + + array a = iota(dims); + array idxs = iota(dim4(5, 4, 3, 2)); + array selected_idx = idxs(af::span, 3, 2, 1); // Offsets in second, third, & fourth dimension + + array expected_selected_idx = range(dim4(5)) * 1 + 3 * 5 + 2 * (5 * 4) + 1 * (5 * 4 * 3); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx, selected_dim); + dim4 output_dims(1); + output_dims[selected_dim] = 5; // output size + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, output_dims), b); // lookup output should be the same as looked up indices +} + +TEST(lookup, IndicesInSecondDimension) { + const int selected_dim = 1; // selected span dimension + dim4 dims(1); + dims[selected_dim] = 3; + + array a = iota(dim4(100)); + array idxs = iota(dim4(3, 3, 3, 3)); + array selected_idx = idxs(0, af::span, 0, 0); // Indices along the second dimension + + array expected_selected_idx = iota(dims) * pow(3, selected_dim); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx); + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, dim4(3)), b); +} + +TEST(lookup, IndicesInThirdDimension) { + const int selected_dim = 2; // selected span dimension + dim4 dims(1); + dims[selected_dim] = 3; + + array a = iota(dim4(100)); + array idxs = iota(dim4(3, 3, 3, 3)); + array selected_idx = idxs(0, 0, af::span, 0); // Indices along the third dimension + + array expected_selected_idx = iota(dims) * pow(3, selected_dim); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx); + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, dim4(3)), b); +} + +TEST(lookup, IndicesInFourthDimension) { + const int selected_dim = 3; // selected span dimension + dim4 dims(1); + dims[selected_dim] = 3; + + array a = iota(dim4(100)); + array idxs = iota(dim4(3, 3, 3, 3)); + array selected_idx = idxs(0, 0, 0, af::span); // Indices along the fourth dimension + + array expected_selected_idx = iota(dims) * pow(3, selected_dim); + ASSERT_ARRAYS_EQ(expected_selected_idx, selected_idx); + + array b = af::lookup(a, selected_idx); + ASSERT_ARRAYS_EQ(af::moddims(expected_selected_idx, dim4(3)), b); +} + TEST(lookup, SNIPPET_lookup1d) { //! [ex_index_lookup1d] diff --git a/test/inverse_deconv.cpp b/test/inverse_deconv.cpp index b6db793f4b..86ac2869ab 100644 --- a/test/inverse_deconv.cpp +++ b/test/inverse_deconv.cpp @@ -25,7 +25,7 @@ template class InverseDeconvolution : public ::testing::Test {}; // create a list of types to be tested -typedef ::testing::Types TestTypes; +typedef ::testing::Types TestTypes; // register the type list TYPED_TEST_SUITE(InverseDeconvolution, TestTypes); diff --git a/test/iota.cpp b/test/iota.cpp index c776d7628e..33ff36e3ba 100644 --- a/test/iota.cpp +++ b/test/iota.cpp @@ -39,7 +39,8 @@ class Iota : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + signed char, unsigned char, short, ushort, + half_float::half> TestTypes; // register the type list diff --git a/test/ireduce.cpp b/test/ireduce.cpp index 2ebd951d46..e93a8267b4 100644 --- a/test/ireduce.cpp +++ b/test/ireduce.cpp @@ -103,6 +103,7 @@ MINMAXOP(min, double) MINMAXOP(min, int) MINMAXOP(min, uint) MINMAXOP(min, char) +MINMAXOP(min, schar) MINMAXOP(min, uchar) MINMAXOP(max, float) @@ -110,6 +111,7 @@ MINMAXOP(max, double) MINMAXOP(max, int) MINMAXOP(max, uint) MINMAXOP(max, char) +MINMAXOP(max, schar) MINMAXOP(max, uchar) TEST(IndexedReduce, MaxIndexedSmall) { diff --git a/test/iterative_deconv.cpp b/test/iterative_deconv.cpp index e59440b977..290b81f0d6 100644 --- a/test/iterative_deconv.cpp +++ b/test/iterative_deconv.cpp @@ -25,7 +25,7 @@ template class IterativeDeconvolution : public ::testing::Test {}; // create a list of types to be tested -typedef ::testing::Types TestTypes; +typedef ::testing::Types TestTypes; // register the type list TYPED_TEST_SUITE(IterativeDeconvolution, TestTypes); @@ -40,6 +40,11 @@ void iterDeconvImageTest(string pTestFile, const unsigned iters, const float rf, SUPPORTED_TYPE_CHECK(T); IMAGEIO_ENABLED_CHECK(); + if (is_same_type::value && + algo == AF_ITERATIVE_DECONV_RICHARDSONLUCY) { + GTEST_SKIP() << "Incompatible with signed values"; + } + using af::dim4; vector inDims; diff --git a/test/join.cpp b/test/join.cpp index cf33fccb67..aef578bcf2 100644 --- a/test/join.cpp +++ b/test/join.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -47,8 +48,8 @@ class Join : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + intl, uintl, char, signed char, unsigned char, short, + ushort, half_float::half> TestTypes; // register the type list @@ -266,3 +267,48 @@ TEST(Join, ManyEmpty) { ASSERT_ARRAYS_EQ(gold, eace); ASSERT_ARRAYS_EQ(gold, acee); } + +TEST(Join, respect_parameters_order_ISSUE3511) { + const float column_host1[] = {1., 2., 3.}; + const float column_host2[] = {4., 5., 6.}; + const af::array buf1(3, 1, column_host1); + const af::array buf2(3, 1, column_host2); + + // We need to avoid that JIT arrays are evaluated during whatever call, + // so we will have to work with copies for single use + const af::array jit1{buf1 + 1.0}; + const af::array jit2{buf2 + 2.0}; + const std::array cases{jit1, -jit1, jit1 + 1.0, jit2, + -jit2, jit1 + jit2, buf1, buf2}; + const std::array cases_name{"JIT1", "-JIT1", "JIT1+1.0", + "JIT2", "-JIT2", "JIT1+JIT2", + "BUF1", "BUF2"}; + assert(cases.size() == cases_name.size()); + for (size_t cl0{0}; cl0 < cases.size(); ++cl0) { + for (size_t cl1{0}; cl1 < cases.size(); ++cl1) { + printf("Testing: af::join(1,%s,%s)\n", cases_name[cl0], + cases_name[cl1]); + const array col0{cases[cl0]}; + const array col1{cases[cl1]}; + const array result{af::join(1, col0, col1)}; + ASSERT_ARRAYS_EQ(result(af::span, 0), col0); + ASSERT_ARRAYS_EQ(result(af::span, 1), col1); + } + } + // Join of 3 arrays + for (size_t cl0{0}; cl0 < cases.size(); ++cl0) { + for (size_t cl1{0}; cl1 < cases.size(); ++cl1) { + for (size_t cl2{0}; cl2 < cases.size(); ++cl2) { + printf("Testing: af::join(1,%s,%s,%s)\n", cases_name[cl0], + cases_name[cl1], cases_name[cl2]); + const array col0{cases[cl0]}; + const array col1{cases[cl1]}; + const array col2{cases[cl2]}; + const array result{af::join(1, col0, col1, col2)}; + ASSERT_ARRAYS_EQ(result(af::span, 0), col0); + ASSERT_ARRAYS_EQ(result(af::span, 1), col1); + ASSERT_ARRAYS_EQ(result(af::span, 2), col2); + } + } + } +} diff --git a/test/match_template.cpp b/test/match_template.cpp index 33b6096815..f5f6eb4fc7 100644 --- a/test/match_template.cpp +++ b/test/match_template.cpp @@ -31,7 +31,8 @@ class MatchTemplate : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -84,16 +85,19 @@ void matchTemplateTest(string pTestFile, af_match_type pMatchType) { } TYPED_TEST(MatchTemplate, Matrix_SAD) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); matchTemplateTest( string(TEST_DIR "/MatchTemplate/matrix_sad.test"), AF_SAD); } TYPED_TEST(MatchTemplate, Matrix_SSD) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); matchTemplateTest( string(TEST_DIR "/MatchTemplate/matrix_ssd.test"), AF_SSD); } TYPED_TEST(MatchTemplate, MatrixBatch_SAD) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); matchTemplateTest( string(TEST_DIR "/MatchTemplate/matrix_sad_batch.test"), AF_SAD); } diff --git a/test/math.cpp b/test/math.cpp index 8e2243e13c..ee42a11423 100644 --- a/test/math.cpp +++ b/test/math.cpp @@ -1,5 +1,5 @@ /******************************************************* - * Copyright (c) 2014, ArrayFire + * Copyright (c) 2025, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. @@ -46,7 +46,7 @@ T rsqrt(T in) { } #define MATH_TEST(T, func, err, lo, hi) \ - TEST(MathTests, Test_##func##_##T) { \ + TEST(Math, func##_##T) { \ try { \ SUPPORTED_TYPE_CHECK(T); \ af_dtype ty = (af_dtype)dtype_traits::af_type; \ @@ -135,7 +135,7 @@ MATH_TESTS_REAL(erf) MATH_TESTS_REAL(erfc) #endif -TEST(MathTests, Not) { +TEST(Math, Not) { array a = randu(5, 5, b8); array b = !a; char *ha = a.host(); @@ -146,3 +146,47 @@ TEST(MathTests, Not) { af_free_host(ha); af_free_host(hb); } + +TEST(Math, Modulus) { + af::dim4 shape(2, 2); + std::vector aData{3, 3, 3, 3}; + std::vector bData{2, 2, 2, 2}; + + auto a = af::array(shape, aData.data(), afHost); + auto b = af::array(shape, bData.data(), afHost); + auto rem = a % b; + auto neg_rem = -a % b; + + ASSERT_ARRAYS_EQ(af::constant(1, shape, s64), rem); + ASSERT_ARRAYS_EQ(af::constant(-1, shape, s64), neg_rem); +} + +TEST(Math, ModulusFloat) { + SUPPORTED_TYPE_CHECK(half_float::half); + af::dim4 shape(2, 2); + + auto a = af::constant(3, shape, af::dtype::f16); + auto b = af::constant(2, shape, af::dtype::f16); + auto a32 = af::constant(3, shape, af::dtype::f32); + auto b32 = af::constant(2, shape, af::dtype::f32); + auto a64 = af::constant(3, shape, af::dtype::f64); + auto b64 = af::constant(2, shape, af::dtype::f64); + + auto rem = a % b; + auto rem32 = a32 % b32; + auto rem64 = a64 % b64; + + auto neg_rem = -a % b; + auto neg_rem32 = -a32 % b32; + auto neg_rem64 = -a64 % b64; + + ASSERT_ARRAYS_EQ(af::constant(1, shape, af::dtype::f16), rem); + ASSERT_ARRAYS_EQ(af::constant(1, shape, af::dtype::f32), rem32); + ASSERT_ARRAYS_EQ(af::constant(1, shape, af::dtype::f64), rem64); + + ASSERT_ARRAYS_EQ(af::constant(-1, shape, af::dtype::f16), neg_rem); + ASSERT_ARRAYS_EQ(af::constant(-1, shape, af::dtype::f32), neg_rem32); + ASSERT_ARRAYS_EQ(af::constant(-1, shape, af::dtype::f64), neg_rem64); + + ASSERT_ARRAYS_EQ(rem32.as(f16), rem); +} diff --git a/test/mean.cpp b/test/mean.cpp index c9c6eb567b..79dd76db2d 100644 --- a/test/mean.cpp +++ b/test/mean.cpp @@ -40,7 +40,7 @@ class Mean : public ::testing::Test { // This list does not allow to cleanly add the af_half/half_float type : at the // moment half tested in some special unittests typedef ::testing::Types + char, schar, uchar, short, ushort, half_float::half> TestTypes; // register the type list @@ -70,9 +70,9 @@ template struct meanOutType { typedef typename cond_type< is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value, + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value, float, typename elseType::type>::type type; }; @@ -228,7 +228,7 @@ TEST(MeanAll, s32) { meanAllTest(2, dim4(5, 5, 2, 2)); } TEST(MeanAll, u32) { meanAllTest(2, dim4(100, 1, 1, 1)); } -TEST(MeanAll, s8) { meanAllTest(2, dim4(5, 5, 2, 2)); } +TEST(MeanAll, s8) { meanAllTest(2, dim4(5, 5, 2, 2)); } TEST(MeanAll, u8) { meanAllTest(2, dim4(100, 1, 1, 1)); } diff --git a/test/meanshift.cpp b/test/meanshift.cpp index 1f0aa697b3..d91648ae52 100644 --- a/test/meanshift.cpp +++ b/test/meanshift.cpp @@ -28,8 +28,8 @@ class Meanshift : public ::testing::Test { virtual void SetUp() {} }; -typedef ::testing::Types +typedef ::testing::Types TestTypes; TYPED_TEST_SUITE(Meanshift, TestTypes); diff --git a/test/meanvar.cpp b/test/meanvar.cpp index 08e4702481..c7eba339a8 100644 --- a/test/meanvar.cpp +++ b/test/meanvar.cpp @@ -40,8 +40,8 @@ struct varOutType { typedef typename cond_type< is_same_type::value || is_same_type::value || is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value, + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value, float, typename elseType::type>::type type; }; @@ -377,5 +377,6 @@ TEST_P(MeanVarHalf, TestingCPP) { } // Only test small sizes because the range of the large arrays go out of bounds +MEANVAR_TEST(SignedChar, signed char) MEANVAR_TEST(UnsignedChar, unsigned char) // MEANVAR_TEST(Bool, unsigned char) // TODO(umar): test this type diff --git a/test/medfilt.cpp b/test/medfilt.cpp index 1939379974..5ef951d5b1 100644 --- a/test/medfilt.cpp +++ b/test/medfilt.cpp @@ -35,7 +35,8 @@ class MedianFilter1d : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -80,24 +81,28 @@ void medfiltTest(string pTestFile, dim_t w_len, dim_t w_wid, } TYPED_TEST(MedianFilter, ZERO_PAD_3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfiltTest( string(TEST_DIR "/medianfilter/zero_pad_3x3_window.test"), 3, 3, AF_PAD_ZERO); } TYPED_TEST(MedianFilter, SYMMETRIC_PAD_3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfiltTest( string(TEST_DIR "/medianfilter/symmetric_pad_3x3_window.test"), 3, 3, AF_PAD_SYM); } TYPED_TEST(MedianFilter, BATCH_ZERO_PAD_3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfiltTest( string(TEST_DIR "/medianfilter/batch_zero_pad_3x3_window.test"), 3, 3, AF_PAD_ZERO); } TYPED_TEST(MedianFilter, BATCH_SYMMETRIC_PAD_3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfiltTest( string(TEST_DIR "/medianfilter/batch_symmetric_pad_3x3_window.test"), 3, 3, AF_PAD_SYM); @@ -140,24 +145,28 @@ void medfilt1_Test(string pTestFile, dim_t w_wid, af_border_type pad) { } TYPED_TEST(MedianFilter1d, ZERO_PAD_3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfilt1_Test( string(TEST_DIR "/medianfilter/zero_pad_3x1_window.test"), 3, AF_PAD_ZERO); } TYPED_TEST(MedianFilter1d, SYMMETRIC_PAD_3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfilt1_Test( string(TEST_DIR "/medianfilter/symmetric_pad_3x1_window.test"), 3, AF_PAD_SYM); } TYPED_TEST(MedianFilter1d, BATCH_ZERO_PAD_3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfilt1_Test( string(TEST_DIR "/medianfilter/batch_zero_pad_3x1_window.test"), 3, AF_PAD_ZERO); } TYPED_TEST(MedianFilter1d, BATCH_SYMMETRIC_PAD_3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); medfilt1_Test( string(TEST_DIR "/medianfilter/batch_symmetric_pad_3x1_window.test"), 3, AF_PAD_SYM); @@ -338,6 +347,7 @@ TYPED_TEST(MedianFilter1d, InvalidPadType) { medfilt1d_PadTest(); } using af::array; TEST(MedianFilter, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const dim_t w_len = 3; const dim_t w_wid = 3; @@ -365,6 +375,7 @@ TEST(MedianFilter, CPP) { } TEST(MedianFilter1d, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const dim_t w_wid = 3; vector numDims; @@ -391,6 +402,7 @@ TEST(MedianFilter1d, CPP) { } TEST(MedianFilter, Docs) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); float input[] = {1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000, 11.0000, 12.0000, 13.0000, 14.0000, 15.0000, 16.0000}; @@ -431,6 +443,7 @@ using af::seq; using af::span; TEST(MedianFilter, GFOR) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); dim4 dims = dim4(10, 10, 3); array A = iota(dims); array B = constant(0, dims); @@ -445,6 +458,7 @@ TEST(MedianFilter, GFOR) { } TEST(MedianFilter1d, GFOR) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); dim4 dims = dim4(10, 10, 3); array A = iota(dims); array B = constant(0, dims); diff --git a/test/median.cpp b/test/median.cpp index c55251e66c..4f64631c6f 100644 --- a/test/median.cpp +++ b/test/median.cpp @@ -119,6 +119,7 @@ void median_test(int nx, int ny = 1, int nz = 1, int nw = 1) { MEDIAN_FLAT(float, float) MEDIAN_FLAT(float, int) MEDIAN_FLAT(float, uint) +MEDIAN_FLAT(float, schar) MEDIAN_FLAT(float, uchar) MEDIAN_FLAT(float, short) MEDIAN_FLAT(float, ushort) @@ -151,6 +152,7 @@ MEDIAN_FLAT(double, double) MEDIAN(float, float) MEDIAN(float, int) MEDIAN(float, uint) +MEDIAN(float, schar) MEDIAN(float, uchar) MEDIAN(float, short) MEDIAN(float, ushort) diff --git a/test/memory.cpp b/test/memory.cpp index 991756ca0b..9214ab472c 100644 --- a/test/memory.cpp +++ b/test/memory.cpp @@ -74,7 +74,8 @@ class MemAlloc : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + intl, uintl, char, signed char, unsigned char, short, + ushort> TestTypes; // register the type list diff --git a/test/moddims.cpp b/test/moddims.cpp index a7dea52a00..c8b98f05d1 100644 --- a/test/moddims.cpp +++ b/test/moddims.cpp @@ -36,8 +36,8 @@ class Moddims : public ::testing::Test { // create a list of types to be tested // TODO: complex types tests have to be added -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/moments.cpp b/test/moments.cpp index 6b02cb614a..bec90e5b5d 100644 --- a/test/moments.cpp +++ b/test/moments.cpp @@ -158,25 +158,30 @@ void momentsOnImageTest(string pTestFile, string pImageFile, bool isColor) { } TEST(IMAGE, MomentsImage) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); momentsOnImageTest(string(TEST_DIR "/moments/gray_seq_16_moments.test"), string(TEST_DIR "/imageio/gray_seq_16.png"), false); } TEST(Image, MomentsImageBatch) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); momentsTest( string(TEST_DIR "/moments/simple_mat_batch_moments.test")); } TEST(Image, MomentsBatch2D) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); momentsOnImageTest(string(TEST_DIR "/moments/color_seq_16_moments.test"), string(TEST_DIR "/imageio/color_seq_16.png"), true); } TYPED_TEST(Image, MomentsSynthTypes) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); momentsTest(string(TEST_DIR "/moments/simple_mat_moments.test")); } TEST(Image, Moment_Issue1957) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); array A = identity(3, 3, b8); double m00; diff --git a/test/morph.cpp b/test/morph.cpp index 9cc2255fb5..b68d95076f 100644 --- a/test/morph.cpp +++ b/test/morph.cpp @@ -30,7 +30,8 @@ class Morph : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -59,16 +60,19 @@ void morphTest(string pTestFile) { maskDims.ndims(), maskDims.get(), (af_dtype)dtype_traits::af_type)); + af_err af_stat; if (isDilation) { - if (isVolume) + if (isVolume) { ASSERT_SUCCESS(af_dilate3(&outArray, inArray, maskArray)); - else + } else { ASSERT_SUCCESS(af_dilate(&outArray, inArray, maskArray)); + } } else { - if (isVolume) + if (isVolume) { ASSERT_SUCCESS(af_erode3(&outArray, inArray, maskArray)); - else + } else { ASSERT_SUCCESS(af_erode(&outArray, inArray, maskArray)); + } } for (size_t testIter = 0; testIter < tests.size(); ++testIter) { @@ -83,52 +87,63 @@ void morphTest(string pTestFile) { } TYPED_TEST(Morph, Dilate3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest(string(TEST_DIR "/morph/dilate3x3.test")); } TYPED_TEST(Morph, Erode3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest(string(TEST_DIR "/morph/erode3x3.test")); } TYPED_TEST(Morph, Dilate4x4) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest(string(TEST_DIR "/morph/dilate4x4.test")); } TYPED_TEST(Morph, Dilate12x12) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/dilate12x12.test")); } TYPED_TEST(Morph, Erode4x4) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest(string(TEST_DIR "/morph/erode4x4.test")); } TYPED_TEST(Morph, Dilate3x3_Batch) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/dilate3x3_batch.test")); } TYPED_TEST(Morph, Erode3x3_Batch) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/erode3x3_batch.test")); } TYPED_TEST(Morph, Dilate3x3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/dilate3x3x3.test")); } TYPED_TEST(Morph, Erode3x3x3) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/erode3x3x3.test")); } TYPED_TEST(Morph, Dilate4x4x4) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/dilate4x4x4.test")); } TYPED_TEST(Morph, Erode4x4x4) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphTest( string(TEST_DIR "/morph/erode4x4x4.test")); } @@ -186,10 +201,10 @@ void morphImageTest(string pTestFile, dim_t seLen) { ASSERT_SUCCESS(error_code); ASSERT_IMAGES_NEAR(goldArray, outArray, 0.018f); #else - ASSERT_EQ(error_code, - (targetType != b8 && seLen > 19 ? AF_ERR_NOT_SUPPORTED - : AF_SUCCESS)); - if (!(targetType != b8 && seLen > 19)) { + if (targetType != b8 && seLen > 19) { + ASSERT_EQ(error_code, AF_ERR_NOT_SUPPORTED); + } else { + ASSERT_SUCCESS(error_code); ASSERT_IMAGES_NEAR(goldArray, outArray, 0.018f); } #endif @@ -204,10 +219,12 @@ void morphImageTest(string pTestFile, dim_t seLen) { } TEST(Morph, GrayscaleDilation3x3StructuringElement) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphImageTest(string(TEST_DIR "/morph/gray.test"), 3); } TEST(Morph, ColorImageErosion3x3StructuringElement) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); morphImageTest(string(TEST_DIR "/morph/color.test"), 3); } @@ -428,14 +445,17 @@ void cppMorphImageTest(string pTestFile) { } TEST(Morph, Grayscale_CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); cppMorphImageTest(string(TEST_DIR "/morph/gray.test")); } TEST(Morph, ColorImage_CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); cppMorphImageTest(string(TEST_DIR "/morph/color.test")); } TEST(Morph, GFOR) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); dim4 dims = dim4(10, 10, 3); array A = iota(dims); array B = constant(0, dims); @@ -451,6 +471,7 @@ TEST(Morph, GFOR) { } TEST(Morph, EdgeIssue1564) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); int inputData[10 * 10] = {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -466,12 +487,13 @@ TEST(Morph, EdgeIssue1564) { array input(10, 10, inputData); int maskData[3 * 3] = {1, 1, 1, 1, 0, 1, 1, 1, 1}; array mask(3, 3, maskData); + array dilated = dilate(input.as(b8), mask.as(b8)); size_t nElems = dilated.elements(); vector outData(nElems); dilated.host((void*)outData.data()); - + for (size_t i = 0; i < nElems; ++i) { ASSERT_EQ((int)outData[i], goldData[i]); } diff --git a/test/nearest_neighbour.cpp b/test/nearest_neighbour.cpp index 01847aea65..82551bc31b 100644 --- a/test/nearest_neighbour.cpp +++ b/test/nearest_neighbour.cpp @@ -34,8 +34,8 @@ class NearestNeighbour : public ::testing::Test { }; // create lists of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; template @@ -53,6 +53,11 @@ struct otype_t { typedef uint otype; }; +template<> +struct otype_t { + typedef int otype; +}; + template<> struct otype_t { typedef uint otype; @@ -117,24 +122,28 @@ void nearestNeighbourTest(string pTestFile, int feat_dim, // SSD ///////////////////////////////////////////////// TYPED_TEST(NearestNeighbour, NN_SSD_100_1000_Dim0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/ssd_100_1000_dim0.test"), 0, AF_SSD); } TYPED_TEST(NearestNeighbour, NN_SSD_100_1000_Dim1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/ssd_100_1000_dim1.test"), 1, AF_SSD); } TYPED_TEST(NearestNeighbour, NN_SSD_500_5000_Dim0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/ssd_500_5000_dim0.test"), 0, AF_SSD); } TYPED_TEST(NearestNeighbour, NN_SSD_500_5000_Dim1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/ssd_500_5000_dim1.test"), 1, AF_SSD); @@ -144,24 +153,28 @@ TYPED_TEST(NearestNeighbour, NN_SSD_500_5000_Dim1) { // SAD ///////////////////////////////////////////////// TYPED_TEST(NearestNeighbour, NN_SAD_100_1000_Dim0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/sad_100_1000_dim0.test"), 0, AF_SAD); } TYPED_TEST(NearestNeighbour, NN_SAD_100_1000_Dim1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/sad_100_1000_dim1.test"), 1, AF_SAD); } TYPED_TEST(NearestNeighbour, NN_SAD_500_5000_Dim0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/sad_500_5000_dim0.test"), 0, AF_SAD); } TYPED_TEST(NearestNeighbour, NN_SAD_500_5000_Dim1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearestNeighbourTest( string(TEST_DIR "/nearest_neighbour/sad_500_5000_dim1.test"), 1, AF_SAD); @@ -170,6 +183,7 @@ TYPED_TEST(NearestNeighbour, NN_SAD_500_5000_Dim1) { ///////////////////////////////////// CPP //////////////////////////////// // TEST(NearestNeighbourSSD, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; @@ -206,6 +220,7 @@ TEST(NearestNeighbourSSD, CPP) { } TEST(NearestNeighbourSAD, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; @@ -242,6 +257,7 @@ TEST(NearestNeighbourSAD, CPP) { } TEST(NearestNeighbourSSD, small) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const int ntrain = 1; const int nquery = 5; const int nfeat = 2; @@ -272,6 +288,7 @@ TEST(NearestNeighbourSSD, small) { } TEST(KNearestNeighbourSSD, small) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const int ntrain = 5; const int nquery = 3; const int nfeat = 2; @@ -435,6 +452,7 @@ INSTANTIATE_TEST_SUITE_P(KNearestNeighborsSSD, KNearestNeighborsTest, testNameGenerator); TEST_P(NearestNeighborsTest, SingleQTests) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearest_neighbors_params params = GetParam(); array query = array(params.qdims_, params.query_.data()); array train = array(params.tdims_, params.train_.data()); @@ -454,6 +472,7 @@ TEST_P(NearestNeighborsTest, SingleQTests) { } TEST_P(KNearestNeighborsTest, SingleQTests) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); nearest_neighbors_params params = GetParam(); array query = array(params.qdims_, params.query_.data()); @@ -504,6 +523,7 @@ TEST(KNearestNeighbours, InvalidLargeK) { } TEST(NearestNeighbour, DocSnippet1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); //! [ex_nearest_1] float h_pts[6] = {1.f, 2.f, 3.f, 8.f, 9.f, 10.f}; array pts(dim4(1, 6), h_pts); @@ -537,6 +557,7 @@ TEST(NearestNeighbour, DocSnippet1) { } TEST(NearestNeighbour, DocSnippet2) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); //! [ex_nearest_2] float h_pts[18] = {0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 8.f, 9.f, 1.f, 9.f, 8.f, 1.f, 9.f, 9.f, 1.f}; diff --git a/test/norm.cpp b/test/norm.cpp new file mode 100644 index 0000000000..c795c112c3 --- /dev/null +++ b/test/norm.cpp @@ -0,0 +1,285 @@ +/******************************************************* + * Copyright (c) 2025, ArrayFire + * All rights reserved. + * + * This file is distributed under 3-clause BSD license. + * The complete license agreement can be obtained at: + * http://arrayfire.com/licenses/BSD-3-Clause + ********************************************************/ + +#include +#include +#include +#include + +using af::array; +using af::constant; +using af::dim4; +using std::complex; +using std::stringstream; +using std::vector; + +std::ostream &operator<<(std::ostream &os, af::normType nt) { + switch (nt) { + case AF_NORM_VECTOR_1: os << "AF_NORM_VECTOR_1"; break; + case AF_NORM_VECTOR_INF: os << "AF_NORM_VECTOR_INF"; break; + case AF_NORM_VECTOR_2: os << "AF_NORM_VECTOR_2"; break; + case AF_NORM_VECTOR_P: os << "AF_NORM_VECTOR_P"; break; + case AF_NORM_MATRIX_1: os << "AF_NORM_MATRIX_1"; break; + case AF_NORM_MATRIX_INF: os << "AF_NORM_MATRIX_INF"; break; + case AF_NORM_MATRIX_2: os << "AF_NORM_MATRIX_2"; break; + case AF_NORM_MATRIX_L_PQ: os << "AF_NORM_MATRIX_L_PQ"; break; + } + return os; +} + +template +double cpu_norm1_impl(af::dim4 &dims, std::vector &value) { + int M = dims[0]; + int N = dims[1]; + + double norm1 = std::numeric_limits::lowest(); + for (int n = 0; n < N; n++) { + T *columnN = value.data() + n * M; + double sum = 0; + for (int m = 0; m < M; m++) { sum += abs(columnN[m]); } + norm1 = std::max(norm1, sum); + } + return norm1; +} + +template +double cpu_norm_pq_impl(af::dim4 &dims, std::vector &value, double p, double q) { + int N = dims[0]; + int M = dims[1]; + + double norm = 0; + for (int n = 0; n < N; n++) { + T *columnN = value.data() + n * M; + double sum = 0; + + for (int m = 0; m < M; m++) { sum += std::pow(std::abs(columnN[m]), p); } + + norm += std::pow(sum, q / p); + } + norm = std::pow(norm, 1.0 / q); + + return norm; +} + +double cpu_norm1(af::array &value) { + double norm1; + af::dim4 dims = value.dims(); + if (value.type() == f16) { + vector values(value.elements()); + value.host(values.data()); + norm1 = cpu_norm1_impl(dims, values); + } else if (value.type() == c32 || value.type() == c64) { + vector > values(value.elements()); + value.as(c64).host(values.data()); + norm1 = cpu_norm1_impl >(dims, values); + } else { + vector values(value.elements()); + value.as(f64).host(values.data()); + norm1 = cpu_norm1_impl(dims, values); + } + return norm1; +} + +double cpu_norm_pq(af::array &value, double p, double q) { + double norm2; + af::dim4 dims = value.dims(); + if (value.type() == f16) { + vector values(value.elements()); + value.host(values.data()); + norm2 = cpu_norm_pq_impl(dims, values, p, q); + } else if (value.type() == c32 || value.type() == c64) { + vector > values(value.elements()); + value.as(c64).host(values.data()); + norm2 = cpu_norm_pq_impl >(dims, values, p, q); + } else { + vector values(value.elements()); + value.as(f64).host(values.data()); + norm2 = cpu_norm_pq_impl(dims, values, p, q); + } + return norm2; +} + +template +double cpu_norm_inf_impl(af::dim4 &dims, std::vector &value) { + int M = dims[0]; + int N = dims[1]; + + double norm_inf = std::numeric_limits::lowest(); + for (int m = 0; m < M; m++) { + T *rowM = value.data() + m; + double sum = 0; + for (int n = 0; n < N; n++) { sum += abs(rowM[n * M]); } + norm_inf = std::max(norm_inf, sum); + } + return norm_inf; +} + +double cpu_norm_inf(af::array &value) { + double norm_inf; + af::dim4 dims = value.dims(); + if (value.type() == c32 || value.type() == c64) { + vector > values(value.elements()); + value.as(c64).host(values.data()); + norm_inf = cpu_norm_inf_impl >(dims, values); + } else { + vector values(value.elements()); + value.as(f64).host(values.data()); + norm_inf = cpu_norm_inf_impl(dims, values); + } + return norm_inf; +} + +using norm_params = std::tuple; +class Norm + : public ::testing::TestWithParam > {}; + +INSTANTIATE_TEST_CASE_P( + Norm, Norm, + ::testing::Combine(::testing::Values(dim4(3, 3), dim4(32, 32), dim4(33, 33), + dim4(64, 64), dim4(128, 128), + dim4(129, 129), dim4(256, 256), + dim4(257, 257)), + ::testing::Values(f32, f64, c32, c64, f16)), + [](const ::testing::TestParamInfo info) { + stringstream ss; + using std::get; + ss << "dims_" << get<0>(info.param)[0] << "_" << get<0>(info.param)[1] + << "_dtype_" << get<1>(info.param); + return ss.str(); + }); + +TEST_P(Norm, Identity_AF_NORM_MATRIX_1) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + + array identity = af::identity(get<0>(param), get<1>(param)); + double result = norm(identity, AF_NORM_MATRIX_1); + double norm1 = cpu_norm1(identity); + + ASSERT_DOUBLE_EQ(norm1, result); +} + +TEST_P(Norm, Random_AF_NORM_MATRIX_1) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + + array in = af::randu(get<0>(param), get<1>(param)) - 0.5f; + double result = norm(in, AF_NORM_MATRIX_1); + double norm1 = cpu_norm1(in); + + ASSERT_NEAR(norm1, result, 2e-4); +} + +TEST_P(Norm, Random_AF_NORM_VECTOR_1) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + + af::dim4 dims = get<0>(param); + dims[1] = 1; // Test a vector + + array in = af::randu(dims, get<1>(param)) - 0.5f; + double result = norm(in, AF_NORM_VECTOR_1); + double norm1 = cpu_norm_pq(in, 1, 1); + + ASSERT_NEAR(norm1, result, 2e-4); +} + +TEST_P(Norm, Random_AF_NORM_VECTOR_INF) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + + af::dim4 dims = get<0>(param); + dims[1] = 1; // Test a vector + + array in = af::randu(dims, get<1>(param)) - 0.5f; + double result = norm(in, AF_NORM_VECTOR_INF); + double norm_inf = cpu_norm_inf(in); + + ASSERT_NEAR(norm_inf, result, 2e-4); +} + +TEST_P(Norm, Random_AF_NORM_VECTOR_2) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + + af::dim4 dims = get<0>(param); + dims[1] = 1; // Test a vector + + array in = af::randu(dims, get<1>(param)) - 0.5f; + double result = norm(in, AF_NORM_VECTOR_2); + double norm2 = cpu_norm_pq(in, 1, 2); // vectors lie in first dims so swap p and q + + ASSERT_NEAR(norm2, result, 3e-4); +} + +TEST_P(Norm, Random_AF_NORM_VECTOR_P_P_EQUAL_3_POINT_5) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + + af::dim4 dims = get<0>(param); + dims[1] = 1; // Test a vector + + array in = af::randu(dims, get<1>(param)) - 0.5f; + double result = norm(in, AF_NORM_VECTOR_P, 3.5); + double normp = cpu_norm_pq(in, 1, 3.5); // vectors lie in first dims so swap p and q + + ASSERT_NEAR(normp, result, 3e-4); +} + +TEST_P(Norm, Identity_AF_NORM_MATRIX_2_NOT_SUPPORTED) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + try { + double result = + norm(af::identity(get<0>(param), get<1>(param)), AF_NORM_MATRIX_2); + FAIL(); + } catch (af::exception &ex) { + ASSERT_EQ(AF_ERR_NOT_SUPPORTED, ex.err()); + return; + } + FAIL(); +} + +TEST_P(Norm, Identity_AF_NORM_MATRIX_INF) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + array in = af::identity(get<0>(param), get<1>(param)); + double result = norm(in, AF_NORM_MATRIX_INF); + double norm_inf = cpu_norm_inf(in); + + ASSERT_DOUBLE_EQ(norm_inf, result); +} + +TEST_P(Norm, Random_AF_NORM_MATRIX_INF) { + using std::get; + norm_params param = GetParam(); + if (get<1>(param) == f16) SUPPORTED_TYPE_CHECK(half_float::half); + if (get<1>(param) == f64) SUPPORTED_TYPE_CHECK(double); + array in = af::randu(get<0>(param), get<1>(param)); + double result = norm(in, AF_NORM_MATRIX_INF); + double norm_inf = cpu_norm_inf(in); + + ASSERT_NEAR(norm_inf, result, 2e-4); +} diff --git a/test/orb.cpp b/test/orb.cpp index e519fd91dc..3ace1f4b05 100644 --- a/test/orb.cpp +++ b/test/orb.cpp @@ -238,14 +238,19 @@ void orbTest(string pTestFile) { } TYPED_TEST(ORB, Square) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); orbTest(string(TEST_DIR "/orb/square.test")); } -TYPED_TEST(ORB, Lena) { orbTest(string(TEST_DIR "/orb/lena.test")); } +TYPED_TEST(ORB, Lena) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); + orbTest(string(TEST_DIR "/orb/lena.test")); +} ///////////////////////////////////// CPP //////////////////////////////// // TEST(ORB, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); IMAGEIO_ENABLED_CHECK(); vector inDims; diff --git a/test/pad_borders.cpp b/test/pad_borders.cpp index 028c946719..2642ed83ca 100644 --- a/test/pad_borders.cpp +++ b/test/pad_borders.cpp @@ -24,8 +24,8 @@ using std::vector; template class PadBorders : public ::testing::Test {}; -typedef ::testing::Types TestTypes; diff --git a/test/random.cpp b/test/random.cpp index d0860b70f2..f6fd0dd45f 100644 --- a/test/random.cpp +++ b/test/random.cpp @@ -36,7 +36,7 @@ class Random : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + uintl, signed char, unsigned char, char, af_half> TestTypes; // register the type list @@ -258,15 +258,15 @@ void testSetSeed(const uintl seed0, const uintl seed1) { ASSERT_EQ(h_in0[i], h_in2[i]) << "at : " << i; // Verify different arrays created with different seeds differ - // b8 and u9 can clash because they generate a small set of values - if (ty != b8 && ty != u8) { + // b8, s8 and u8 can clash because they generate a small set of values + if (ty != b8 && ty != s8 && ty != u8) { ASSERT_NE(h_in0[i], h_in1[i]) << "at : " << i; } // Verify different arrays created one after the other with same seed - // differ b8 and u9 can clash because they generate a small set of + // differ b8, s8 and u8 can clash because they generate a small set of // values - if (ty != b8 && ty != u8) { + if (ty != b8 && ty != s8 && ty != u8) { ASSERT_NE(h_in2[i], h_in3[i]) << "at : " << i; } } @@ -394,7 +394,7 @@ void testRandomEngineSeed(randomEngineType type) { for (int i = 0; i < elem; i++) { ASSERT_EQ(h1[i], h3[i]) << "at : " << i; - if (ty != b8 && ty != u8) { + if (ty != b8 && ty != s8 && ty != u8) { ASSERT_NE(h1[i], h2[i]) << "at : " << i; ASSERT_NE(h3[i], h4[i]) << "at : " << i; } diff --git a/test/range.cpp b/test/range.cpp index 35708bde09..0e708160c2 100644 --- a/test/range.cpp +++ b/test/range.cpp @@ -46,12 +46,13 @@ class RangeMax : public Range {}; // create a list of types to be tested typedef ::testing::Types + signed char, unsigned char, short, ushort, + half_float::half> AllTypes; // create a list of types to be tested typedef ::testing::Types + signed char, unsigned char, short, ushort> RegularTypes; // register the type list diff --git a/test/reduce.cpp b/test/reduce.cpp index 0b8317a960..0d4ab59225 100644 --- a/test/reduce.cpp +++ b/test/reduce.cpp @@ -36,10 +36,14 @@ using std::vector; template class Reduce : public ::testing::Test {}; +template +class ReduceByKey : public ::testing::Test {}; + typedef ::testing::Types + schar, uchar, short, ushort> TestTypes; TYPED_TEST_SUITE(Reduce, TestTypes); +TYPED_TEST_SUITE(ReduceByKey, TestTypes); typedef af_err (*reduceFunc)(af_array *, const af_array, const int); @@ -122,6 +126,10 @@ struct promote_type { // char and uchar are promoted to int for sum and product template<> +struct promote_type { + typedef int type; +}; +template<> struct promote_type { typedef uint type; }; @@ -138,6 +146,10 @@ struct promote_type { typedef uint type; }; template<> +struct promote_type { + typedef int type; +}; +template<> struct promote_type { typedef uint type; }; @@ -154,6 +166,16 @@ struct promote_type { typedef uint type; }; +// float16 is promoted to float32 for sum and product +template<> +struct promote_type { + typedef float type; +}; +template<> +struct promote_type { + typedef float type; +}; + #define REDUCE_TESTS(FN) \ TYPED_TEST(Reduce, Test_##FN) { \ reduceTest::type, \ @@ -375,6 +397,7 @@ array ptrToArray(size_t size, void *ptr, af_dtype type) { case u16: res = array(size, (unsigned short *)ptr); break; case s16: res = array(size, (short *)ptr); break; case b8: res = array(size, (char *)ptr); break; + case s8: res = array(size, (signed char *)ptr); break; case u8: res = array(size, (unsigned char *)ptr); break; case f16: res = array(size, (half_float::half *)ptr); break; } @@ -395,6 +418,7 @@ array ptrToArray(af::dim4 size, void *ptr, af_dtype type) { case u16: res = array(size, (unsigned short *)ptr); break; case s16: res = array(size, (short *)ptr); break; case b8: res = array(size, (char *)ptr); break; + case s8: res = array(size, (signed char *)ptr); break; case u8: res = array(size, (unsigned char *)ptr); break; case f16: res = array(size, (half_float::half *)ptr); break; } @@ -598,12 +622,16 @@ TEST_P(ReduceByKeyP, SumDim2) { ASSERT_ARRAYS_NEAR(valsReducedGold, valsReduced, 1e-5); } -TEST(ReduceByKey, MultiBlockReduceSingleval) { +TYPED_TEST(ReduceByKey, MultiBlockReduceSingleval) { + SUPPORTED_TYPE_CHECK(TypeParam); array keys = constant(0, 1024 * 1024, s32); - array vals = constant(1, 1024 * 1024, f32); + array vals = constant(1, 1024 * 1024, + (af_dtype)af::dtype_traits::af_type); array keyResGold = constant(0, 1); - array valsReducedGold = constant(1024 * 1024, 1, f32); + using promoted_t = typename promote_type::type; + array valsReducedGold = constant(1024 * 1024, 1, + (af_dtype)af::dtype_traits::af_type); array keyRes, valsReduced; sumByKey(keyRes, valsReduced, keys, vals); @@ -701,10 +729,11 @@ TEST(ReduceByKey, MultiBlockReduceByKeyRandom500) { reduce_by_key_test(string(TEST_DIR "/reduce/test_random500_by_key.test")); } -TEST(ReduceByKey, productReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, productReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -713,15 +742,17 @@ TEST(ReduceByKey, productReduceByKey) { productByKey(reduced_keys, reduced_vals, keys, vals, 0, 1); const int goldSz = 5; - const vector gold_reduce{0, 7, 6, 30, 4}; + using promoted_t = typename promote_type::type; + const vector gold_reduce{0, 7, 6, 30, 4}; ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, minReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, minReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -730,14 +761,15 @@ TEST(ReduceByKey, minReduceByKey) { minByKey(reduced_keys, reduced_vals, keys, vals); const int goldSz = 5; - const vector gold_reduce{0, 1, 6, 2, 4}; + const vector gold_reduce{0, 1, 6, 2, 4}; ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, maxReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, maxReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -746,14 +778,15 @@ TEST(ReduceByKey, maxReduceByKey) { maxByKey(reduced_keys, reduced_vals, keys, vals); const int goldSz = 5; - const vector gold_reduce{0, 7, 6, 5, 4}; + const vector gold_reduce{0, 7, 6, 5, 4}; ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, allTrueReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 1, 1, 1, 0, 1, 1, 1}; +TYPED_TEST(ReduceByKey, allTrueReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 1, 1, 1, 0, 1, 1, 1}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -766,10 +799,11 @@ TEST(ReduceByKey, allTrueReduceByKey) { ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, anyTrueReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 8, 8}; - const float testVals[testSz] = {0, 1, 1, 1, 0, 1, 0, 0}; +TYPED_TEST(ReduceByKey, anyTrueReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 8, 8}; + const TypeParam testVals[testSz] = {0, 1, 1, 1, 0, 1, 0, 0}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -783,10 +817,11 @@ TEST(ReduceByKey, anyTrueReduceByKey) { ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, countReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 5}; - const float testVals[testSz] = {0, 1, 1, 1, 0, 1, 1, 1}; +TYPED_TEST(ReduceByKey, countReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 5}; + const TypeParam testVals[testSz] = {0, 1, 1, 1, 0, 1, 1, 1}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -799,11 +834,18 @@ TEST(ReduceByKey, countReduceByKey) { ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, ReduceByKeyNans) { +TYPED_TEST(ReduceByKey, ReduceByKeyNans) { + if (!IsFloatingPoint::value) { + SUCCEED() << "Not a floating point type."; + return; + } + SKIP_IF_FAST_MATH_ENABLED(); - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, NAN, 6, 2, 5, 3, 4}; + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam nan = std::numeric_limits::quiet_NaN(); + const TypeParam testVals[testSz] = {0, 7, nan, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -812,14 +854,16 @@ TEST(ReduceByKey, ReduceByKeyNans) { productByKey(reduced_keys, reduced_vals, keys, vals, 0, 1); const int goldSz = 5; - const vector gold_reduce{0, 7, 6, 30, 4}; + using promoted_t = typename promote_type::type; + const vector gold_reduce{0, 7, 6, 30, 4}; ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, nDim0ReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, nDim0ReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -833,20 +877,22 @@ TEST(ReduceByKey, nDim0ReduceByKey) { sumByKey(reduced_keys, reduced_vals, keys, vals, dim, nanval); const dim4 goldSz(5, 2, 2, 2); - const vector gold_reduce{0, 8, 6, 10, 4, 0, 8, 6, 10, 4, + using promoted_t = typename promote_type::type; + const vector gold_reduce{0, 8, 6, 10, 4, 0, 8, 6, 10, 4, - 0, 8, 6, 10, 4, 0, 8, 6, 10, 4, + 0, 8, 6, 10, 4, 0, 8, 6, 10, 4, - 0, 8, 6, 10, 4, 0, 8, 6, 10, 4, + 0, 8, 6, 10, 4, 0, 8, 6, 10, 4, - 0, 8, 6, 10, 4, 0, 8, 6, 10, 4}; + 0, 8, 6, 10, 4, 0, 8, 6, 10, 4}; ASSERT_VEC_ARRAY_EQ(gold_reduce, goldSz, reduced_vals); } -TEST(ReduceByKey, nDim1ReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, nDim1ReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -861,8 +907,9 @@ TEST(ReduceByKey, nDim1ReduceByKey) { sumByKey(reduced_keys, reduced_vals, keys, vals, dim, nanval); const int goldSz = 5; - const float gold_reduce[goldSz] = {0, 8, 6, 10, 4}; - vector hreduce(reduced_vals.elements()); + using promoted_t = typename promote_type::type; + const promoted_t gold_reduce[goldSz] = {0, 8, 6, 10, 4}; + vector hreduce(reduced_vals.elements()); reduced_vals.host(hreduce.data()); for (int i = 0; i < goldSz * ntile; i++) { @@ -870,10 +917,11 @@ TEST(ReduceByKey, nDim1ReduceByKey) { } } -TEST(ReduceByKey, nDim2ReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, nDim2ReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -888,8 +936,9 @@ TEST(ReduceByKey, nDim2ReduceByKey) { sumByKey(reduced_keys, reduced_vals, keys, vals, dim, nanval); const int goldSz = 5; - const float gold_reduce[goldSz] = {0, 8, 6, 10, 4}; - vector h_a(reduced_vals.elements()); + using promoted_t = typename promote_type::type; + const promoted_t gold_reduce[goldSz] = {0, 8, 6, 10, 4}; + vector h_a(reduced_vals.elements()); reduced_vals.host(h_a.data()); for (int i = 0; i < goldSz * ntile; i++) { @@ -897,10 +946,11 @@ TEST(ReduceByKey, nDim2ReduceByKey) { } } -TEST(ReduceByKey, nDim3ReduceByKey) { - const static int testSz = 8; - const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; - const float testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; +TYPED_TEST(ReduceByKey, nDim3ReduceByKey) { + SUPPORTED_TYPE_CHECK(TypeParam); + const static int testSz = 8; + const int testKeys[testSz] = {0, 2, 2, 9, 5, 5, 5, 8}; + const TypeParam testVals[testSz] = {0, 7, 1, 6, 2, 5, 3, 4}; array keys(testSz, testKeys); array vals(testSz, testVals); @@ -915,8 +965,9 @@ TEST(ReduceByKey, nDim3ReduceByKey) { sumByKey(reduced_keys, reduced_vals, keys, vals, dim, nanval); const int goldSz = 5; - const float gold_reduce[goldSz] = {0, 8, 6, 10, 4}; - vector h_a(reduced_vals.elements()); + using promoted_t = typename promote_type::type; + const promoted_t gold_reduce[goldSz] = {0, 8, 6, 10, 4}; + vector h_a(reduced_vals.elements()); reduced_vals.host(h_a.data()); for (int i = 0; i < goldSz * ntile; i++) { diff --git a/test/regions.cpp b/test/regions.cpp index 182a22e9b5..a6f14ede81 100644 --- a/test/regions.cpp +++ b/test/regions.cpp @@ -71,7 +71,7 @@ void regionsTest(string pTestFile, af_connectivity connectivity, } ASSERT_SUCCESS(af_regions(&outArray, inArray, connectivity, - (af_dtype)dtype_traits::af_type)); + (af_dtype)dtype_traits::af_type)); // Get result T* outData = new T[idims.elements()]; @@ -97,6 +97,7 @@ void regionsTest(string pTestFile, af_connectivity connectivity, #define REGIONS_INIT(desc, file, conn, conn_type) \ TYPED_TEST(Regions, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ regionsTest( \ string(TEST_DIR "/regions/" #file "_" #conn ".test"), conn_type); \ } @@ -109,6 +110,7 @@ REGIONS_INIT(Regions3, regions_128x128, 8, AF_CONNECTIVITY_8); ///////////////////////////////////// CPP //////////////////////////////// // TEST(Regions, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); vector numDims; vector> in; vector> tests; @@ -139,6 +141,7 @@ TEST(Regions, CPP) { ///////////////////////////////// Documentation Examples /////////////////// TEST(Regions, Docs_8) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); // input data uchar input[64] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, @@ -185,6 +188,7 @@ TEST(Regions, Docs_8) { } TEST(Regions, Docs_4) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); // input data uchar input[64] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, @@ -236,6 +240,7 @@ TEST(Regions, Docs_4) { } TEST(Regions, WholeImageComponent) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const int dim = 101; const int sz = dim * dim; vector input(sz, 1); @@ -252,6 +257,7 @@ TEST(Regions, WholeImageComponent) { } TEST(Regions, NoComponentImage) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const int dim = 101; const int sz = dim * dim; vector input(sz, 0); diff --git a/test/reorder.cpp b/test/reorder.cpp index b06f72cdda..3109839786 100644 --- a/test/reorder.cpp +++ b/test/reorder.cpp @@ -44,7 +44,7 @@ class Reorder : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + char, signed char, unsigned char, short, ushort> TestTypes; // register the type list diff --git a/test/replace.cpp b/test/replace.cpp index 6d72cf7fc9..1156731732 100644 --- a/test/replace.cpp +++ b/test/replace.cpp @@ -35,7 +35,7 @@ template class Replace : public ::testing::Test {}; typedef ::testing::Types + int, intl, uintl, schar, uchar, char, short, ushort> TestTypes; TYPED_TEST_SUITE(Replace, TestTypes); diff --git a/test/resize.cpp b/test/resize.cpp index 423bb55416..50c46730f9 100644 --- a/test/resize.cpp +++ b/test/resize.cpp @@ -55,8 +55,8 @@ class ResizeI : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types TestTypesF; -typedef ::testing::Types +typedef ::testing::Types TestTypesI; // register the type list diff --git a/test/rotate.cpp b/test/rotate.cpp index 01675fa1d7..986398f88f 100644 --- a/test/rotate.cpp +++ b/test/rotate.cpp @@ -34,7 +34,8 @@ class Rotate : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/rotate_linear.cpp b/test/rotate_linear.cpp index ea19f217e7..1324a59a77 100644 --- a/test/rotate_linear.cpp +++ b/test/rotate_linear.cpp @@ -39,7 +39,8 @@ class RotateLinear : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -53,6 +54,10 @@ void rotateTest(string pTestFile, const unsigned resultIdx, const float angle, const vector* seqv = NULL) { SUPPORTED_TYPE_CHECK(T); + if (is_same_type::value && (int)angle % 90 != 0) { + GTEST_SKIP() << "Incompatible test data for s8"; + } + vector numDims; vector> in; vector> tests; diff --git a/test/sat.cpp b/test/sat.cpp index 892e2f8f4e..f87b356b85 100644 --- a/test/sat.cpp +++ b/test/sat.cpp @@ -31,8 +31,8 @@ class SAT : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/scan.cpp b/test/scan.cpp index a29c6e0e52..8bfbe0dd20 100644 --- a/test/scan.cpp +++ b/test/scan.cpp @@ -113,6 +113,7 @@ SCAN_TESTS(accum, cdouble, cdouble, cdouble); SCAN_TESTS(accum, unsigned, unsigned, unsigned); SCAN_TESTS(accum, intl, intl, intl); SCAN_TESTS(accum, uintl, uintl, uintl); +SCAN_TESTS(accum, schar, schar, int); SCAN_TESTS(accum, uchar, uchar, unsigned); SCAN_TESTS(accum, short, short, int); SCAN_TESTS(accum, ushort, ushort, uint); diff --git a/test/scan_by_key.cpp b/test/scan_by_key.cpp index fe4d61d095..0ea1dd8ecb 100644 --- a/test/scan_by_key.cpp +++ b/test/scan_by_key.cpp @@ -127,6 +127,7 @@ void scanByKeyTest(dim4 dims, int scanDim, vector nodeLengths, #define SCAN_BY_KEY_TEST(FN, X, Y, Z, W, Ti, To, INC, DIM, DSTART, DEND, EPS) \ TEST(ScanByKey, Test_Scan_By_Key_##FN##_##Ti##_##INC##_##DIM) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ dim4 dims(X, Y, Z, W); \ int scanDim = DIM; \ int nodel[] = {37, 256}; \ @@ -194,6 +195,7 @@ SCAN_BY_KEY_TEST(AF_BINARY_MAX, 4 * 1024, 512, 1, 1, float, float, false, 1, -5, 5, 1e-3); TEST(ScanByKey, Test_Scan_By_key_Simple_0) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); dim4 dims(16, 8, 2, 1); int scanDim = 0; int nodel[] = {4, 8}; @@ -207,6 +209,7 @@ TEST(ScanByKey, Test_Scan_By_key_Simple_0) { } TEST(ScanByKey, Test_Scan_By_key_Simple_1) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); dim4 dims(8, 256 + 128, 1, 1); int scanDim = 1; int nodel[] = {4, 8}; @@ -220,6 +223,7 @@ TEST(ScanByKey, Test_Scan_By_key_Simple_1) { } TEST(ScanByKey, FixOverflowWrite) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); const int SIZE = 41000; vector keys(SIZE, 0); vector vals(SIZE, 1.0f); diff --git a/test/select.cpp b/test/select.cpp index 0b6724d8fa..4b4c96dd21 100644 --- a/test/select.cpp +++ b/test/select.cpp @@ -42,7 +42,7 @@ template class Select : public ::testing::Test {}; typedef ::testing::Types + schar, uchar, char, short, ushort, half_float::half> TestTypes; TYPED_TEST_SUITE(Select, TestTypes); diff --git a/test/set.cpp b/test/set.cpp index 97e05d484b..0e1ececadc 100644 --- a/test/set.cpp +++ b/test/set.cpp @@ -77,6 +77,7 @@ UNIQUE_TESTS(float) UNIQUE_TESTS(double) UNIQUE_TESTS(int) UNIQUE_TESTS(uint) +UNIQUE_TESTS(schar) UNIQUE_TESTS(uchar) UNIQUE_TESTS(short) UNIQUE_TESTS(ushort) @@ -149,6 +150,7 @@ SET_TESTS(float) SET_TESTS(double) SET_TESTS(int) SET_TESTS(uint) +SET_TESTS(schar) SET_TESTS(uchar) SET_TESTS(short) SET_TESTS(ushort) diff --git a/test/shift.cpp b/test/shift.cpp index 2de341b3bc..c86c43c8e3 100644 --- a/test/shift.cpp +++ b/test/shift.cpp @@ -42,7 +42,8 @@ class Shift : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + intl, uintl, char, signed char, unsigned char, short, + ushort> TestTypes; // register the type list TYPED_TEST_SUITE(Shift, TestTypes); diff --git a/test/sift.cpp b/test/sift.cpp index 621659e259..b96325d672 100644 --- a/test/sift.cpp +++ b/test/sift.cpp @@ -162,9 +162,9 @@ void siftTest(string pTestFile, unsigned nLayers, float contrastThr, af_load_image(&inArray_f32, inFiles[testId].c_str(), false)); ASSERT_SUCCESS(conv_image(&inArray, inArray_f32)); - ASSERT_SUCCESS(af_sift(&feat, &desc, inArray, nLayers, contrastThr, - edgeThr, initSigma, doubleInput, 1.f / 256.f, - 0.05f)); + ASSERT_SUCCESS(af_sift(&feat, &desc, inArray, nLayers, + contrastThr, edgeThr, initSigma, + doubleInput, 1.f / 256.f, 0.05f)); dim_t n = 0; af_array x, y, score, orientation, size; @@ -256,6 +256,7 @@ void siftTest(string pTestFile, unsigned nLayers, float contrastThr, #define SIFT_INIT(desc, image, nLayers, contrastThr, edgeThr, initSigma, \ doubleInput) \ TYPED_TEST(SIFT, desc) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ for (int i = 0; i < 1; i++) \ siftTest(string(TEST_DIR "/sift/" #image ".test"), \ nLayers, contrastThr, edgeThr, initSigma, \ @@ -272,6 +273,7 @@ SIFT_INIT(Man_NoDoubleInput, man_nodoubleinput, 3, 0.04f, 10.0f, 1.6f, false); ///////////////////////////////////// CPP //////////////////////////////// // TEST(SIFT, CPP) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); IMAGEIO_ENABLED_CHECK(); vector inDims; diff --git a/test/sobel.cpp b/test/sobel.cpp index 298d36d299..72a70ddde3 100644 --- a/test/sobel.cpp +++ b/test/sobel.cpp @@ -35,7 +35,8 @@ class Sobel_Integer : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types TestTypes; -typedef ::testing::Types +typedef ::testing::Types TestTypesInt; // register the type list @@ -79,11 +80,13 @@ void testSobelDerivatives(string pTestFile) { // border type is set to cv.BORDER_REFLECT_101 in opencv TYPED_TEST(Sobel, Rectangle) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); testSobelDerivatives( string(TEST_DIR "/sobel/rectangle.test")); } TYPED_TEST(Sobel_Integer, Rectangle) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); testSobelDerivatives( string(TEST_DIR "/sobel/rectangle.test")); } diff --git a/test/sort.cpp b/test/sort.cpp index c9da609f93..bd60edb5b5 100644 --- a/test/sort.cpp +++ b/test/sort.cpp @@ -40,8 +40,8 @@ class Sort : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/sort_by_key.cpp b/test/sort_by_key.cpp index afd7908660..265ee570b7 100644 --- a/test/sort_by_key.cpp +++ b/test/sort_by_key.cpp @@ -40,8 +40,8 @@ class SortByKey : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/sort_index.cpp b/test/sort_index.cpp index f3a10b9084..5e1b88a97d 100644 --- a/test/sort_index.cpp +++ b/test/sort_index.cpp @@ -40,8 +40,8 @@ class SortIndex : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/sparse.cpp b/test/sparse.cpp index a130a6bb58..f1e1b67d72 100644 --- a/test/sparse.cpp +++ b/test/sparse.cpp @@ -19,6 +19,7 @@ using af::dtype_traits; using af::identity; using af::randu; using af::span; +using af::seq; #define SPARSE_TESTS(T, eps) \ TEST(Sparse, T##Square) { sparseTester(1000, 1000, 100, 5, eps); } \ @@ -109,6 +110,42 @@ TEST(Sparse, ISSUE_1745) { row_idx.get(), col_idx.get(), AF_STORAGE_CSR)); } +TEST(Sparse, offsets_work_csr_to_dense_ISSUE_1918) { + array reference(2,2); + reference(0, span) = 0; + reference(1, span) = 2; + float value[] = { 1, 1, 2, 2 }; + int row_csr[] = { 0, 2, 2, 0, 0, 2 }; + int col[] = { 0, 1, 0, 1 }; + array values(4, 1, value, afHost); + array rows_csr(6, 1, row_csr, afHost); + array cols(4, 1, col, afHost); + array S_csr; + + S_csr = sparse(2, 2, values(seq(2, 3)), rows_csr(seq(3, 5)), cols(seq(2, 3))); + array output_csr = dense(S_csr); + + EXPECT_ARRAYS_EQ(reference, output_csr); +} + +TEST(Sparse, offsets_work_coo_to_dense_ISSUE_1918) { + array reference(2,2); + reference(0, span) = 0; + reference(1, span) = 2; + float value[] = { 1, 1, 2, 2 }; + int row_coo[] = { 0, 0, 1, 1 }; + int col[] = { 0, 1, 0, 1 }; + array values(4, 1, value, afHost); + array rows_coo(4, 1, row_coo, afHost); + array cols(4, 1, col, afHost); + array S_coo; + + S_coo = sparse(2, 2, values(seq(2, 3)), rows_coo(seq(2, 3)), cols(seq(2, 3)), AF_STORAGE_COO); + array output_coo = dense(S_coo); + + EXPECT_ARRAYS_EQ(reference, output_coo); +} + TEST(Sparse, ISSUE_2134_COO) { int rows[] = {0, 0, 0, 1, 1, 2, 2}; int cols[] = {0, 1, 2, 0, 1, 0, 2}; @@ -416,3 +453,24 @@ TEST(Sparse, CPPDenseToSparseToDenseUsage) { ASSERT_ARRAYS_EQ(in, gold); ASSERT_ARRAYS_EQ(dense, gold); } + +TEST(Sparse, CPPDenseToSparseConversions) { + array in = af::randu(200, 200); + in(in < 0.75) = 0; + + array coo_sparse_arr = af::sparse(in, AF_STORAGE_COO); + array csr_sparse_arr = af::sparse(in, AF_STORAGE_CSR); + + array coo_dense_arr = af::dense(coo_sparse_arr); + array csr_dense_arr = af::dense(csr_sparse_arr); + + ASSERT_ARRAYS_EQ(in, coo_dense_arr); + ASSERT_ARRAYS_EQ(in, csr_dense_arr); + + array non_zero = af::flat(in)(af::where(in)); + array non_zero_T = af::flat(in.T())(af::where(in.T())); + ASSERT_ARRAYS_EQ(non_zero, af::sparseGetValues(coo_sparse_arr)); + ASSERT_ARRAYS_EQ( + non_zero_T, + af::sparseGetValues(csr_sparse_arr)); // csr values are transposed +} diff --git a/test/stdev.cpp b/test/stdev.cpp index 4b93f5b220..bf95801fed 100644 --- a/test/stdev.cpp +++ b/test/stdev.cpp @@ -37,7 +37,8 @@ class StandardDev : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list @@ -67,9 +68,9 @@ template struct sdOutType { typedef typename cond_type< is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value, + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value, float, typename elseType::type>::type type; }; diff --git a/test/susan.cpp b/test/susan.cpp index 34929c22c0..c488bda775 100644 --- a/test/susan.cpp +++ b/test/susan.cpp @@ -59,7 +59,8 @@ class Susan : public ::testing::Test { virtual void SetUp() {} }; -typedef ::testing::Types +typedef ::testing::Types TestTypes; TYPED_TEST_SUITE(Susan, TestTypes); @@ -125,6 +126,7 @@ void susanTest(string pTestFile, float t, float g) { #define SUSAN_TEST(image, tval, gval) \ TYPED_TEST(Susan, image) { \ + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); \ susanTest(string(TEST_DIR "/susan/" #image ".test"), tval, \ gval); \ } diff --git a/test/testHelpers.hpp b/test/testHelpers.hpp index 84ac83839f..5f6b02b5a4 100644 --- a/test/testHelpers.hpp +++ b/test/testHelpers.hpp @@ -88,11 +88,12 @@ struct dtype_traits { } // namespace af +typedef signed char schar; typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned short ushort; -std::string getBackendName(); +std::string getBackendName(bool lower = false); std::string getTestName(); std::string readNextNonEmptyLine(std::ifstream &file); @@ -242,6 +243,15 @@ bool noHalfTests(af::dtype ty); if (noHalfTests((af_dtype)af::dtype_traits::af_type)) \ GTEST_SKIP() << "Device doesn't support Half" +#ifdef SKIP_UNSUPPORTED_TESTS +#define UNSUPPORTED_BACKEND(backend) \ + if(backend == af::getActiveBackend()) \ + GTEST_SKIP() << "Skipping unsupported function on " \ + + getBackendName() + " backend" +#else +#define UNSUPPORTED_BACKEND(backend) +#endif + #define LAPACK_ENABLED_CHECK() \ if (!af::isLAPACKAvailable()) GTEST_SKIP() << "LAPACK Not Configured." diff --git a/test/threading.cpp b/test/threading.cpp index 41c4ebb723..1b71411f0e 100644 --- a/test/threading.cpp +++ b/test/threading.cpp @@ -130,6 +130,7 @@ int nextTargetDeviceId() { void morphTest(const array input, const array mask, const bool isDilation, const array gold, int targetDevice) { + UNSUPPORTED_BACKEND(AF_BACKEND_ONEAPI); setDevice(targetDevice); array out; diff --git a/test/tile.cpp b/test/tile.cpp index bc0cdddba7..3a608fa987 100644 --- a/test/tile.cpp +++ b/test/tile.cpp @@ -47,8 +47,8 @@ class Tile : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + intl, uintl, char, signed char, unsigned char, short, + ushort, half_float::half> TestTypes; // register the type list diff --git a/test/transform.cpp b/test/transform.cpp index e3e0efe640..ef3b0dd4f9 100644 --- a/test/transform.cpp +++ b/test/transform.cpp @@ -38,7 +38,7 @@ class TransformInt : public ::testing::Test { }; typedef ::testing::Types TestTypes; -typedef ::testing::Types +typedef ::testing::Types TestTypesInt; TYPED_TEST_SUITE(Transform, TestTypes); diff --git a/test/translate.cpp b/test/translate.cpp index 55fd570ffb..edbab15a2c 100644 --- a/test/translate.cpp +++ b/test/translate.cpp @@ -39,7 +39,7 @@ class TranslateInt : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types TestTypes; -typedef ::testing::Types TestTypesInt; +typedef ::testing::Types TestTypesInt; // register the type list TYPED_TEST_SUITE(Translate, TestTypes); diff --git a/test/transpose.cpp b/test/transpose.cpp index 72a32194fa..420f6d88e3 100644 --- a/test/transpose.cpp +++ b/test/transpose.cpp @@ -44,8 +44,8 @@ class Transpose : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/transpose_inplace.cpp b/test/transpose_inplace.cpp index 82b071488a..7e542fd34f 100644 --- a/test/transpose_inplace.cpp +++ b/test/transpose_inplace.cpp @@ -30,8 +30,8 @@ class Transpose : public ::testing::Test { }; // create a list of types to be tested -typedef ::testing::Types +typedef ::testing::Types TestTypes; // register the type list diff --git a/test/triangle.cpp b/test/triangle.cpp index 90b50bb6dc..a7d47832e5 100644 --- a/test/triangle.cpp +++ b/test/triangle.cpp @@ -35,7 +35,8 @@ template class Triangle : public ::testing::Test {}; typedef ::testing::Types + schar, uchar, uintl, intl, short, ushort, + half_float::half> TestTypes; TYPED_TEST_SUITE(Triangle, TestTypes); diff --git a/test/unwrap.cpp b/test/unwrap.cpp index f43b73e7f4..9b97059dac 100644 --- a/test/unwrap.cpp +++ b/test/unwrap.cpp @@ -37,7 +37,8 @@ class Unwrap : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + intl, uintl, char, signed char, unsigned char, short, + ushort> TestTypes; // register the type list diff --git a/test/var.cpp b/test/var.cpp index db846f5d57..b889413646 100644 --- a/test/var.cpp +++ b/test/var.cpp @@ -26,7 +26,7 @@ template class Var : public ::testing::Test {}; typedef ::testing::Types + char, schar, uchar, short, ushort, half_float::half> TestTypes; TYPED_TEST_SUITE(Var, TestTypes); @@ -42,8 +42,8 @@ struct varOutType { typedef typename cond_type< is_same_type::value || is_same_type::value || is_same_type::value || is_same_type::value || - is_same_type::value || is_same_type::value || - is_same_type::value, + is_same_type::value || is_same_type::value || + is_same_type::value || is_same_type::value, float, typename elseType::type>::type type; }; diff --git a/test/where.cpp b/test/where.cpp index bb5375822c..265c0d4d7b 100644 --- a/test/where.cpp +++ b/test/where.cpp @@ -34,7 +34,7 @@ template class Where : public ::testing::Test {}; typedef ::testing::Types + char, schar, uchar, short, ushort> TestTypes; TYPED_TEST_SUITE(Where, TestTypes); diff --git a/test/wrap.cpp b/test/wrap.cpp index baff77c5b1..4f53d9fd34 100644 --- a/test/wrap.cpp +++ b/test/wrap.cpp @@ -42,7 +42,8 @@ class Wrap : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + intl, uintl, char, signed char, unsigned char, short, + ushort> TestTypes; // register the type list diff --git a/test/write.cpp b/test/write.cpp index 8f18f6e954..db751939ab 100644 --- a/test/write.cpp +++ b/test/write.cpp @@ -34,7 +34,7 @@ class Write : public ::testing::Test { // create a list of types to be tested typedef ::testing::Types + signed char, unsigned char, short, ushort> TestTypes; // register the type list diff --git a/vcpkg.json b/vcpkg.json index db3318eb47..d811275a6f 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -19,6 +19,10 @@ { "name": "spdlog", "version": "1.9.2" + }, + { + "name": "jasper", + "version": "4.2.0" } ], "features": { @@ -67,15 +71,10 @@ "description": "Build OpenCL backend", "dependencies": [ "boost-compute", + "boost-program-options", "opencl" ] }, - "mkl": { - "description": "Build with MKL", - "dependencies": [ - "intel-mkl" - ] - }, "cudnn": { "description": "Build CUDA with support for cuDNN", "dependencies": [ @@ -83,5 +82,5 @@ ] } }, - "builtin-baseline": "9d47b24eacbd1cd94f139457ef6cd35e5d92cc84" + "builtin-baseline": "b02e341c927f16d991edbd915d8ea43eac52096c" }