From 4280d9a439405e1a06f205613e300410839cb0c7 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Thu, 26 Mar 2026 15:14:14 +0100 Subject: [PATCH 1/7] Implement VEX Encoding for add function to have AVX2 add loop similarly to stock NumPy in lenet benchmark --- CMakeLists.txt | 33 +- conda-recipe/meta.yaml | 4 +- mkl_umath/src/mkl_umath_loops.c.src | 280 +++++-- mkl_umath/src/npyv/array_assign.h | 118 +++ mkl_umath/src/npyv/avx2/arithmetic.h | 347 ++++++++ mkl_umath/src/npyv/avx2/avx2.h | 77 ++ mkl_umath/src/npyv/avx2/conversion.h | 99 +++ mkl_umath/src/npyv/avx2/math.h | 253 ++++++ mkl_umath/src/npyv/avx2/memory.h | 761 +++++++++++++++++ mkl_umath/src/npyv/avx2/misc.h | 258 ++++++ mkl_umath/src/npyv/avx2/operators.h | 282 +++++++ mkl_umath/src/npyv/avx2/reorder.h | 216 +++++ mkl_umath/src/npyv/avx2/utils.h | 21 + mkl_umath/src/npyv/avx512/arithmetic.h | 446 ++++++++++ mkl_umath/src/npyv/avx512/avx512.h | 82 ++ mkl_umath/src/npyv/avx512/conversion.h | 204 +++++ mkl_umath/src/npyv/avx512/maskop.h | 67 ++ mkl_umath/src/npyv/avx512/math.h | 309 +++++++ mkl_umath/src/npyv/avx512/memory.h | 715 ++++++++++++++++ mkl_umath/src/npyv/avx512/misc.h | 292 +++++++ mkl_umath/src/npyv/avx512/operators.h | 380 +++++++++ mkl_umath/src/npyv/avx512/reorder.h | 378 +++++++++ mkl_umath/src/npyv/avx512/utils.h | 102 +++ mkl_umath/src/npyv/binop_override.h | 215 +++++ mkl_umath/src/npyv/cblasfuncs.h | 7 + mkl_umath/src/npyv/emulate_maskop.h | 80 ++ mkl_umath/src/npyv/get_attr_string.h | 95 +++ mkl_umath/src/npyv/gil_utils.h | 15 + mkl_umath/src/npyv/intdiv.h | 475 +++++++++++ mkl_umath/src/npyv/lowlevel_strided_loops.h | 790 ++++++++++++++++++ mkl_umath/src/npyv/mem_overlap.h | 49 ++ mkl_umath/src/npyv/neon/arithmetic.h | 343 ++++++++ mkl_umath/src/npyv/neon/conversion.h | 150 ++++ mkl_umath/src/npyv/neon/math.h | 416 +++++++++ mkl_umath/src/npyv/neon/memory.h | 678 +++++++++++++++ mkl_umath/src/npyv/neon/misc.h | 275 ++++++ mkl_umath/src/npyv/neon/neon.h | 82 ++ mkl_umath/src/npyv/neon/operators.h | 399 +++++++++ mkl_umath/src/npyv/neon/reorder.h | 189 +++++ mkl_umath/src/npyv/npy_argparse.h | 96 +++ mkl_umath/src/npyv/npy_binsearch.h | 31 + mkl_umath/src/npyv/npy_cblas.h | 129 +++ mkl_umath/src/npyv/npy_cblas_base.h | 562 +++++++++++++ mkl_umath/src/npyv/npy_config.h | 188 +++++ mkl_umath/src/npyv/npy_cpu_dispatch.h | 132 +++ .../src/npyv/npy_cpu_dispatch_distutils.h | 116 +++ mkl_umath/src/npyv/npy_cpu_features.h | 201 +++++ mkl_umath/src/npyv/npy_cpuinfo_parser.h | 263 ++++++ mkl_umath/src/npyv/npy_ctypes.h | 50 ++ mkl_umath/src/npyv/npy_dlpack.h | 28 + mkl_umath/src/npyv/npy_extint128.h | 317 +++++++ mkl_umath/src/npyv/npy_fpmath.h | 30 + mkl_umath/src/npyv/npy_hashtable.h | 32 + mkl_umath/src/npyv/npy_import.h | 32 + mkl_umath/src/npyv/npy_longdouble.h | 27 + mkl_umath/src/npyv/npy_partition.h | 34 + mkl_umath/src/npyv/npy_pycompat.h | 22 + mkl_umath/src/npyv/npy_svml.h | 71 ++ mkl_umath/src/npyv/npyv.h | 112 +++ mkl_umath/src/npyv/numpy_tag.h | 259 ++++++ mkl_umath/src/npyv/numpyos.h | 68 ++ mkl_umath/src/npyv/simd.h | 171 ++++ mkl_umath/src/npyv/simd_utils.h | 48 ++ mkl_umath/src/npyv/sse/arithmetic.h | 415 +++++++++ mkl_umath/src/npyv/sse/conversion.h | 94 +++ mkl_umath/src/npyv/sse/math.h | 463 ++++++++++ mkl_umath/src/npyv/sse/memory.h | 759 +++++++++++++++++ mkl_umath/src/npyv/sse/misc.h | 258 ++++++ mkl_umath/src/npyv/sse/operators.h | 342 ++++++++ mkl_umath/src/npyv/sse/reorder.h | 212 +++++ mkl_umath/src/npyv/sse/sse.h | 76 ++ mkl_umath/src/npyv/sse/utils.h | 19 + mkl_umath/src/npyv/ucsnarrow.h | 7 + mkl_umath/src/npyv/ufunc_override.h | 38 + mkl_umath/src/npyv/umathmodule.h | 18 + mkl_umath/src/npyv/vec/arithmetic.h | 409 +++++++++ mkl_umath/src/npyv/vec/conversion.h | 237 ++++++ mkl_umath/src/npyv/vec/math.h | 285 +++++++ mkl_umath/src/npyv/vec/memory.h | 703 ++++++++++++++++ mkl_umath/src/npyv/vec/misc.h | 233 ++++++ mkl_umath/src/npyv/vec/operators.h | 303 +++++++ mkl_umath/src/npyv/vec/reorder.h | 213 +++++ mkl_umath/src/npyv/vec/utils.h | 84 ++ mkl_umath/src/npyv/vec/vec.h | 111 +++ 84 files changed, 18202 insertions(+), 78 deletions(-) create mode 100644 mkl_umath/src/npyv/array_assign.h create mode 100644 mkl_umath/src/npyv/avx2/arithmetic.h create mode 100644 mkl_umath/src/npyv/avx2/avx2.h create mode 100644 mkl_umath/src/npyv/avx2/conversion.h create mode 100644 mkl_umath/src/npyv/avx2/math.h create mode 100644 mkl_umath/src/npyv/avx2/memory.h create mode 100644 mkl_umath/src/npyv/avx2/misc.h create mode 100644 mkl_umath/src/npyv/avx2/operators.h create mode 100644 mkl_umath/src/npyv/avx2/reorder.h create mode 100644 mkl_umath/src/npyv/avx2/utils.h create mode 100644 mkl_umath/src/npyv/avx512/arithmetic.h create mode 100644 mkl_umath/src/npyv/avx512/avx512.h create mode 100644 mkl_umath/src/npyv/avx512/conversion.h create mode 100644 mkl_umath/src/npyv/avx512/maskop.h create mode 100644 mkl_umath/src/npyv/avx512/math.h create mode 100644 mkl_umath/src/npyv/avx512/memory.h create mode 100644 mkl_umath/src/npyv/avx512/misc.h create mode 100644 mkl_umath/src/npyv/avx512/operators.h create mode 100644 mkl_umath/src/npyv/avx512/reorder.h create mode 100644 mkl_umath/src/npyv/avx512/utils.h create mode 100644 mkl_umath/src/npyv/binop_override.h create mode 100644 mkl_umath/src/npyv/cblasfuncs.h create mode 100644 mkl_umath/src/npyv/emulate_maskop.h create mode 100644 mkl_umath/src/npyv/get_attr_string.h create mode 100644 mkl_umath/src/npyv/gil_utils.h create mode 100644 mkl_umath/src/npyv/intdiv.h create mode 100644 mkl_umath/src/npyv/lowlevel_strided_loops.h create mode 100644 mkl_umath/src/npyv/mem_overlap.h create mode 100644 mkl_umath/src/npyv/neon/arithmetic.h create mode 100644 mkl_umath/src/npyv/neon/conversion.h create mode 100644 mkl_umath/src/npyv/neon/math.h create mode 100644 mkl_umath/src/npyv/neon/memory.h create mode 100644 mkl_umath/src/npyv/neon/misc.h create mode 100644 mkl_umath/src/npyv/neon/neon.h create mode 100644 mkl_umath/src/npyv/neon/operators.h create mode 100644 mkl_umath/src/npyv/neon/reorder.h create mode 100644 mkl_umath/src/npyv/npy_argparse.h create mode 100644 mkl_umath/src/npyv/npy_binsearch.h create mode 100644 mkl_umath/src/npyv/npy_cblas.h create mode 100644 mkl_umath/src/npyv/npy_cblas_base.h create mode 100644 mkl_umath/src/npyv/npy_config.h create mode 100644 mkl_umath/src/npyv/npy_cpu_dispatch.h create mode 100644 mkl_umath/src/npyv/npy_cpu_dispatch_distutils.h create mode 100644 mkl_umath/src/npyv/npy_cpu_features.h create mode 100644 mkl_umath/src/npyv/npy_cpuinfo_parser.h create mode 100644 mkl_umath/src/npyv/npy_ctypes.h create mode 100644 mkl_umath/src/npyv/npy_dlpack.h create mode 100644 mkl_umath/src/npyv/npy_extint128.h create mode 100644 mkl_umath/src/npyv/npy_fpmath.h create mode 100644 mkl_umath/src/npyv/npy_hashtable.h create mode 100644 mkl_umath/src/npyv/npy_import.h create mode 100644 mkl_umath/src/npyv/npy_longdouble.h create mode 100644 mkl_umath/src/npyv/npy_partition.h create mode 100644 mkl_umath/src/npyv/npy_pycompat.h create mode 100644 mkl_umath/src/npyv/npy_svml.h create mode 100644 mkl_umath/src/npyv/npyv.h create mode 100644 mkl_umath/src/npyv/numpy_tag.h create mode 100644 mkl_umath/src/npyv/numpyos.h create mode 100644 mkl_umath/src/npyv/simd.h create mode 100644 mkl_umath/src/npyv/simd_utils.h create mode 100644 mkl_umath/src/npyv/sse/arithmetic.h create mode 100644 mkl_umath/src/npyv/sse/conversion.h create mode 100644 mkl_umath/src/npyv/sse/math.h create mode 100644 mkl_umath/src/npyv/sse/memory.h create mode 100644 mkl_umath/src/npyv/sse/misc.h create mode 100644 mkl_umath/src/npyv/sse/operators.h create mode 100644 mkl_umath/src/npyv/sse/reorder.h create mode 100644 mkl_umath/src/npyv/sse/sse.h create mode 100644 mkl_umath/src/npyv/sse/utils.h create mode 100644 mkl_umath/src/npyv/ucsnarrow.h create mode 100644 mkl_umath/src/npyv/ufunc_override.h create mode 100644 mkl_umath/src/npyv/umathmodule.h create mode 100644 mkl_umath/src/npyv/vec/arithmetic.h create mode 100644 mkl_umath/src/npyv/vec/conversion.h create mode 100644 mkl_umath/src/npyv/vec/math.h create mode 100644 mkl_umath/src/npyv/vec/memory.h create mode 100644 mkl_umath/src/npyv/vec/misc.h create mode 100644 mkl_umath/src/npyv/vec/operators.h create mode 100644 mkl_umath/src/npyv/vec/reorder.h create mode 100644 mkl_umath/src/npyv/vec/utils.h create mode 100644 mkl_umath/src/npyv/vec/vec.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f08b5dd..5ccd8fae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,11 +83,17 @@ elseif(UNIX) "${WARNING_FLAGS}" "${SDL_FLAGS}" ) - string(CONCAT PRECISION_FLAGS - "-fprotect-parens " - "-fimf-precision=high " - "-fno-fast-math " - ) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + string(CONCAT PRECISION_FLAGS + "-fprotect-parens " + "-fimf-precision=high " + "-fno-fast-math " + ) + else() + string(CONCAT PRECISION_FLAGS + "-fno-fast-math " + ) + endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 ${CFLAGS} ${PRECISION_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CFLAGS} -fno-fast-math -O0 -g1 -DDEBUG" @@ -109,14 +115,21 @@ set_target_properties(${_trgt} PROPERTIES CMAKE_POSITION_INDEPENDENT_CODE ON C_STANDARD 99 ) -target_include_directories(${_trgt} PUBLIC mkl_umath/src/ ${Python_NumPy_INCLUDE_DIRS} ${Python_INCLUDE_DIRS}) +target_include_directories(${_trgt} PUBLIC mkl_umath/src/ mkl_umath/src/npyv/ ${Python_NumPy_INCLUDE_DIRS} ${Python_INCLUDE_DIRS}) target_link_libraries(${_trgt} PUBLIC MKL::MKL ${Python_LIBRARIES}) target_link_options(${_trgt} PUBLIC ${_linker_options}) -target_compile_options(${_trgt} PUBLIC -fveclib=SVML) -target_compile_options(${_trgt} PUBLIC -fvectorize) -if(OPTIMIZATION_REPORT) - target_compile_options(${_trgt} PRIVATE -qopt-report=3) +# Compiler-specific vectorization flags +if(CMAKE_C_COMPILER_ID MATCHES "Intel") + target_compile_options(${_trgt} PUBLIC -fveclib=SVML) + target_compile_options(${_trgt} PUBLIC -fvectorize) + if(OPTIMIZATION_REPORT) + target_compile_options(${_trgt} PRIVATE -qopt-report=3) + endif() endif() +# Enable AVX2 for npyv SIMD acceleration +# -mvzeroupper: Prefer VEX encoding even for scalar ops +# -mtune=native: Optimize for build machine (can change to -mtune=haswell for generic AVX2) +target_compile_options(${_trgt} PUBLIC -mavx2 -mfma -mvzeroupper) install(TARGETS ${_trgt} LIBRARY DESTINATION mkl_umath ARCHIVE DESTINATION mkl_umath diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 4ee562a4..1d44af71 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -9,7 +9,7 @@ source: path: ../ build: - number: {{ GIT_DESCRIBE_NUMBER }} + number: 4 script_env: - WHEELS_OUTPUT_FOLDER ignore_run_exports: @@ -20,7 +20,7 @@ requirements: - {{ compiler('c') }} - {{ compiler('cxx') }} - {{ stdlib('c') }} - - {{ compiler('dpcpp') }} >=2024.2 # [not osx] + - {{ compiler('dpcpp') }} 2025.3.0 # [not osx] host: - setuptools >=77 - cmake diff --git a/mkl_umath/src/mkl_umath_loops.c.src b/mkl_umath/src/mkl_umath_loops.c.src index b588ca6f..9f889b27 100644 --- a/mkl_umath/src/mkl_umath_loops.c.src +++ b/mkl_umath/src/mkl_umath_loops.c.src @@ -68,8 +68,10 @@ */ #define PW_BLOCKSIZE 128 #define VML_TRANSCEDENTAL_THRESHOLD 8192 +#define VML_SIMPLE_OPS_THRESHOLD 8192 #define VML_ASM_THRESHOLD 100000 #define VML_D_THRESHOLD 8000 +#define SMALL_ARRAY_THRESHOLD 2048 #define MKL_INT_MAX ((npy_intp) ((~((MKL_UINT) 0)) >> 1)) @@ -130,7 +132,14 @@ /* for pointers p1, and p2 pointing at contiguous arrays n-elements of size s, are arrays disjoint or same * when these conditions are not met VML functions may produce incorrect output */ -#define DISJOINT_OR_SAME(p1, p2, n, s) (((p1) == (p2)) || ((p2) + (n)*(s) < (p1)) || ((p1) + (n)*(s) < (p2))) +static inline int disjoint_or_same_check(const void *p1, const void *p2, npy_intp n, npy_intp s) { + const char *_p1 = (const char*)p1; + const char *_p2 = (const char*)p2; + if (_p1 == _p2) return 1; + const npy_intp size = n * s; + return (_p2 + size <= _p1) || (_p1 + size <= _p2); +} +#define DISJOINT_OR_SAME(p1, p2, n, s) disjoint_or_same_check((p1), (p2), (n), (s)) #define DISJOINT_OR_SAME_TWO_DTYPES(p1, p2, n, s1, s2) (((p1) == (p2)) || ((p2) + (n)*(s2) < (p1)) || ((p1) + (n)*(s1) < (p2))) /* @@ -142,7 +151,6 @@ /** Provides the various *_LOOP macros */ #include "fast_loop_macros.h" -#include static inline npy_double spacing(npy_double x) { if (isinf(x)) @@ -230,6 +238,7 @@ divmod@c@(@type@ a, @type@ b, @type@ *modulus) * #TYPE = FLOAT, DOUBLE# * #c = f, # * #s = s, d# + * #sfx = f32, f64# */ /* @@ -311,35 +320,186 @@ pairwise_sum_@TYPE@(char *a, npy_intp n, npy_intp stride) } } -/**begin repeat1 - * # kind = add, subtract# - * # OP = +, -# - * # PW = 1, 0# - * # VML = Add, Sub# - */ +/* Special npyv-accelerated add implementation */ +#include "npyv/npyv.h" + void -mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func)) +mkl_umath_@TYPE@_add(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func)) +{ + npy_intp len = dimensions[0]; + char *src0 = args[0], *src1 = args[1], *dst = args[2]; + npy_intp ssrc0 = steps[0], ssrc1 = steps[1], sdst = steps[2]; + + /* + * TIER 1: Tiny arrays - simple scalar loop + * Overhead of SIMD setup not worth it + */ + if (len < 32) { + for (; len > 0; --len, src0 += ssrc0, src1 += ssrc1, dst += sdst) { + const @type@ a = *(@type@*)src0; + const @type@ b = *(@type@*)src1; + *(@type@*)dst = a + b; + } + return; + } + + /* + * TIER 3: Large arrays - use MKL VML + * MKL's overhead is amortized, can use multi-threading + */ + const int is_contiguous = (ssrc0 == sizeof(@type@) && + ssrc1 == sizeof(@type@) && + sdst == sizeof(@type@)); + + if (len >= VML_SIMPLE_OPS_THRESHOLD && is_contiguous) { + const int disjoint_or_same1 = DISJOINT_OR_SAME(src0, dst, len, sizeof(@type@)); + const int disjoint_or_same2 = DISJOINT_OR_SAME(src1, dst, len, sizeof(@type@)); + + if (disjoint_or_same1 && disjoint_or_same2) { + CHUNKED_VML_CALL3(v@s@Add, len, @type@, @type@, src0, src1, dst); + return; + } + } + + /* + * TIER 2: Medium arrays - use npyv SIMD + * Better than scalar, no MKL overhead + */ +#if NPYV_CAN_VECTORIZE_@TYPE@ + if (!is_mem_overlap(src0, ssrc0, dst, sdst, len) && + !is_mem_overlap(src1, ssrc1, dst, sdst, len)) { + + const int vstep = npyv_nlanes_u8; // Byte step (32 for AVX2) + const int wstep = vstep * 2; // Double vector step + const int hstep = npyv_nlanes_@sfx@; // Element step (8 for f32/AVX2) + const int lstep = hstep * 2; // Double element step + + // PATTERN 1: Fully contiguous + if (ssrc0 == sizeof(@type@) && ssrc1 == sizeof(@type@) && sdst == sizeof(@type@)) { + // Main loop: process 2 vectors per iteration + for (; len >= lstep; len -= lstep, src0 += wstep, src1 += wstep, dst += wstep) { + npyv_@sfx@ a0 = npyv_load_@sfx@((const @type@*)src0); + npyv_@sfx@ a1 = npyv_load_@sfx@((const @type@*)(src0 + vstep)); + npyv_@sfx@ b0 = npyv_load_@sfx@((const @type@*)src1); + npyv_@sfx@ b1 = npyv_load_@sfx@((const @type@*)(src1 + vstep)); + npyv_@sfx@ r0 = npyv_add_@sfx@(a0, b0); + npyv_@sfx@ r1 = npyv_add_@sfx@(a1, b1); + npyv_store_@sfx@((@type@*)dst, r0); + npyv_store_@sfx@((@type@*)(dst + vstep), r1); + } + + // Remainder loop: handle trailing elements + for (; len > 0; len -= hstep, src0 += vstep, src1 += vstep, dst += vstep) { + npyv_@sfx@ a = npyv_load_tillz_@sfx@((const @type@*)src0, len); + npyv_@sfx@ b = npyv_load_tillz_@sfx@((const @type@*)src1, len); + npyv_@sfx@ r = npyv_add_@sfx@(a, b); + npyv_store_till_@sfx@((@type@*)dst, len, r); + } + + npyv_cleanup(); + return; + } + + // PATTERN 2: Broadcast first argument (e.g., scalar + array) + if (ssrc0 == 0 && ssrc1 == sizeof(@type@) && sdst == sizeof(@type@)) { + npyv_@sfx@ a = npyv_setall_@sfx@(*(@type@*)src0); + + for (; len >= lstep; len -= lstep, src1 += wstep, dst += wstep) { + npyv_@sfx@ b0 = npyv_load_@sfx@((const @type@*)src1); + npyv_@sfx@ b1 = npyv_load_@sfx@((const @type@*)(src1 + vstep)); + npyv_@sfx@ r0 = npyv_add_@sfx@(a, b0); + npyv_@sfx@ r1 = npyv_add_@sfx@(a, b1); + npyv_store_@sfx@((@type@*)dst, r0); + npyv_store_@sfx@((@type@*)(dst + vstep), r1); + } + + for (; len > 0; len -= hstep, src1 += vstep, dst += vstep) { + npyv_@sfx@ b = npyv_load_tillz_@sfx@((const @type@*)src1, len); + npyv_@sfx@ r = npyv_add_@sfx@(a, b); + npyv_store_till_@sfx@((@type@*)dst, len, r); + } + + npyv_cleanup(); + return; + } + + // PATTERN 3: Broadcast second argument (e.g., array + scalar) + if (ssrc1 == 0 && ssrc0 == sizeof(@type@) && sdst == sizeof(@type@)) { + npyv_@sfx@ b = npyv_setall_@sfx@(*(@type@*)src1); + + for (; len >= lstep; len -= lstep, src0 += wstep, dst += wstep) { + npyv_@sfx@ a0 = npyv_load_@sfx@((const @type@*)src0); + npyv_@sfx@ a1 = npyv_load_@sfx@((const @type@*)(src0 + vstep)); + npyv_@sfx@ r0 = npyv_add_@sfx@(a0, b); + npyv_@sfx@ r1 = npyv_add_@sfx@(a1, b); + npyv_store_@sfx@((@type@*)dst, r0); + npyv_store_@sfx@((@type@*)(dst + vstep), r1); + } + + for (; len > 0; len -= hstep, src0 += vstep, dst += vstep) { + npyv_@sfx@ a = npyv_load_tillz_@sfx@((const @type@*)src0, len); + npyv_@sfx@ r = npyv_add_@sfx@(a, b); + npyv_store_till_@sfx@((@type@*)dst, len, r); + } + + npyv_cleanup(); + return; + } + + // Future: Add strided memory patterns here + } +#endif // NPYV_CAN_VECTORIZE + + /* + * FALLBACK: Scalar loop for all other cases + * - Non-contiguous with complex strides + * - Memory overlap detected + * - SIMD not available + */ + for (; len > 0; --len, src0 += ssrc0, src1 += ssrc1, dst += sdst) { + const @type@ a = *(@type@*)src0; + const @type@ b = *(@type@*)src1; + *(@type@*)dst = a + b; + } +} + +/* Keep subtract with original implementation for now */ +void +mkl_umath_@TYPE@_subtract(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func)) { + const npy_intp n = dimensions[0]; + + /* FAST PATH: Small contiguous arrays - avoid all overhead */ + if (IS_BINARY_CONT(@type@, @type@) && n <= SMALL_ARRAY_THRESHOLD) { + @type@ *ip1 = (@type@*)args[0]; + @type@ *ip2 = (@type@*)args[1]; + @type@ *op1 = (@type@*)args[2]; + + NPY_PRAGMA_VECTOR + for(npy_intp i = 0; i < n; i++) { + op1[i] = ip1[i] - ip2[i]; + } + return; + } + const int disjoint_or_same1 = DISJOINT_OR_SAME(args[0], args[2], dimensions[0], sizeof(@type@)); const int disjoint_or_same2 = DISJOINT_OR_SAME(args[1], args[2], dimensions[0], sizeof(@type@)); if (IS_BINARY_CONT(@type@, @type@)) { - if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same1 && disjoint_or_same2) { - CHUNKED_VML_CALL3(v@s@@VML@, dimensions[0], @type@, @type@, args[0], args[1], args[2]); - /* v@s@@VML@(dimensions[0], (@type@*) args[0], (@type@*) args[1], (@type@*) args[2]); */ + if (dimensions[0] > VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same1 && disjoint_or_same2) { + CHUNKED_VML_CALL3(v@s@Sub, dimensions[0], @type@, @type@, args[0], args[1], args[2]); } else { @type@ *ip1 = (@type@*)args[0]; @type@ *ip2 = (@type@*)args[1]; @type@ *op1 = (@type@*)args[2]; const npy_intp vsize = 64; - const npy_intp n = dimensions[0]; const npy_intp peel = npy_aligned_block_offset(ip1, sizeof(@type@), vsize, n); const npy_intp blocked_end = npy_blocked_end(peel, sizeof(@type@), vsize, n); npy_intp i; for(i = 0; i < peel; i++) { - op1[i] = ip1[i] @OP@ ip2[i]; + op1[i] = ip1[i] - ip2[i]; } { @@ -349,19 +509,10 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp @type@ *op1_shifted = op1 + peel; @type@ *ip2_shifted = ip2 + peel; - if (DISJOINT_OR_SAME(op1_shifted, ip1_aligned, j_max, 1) && - DISJOINT_OR_SAME(op1_shifted, ip2_shifted, j_max, 1)) { - NPY_ASSUME_ALIGNED(ip1_aligned, 64) - NPY_PRAGMA_VECTOR - for(j = 0; j < j_max; j++) { - op1_shifted[j] = ip1_aligned[j] @OP@ ip2_shifted[j]; - } - } - else { - NPY_ASSUME_ALIGNED(ip1_aligned, 64) - for(j = 0; j < j_max; j++) { - op1_shifted[j] = ip1_aligned[j] @OP@ ip2_shifted[j]; - } + NPY_ASSUME_ALIGNED(ip1_aligned, 64) + NPY_PRAGMA_VECTOR + for(j = 0; j < j_max; j++) { + op1_shifted[j] = ip1_aligned[j] - ip2_shifted[j]; } i = blocked_end; @@ -369,14 +520,13 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp } for(; i < n; i++) { - op1[i] = ip1[i] @OP@ ip2[i]; + op1[i] = ip1[i] - ip2[i]; } } } else if (IS_BINARY_CONT_S1(@type@, @type@)) { - if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same2) { - CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[1], args[2], @OP@1.0, *(@type@*)args[0], 0.0, 1.0); - /* v@s@LinearFrac(dimensions[0], (@type@*) args[1], (@type@*) args[1], @OP@1.0, *(@type@*)args[0], 0.0, 1.0, (@type@*) args[2]); */ + if (dimensions[0] > VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same2) { + CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[1], args[2], -1.0, *(@type@*)args[0], 0.0, 1.0); } else { @type@ *ip1 = (@type@*)args[0]; @@ -390,7 +540,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp const @type@ ip1c = ip1[0]; for(i = 0; i < peel; i++) { - op1[i] = ip1c @OP@ ip2[i]; + op1[i] = ip1c - ip2[i]; } { @@ -401,7 +551,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp NPY_ASSUME_ALIGNED(ip2_aligned, 64) for(j = 0; j < j_max; j++) { - op1_shifted[j] = ip1c @OP@ ip2_aligned[j]; + op1_shifted[j] = ip1c - ip2_aligned[j]; } i = blocked_end; @@ -409,14 +559,13 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp } for(; i < n; i++) { - op1[i] = ip1c @OP@ ip2[i]; + op1[i] = ip1c - ip2[i]; } } } else if (IS_BINARY_CONT_S2(@type@, @type@)) { - if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same1) { - CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[0], args[2], 1.0, @OP@(*(@type@*)args[1]), 0.0, 1.0); - /* v@s@LinearFrac(dimensions[0], (@type@*) args[0], (@type@*) args[0], 1.0, @OP@(*(@type@*)args[1]), 0.0, 1.0, (@type@*) args[2]); */ + if (dimensions[0] > VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same1) { + CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[0], args[2], 1.0, -(*(@type@*)args[1]), 0.0, 1.0); } else { @type@ *ip1 = (@type@*)args[0]; @@ -430,7 +579,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp const @type@ ip2c = ip2[0]; for(i = 0; i < peel; i++) { - op1[i] = ip1[i] @OP@ ip2c; + op1[i] = ip1[i] - ip2c; } { @@ -441,7 +590,7 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp NPY_ASSUME_ALIGNED(ip1_aligned, 64) for(j = 0; j < j_max; j++) { - op1_shifted[j] = ip1_aligned[j] @OP@ ip2c; + op1_shifted[j] = ip1_aligned[j] - ip2c; } i = blocked_end; @@ -449,41 +598,49 @@ mkl_umath_@TYPE@_@kind@(char **args, const npy_intp *dimensions, const npy_intp } for(; i < n; i++) { - op1[i] = ip1[i] @OP@ ip2c; + op1[i] = ip1[i] - ip2c; } } } + } else if (IS_BINARY_REDUCE) { -#if @PW@ - @type@ * iop1 = (@type@ *)args[0]; - npy_intp n = dimensions[0]; - - *iop1 @OP@= pairwise_sum_@TYPE@(args[1], n, steps[1]); -#else BINARY_REDUCE_LOOP(@type@) { - io1 @OP@= *(@type@ *)ip2; + io1 -= *(@type@ *)ip2; } *((@type@ *)iop1) = io1; -#endif } else { BINARY_LOOP { const @type@ in1 = *(@type@ *)ip1; const @type@ in2 = *(@type@ *)ip2; - *((@type@ *)op1) = in1 @OP@ in2; + *((@type@ *)op1) = in1 - in2; } } } -/**end repeat1**/ void mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func)) { + const npy_intp n = dimensions[0]; + + /* FAST PATH: Small contiguous arrays - avoid all overhead */ + if (IS_BINARY_CONT(@type@, @type@) && n <= SMALL_ARRAY_THRESHOLD) { + @type@ *ip1 = (@type@*)args[0]; + @type@ *ip2 = (@type@*)args[1]; + @type@ *op1 = (@type@*)args[2]; + + NPY_PRAGMA_VECTOR + for(npy_intp i = 0; i < n; i++) { + op1[i] = ip1[i] * ip2[i]; + } + return; + } + const int disjoint_or_same1 = DISJOINT_OR_SAME(args[0], args[2], dimensions[0], sizeof(@type@)); const int disjoint_or_same2 = DISJOINT_OR_SAME(args[1], args[2], dimensions[0], sizeof(@type@)); if (IS_BINARY_CONT(@type@, @type@)) { - if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same1 && disjoint_or_same2) { + if (dimensions[0] > VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same1 && disjoint_or_same2) { CHUNKED_VML_CALL3(v@s@Mul, dimensions[0], @type@, @type@, args[0], args[1], args[2]); /* v@s@Mul(dimensions[0], (@type@*) args[0], (@type@*) args[1], (@type@*) args[2]); */ } @@ -492,7 +649,6 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int @type@ *ip2 = (@type@*)args[1]; @type@ *op1 = (@type@*)args[2]; const npy_intp vsize = 64; - const npy_intp n = dimensions[0]; const npy_intp peel = npy_aligned_block_offset(ip1, sizeof(@type@), vsize, n); const npy_intp blocked_end = npy_blocked_end(peel, sizeof(@type@), vsize, n); npy_intp i; @@ -508,19 +664,11 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int @type@ *op1_shifted = op1 + peel; @type@ *ip2_shifted = ip2 + peel; - if ( DISJOINT_OR_SAME(op1_shifted, ip1_aligned, j_max, 1) && - DISJOINT_OR_SAME(op1_shifted, ip2_shifted, j_max, 1)) { - NPY_ASSUME_ALIGNED(ip1_aligned, 64) - NPY_PRAGMA_VECTOR - for(j = 0; j < j_max; j++) { - op1_shifted[j] = ip1_aligned[j] * ip2_shifted[j]; - } - } - else { - NPY_ASSUME_ALIGNED(ip1_aligned, 64) - for(j = 0; j < j_max; j++) { - op1_shifted[j] = ip1_aligned[j] * ip2_shifted[j]; - } + /* Redundant check removed - already verified disjoint_or_same above */ + NPY_ASSUME_ALIGNED(ip1_aligned, 64) + NPY_PRAGMA_VECTOR + for(j = 0; j < j_max; j++) { + op1_shifted[j] = ip1_aligned[j] * ip2_shifted[j]; } i = blocked_end; @@ -533,7 +681,7 @@ mkl_umath_@TYPE@_multiply(char **args, const npy_intp *dimensions, const npy_int } } else if (IS_BINARY_CONT_S1(@type@, @type@)) { - if (dimensions[0] > VML_ASM_THRESHOLD && disjoint_or_same2) { + if (dimensions[0] > VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same2) { CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, dimensions[0], @type@, args[1], args[2], *(@type@*)args[0], 0.0, 0.0, 1.0); /* v@s@LinearFrac(dimensions[0], (@type@*) args[1], (@type@*) args[1], *(@type@*)args[0], 0.0, 0.0, 1.0, (@type@*) args[2]); */ } diff --git a/mkl_umath/src/npyv/array_assign.h b/mkl_umath/src/npyv/array_assign.h new file mode 100644 index 00000000..8a28ed1d --- /dev/null +++ b/mkl_umath/src/npyv/array_assign.h @@ -0,0 +1,118 @@ +#ifndef NUMPY_CORE_SRC_COMMON_ARRAY_ASSIGN_H_ +#define NUMPY_CORE_SRC_COMMON_ARRAY_ASSIGN_H_ + +/* + * An array assignment function for copying arrays, treating the + * arrays as flat according to their respective ordering rules. + * This function makes a temporary copy of 'src' if 'src' and + * 'dst' overlap, to be able to handle views of the same data with + * different strides. + * + * dst: The destination array. + * dst_order: The rule for how 'dst' is to be made flat. + * src: The source array. + * src_order: The rule for how 'src' is to be made flat. + * casting: An exception is raised if the copy violates this + * casting rule. + * + * Returns 0 on success, -1 on failure. + */ +/* Not yet implemented +NPY_NO_EXPORT int +PyArray_AssignArrayAsFlat(PyArrayObject *dst, NPY_ORDER dst_order, + PyArrayObject *src, NPY_ORDER src_order, + NPY_CASTING casting, + npy_bool preservena, npy_bool *preservewhichna); +*/ + +NPY_NO_EXPORT int +PyArray_AssignArray(PyArrayObject *dst, PyArrayObject *src, + PyArrayObject *wheremask, + NPY_CASTING casting); + +NPY_NO_EXPORT int +PyArray_AssignRawScalar(PyArrayObject *dst, + PyArray_Descr *src_dtype, char *src_data, + PyArrayObject *wheremask, + NPY_CASTING casting); + +/******** LOW-LEVEL SCALAR TO ARRAY ASSIGNMENT ********/ + +/* + * Assigns the scalar value to every element of the destination raw array. + * + * Returns 0 on success, -1 on failure. + */ +NPY_NO_EXPORT int +raw_array_assign_scalar(int ndim, npy_intp const *shape, + PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides, + PyArray_Descr *src_dtype, char *src_data); + +/* + * Assigns the scalar value to every element of the destination raw array + * where the 'wheremask' value is True. + * + * Returns 0 on success, -1 on failure. + */ +NPY_NO_EXPORT int +raw_array_wheremasked_assign_scalar(int ndim, npy_intp const *shape, + PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides, + PyArray_Descr *src_dtype, char *src_data, + PyArray_Descr *wheremask_dtype, char *wheremask_data, + npy_intp const *wheremask_strides); + +/******** LOW-LEVEL ARRAY MANIPULATION HELPERS ********/ + +/* + * Internal detail of how much to buffer during array assignments which + * need it. This is for more complex NA masking operations where masks + * need to be inverted or combined together. + */ +#define NPY_ARRAY_ASSIGN_BUFFERSIZE 8192 + +/* + * Broadcasts strides to match the given dimensions. Can be used, + * for instance, to set up a raw iteration. + * + * 'strides_name' is used to produce an error message if the strides + * cannot be broadcast. + * + * Returns 0 on success, -1 on failure. + */ +NPY_NO_EXPORT int +broadcast_strides(int ndim, npy_intp const *shape, + int strides_ndim, npy_intp const *strides_shape, npy_intp const *strides, + char const *strides_name, + npy_intp *out_strides); + +/* + * Checks whether a data pointer + set of strides refers to a raw + * array whose elements are all aligned to a given alignment. Returns + * 1 if data is aligned to alignment or 0 if not. + * alignment should be a power of two, or may be the sentinel value 0 to mean + * cannot-be-aligned, in which case 0 (false) is always returned. + */ +NPY_NO_EXPORT int +raw_array_is_aligned(int ndim, npy_intp const *shape, + char *data, npy_intp const *strides, int alignment); + +/* + * Checks if an array is aligned to its "true alignment" + * given by dtype->alignment. + */ +NPY_NO_EXPORT int +IsAligned(PyArrayObject *ap); + +/* + * Checks if an array is aligned to its "uint alignment" + * given by npy_uint_alignment(dtype->elsize). + */ +NPY_NO_EXPORT int +IsUintAligned(PyArrayObject *ap); + +/* Returns 1 if the arrays have overlapping data, 0 otherwise */ +NPY_NO_EXPORT int +arrays_overlap(PyArrayObject *arr1, PyArrayObject *arr2); + + +#endif /* NUMPY_CORE_SRC_COMMON_ARRAY_ASSIGN_H_ */ diff --git a/mkl_umath/src/npyv/avx2/arithmetic.h b/mkl_umath/src/npyv/avx2/arithmetic.h new file mode 100644 index 00000000..58d842a6 --- /dev/null +++ b/mkl_umath/src/npyv/avx2/arithmetic.h @@ -0,0 +1,347 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_ARITHMETIC_H +#define _NPY_SIMD_AVX2_ARITHMETIC_H + +#include "../sse/utils.h" +/*************************** + * Addition + ***************************/ +// non-saturated +#define npyv_add_u8 _mm256_add_epi8 +#define npyv_add_s8 _mm256_add_epi8 +#define npyv_add_u16 _mm256_add_epi16 +#define npyv_add_s16 _mm256_add_epi16 +#define npyv_add_u32 _mm256_add_epi32 +#define npyv_add_s32 _mm256_add_epi32 +#define npyv_add_u64 _mm256_add_epi64 +#define npyv_add_s64 _mm256_add_epi64 +#define npyv_add_f32 _mm256_add_ps +#define npyv_add_f64 _mm256_add_pd + +// saturated +#define npyv_adds_u8 _mm256_adds_epu8 +#define npyv_adds_s8 _mm256_adds_epi8 +#define npyv_adds_u16 _mm256_adds_epu16 +#define npyv_adds_s16 _mm256_adds_epi16 +// TODO: rest, after implement Packs intrins + +/*************************** + * Subtraction + ***************************/ +// non-saturated +#define npyv_sub_u8 _mm256_sub_epi8 +#define npyv_sub_s8 _mm256_sub_epi8 +#define npyv_sub_u16 _mm256_sub_epi16 +#define npyv_sub_s16 _mm256_sub_epi16 +#define npyv_sub_u32 _mm256_sub_epi32 +#define npyv_sub_s32 _mm256_sub_epi32 +#define npyv_sub_u64 _mm256_sub_epi64 +#define npyv_sub_s64 _mm256_sub_epi64 +#define npyv_sub_f32 _mm256_sub_ps +#define npyv_sub_f64 _mm256_sub_pd + +// saturated +#define npyv_subs_u8 _mm256_subs_epu8 +#define npyv_subs_s8 _mm256_subs_epi8 +#define npyv_subs_u16 _mm256_subs_epu16 +#define npyv_subs_s16 _mm256_subs_epi16 +// TODO: rest, after implement Packs intrins + +/*************************** + * Multiplication + ***************************/ +// non-saturated +#define npyv_mul_u8 npyv256_mul_u8 +#define npyv_mul_s8 npyv_mul_u8 +#define npyv_mul_u16 _mm256_mullo_epi16 +#define npyv_mul_s16 _mm256_mullo_epi16 +#define npyv_mul_u32 _mm256_mullo_epi32 +#define npyv_mul_s32 _mm256_mullo_epi32 +#define npyv_mul_f32 _mm256_mul_ps +#define npyv_mul_f64 _mm256_mul_pd + +// saturated +// TODO: after implement Packs intrins + +/*************************** + * Integer Division + ***************************/ +// See simd/intdiv.h for more clarification +// divide each unsigned 8-bit element by a precomputed divisor +NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor) +{ + const __m256i bmask = _mm256_set1_epi32(0x00FF00FF); + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + const __m128i shf2 = _mm256_castsi256_si128(divisor.val[2]); + const __m256i shf1b = _mm256_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf1)); + const __m256i shf2b = _mm256_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf2)); + // high part of unsigned multiplication + __m256i mulhi_even = _mm256_mullo_epi16(_mm256_and_si256(a, bmask), divisor.val[0]); + mulhi_even = _mm256_srli_epi16(mulhi_even, 8); + __m256i mulhi_odd = _mm256_mullo_epi16(_mm256_srli_epi16(a, 8), divisor.val[0]); + __m256i mulhi = _mm256_blendv_epi8(mulhi_odd, mulhi_even, bmask); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m256i q = _mm256_sub_epi8(a, mulhi); + q = _mm256_and_si256(_mm256_srl_epi16(q, shf1), shf1b); + q = _mm256_add_epi8(mulhi, q); + q = _mm256_and_si256(_mm256_srl_epi16(q, shf2), shf2b); + return q; +} +// divide each signed 8-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor); +NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor) +{ + const __m256i bmask = _mm256_set1_epi32(0x00FF00FF); + // instead of _mm256_cvtepi8_epi16/_mm256_packs_epi16 to wrap around overflow + __m256i divc_even = npyv_divc_s16(_mm256_srai_epi16(_mm256_slli_epi16(a, 8), 8), divisor); + __m256i divc_odd = npyv_divc_s16(_mm256_srai_epi16(a, 8), divisor); + divc_odd = _mm256_slli_epi16(divc_odd, 8); + return _mm256_blendv_epi8(divc_odd, divc_even, bmask); +} +// divide each unsigned 16-bit element by a precomputed divisor +NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor) +{ + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + const __m128i shf2 = _mm256_castsi256_si128(divisor.val[2]); + // high part of unsigned multiplication + __m256i mulhi = _mm256_mulhi_epu16(a, divisor.val[0]); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m256i q = _mm256_sub_epi16(a, mulhi); + q = _mm256_srl_epi16(q, shf1); + q = _mm256_add_epi16(mulhi, q); + q = _mm256_srl_epi16(q, shf2); + return q; +} +// divide each signed 16-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor) +{ + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + // high part of signed multiplication + __m256i mulhi = _mm256_mulhi_epi16(a, divisor.val[0]); + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + __m256i q = _mm256_sra_epi16(_mm256_add_epi16(a, mulhi), shf1); + q = _mm256_sub_epi16(q, _mm256_srai_epi16(a, 15)); + q = _mm256_sub_epi16(_mm256_xor_si256(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 32-bit element by a precomputed divisor +NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor) +{ + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + const __m128i shf2 = _mm256_castsi256_si128(divisor.val[2]); + // high part of unsigned multiplication + __m256i mulhi_even = _mm256_srli_epi64(_mm256_mul_epu32(a, divisor.val[0]), 32); + __m256i mulhi_odd = _mm256_mul_epu32(_mm256_srli_epi64(a, 32), divisor.val[0]); + __m256i mulhi = _mm256_blend_epi32(mulhi_even, mulhi_odd, 0xAA); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m256i q = _mm256_sub_epi32(a, mulhi); + q = _mm256_srl_epi32(q, shf1); + q = _mm256_add_epi32(mulhi, q); + q = _mm256_srl_epi32(q, shf2); + return q; +} +// divide each signed 32-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor) +{ + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + // high part of signed multiplication + __m256i mulhi_even = _mm256_srli_epi64(_mm256_mul_epi32(a, divisor.val[0]), 32); + __m256i mulhi_odd = _mm256_mul_epi32(_mm256_srli_epi64(a, 32), divisor.val[0]); + __m256i mulhi = _mm256_blend_epi32(mulhi_even, mulhi_odd, 0xAA); + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + __m256i q = _mm256_sra_epi32(_mm256_add_epi32(a, mulhi), shf1); + q = _mm256_sub_epi32(q, _mm256_srai_epi32(a, 31)); + q = _mm256_sub_epi32(_mm256_xor_si256(q, divisor.val[2]), divisor.val[2]); + return q; +} +// returns the high 64 bits of unsigned 64-bit multiplication +// xref https://stackoverflow.com/a/28827013 +NPY_FINLINE npyv_u64 npyv__mullhi_u64(npyv_u64 a, npyv_u64 b) +{ + __m256i lomask = npyv_setall_s64(0xffffffff); + __m256i a_hi = _mm256_srli_epi64(a, 32); // a0l, a0h, a1l, a1h + __m256i b_hi = _mm256_srli_epi64(b, 32); // b0l, b0h, b1l, b1h + // compute partial products + __m256i w0 = _mm256_mul_epu32(a, b); // a0l*b0l, a1l*b1l + __m256i w1 = _mm256_mul_epu32(a, b_hi); // a0l*b0h, a1l*b1h + __m256i w2 = _mm256_mul_epu32(a_hi, b); // a0h*b0l, a1h*b0l + __m256i w3 = _mm256_mul_epu32(a_hi, b_hi); // a0h*b0h, a1h*b1h + // sum partial products + __m256i w0h = _mm256_srli_epi64(w0, 32); + __m256i s1 = _mm256_add_epi64(w1, w0h); + __m256i s1l = _mm256_and_si256(s1, lomask); + __m256i s1h = _mm256_srli_epi64(s1, 32); + + __m256i s2 = _mm256_add_epi64(w2, s1l); + __m256i s2h = _mm256_srli_epi64(s2, 32); + + __m256i hi = _mm256_add_epi64(w3, s1h); + hi = _mm256_add_epi64(hi, s2h); + return hi; +} +// divide each unsigned 64-bit element by a divisor +NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor) +{ + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + const __m128i shf2 = _mm256_castsi256_si128(divisor.val[2]); + // high part of unsigned multiplication + __m256i mulhi = npyv__mullhi_u64(a, divisor.val[0]); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m256i q = _mm256_sub_epi64(a, mulhi); + q = _mm256_srl_epi64(q, shf1); + q = _mm256_add_epi64(mulhi, q); + q = _mm256_srl_epi64(q, shf2); + return q; +} +// divide each unsigned 64-bit element by a divisor (round towards zero) +NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor) +{ + const __m128i shf1 = _mm256_castsi256_si128(divisor.val[1]); + // high part of unsigned multiplication + __m256i mulhi = npyv__mullhi_u64(a, divisor.val[0]); + // convert unsigned to signed high multiplication + // mulhi - ((a < 0) ? m : 0) - ((m < 0) ? a : 0); + __m256i asign = _mm256_cmpgt_epi64(_mm256_setzero_si256(), a); + __m256i msign = _mm256_cmpgt_epi64(_mm256_setzero_si256(), divisor.val[0]); + __m256i m_asign = _mm256_and_si256(divisor.val[0], asign); + __m256i a_msign = _mm256_and_si256(a, msign); + mulhi = _mm256_sub_epi64(mulhi, m_asign); + mulhi = _mm256_sub_epi64(mulhi, a_msign); + // q = (a + mulhi) >> sh + __m256i q = _mm256_add_epi64(a, mulhi); + // emulate arithmetic right shift + const __m256i sigb = npyv_setall_s64(1LL << 63); + q = _mm256_srl_epi64(_mm256_add_epi64(q, sigb), shf1); + q = _mm256_sub_epi64(q, _mm256_srl_epi64(sigb, shf1)); + // q = q - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + q = _mm256_sub_epi64(q, asign); + q = _mm256_sub_epi64(_mm256_xor_si256(q, divisor.val[2]), divisor.val[2]); + return q; +} +/*************************** + * Division + ***************************/ +// TODO: emulate integer division +#define npyv_div_f32 _mm256_div_ps +#define npyv_div_f64 _mm256_div_pd + +/*************************** + * FUSED + ***************************/ +#ifdef NPY_HAVE_FMA3 + // multiply and add, a*b + c + #define npyv_muladd_f32 _mm256_fmadd_ps + #define npyv_muladd_f64 _mm256_fmadd_pd + // multiply and subtract, a*b - c + #define npyv_mulsub_f32 _mm256_fmsub_ps + #define npyv_mulsub_f64 _mm256_fmsub_pd + // negate multiply and add, -(a*b) + c + #define npyv_nmuladd_f32 _mm256_fnmadd_ps + #define npyv_nmuladd_f64 _mm256_fnmadd_pd + // negate multiply and subtract, -(a*b) - c + #define npyv_nmulsub_f32 _mm256_fnmsub_ps + #define npyv_nmulsub_f64 _mm256_fnmsub_pd + // multiply, add for odd elements and subtract even elements. + // (a * b) -+ c + #define npyv_muladdsub_f32 _mm256_fmaddsub_ps + #define npyv_muladdsub_f64 _mm256_fmaddsub_pd +#else + // multiply and add, a*b + c + NPY_FINLINE npyv_f32 npyv_muladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return npyv_add_f32(npyv_mul_f32(a, b), c); } + NPY_FINLINE npyv_f64 npyv_muladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return npyv_add_f64(npyv_mul_f64(a, b), c); } + // multiply and subtract, a*b - c + NPY_FINLINE npyv_f32 npyv_mulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return npyv_sub_f32(npyv_mul_f32(a, b), c); } + NPY_FINLINE npyv_f64 npyv_mulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return npyv_sub_f64(npyv_mul_f64(a, b), c); } + // negate multiply and add, -(a*b) + c + NPY_FINLINE npyv_f32 npyv_nmuladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return npyv_sub_f32(c, npyv_mul_f32(a, b)); } + NPY_FINLINE npyv_f64 npyv_nmuladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return npyv_sub_f64(c, npyv_mul_f64(a, b)); } + // negate multiply and subtract, -(a*b) - c + NPY_FINLINE npyv_f32 npyv_nmulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { + npyv_f32 neg_a = npyv_xor_f32(a, npyv_setall_f32(-0.0f)); + return npyv_sub_f32(npyv_mul_f32(neg_a, b), c); + } + NPY_FINLINE npyv_f64 npyv_nmulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { + npyv_f64 neg_a = npyv_xor_f64(a, npyv_setall_f64(-0.0)); + return npyv_sub_f64(npyv_mul_f64(neg_a, b), c); + } + // multiply, add for odd elements and subtract even elements. + // (a * b) -+ c + NPY_FINLINE npyv_f32 npyv_muladdsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return _mm256_addsub_ps(npyv_mul_f32(a, b), c); } + NPY_FINLINE npyv_f64 npyv_muladdsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return _mm256_addsub_pd(npyv_mul_f64(a, b), c); } + +#endif // !NPY_HAVE_FMA3 + +/*************************** + * Summation + ***************************/ +// reduce sum across vector +NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) +{ + __m256i s0 = _mm256_hadd_epi32(a, a); + s0 = _mm256_hadd_epi32(s0, s0); + __m128i s1 = _mm256_extracti128_si256(s0, 1); + s1 = _mm_add_epi32(_mm256_castsi256_si128(s0), s1); + return _mm_cvtsi128_si32(s1); +} + +NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) +{ + __m256i two = _mm256_add_epi64(a, _mm256_shuffle_epi32(a, _MM_SHUFFLE(1, 0, 3, 2))); + __m128i one = _mm_add_epi64(_mm256_castsi256_si128(two), _mm256_extracti128_si256(two, 1)); + return (npy_uint64)npyv128_cvtsi128_si64(one); +} + +NPY_FINLINE float npyv_sum_f32(npyv_f32 a) +{ + __m256 sum_halves = _mm256_hadd_ps(a, a); + sum_halves = _mm256_hadd_ps(sum_halves, sum_halves); + __m128 lo = _mm256_castps256_ps128(sum_halves); + __m128 hi = _mm256_extractf128_ps(sum_halves, 1); + __m128 sum = _mm_add_ps(lo, hi); + return _mm_cvtss_f32(sum); +} + +NPY_FINLINE double npyv_sum_f64(npyv_f64 a) +{ + __m256d sum_halves = _mm256_hadd_pd(a, a); + __m128d lo = _mm256_castpd256_pd128(sum_halves); + __m128d hi = _mm256_extractf128_pd(sum_halves, 1); + __m128d sum = _mm_add_pd(lo, hi); + return _mm_cvtsd_f64(sum); +} + +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ + __m256i four = _mm256_sad_epu8(a, _mm256_setzero_si256()); + __m128i two = _mm_add_epi16(_mm256_castsi256_si128(four), _mm256_extracti128_si256(four, 1)); + __m128i one = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two)); + return (npy_uint16)_mm_cvtsi128_si32(one); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const npyv_u16 even_mask = _mm256_set1_epi32(0x0000FFFF); + __m256i even = _mm256_and_si256(a, even_mask); + __m256i odd = _mm256_srli_epi32(a, 16); + __m256i eight = _mm256_add_epi32(even, odd); + return npyv_sum_u32(eight); +} + +#endif // _NPY_SIMD_AVX2_ARITHMETIC_H diff --git a/mkl_umath/src/npyv/avx2/avx2.h b/mkl_umath/src/npyv/avx2/avx2.h new file mode 100644 index 00000000..d64f3c6d --- /dev/null +++ b/mkl_umath/src/npyv/avx2/avx2.h @@ -0,0 +1,77 @@ +#ifndef _NPY_SIMD_H_ + #error "Not a standalone header" +#endif +#define NPY_SIMD 256 +#define NPY_SIMD_WIDTH 32 +#define NPY_SIMD_F32 1 +#define NPY_SIMD_F64 1 +#ifdef NPY_HAVE_FMA3 + #define NPY_SIMD_FMA3 1 // native support +#else + #define NPY_SIMD_FMA3 0 // fast emulated +#endif +#define NPY_SIMD_BIGENDIAN 0 +#define NPY_SIMD_CMPSIGNAL 0 +// Enough limit to allow us to use _mm256_i32gather_* +#define NPY_SIMD_MAXLOAD_STRIDE32 (0x7fffffff / 8) + +typedef __m256i npyv_u8; +typedef __m256i npyv_s8; +typedef __m256i npyv_u16; +typedef __m256i npyv_s16; +typedef __m256i npyv_u32; +typedef __m256i npyv_s32; +typedef __m256i npyv_u64; +typedef __m256i npyv_s64; +typedef __m256 npyv_f32; +typedef __m256d npyv_f64; + +typedef __m256i npyv_b8; +typedef __m256i npyv_b16; +typedef __m256i npyv_b32; +typedef __m256i npyv_b64; + +typedef struct { __m256i val[2]; } npyv_m256ix2; +typedef npyv_m256ix2 npyv_u8x2; +typedef npyv_m256ix2 npyv_s8x2; +typedef npyv_m256ix2 npyv_u16x2; +typedef npyv_m256ix2 npyv_s16x2; +typedef npyv_m256ix2 npyv_u32x2; +typedef npyv_m256ix2 npyv_s32x2; +typedef npyv_m256ix2 npyv_u64x2; +typedef npyv_m256ix2 npyv_s64x2; + +typedef struct { __m256i val[3]; } npyv_m256ix3; +typedef npyv_m256ix3 npyv_u8x3; +typedef npyv_m256ix3 npyv_s8x3; +typedef npyv_m256ix3 npyv_u16x3; +typedef npyv_m256ix3 npyv_s16x3; +typedef npyv_m256ix3 npyv_u32x3; +typedef npyv_m256ix3 npyv_s32x3; +typedef npyv_m256ix3 npyv_u64x3; +typedef npyv_m256ix3 npyv_s64x3; + +typedef struct { __m256 val[2]; } npyv_f32x2; +typedef struct { __m256d val[2]; } npyv_f64x2; +typedef struct { __m256 val[3]; } npyv_f32x3; +typedef struct { __m256d val[3]; } npyv_f64x3; + +#define npyv_nlanes_u8 32 +#define npyv_nlanes_s8 32 +#define npyv_nlanes_u16 16 +#define npyv_nlanes_s16 16 +#define npyv_nlanes_u32 8 +#define npyv_nlanes_s32 8 +#define npyv_nlanes_u64 4 +#define npyv_nlanes_s64 4 +#define npyv_nlanes_f32 8 +#define npyv_nlanes_f64 4 + +#include "utils.h" +#include "memory.h" +#include "misc.h" +#include "reorder.h" +#include "operators.h" +#include "conversion.h" +#include "arithmetic.h" +#include "math.h" diff --git a/mkl_umath/src/npyv/avx2/conversion.h b/mkl_umath/src/npyv/avx2/conversion.h new file mode 100644 index 00000000..00ac0d38 --- /dev/null +++ b/mkl_umath/src/npyv/avx2/conversion.h @@ -0,0 +1,99 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_CVT_H +#define _NPY_SIMD_AVX2_CVT_H + +// convert mask types to integer types +#define npyv_cvt_u8_b8(A) A +#define npyv_cvt_s8_b8(A) A +#define npyv_cvt_u16_b16(A) A +#define npyv_cvt_s16_b16(A) A +#define npyv_cvt_u32_b32(A) A +#define npyv_cvt_s32_b32(A) A +#define npyv_cvt_u64_b64(A) A +#define npyv_cvt_s64_b64(A) A +#define npyv_cvt_f32_b32 _mm256_castsi256_ps +#define npyv_cvt_f64_b64 _mm256_castsi256_pd + +// convert integer types to mask types +#define npyv_cvt_b8_u8(BL) BL +#define npyv_cvt_b8_s8(BL) BL +#define npyv_cvt_b16_u16(BL) BL +#define npyv_cvt_b16_s16(BL) BL +#define npyv_cvt_b32_u32(BL) BL +#define npyv_cvt_b32_s32(BL) BL +#define npyv_cvt_b64_u64(BL) BL +#define npyv_cvt_b64_s64(BL) BL +#define npyv_cvt_b32_f32 _mm256_castps_si256 +#define npyv_cvt_b64_f64 _mm256_castpd_si256 + +// convert boolean vector to integer bitfield +NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) +{ return (npy_uint32)_mm256_movemask_epi8(a); } + +NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a) +{ + __m128i pack = _mm_packs_epi16(_mm256_castsi256_si128(a), _mm256_extracti128_si256(a, 1)); + return (npy_uint16)_mm_movemask_epi8(pack); +} +NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a) +{ return (npy_uint8)_mm256_movemask_ps(_mm256_castsi256_ps(a)); } +NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a) +{ return (npy_uint8)_mm256_movemask_pd(_mm256_castsi256_pd(a)); } + +// expand +NPY_FINLINE npyv_u16x2 npyv_expand_u16_u8(npyv_u8 data) { + npyv_u16x2 r; + r.val[0] = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(data)); + r.val[1] = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(data, 1)); + return r; +} + +NPY_FINLINE npyv_u32x2 npyv_expand_u32_u16(npyv_u16 data) { + npyv_u32x2 r; + r.val[0] = _mm256_cvtepu16_epi32(_mm256_castsi256_si128(data)); + r.val[1] = _mm256_cvtepu16_epi32(_mm256_extracti128_si256(data, 1)); + return r; +} + +// pack two 16-bit boolean into one 8-bit boolean vector +NPY_FINLINE npyv_b8 npyv_pack_b8_b16(npyv_b16 a, npyv_b16 b) { + __m256i ab = _mm256_packs_epi16(a, b); + return npyv256_shuffle_odd(ab); +} + +// pack four 32-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b32(npyv_b32 a, npyv_b32 b, npyv_b32 c, npyv_b32 d) { + __m256i ab = _mm256_packs_epi32(a, b); + __m256i cd = _mm256_packs_epi32(c, d); + __m256i abcd = npyv_pack_b8_b16(ab, cd); + return _mm256_shuffle_epi32(abcd, _MM_SHUFFLE(3, 1, 2, 0)); +} + +// pack eight 64-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b64(npyv_b64 a, npyv_b64 b, npyv_b64 c, npyv_b64 d, + npyv_b64 e, npyv_b64 f, npyv_b64 g, npyv_b64 h) { + __m256i ab = _mm256_packs_epi32(a, b); + __m256i cd = _mm256_packs_epi32(c, d); + __m256i ef = _mm256_packs_epi32(e, f); + __m256i gh = _mm256_packs_epi32(g, h); + __m256i abcd = _mm256_packs_epi32(ab, cd); + __m256i efgh = _mm256_packs_epi32(ef, gh); + __m256i all = npyv256_shuffle_odd(_mm256_packs_epi16(abcd, efgh)); + __m256i rev128 = _mm256_alignr_epi8(all, all, 8); + return _mm256_unpacklo_epi16(all, rev128); +} + +// round to nearest integer (assuming even) +#define npyv_round_s32_f32 _mm256_cvtps_epi32 +NPY_FINLINE npyv_s32 npyv_round_s32_f64(npyv_f64 a, npyv_f64 b) +{ + __m128i lo = _mm256_cvtpd_epi32(a), hi = _mm256_cvtpd_epi32(b); + return _mm256_inserti128_si256(_mm256_castsi128_si256(lo), hi, 1); +} + +#endif // _NPY_SIMD_AVX2_CVT_H diff --git a/mkl_umath/src/npyv/avx2/math.h b/mkl_umath/src/npyv/avx2/math.h new file mode 100644 index 00000000..1ef9cd36 --- /dev/null +++ b/mkl_umath/src/npyv/avx2/math.h @@ -0,0 +1,253 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_MATH_H +#define _NPY_SIMD_AVX2_MATH_H +/*************************** + * Elementary + ***************************/ +// Square root +#define npyv_sqrt_f32 _mm256_sqrt_ps +#define npyv_sqrt_f64 _mm256_sqrt_pd + +// Reciprocal +NPY_FINLINE npyv_f32 npyv_recip_f32(npyv_f32 a) +{ return _mm256_div_ps(_mm256_set1_ps(1.0f), a); } +NPY_FINLINE npyv_f64 npyv_recip_f64(npyv_f64 a) +{ return _mm256_div_pd(_mm256_set1_pd(1.0), a); } + +// Absolute +NPY_FINLINE npyv_f32 npyv_abs_f32(npyv_f32 a) +{ + return _mm256_and_ps( + a, _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff)) + ); +} +NPY_FINLINE npyv_f64 npyv_abs_f64(npyv_f64 a) +{ + return _mm256_and_pd( + a, _mm256_castsi256_pd(npyv_setall_s64(0x7fffffffffffffffLL)) + ); +} + +// Square +NPY_FINLINE npyv_f32 npyv_square_f32(npyv_f32 a) +{ return _mm256_mul_ps(a, a); } +NPY_FINLINE npyv_f64 npyv_square_f64(npyv_f64 a) +{ return _mm256_mul_pd(a, a); } + +// Maximum, natively mapping with no guarantees to handle NaN. +#define npyv_max_f32 _mm256_max_ps +#define npyv_max_f64 _mm256_max_pd +// Maximum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_maxp_f32(npyv_f32 a, npyv_f32 b) +{ + __m256 nn = _mm256_cmp_ps(b, b, _CMP_ORD_Q); + __m256 max = _mm256_max_ps(a, b); + return _mm256_blendv_ps(a, max, nn); +} +NPY_FINLINE npyv_f64 npyv_maxp_f64(npyv_f64 a, npyv_f64 b) +{ + __m256d nn = _mm256_cmp_pd(b, b, _CMP_ORD_Q); + __m256d max = _mm256_max_pd(a, b); + return _mm256_blendv_pd(a, max, nn); +} +// Maximum, propagates NaNs +// If any of corresponded elements is NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_maxn_f32(npyv_f32 a, npyv_f32 b) +{ + __m256 nn = _mm256_cmp_ps(a, a, _CMP_ORD_Q); + __m256 max = _mm256_max_ps(a, b); + return _mm256_blendv_ps(a, max, nn); +} +NPY_FINLINE npyv_f64 npyv_maxn_f64(npyv_f64 a, npyv_f64 b) +{ + __m256d nn = _mm256_cmp_pd(a, a, _CMP_ORD_Q); + __m256d max = _mm256_max_pd(a, b); + return _mm256_blendv_pd(a, max, nn); +} + +// Maximum, integer operations +#define npyv_max_u8 _mm256_max_epu8 +#define npyv_max_s8 _mm256_max_epi8 +#define npyv_max_u16 _mm256_max_epu16 +#define npyv_max_s16 _mm256_max_epi16 +#define npyv_max_u32 _mm256_max_epu32 +#define npyv_max_s32 _mm256_max_epi32 +NPY_FINLINE npyv_u64 npyv_max_u64(npyv_u64 a, npyv_u64 b) +{ + return _mm256_blendv_epi8(b, a, npyv_cmpgt_u64(a, b)); +} +NPY_FINLINE npyv_s64 npyv_max_s64(npyv_s64 a, npyv_s64 b) +{ + return _mm256_blendv_epi8(b, a, _mm256_cmpgt_epi64(a, b)); +} + +// Minimum, natively mapping with no guarantees to handle NaN. +#define npyv_min_f32 _mm256_min_ps +#define npyv_min_f64 _mm256_min_pd +// Minimum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_minp_f32(npyv_f32 a, npyv_f32 b) +{ + __m256 nn = _mm256_cmp_ps(b, b, _CMP_ORD_Q); + __m256 min = _mm256_min_ps(a, b); + return _mm256_blendv_ps(a, min, nn); +} +NPY_FINLINE npyv_f64 npyv_minp_f64(npyv_f64 a, npyv_f64 b) +{ + __m256d nn = _mm256_cmp_pd(b, b, _CMP_ORD_Q); + __m256d min = _mm256_min_pd(a, b); + return _mm256_blendv_pd(a, min, nn); +} +// Minimum, propagates NaNs +// If any of corresponded element is NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_minn_f32(npyv_f32 a, npyv_f32 b) +{ + __m256 nn = _mm256_cmp_ps(a, a, _CMP_ORD_Q); + __m256 min = _mm256_min_ps(a, b); + return _mm256_blendv_ps(a, min, nn); +} +NPY_FINLINE npyv_f64 npyv_minn_f64(npyv_f64 a, npyv_f64 b) +{ + __m256d nn = _mm256_cmp_pd(a, a, _CMP_ORD_Q); + __m256d min = _mm256_min_pd(a, b); + return _mm256_blendv_pd(a, min, nn); +} +// Minimum, integer operations +#define npyv_min_u8 _mm256_min_epu8 +#define npyv_min_s8 _mm256_min_epi8 +#define npyv_min_u16 _mm256_min_epu16 +#define npyv_min_s16 _mm256_min_epi16 +#define npyv_min_u32 _mm256_min_epu32 +#define npyv_min_s32 _mm256_min_epi32 +NPY_FINLINE npyv_u64 npyv_min_u64(npyv_u64 a, npyv_u64 b) +{ + return _mm256_blendv_epi8(b, a, npyv_cmplt_u64(a, b)); +} +NPY_FINLINE npyv_s64 npyv_min_s64(npyv_s64 a, npyv_s64 b) +{ + return _mm256_blendv_epi8(a, b, _mm256_cmpgt_epi64(a, b)); +} +// reduce min&max for 32&64-bits +#define NPY_IMPL_AVX2_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN) \ + NPY_FINLINE STYPE##32 npyv_reduce_##INTRIN##32(__m256i a) \ + { \ + __m128i v128 = _mm_##VINTRIN##32(_mm256_castsi256_si128(a), _mm256_extracti128_si256(a, 1)); \ + __m128i v64 = _mm_##VINTRIN##32(v128, _mm_shuffle_epi32(v128, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = _mm_##VINTRIN##32(v64, _mm_shuffle_epi32(v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + return (STYPE##32)_mm_cvtsi128_si32(v32); \ + } \ + NPY_FINLINE STYPE##64 npyv_reduce_##INTRIN##64(__m256i a) \ + { \ + __m256i v128 = npyv_##INTRIN##64(a, _mm256_permute2f128_si256(a, a, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m256i v64 = npyv_##INTRIN##64(v128, _mm256_shuffle_epi32(v128, _MM_SHUFFLE(0, 0, 3, 2))); \ + return (STYPE##64)npyv_extract0_u64(v64); \ + } +NPY_IMPL_AVX2_REDUCE_MINMAX(npy_uint, min_u, min_epu) +NPY_IMPL_AVX2_REDUCE_MINMAX(npy_int, min_s, min_epi) +NPY_IMPL_AVX2_REDUCE_MINMAX(npy_uint, max_u, max_epu) +NPY_IMPL_AVX2_REDUCE_MINMAX(npy_int, max_s, max_epi) +#undef NPY_IMPL_AVX2_REDUCE_MINMAX + +// reduce min&max for ps & pd +#define NPY_IMPL_AVX2_REDUCE_MINMAX(INTRIN, INF, INF64) \ + NPY_FINLINE float npyv_reduce_##INTRIN##_f32(npyv_f32 a) \ + { \ + __m128 v128 = _mm_##INTRIN##_ps(_mm256_castps256_ps128(a), _mm256_extractf128_ps(a, 1)); \ + __m128 v64 = _mm_##INTRIN##_ps(v128, _mm_shuffle_ps(v128, v128, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128 v32 = _mm_##INTRIN##_ps(v64, _mm_shuffle_ps(v64, v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + return _mm_cvtss_f32(v32); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##_f64(npyv_f64 a) \ + { \ + __m128d v128 = _mm_##INTRIN##_pd(_mm256_castpd256_pd128(a), _mm256_extractf128_pd(a, 1)); \ + __m128d v64 = _mm_##INTRIN##_pd(v128, _mm_shuffle_pd(v128, v128, _MM_SHUFFLE(0, 0, 0, 1))); \ + return _mm_cvtsd_f64(v64); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##p_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_any_b32(notnan))) { \ + return _mm_cvtss_f32(_mm256_castps256_ps128(a)); \ + } \ + a = npyv_select_f32(notnan, a, npyv_reinterpret_f32_u32(npyv_setall_u32(INF))); \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##p_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_any_b64(notnan))) { \ + return _mm_cvtsd_f64(_mm256_castpd256_pd128(a)); \ + } \ + a = npyv_select_f64(notnan, a, npyv_reinterpret_f64_u64(npyv_setall_u64(INF64))); \ + return npyv_reduce_##INTRIN##_f64(a); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##n_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_all_b32(notnan))) { \ + const union { npy_uint32 i; float f;} pnan = {0x7fc00000UL}; \ + return pnan.f; \ + } \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##n_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_all_b64(notnan))) { \ + const union { npy_uint64 i; double d;} pnan = {0x7ff8000000000000ull}; \ + return pnan.d; \ + } \ + return npyv_reduce_##INTRIN##_f64(a); \ + } +NPY_IMPL_AVX2_REDUCE_MINMAX(min, 0x7f800000, 0x7ff0000000000000) +NPY_IMPL_AVX2_REDUCE_MINMAX(max, 0xff800000, 0xfff0000000000000) +#undef NPY_IMPL_AVX2_REDUCE_MINMAX + +// reduce min&max for 8&16-bits +#define NPY_IMPL_AVX256_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN) \ + NPY_FINLINE STYPE##16 npyv_reduce_##INTRIN##16(__m256i a) \ + { \ + __m128i v128 = _mm_##VINTRIN##16(_mm256_castsi256_si128(a), _mm256_extracti128_si256(a, 1)); \ + __m128i v64 = _mm_##VINTRIN##16(v128, _mm_shuffle_epi32(v128, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = _mm_##VINTRIN##16(v64, _mm_shuffle_epi32(v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v16 = _mm_##VINTRIN##16(v32, _mm_shufflelo_epi16(v32, _MM_SHUFFLE(0, 0, 0, 1))); \ + return (STYPE##16)_mm_cvtsi128_si32(v16); \ + } \ + NPY_FINLINE STYPE##8 npyv_reduce_##INTRIN##8(__m256i a) \ + { \ + __m128i v128 = _mm_##VINTRIN##8(_mm256_castsi256_si128(a), _mm256_extracti128_si256(a, 1)); \ + __m128i v64 = _mm_##VINTRIN##8(v128, _mm_shuffle_epi32(v128, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = _mm_##VINTRIN##8(v64, _mm_shuffle_epi32(v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v16 = _mm_##VINTRIN##8(v32, _mm_shufflelo_epi16(v32, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v8 = _mm_##VINTRIN##8(v16, _mm_srli_epi16(v16, 8)); \ + return (STYPE##16)_mm_cvtsi128_si32(v8); \ + } +NPY_IMPL_AVX256_REDUCE_MINMAX(npy_uint, min_u, min_epu) +NPY_IMPL_AVX256_REDUCE_MINMAX(npy_int, min_s, min_epi) +NPY_IMPL_AVX256_REDUCE_MINMAX(npy_uint, max_u, max_epu) +NPY_IMPL_AVX256_REDUCE_MINMAX(npy_int, max_s, max_epi) +#undef NPY_IMPL_AVX256_REDUCE_MINMAX + +// round to nearest integer even +#define npyv_rint_f32(A) _mm256_round_ps(A, _MM_FROUND_TO_NEAREST_INT) +#define npyv_rint_f64(A) _mm256_round_pd(A, _MM_FROUND_TO_NEAREST_INT) + +// ceil +#define npyv_ceil_f32 _mm256_ceil_ps +#define npyv_ceil_f64 _mm256_ceil_pd + +// trunc +#define npyv_trunc_f32(A) _mm256_round_ps(A, _MM_FROUND_TO_ZERO) +#define npyv_trunc_f64(A) _mm256_round_pd(A, _MM_FROUND_TO_ZERO) + +// floor +#define npyv_floor_f32 _mm256_floor_ps +#define npyv_floor_f64 _mm256_floor_pd + +#endif // _NPY_SIMD_AVX2_MATH_H diff --git a/mkl_umath/src/npyv/avx2/memory.h b/mkl_umath/src/npyv/avx2/memory.h new file mode 100644 index 00000000..f1863653 --- /dev/null +++ b/mkl_umath/src/npyv/avx2/memory.h @@ -0,0 +1,761 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#include "misc.h" + +#ifndef _NPY_SIMD_AVX2_MEMORY_H +#define _NPY_SIMD_AVX2_MEMORY_H + +/*************************** + * load/store + ***************************/ +#define NPYV_IMPL_AVX2_MEM_INT(CTYPE, SFX) \ + NPY_FINLINE npyv_##SFX npyv_load_##SFX(const CTYPE *ptr) \ + { return _mm256_loadu_si256((const __m256i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loada_##SFX(const CTYPE *ptr) \ + { return _mm256_load_si256((const __m256i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loads_##SFX(const CTYPE *ptr) \ + { return _mm256_stream_load_si256((const __m256i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loadl_##SFX(const CTYPE *ptr) \ + { return _mm256_castsi128_si256(_mm_loadu_si128((const __m128i*)ptr)); } \ + NPY_FINLINE void npyv_store_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm256_storeu_si256((__m256i*)ptr, vec); } \ + NPY_FINLINE void npyv_storea_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm256_store_si256((__m256i*)ptr, vec); } \ + NPY_FINLINE void npyv_stores_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm256_stream_si256((__m256i*)ptr, vec); } \ + NPY_FINLINE void npyv_storel_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_storeu_si128((__m128i*)(ptr), _mm256_castsi256_si128(vec)); } \ + NPY_FINLINE void npyv_storeh_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_storeu_si128((__m128i*)(ptr), _mm256_extracti128_si256(vec, 1)); } + +NPYV_IMPL_AVX2_MEM_INT(npy_uint8, u8) +NPYV_IMPL_AVX2_MEM_INT(npy_int8, s8) +NPYV_IMPL_AVX2_MEM_INT(npy_uint16, u16) +NPYV_IMPL_AVX2_MEM_INT(npy_int16, s16) +NPYV_IMPL_AVX2_MEM_INT(npy_uint32, u32) +NPYV_IMPL_AVX2_MEM_INT(npy_int32, s32) +NPYV_IMPL_AVX2_MEM_INT(npy_uint64, u64) +NPYV_IMPL_AVX2_MEM_INT(npy_int64, s64) + +// unaligned load +#define npyv_load_f32 _mm256_loadu_ps +#define npyv_load_f64 _mm256_loadu_pd +// aligned load +#define npyv_loada_f32 _mm256_load_ps +#define npyv_loada_f64 _mm256_load_pd +// stream load +#define npyv_loads_f32(PTR) \ + _mm256_castsi256_ps(_mm256_stream_load_si256((const __m256i*)(PTR))) +#define npyv_loads_f64(PTR) \ + _mm256_castsi256_pd(_mm256_stream_load_si256((const __m256i*)(PTR))) +// load lower part +#define npyv_loadl_f32(PTR) _mm256_castps128_ps256(_mm_loadu_ps(PTR)) +#define npyv_loadl_f64(PTR) _mm256_castpd128_pd256(_mm_loadu_pd(PTR)) +// unaligned store +#define npyv_store_f32 _mm256_storeu_ps +#define npyv_store_f64 _mm256_storeu_pd +// aligned store +#define npyv_storea_f32 _mm256_store_ps +#define npyv_storea_f64 _mm256_store_pd +// stream store +#define npyv_stores_f32 _mm256_stream_ps +#define npyv_stores_f64 _mm256_stream_pd +// store lower part +#define npyv_storel_f32(PTR, VEC) _mm_storeu_ps(PTR, _mm256_castps256_ps128(VEC)) +#define npyv_storel_f64(PTR, VEC) _mm_storeu_pd(PTR, _mm256_castpd256_pd128(VEC)) +// store higher part +#define npyv_storeh_f32(PTR, VEC) _mm_storeu_ps(PTR, _mm256_extractf128_ps(VEC, 1)) +#define npyv_storeh_f64(PTR, VEC) _mm_storeu_pd(PTR, _mm256_extractf128_pd(VEC, 1)) +/*************************** + * Non-contiguous Load + ***************************/ +//// 32 +NPY_FINLINE npyv_u32 npyv_loadn_u32(const npy_uint32 *ptr, npy_intp stride) +{ + assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE32); + const __m256i steps = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); + const __m256i idx = _mm256_mullo_epi32(_mm256_set1_epi32((int)stride), steps); + return _mm256_i32gather_epi32((const int*)ptr, idx, 4); +} +NPY_FINLINE npyv_s32 npyv_loadn_s32(const npy_int32 *ptr, npy_intp stride) +{ return npyv_loadn_u32((const npy_uint32*)ptr, stride); } +NPY_FINLINE npyv_f32 npyv_loadn_f32(const float *ptr, npy_intp stride) +{ return _mm256_castsi256_ps(npyv_loadn_u32((const npy_uint32*)ptr, stride)); } +//// 64 +NPY_FINLINE npyv_f64 npyv_loadn_f64(const double *ptr, npy_intp stride) +{ + __m128d a0 = _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)ptr)); + __m128d a2 = _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*2))); + __m128d a01 = _mm_loadh_pd(a0, ptr + stride); + __m128d a23 = _mm_loadh_pd(a2, ptr + stride*3); + return _mm256_insertf128_pd(_mm256_castpd128_pd256(a01), a23, 1); +} +NPY_FINLINE npyv_u64 npyv_loadn_u64(const npy_uint64 *ptr, npy_intp stride) +{ return _mm256_castpd_si256(npyv_loadn_f64((const double*)ptr, stride)); } +NPY_FINLINE npyv_s64 npyv_loadn_s64(const npy_int64 *ptr, npy_intp stride) +{ return _mm256_castpd_si256(npyv_loadn_f64((const double*)ptr, stride)); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_f32 npyv_loadn2_f32(const float *ptr, npy_intp stride) +{ + __m128d a0 = _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)ptr)); + __m128d a2 = _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*2))); + __m128d a01 = _mm_loadh_pd(a0, (const double*)(ptr + stride)); + __m128d a23 = _mm_loadh_pd(a2, (const double*)(ptr + stride*3)); + return _mm256_castpd_ps(_mm256_insertf128_pd(_mm256_castpd128_pd256(a01), a23, 1)); +} +NPY_FINLINE npyv_u32 npyv_loadn2_u32(const npy_uint32 *ptr, npy_intp stride) +{ return _mm256_castps_si256(npyv_loadn2_f32((const float*)ptr, stride)); } +NPY_FINLINE npyv_s32 npyv_loadn2_s32(const npy_int32 *ptr, npy_intp stride) +{ return _mm256_castps_si256(npyv_loadn2_f32((const float*)ptr, stride)); } + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_f64 npyv_loadn2_f64(const double *ptr, npy_intp stride) +{ + __m256d a = npyv_loadl_f64(ptr); + return _mm256_insertf128_pd(a, _mm_loadu_pd(ptr + stride), 1); +} +NPY_FINLINE npyv_u64 npyv_loadn2_u64(const npy_uint64 *ptr, npy_intp stride) +{ return _mm256_castpd_si256(npyv_loadn2_f64((const double*)ptr, stride)); } +NPY_FINLINE npyv_s64 npyv_loadn2_s64(const npy_int64 *ptr, npy_intp stride) +{ return _mm256_castpd_si256(npyv_loadn2_f64((const double*)ptr, stride)); } + +/*************************** + * Non-contiguous Store + ***************************/ +//// 32 +NPY_FINLINE void npyv_storen_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ + __m128i a0 = _mm256_castsi256_si128(a); + __m128i a1 = _mm256_extracti128_si256(a, 1); + ptr[stride * 0] = _mm_cvtsi128_si32(a0); + ptr[stride * 1] = _mm_extract_epi32(a0, 1); + ptr[stride * 2] = _mm_extract_epi32(a0, 2); + ptr[stride * 3] = _mm_extract_epi32(a0, 3); + ptr[stride * 4] = _mm_cvtsi128_si32(a1); + ptr[stride * 5] = _mm_extract_epi32(a1, 1); + ptr[stride * 6] = _mm_extract_epi32(a1, 2); + ptr[stride * 7] = _mm_extract_epi32(a1, 3); +} +NPY_FINLINE void npyv_storen_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ npyv_storen_s32((npy_int32*)ptr, stride, a); } +NPY_FINLINE void npyv_storen_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen_s32((npy_int32*)ptr, stride, _mm256_castps_si256(a)); } +//// 64 +NPY_FINLINE void npyv_storen_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ + __m128d a0 = _mm256_castpd256_pd128(a); + __m128d a1 = _mm256_extractf128_pd(a, 1); + _mm_storel_pd(ptr + stride * 0, a0); + _mm_storeh_pd(ptr + stride * 1, a0); + _mm_storel_pd(ptr + stride * 2, a1); + _mm_storeh_pd(ptr + stride * 3, a1); +} +NPY_FINLINE void npyv_storen_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ npyv_storen_f64((double*)ptr, stride, _mm256_castsi256_pd(a)); } +NPY_FINLINE void npyv_storen_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ npyv_storen_f64((double*)ptr, stride, _mm256_castsi256_pd(a)); } + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ + __m128d a0 = _mm256_castpd256_pd128(_mm256_castsi256_pd(a)); + __m128d a1 = _mm256_extractf128_pd(_mm256_castsi256_pd(a), 1); + _mm_storel_pd((double*)ptr, a0); + _mm_storeh_pd((double*)(ptr + stride), a0); + _mm_storel_pd((double*)(ptr + stride*2), a1); + _mm_storeh_pd((double*)(ptr + stride*3), a1); +} +NPY_FINLINE void npyv_storen2_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, a); } +NPY_FINLINE void npyv_storen2_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, _mm256_castps_si256(a)); } + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ + npyv_storel_u64(ptr, a); + npyv_storeh_u64(ptr + stride, a); +} +NPY_FINLINE void npyv_storen2_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ npyv_storen2_u64((npy_uint64*)ptr, stride, a); } +NPY_FINLINE void npyv_storen2_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ npyv_storen2_u64((npy_uint64*)ptr, stride, _mm256_castpd_si256(a)); } + +/********************************* + * Partial Load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 npyv_load_till_s32(const npy_int32 *ptr, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + const __m256i vfill = _mm256_set1_epi32(fill); + const __m256i steps = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); + __m256i vnlane = _mm256_set1_epi32(nlane > 8 ? 8 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi32(vnlane, steps); + __m256i payload = _mm256_maskload_epi32((const int*)ptr, mask); + __m256i ret = _mm256_blendv_epi8(vfill, payload, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + const __m256i steps = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); + __m256i vnlane = _mm256_set1_epi32(nlane > 8 ? 8 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi32(vnlane, steps); + __m256i ret = _mm256_maskload_epi32((const int*)ptr, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +//// 64 +NPY_FINLINE npyv_s64 npyv_load_till_s64(const npy_int64 *ptr, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + const __m256i vfill = npyv_setall_s64(fill); + const __m256i steps = npyv_set_s64(0, 1, 2, 3); + __m256i vnlane = npyv_setall_s64(nlane > 4 ? 4 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi64(vnlane, steps); + __m256i payload = _mm256_maskload_epi64((const long long*)ptr, mask); + __m256i ret = _mm256_blendv_epi8(vfill, payload, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_load_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + const __m256i steps = npyv_set_s64(0, 1, 2, 3); + __m256i vnlane = npyv_setall_s64(nlane > 4 ? 4 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi64(vnlane, steps); + __m256i ret = _mm256_maskload_epi64((const long long*)ptr, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} + +//// 64-bit nlane +NPY_FINLINE npyv_s32 npyv_load2_till_s32(const npy_int32 *ptr, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + const __m256i vfill = npyv_set_s32( + fill_lo, fill_hi, fill_lo, fill_hi, + fill_lo, fill_hi, fill_lo, fill_hi + ); + const __m256i steps = npyv_set_s64(0, 1, 2, 3); + __m256i vnlane = npyv_setall_s64(nlane > 4 ? 4 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi64(vnlane, steps); + __m256i payload = _mm256_maskload_epi64((const long long*)ptr, mask); + __m256i ret = _mm256_blendv_epi8(vfill, payload, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load2_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ return npyv_load_tillz_s64((const npy_int64*)ptr, nlane); } + +/// 128-bit nlane +NPY_FINLINE npyv_u64 npyv_load2_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + npy_int64 m = -((npy_int64)(nlane > 1)); + __m256i mask = npyv_set_s64(-1, -1, m, m); + __m256i ret = _mm256_maskload_epi64((const long long*)ptr, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_u64 npyv_load2_till_s64(const npy_int64 *ptr, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ + const __m256i vfill = npyv_set_s64(0, 0, fill_lo, fill_hi); + npy_int64 m = -((npy_int64)(nlane > 1)); + __m256i mask = npyv_set_s64(-1, -1, m, m); + __m256i payload = _mm256_maskload_epi64((const long long*)ptr, mask); + __m256i ret =_mm256_blendv_epi8(vfill, payload, mask); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +/********************************* + * Non-contiguous partial load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 +npyv_loadn_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE32); + const __m256i vfill = _mm256_set1_epi32(fill); + const __m256i steps = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); + const __m256i idx = _mm256_mullo_epi32(_mm256_set1_epi32((int)stride), steps); + __m256i vnlane = _mm256_set1_epi32(nlane > 8 ? 8 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi32(vnlane, steps); + __m256i ret = _mm256_mask_i32gather_epi32(vfill, (const int*)ptr, idx, mask, 4); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 +npyv_loadn_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s32(ptr, stride, nlane, 0); } +//// 64 +NPY_FINLINE npyv_s64 +npyv_loadn_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + const __m256i vfill = npyv_setall_s64(fill); + const __m256i idx = npyv_set_s64(0, 1*stride, 2*stride, 3*stride); + const __m256i steps = npyv_set_s64(0, 1, 2, 3); + __m256i vnlane = npyv_setall_s64(nlane > 4 ? 4 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi64(vnlane, steps); + __m256i ret = _mm256_mask_i64gather_epi64(vfill, (const long long*)ptr, idx, mask, 8); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 +npyv_loadn_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s64(ptr, stride, nlane, 0); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + const __m256i vfill = npyv_set_s32( + fill_lo, fill_hi, fill_lo, fill_hi, + fill_lo, fill_hi, fill_lo, fill_hi + ); + const __m256i idx = npyv_set_s64(0, 1*stride, 2*stride, 3*stride); + const __m256i steps = npyv_set_s64(0, 1, 2, 3); + __m256i vnlane = npyv_setall_s64(nlane > 4 ? 4 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi64(vnlane, steps); + __m256i ret = _mm256_mask_i64gather_epi64(vfill, (const long long*)ptr, idx, mask, 4); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_loadn2_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn2_till_s32(ptr, stride, nlane, 0, 0); } + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ + assert(nlane > 0); + __m256i a = npyv_loadl_s64(ptr); +#if defined(_MSC_VER) && defined(_M_IX86) + __m128i fill =_mm_setr_epi32( + (int)fill_lo, (int)(fill_lo >> 32), + (int)fill_hi, (int)(fill_hi >> 32) + ); +#else + __m128i fill = _mm_set_epi64x(fill_hi, fill_lo); +#endif + __m128i b = nlane > 1 ? _mm_loadu_si128((const __m128i*)(ptr + stride)) : fill; + __m256i ret = _mm256_inserti128_si256(a, b, 1); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m256i workaround = ret; + ret = _mm256_or_si256(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_loadn2_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn2_till_s64(ptr, stride, nlane, 0, 0); } + +/********************************* + * Partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_store_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + const __m256i steps = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); + __m256i vnlane = _mm256_set1_epi32(nlane > 8 ? 8 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi32(vnlane, steps); + _mm256_maskstore_epi32((int*)ptr, mask, a); +} +//// 64 +NPY_FINLINE void npyv_store_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + const __m256i steps = npyv_set_s64(0, 1, 2, 3); + __m256i vnlane = npyv_setall_s64(nlane > 8 ? 8 : (int)nlane); + __m256i mask = _mm256_cmpgt_epi64(vnlane, steps); + _mm256_maskstore_epi64((long long*)ptr, mask, a); +} + +//// 64-bit nlane +NPY_FINLINE void npyv_store2_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ npyv_store_till_s64((npy_int64*)ptr, nlane, a); } + +//// 128-bit nlane +NPY_FINLINE void npyv_store2_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); +#ifdef _MSC_VER + /* + * Although this version is compatible with all other compilers, + * there is no performance benefit in retaining the other branch. + * However, it serves as evidence of a newly emerging bug in MSVC + * that started to appear since v19.30. + * For some reason, the MSVC optimizer chooses to ignore the lower store (128-bit mov) + * and replace with full mov counting on ymmword pointer. + * + * For more details, please refer to the discussion on https://github.com/numpy/numpy/issues/23896. + */ + if (nlane > 1) { + npyv_store_s64(ptr, a); + } + else { + npyv_storel_s64(ptr, a); + } +#else + npyv_storel_s64(ptr, a); + if (nlane > 1) { + npyv_storeh_s64(ptr + 2, a); + } +#endif +} +/********************************* + * Non-contiguous partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_storen_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + __m128i a0 = _mm256_castsi256_si128(a); + __m128i a1 = _mm256_extracti128_si256(a, 1); + + ptr[stride*0] = _mm_extract_epi32(a0, 0); + switch(nlane) { + case 1: + return; + case 2: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + return; + case 3: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + ptr[stride*2] = _mm_extract_epi32(a0, 2); + return; + case 4: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + ptr[stride*2] = _mm_extract_epi32(a0, 2); + ptr[stride*3] = _mm_extract_epi32(a0, 3); + return; + case 5: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + ptr[stride*2] = _mm_extract_epi32(a0, 2); + ptr[stride*3] = _mm_extract_epi32(a0, 3); + ptr[stride*4] = _mm_extract_epi32(a1, 0); + return; + case 6: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + ptr[stride*2] = _mm_extract_epi32(a0, 2); + ptr[stride*3] = _mm_extract_epi32(a0, 3); + ptr[stride*4] = _mm_extract_epi32(a1, 0); + ptr[stride*5] = _mm_extract_epi32(a1, 1); + return; + case 7: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + ptr[stride*2] = _mm_extract_epi32(a0, 2); + ptr[stride*3] = _mm_extract_epi32(a0, 3); + ptr[stride*4] = _mm_extract_epi32(a1, 0); + ptr[stride*5] = _mm_extract_epi32(a1, 1); + ptr[stride*6] = _mm_extract_epi32(a1, 2); + return; + default: + ptr[stride*1] = _mm_extract_epi32(a0, 1); + ptr[stride*2] = _mm_extract_epi32(a0, 2); + ptr[stride*3] = _mm_extract_epi32(a0, 3); + ptr[stride*4] = _mm_extract_epi32(a1, 0); + ptr[stride*5] = _mm_extract_epi32(a1, 1); + ptr[stride*6] = _mm_extract_epi32(a1, 2); + ptr[stride*7] = _mm_extract_epi32(a1, 3); + } +} +//// 64 +NPY_FINLINE void npyv_storen_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + __m128d a0 = _mm256_castpd256_pd128(_mm256_castsi256_pd(a)); + __m128d a1 = _mm256_extractf128_pd(_mm256_castsi256_pd(a), 1); + + double *dptr = (double*)ptr; + _mm_storel_pd(dptr, a0); + switch(nlane) { + case 1: + return; + case 2: + _mm_storeh_pd(dptr + stride * 1, a0); + return; + case 3: + _mm_storeh_pd(dptr + stride * 1, a0); + _mm_storel_pd(dptr + stride * 2, a1); + return; + default: + _mm_storeh_pd(dptr + stride * 1, a0); + _mm_storel_pd(dptr + stride * 2, a1); + _mm_storeh_pd(dptr + stride * 3, a1); + } +} + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + __m128d a0 = _mm256_castpd256_pd128(_mm256_castsi256_pd(a)); + __m128d a1 = _mm256_extractf128_pd(_mm256_castsi256_pd(a), 1); + + _mm_storel_pd((double*)ptr, a0); + switch(nlane) { + case 1: + return; + case 2: + _mm_storeh_pd((double*)(ptr + stride * 1), a0); + return; + case 3: + _mm_storeh_pd((double*)(ptr + stride * 1), a0); + _mm_storel_pd((double*)(ptr + stride * 2), a1); + return; + default: + _mm_storeh_pd((double*)(ptr + stride * 1), a0); + _mm_storel_pd((double*)(ptr + stride * 2), a1); + _mm_storeh_pd((double*)(ptr + stride * 3), a1); + } +} + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + npyv_storel_s64(ptr, a); + if (nlane > 1) { + npyv_storeh_s64(ptr + stride, a); + } +} +/***************************************************************************** + * Implement partial load/store for u32/f32/u64/f64... via reinterpret cast + *****************************************************************************/ +#define NPYV_IMPL_AVX2_REST_PARTIAL_TYPES(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES(u32, s32) +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES(f32, s32) +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES(u64, s64) +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES(f64, s64) + +// 128-bit/64-bit stride (load/store pair) +#define NPYV_IMPL_AVX2_REST_PARTIAL_TYPES_PAIR(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun_lo.to_##T_SFX, pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun_lo.to_##T_SFX, \ + pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES_PAIR(u32, s32) +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES_PAIR(f32, s32) +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES_PAIR(u64, s64) +NPYV_IMPL_AVX2_REST_PARTIAL_TYPES_PAIR(f64, s64) + +/************************************************************ + * de-interlave load / interleave contiguous store + ************************************************************/ +// two channels +#define NPYV_IMPL_AVX2_MEM_INTERLEAVE(SFX, ZSFX) \ + NPY_FINLINE npyv_##ZSFX##x2 npyv_zip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX); \ + NPY_FINLINE npyv_##ZSFX##x2 npyv_unzip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX); \ + NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2( \ + const npyv_lanetype_##SFX *ptr \ + ) { \ + return npyv_unzip_##ZSFX( \ + npyv_load_##SFX(ptr), npyv_load_##SFX(ptr+npyv_nlanes_##SFX) \ + ); \ + } \ + NPY_FINLINE void npyv_store_##SFX##x2( \ + npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v \ + ) { \ + npyv_##SFX##x2 zip = npyv_zip_##ZSFX(v.val[0], v.val[1]); \ + npyv_store_##SFX(ptr, zip.val[0]); \ + npyv_store_##SFX(ptr + npyv_nlanes_##SFX, zip.val[1]); \ + } + +NPYV_IMPL_AVX2_MEM_INTERLEAVE(u8, u8) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(s8, u8) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(u16, u16) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(s16, u16) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(u32, u32) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(s32, u32) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(u64, u64) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(s64, u64) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(f32, f32) +NPYV_IMPL_AVX2_MEM_INTERLEAVE(f64, f64) + +/********************************* + * Lookup tables + *********************************/ +// uses vector as indexes into a table +// that contains 32 elements of float32. +NPY_FINLINE npyv_f32 npyv_lut32_f32(const float *table, npyv_u32 idx) +{ return _mm256_i32gather_ps(table, idx, 4); } +NPY_FINLINE npyv_u32 npyv_lut32_u32(const npy_uint32 *table, npyv_u32 idx) +{ return npyv_reinterpret_u32_f32(npyv_lut32_f32((const float*)table, idx)); } +NPY_FINLINE npyv_s32 npyv_lut32_s32(const npy_int32 *table, npyv_u32 idx) +{ return npyv_reinterpret_s32_f32(npyv_lut32_f32((const float*)table, idx)); } + +// uses vector as indexes into a table +// that contains 16 elements of float64. +NPY_FINLINE npyv_f64 npyv_lut16_f64(const double *table, npyv_u64 idx) +{ return _mm256_i64gather_pd(table, idx, 8); } +NPY_FINLINE npyv_u64 npyv_lut16_u64(const npy_uint64 *table, npyv_u64 idx) +{ return npyv_reinterpret_u64_f64(npyv_lut16_f64((const double*)table, idx)); } +NPY_FINLINE npyv_s64 npyv_lut16_s64(const npy_int64 *table, npyv_u64 idx) +{ return npyv_reinterpret_s64_f64(npyv_lut16_f64((const double*)table, idx)); } + +#endif // _NPY_SIMD_AVX2_MEMORY_H diff --git a/mkl_umath/src/npyv/avx2/misc.h b/mkl_umath/src/npyv/avx2/misc.h new file mode 100644 index 00000000..41e788c7 --- /dev/null +++ b/mkl_umath/src/npyv/avx2/misc.h @@ -0,0 +1,258 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_MISC_H +#define _NPY_SIMD_AVX2_MISC_H + +// vector with zero lanes +#define npyv_zero_u8 _mm256_setzero_si256 +#define npyv_zero_s8 _mm256_setzero_si256 +#define npyv_zero_u16 _mm256_setzero_si256 +#define npyv_zero_s16 _mm256_setzero_si256 +#define npyv_zero_u32 _mm256_setzero_si256 +#define npyv_zero_s32 _mm256_setzero_si256 +#define npyv_zero_u64 _mm256_setzero_si256 +#define npyv_zero_s64 _mm256_setzero_si256 +#define npyv_zero_f32 _mm256_setzero_ps +#define npyv_zero_f64 _mm256_setzero_pd + +// vector with a specific value set to all lanes +#define npyv_setall_u8(VAL) _mm256_set1_epi8((char)VAL) +#define npyv_setall_s8(VAL) _mm256_set1_epi8((char)VAL) +#define npyv_setall_u16(VAL) _mm256_set1_epi16((short)VAL) +#define npyv_setall_s16(VAL) _mm256_set1_epi16((short)VAL) +#define npyv_setall_u32(VAL) _mm256_set1_epi32((int)VAL) +#define npyv_setall_s32(VAL) _mm256_set1_epi32(VAL) +#define npyv_setall_f32(VAL) _mm256_set1_ps(VAL) +#define npyv_setall_f64(VAL) _mm256_set1_pd(VAL) + +NPY_FINLINE __m256i npyv__setr_epi64(npy_int64, npy_int64, npy_int64, npy_int64); +NPY_FINLINE npyv_u64 npyv_setall_u64(npy_uint64 a) +{ + npy_int64 ai = (npy_int64)a; +#if defined(_MSC_VER) && defined(_M_IX86) + return npyv__setr_epi64(ai, ai, ai, ai); +#else + return _mm256_set1_epi64x(ai); +#endif +} +NPY_FINLINE npyv_s64 npyv_setall_s64(npy_int64 a) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return npyv__setr_epi64(a, a, a, a); +#else + return _mm256_set1_epi64x(a); +#endif +} +/* + * vector with specific values set to each lane and + * set a specific value to all remained lanes + * + * Args that generated by NPYV__SET_FILL_* not going to expand if + * _mm256_setr_* are defined as macros. +*/ +NPY_FINLINE __m256i npyv__setr_epi8( + char i0, char i1, char i2, char i3, char i4, char i5, char i6, char i7, + char i8, char i9, char i10, char i11, char i12, char i13, char i14, char i15, + char i16, char i17, char i18, char i19, char i20, char i21, char i22, char i23, + char i24, char i25, char i26, char i27, char i28, char i29, char i30, char i31) +{ + return _mm256_setr_epi8( + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, + i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31 + ); +} +NPY_FINLINE __m256i npyv__setr_epi16( + short i0, short i1, short i2, short i3, short i4, short i5, short i6, short i7, + short i8, short i9, short i10, short i11, short i12, short i13, short i14, short i15) +{ + return _mm256_setr_epi16(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15); +} +NPY_FINLINE __m256i npyv__setr_epi32(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7) +{ + return _mm256_setr_epi32(i0, i1, i2, i3, i4, i5, i6, i7); +} +NPY_FINLINE __m256i npyv__setr_epi64(npy_int64 i0, npy_int64 i1, npy_int64 i2, npy_int64 i3) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return _mm256_setr_epi32( + (int)i0, (int)(i0 >> 32), (int)i1, (int)(i1 >> 32), + (int)i2, (int)(i2 >> 32), (int)i3, (int)(i3 >> 32) + ); +#else + return _mm256_setr_epi64x(i0, i1, i2, i3); +#endif +} + +NPY_FINLINE __m256 npyv__setr_ps(float i0, float i1, float i2, float i3, float i4, float i5, + float i6, float i7) +{ + return _mm256_setr_ps(i0, i1, i2, i3, i4, i5, i6, i7); +} +NPY_FINLINE __m256d npyv__setr_pd(double i0, double i1, double i2, double i3) +{ + return _mm256_setr_pd(i0, i1, i2, i3); +} +#define npyv_setf_u8(FILL, ...) npyv__setr_epi8(NPYV__SET_FILL_32(char, FILL, __VA_ARGS__)) +#define npyv_setf_s8(FILL, ...) npyv__setr_epi8(NPYV__SET_FILL_32(char, FILL, __VA_ARGS__)) +#define npyv_setf_u16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_16(short, FILL, __VA_ARGS__)) +#define npyv_setf_s16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_16(short, FILL, __VA_ARGS__)) +#define npyv_setf_u32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_8(int, FILL, __VA_ARGS__)) +#define npyv_setf_s32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_8(int, FILL, __VA_ARGS__)) +#define npyv_setf_u64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_4(npy_uint64, FILL, __VA_ARGS__)) +#define npyv_setf_s64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_4(npy_int64, FILL, __VA_ARGS__)) +#define npyv_setf_f32(FILL, ...) npyv__setr_ps(NPYV__SET_FILL_8(float, FILL, __VA_ARGS__)) +#define npyv_setf_f64(FILL, ...) npyv__setr_pd(NPYV__SET_FILL_4(double, FILL, __VA_ARGS__)) + +// vector with specific values set to each lane and +// set zero to all remained lanes +#define npyv_set_u8(...) npyv_setf_u8(0, __VA_ARGS__) +#define npyv_set_s8(...) npyv_setf_s8(0, __VA_ARGS__) +#define npyv_set_u16(...) npyv_setf_u16(0, __VA_ARGS__) +#define npyv_set_s16(...) npyv_setf_s16(0, __VA_ARGS__) +#define npyv_set_u32(...) npyv_setf_u32(0, __VA_ARGS__) +#define npyv_set_s32(...) npyv_setf_s32(0, __VA_ARGS__) +#define npyv_set_u64(...) npyv_setf_u64(0, __VA_ARGS__) +#define npyv_set_s64(...) npyv_setf_s64(0, __VA_ARGS__) +#define npyv_set_f32(...) npyv_setf_f32(0, __VA_ARGS__) +#define npyv_set_f64(...) npyv_setf_f64(0, __VA_ARGS__) + +// Per lane select +#define npyv_select_u8(MASK, A, B) _mm256_blendv_epi8(B, A, MASK) +#define npyv_select_s8 npyv_select_u8 +#define npyv_select_u16 npyv_select_u8 +#define npyv_select_s16 npyv_select_u8 +#define npyv_select_u32 npyv_select_u8 +#define npyv_select_s32 npyv_select_u8 +#define npyv_select_u64 npyv_select_u8 +#define npyv_select_s64 npyv_select_u8 +#define npyv_select_f32(MASK, A, B) _mm256_blendv_ps(B, A, _mm256_castsi256_ps(MASK)) +#define npyv_select_f64(MASK, A, B) _mm256_blendv_pd(B, A, _mm256_castsi256_pd(MASK)) + +// extract the first vector's lane +#define npyv_extract0_u8(A) ((npy_uint8)_mm_cvtsi128_si32(_mm256_castsi256_si128(A))) +#define npyv_extract0_s8(A) ((npy_int8)_mm_cvtsi128_si32(_mm256_castsi256_si128(A))) +#define npyv_extract0_u16(A) ((npy_uint16)_mm_cvtsi128_si32(_mm256_castsi256_si128(A))) +#define npyv_extract0_s16(A) ((npy_int16)_mm_cvtsi128_si32(_mm256_castsi256_si128(A))) +#define npyv_extract0_u32(A) ((npy_uint32)_mm_cvtsi128_si32(_mm256_castsi256_si128(A))) +#define npyv_extract0_s32(A) ((npy_int32)_mm_cvtsi128_si32(_mm256_castsi256_si128(A))) +#define npyv_extract0_u64(A) ((npy_uint64)npyv128_cvtsi128_si64(_mm256_castsi256_si128(A))) +#define npyv_extract0_s64(A) ((npy_int64)npyv128_cvtsi128_si64(_mm256_castsi256_si128(A))) +#define npyv_extract0_f32(A) _mm_cvtss_f32(_mm256_castps256_ps128(A)) +#define npyv_extract0_f64(A) _mm_cvtsd_f64(_mm256_castpd256_pd128(A)) + +// Reinterpret +#define npyv_reinterpret_u8_u8(X) X +#define npyv_reinterpret_u8_s8(X) X +#define npyv_reinterpret_u8_u16(X) X +#define npyv_reinterpret_u8_s16(X) X +#define npyv_reinterpret_u8_u32(X) X +#define npyv_reinterpret_u8_s32(X) X +#define npyv_reinterpret_u8_u64(X) X +#define npyv_reinterpret_u8_s64(X) X +#define npyv_reinterpret_u8_f32 _mm256_castps_si256 +#define npyv_reinterpret_u8_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_s8_s8(X) X +#define npyv_reinterpret_s8_u8(X) X +#define npyv_reinterpret_s8_u16(X) X +#define npyv_reinterpret_s8_s16(X) X +#define npyv_reinterpret_s8_u32(X) X +#define npyv_reinterpret_s8_s32(X) X +#define npyv_reinterpret_s8_u64(X) X +#define npyv_reinterpret_s8_s64(X) X +#define npyv_reinterpret_s8_f32 _mm256_castps_si256 +#define npyv_reinterpret_s8_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_u16_u16(X) X +#define npyv_reinterpret_u16_u8(X) X +#define npyv_reinterpret_u16_s8(X) X +#define npyv_reinterpret_u16_s16(X) X +#define npyv_reinterpret_u16_u32(X) X +#define npyv_reinterpret_u16_s32(X) X +#define npyv_reinterpret_u16_u64(X) X +#define npyv_reinterpret_u16_s64(X) X +#define npyv_reinterpret_u16_f32 _mm256_castps_si256 +#define npyv_reinterpret_u16_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_s16_s16(X) X +#define npyv_reinterpret_s16_u8(X) X +#define npyv_reinterpret_s16_s8(X) X +#define npyv_reinterpret_s16_u16(X) X +#define npyv_reinterpret_s16_u32(X) X +#define npyv_reinterpret_s16_s32(X) X +#define npyv_reinterpret_s16_u64(X) X +#define npyv_reinterpret_s16_s64(X) X +#define npyv_reinterpret_s16_f32 _mm256_castps_si256 +#define npyv_reinterpret_s16_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_u32_u32(X) X +#define npyv_reinterpret_u32_u8(X) X +#define npyv_reinterpret_u32_s8(X) X +#define npyv_reinterpret_u32_u16(X) X +#define npyv_reinterpret_u32_s16(X) X +#define npyv_reinterpret_u32_s32(X) X +#define npyv_reinterpret_u32_u64(X) X +#define npyv_reinterpret_u32_s64(X) X +#define npyv_reinterpret_u32_f32 _mm256_castps_si256 +#define npyv_reinterpret_u32_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_s32_s32(X) X +#define npyv_reinterpret_s32_u8(X) X +#define npyv_reinterpret_s32_s8(X) X +#define npyv_reinterpret_s32_u16(X) X +#define npyv_reinterpret_s32_s16(X) X +#define npyv_reinterpret_s32_u32(X) X +#define npyv_reinterpret_s32_u64(X) X +#define npyv_reinterpret_s32_s64(X) X +#define npyv_reinterpret_s32_f32 _mm256_castps_si256 +#define npyv_reinterpret_s32_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_u64_u64(X) X +#define npyv_reinterpret_u64_u8(X) X +#define npyv_reinterpret_u64_s8(X) X +#define npyv_reinterpret_u64_u16(X) X +#define npyv_reinterpret_u64_s16(X) X +#define npyv_reinterpret_u64_u32(X) X +#define npyv_reinterpret_u64_s32(X) X +#define npyv_reinterpret_u64_s64(X) X +#define npyv_reinterpret_u64_f32 _mm256_castps_si256 +#define npyv_reinterpret_u64_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_s64_s64(X) X +#define npyv_reinterpret_s64_u8(X) X +#define npyv_reinterpret_s64_s8(X) X +#define npyv_reinterpret_s64_u16(X) X +#define npyv_reinterpret_s64_s16(X) X +#define npyv_reinterpret_s64_u32(X) X +#define npyv_reinterpret_s64_s32(X) X +#define npyv_reinterpret_s64_u64(X) X +#define npyv_reinterpret_s64_f32 _mm256_castps_si256 +#define npyv_reinterpret_s64_f64 _mm256_castpd_si256 + +#define npyv_reinterpret_f32_f32(X) X +#define npyv_reinterpret_f32_u8 _mm256_castsi256_ps +#define npyv_reinterpret_f32_s8 _mm256_castsi256_ps +#define npyv_reinterpret_f32_u16 _mm256_castsi256_ps +#define npyv_reinterpret_f32_s16 _mm256_castsi256_ps +#define npyv_reinterpret_f32_u32 _mm256_castsi256_ps +#define npyv_reinterpret_f32_s32 _mm256_castsi256_ps +#define npyv_reinterpret_f32_u64 _mm256_castsi256_ps +#define npyv_reinterpret_f32_s64 _mm256_castsi256_ps +#define npyv_reinterpret_f32_f64 _mm256_castpd_ps + +#define npyv_reinterpret_f64_f64(X) X +#define npyv_reinterpret_f64_u8 _mm256_castsi256_pd +#define npyv_reinterpret_f64_s8 _mm256_castsi256_pd +#define npyv_reinterpret_f64_u16 _mm256_castsi256_pd +#define npyv_reinterpret_f64_s16 _mm256_castsi256_pd +#define npyv_reinterpret_f64_u32 _mm256_castsi256_pd +#define npyv_reinterpret_f64_s32 _mm256_castsi256_pd +#define npyv_reinterpret_f64_u64 _mm256_castsi256_pd +#define npyv_reinterpret_f64_s64 _mm256_castsi256_pd +#define npyv_reinterpret_f64_f32 _mm256_castps_pd + +#define npyv_cleanup _mm256_zeroall + +#endif // _NPY_SIMD_SSE_MISC_H diff --git a/mkl_umath/src/npyv/avx2/operators.h b/mkl_umath/src/npyv/avx2/operators.h new file mode 100644 index 00000000..7b9b6a34 --- /dev/null +++ b/mkl_umath/src/npyv/avx2/operators.h @@ -0,0 +1,282 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_OPERATORS_H +#define _NPY_SIMD_AVX2_OPERATORS_H + +/*************************** + * Shifting + ***************************/ + +// left +#define npyv_shl_u16(A, C) _mm256_sll_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s16(A, C) _mm256_sll_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_u32(A, C) _mm256_sll_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s32(A, C) _mm256_sll_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_u64(A, C) _mm256_sll_epi64(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s64(A, C) _mm256_sll_epi64(A, _mm_cvtsi32_si128(C)) + +// left by an immediate constant +#define npyv_shli_u16 _mm256_slli_epi16 +#define npyv_shli_s16 _mm256_slli_epi16 +#define npyv_shli_u32 _mm256_slli_epi32 +#define npyv_shli_s32 _mm256_slli_epi32 +#define npyv_shli_u64 _mm256_slli_epi64 +#define npyv_shli_s64 _mm256_slli_epi64 + +// right +#define npyv_shr_u16(A, C) _mm256_srl_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_s16(A, C) _mm256_sra_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_u32(A, C) _mm256_srl_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_s32(A, C) _mm256_sra_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_u64(A, C) _mm256_srl_epi64(A, _mm_cvtsi32_si128(C)) +NPY_FINLINE __m256i npyv_shr_s64(__m256i a, int c) +{ + const __m256i sbit = _mm256_set1_epi64x(0x8000000000000000); + const __m128i c64 = _mm_cvtsi32_si128(c); + __m256i r = _mm256_srl_epi64(_mm256_add_epi64(a, sbit), c64); + return _mm256_sub_epi64(r, _mm256_srl_epi64(sbit, c64)); +} + +// right by an immediate constant +#define npyv_shri_u16 _mm256_srli_epi16 +#define npyv_shri_s16 _mm256_srai_epi16 +#define npyv_shri_u32 _mm256_srli_epi32 +#define npyv_shri_s32 _mm256_srai_epi32 +#define npyv_shri_u64 _mm256_srli_epi64 +#define npyv_shri_s64 npyv_shr_s64 + +/*************************** + * Logical + ***************************/ +// AND +#define npyv_and_u8 _mm256_and_si256 +#define npyv_and_s8 _mm256_and_si256 +#define npyv_and_u16 _mm256_and_si256 +#define npyv_and_s16 _mm256_and_si256 +#define npyv_and_u32 _mm256_and_si256 +#define npyv_and_s32 _mm256_and_si256 +#define npyv_and_u64 _mm256_and_si256 +#define npyv_and_s64 _mm256_and_si256 +#define npyv_and_f32 _mm256_and_ps +#define npyv_and_f64 _mm256_and_pd +#define npyv_and_b8 _mm256_and_si256 +#define npyv_and_b16 _mm256_and_si256 +#define npyv_and_b32 _mm256_and_si256 +#define npyv_and_b64 _mm256_and_si256 + +// OR +#define npyv_or_u8 _mm256_or_si256 +#define npyv_or_s8 _mm256_or_si256 +#define npyv_or_u16 _mm256_or_si256 +#define npyv_or_s16 _mm256_or_si256 +#define npyv_or_u32 _mm256_or_si256 +#define npyv_or_s32 _mm256_or_si256 +#define npyv_or_u64 _mm256_or_si256 +#define npyv_or_s64 _mm256_or_si256 +#define npyv_or_f32 _mm256_or_ps +#define npyv_or_f64 _mm256_or_pd +#define npyv_or_b8 _mm256_or_si256 +#define npyv_or_b16 _mm256_or_si256 +#define npyv_or_b32 _mm256_or_si256 +#define npyv_or_b64 _mm256_or_si256 + +// XOR +#define npyv_xor_u8 _mm256_xor_si256 +#define npyv_xor_s8 _mm256_xor_si256 +#define npyv_xor_u16 _mm256_xor_si256 +#define npyv_xor_s16 _mm256_xor_si256 +#define npyv_xor_u32 _mm256_xor_si256 +#define npyv_xor_s32 _mm256_xor_si256 +#define npyv_xor_u64 _mm256_xor_si256 +#define npyv_xor_s64 _mm256_xor_si256 +#define npyv_xor_f32 _mm256_xor_ps +#define npyv_xor_f64 _mm256_xor_pd +#define npyv_xor_b8 _mm256_xor_si256 +#define npyv_xor_b16 _mm256_xor_si256 +#define npyv_xor_b32 _mm256_xor_si256 +#define npyv_xor_b64 _mm256_xor_si256 + +// NOT +#define npyv_not_u8(A) _mm256_xor_si256(A, _mm256_set1_epi32(-1)) +#define npyv_not_s8 npyv_not_u8 +#define npyv_not_u16 npyv_not_u8 +#define npyv_not_s16 npyv_not_u8 +#define npyv_not_u32 npyv_not_u8 +#define npyv_not_s32 npyv_not_u8 +#define npyv_not_u64 npyv_not_u8 +#define npyv_not_s64 npyv_not_u8 +#define npyv_not_f32(A) _mm256_xor_ps(A, _mm256_castsi256_ps(_mm256_set1_epi32(-1))) +#define npyv_not_f64(A) _mm256_xor_pd(A, _mm256_castsi256_pd(_mm256_set1_epi32(-1))) +#define npyv_not_b8 npyv_not_u8 +#define npyv_not_b16 npyv_not_u8 +#define npyv_not_b32 npyv_not_u8 +#define npyv_not_b64 npyv_not_u8 + +// ANDC, ORC and XNOR +#define npyv_andc_u8(A, B) _mm256_andnot_si256(B, A) +#define npyv_andc_b8(A, B) _mm256_andnot_si256(B, A) +#define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A) +#define npyv_xnor_b8 _mm256_cmpeq_epi8 + +/*************************** + * Comparison + ***************************/ + +// int Equal +#define npyv_cmpeq_u8 _mm256_cmpeq_epi8 +#define npyv_cmpeq_s8 _mm256_cmpeq_epi8 +#define npyv_cmpeq_u16 _mm256_cmpeq_epi16 +#define npyv_cmpeq_s16 _mm256_cmpeq_epi16 +#define npyv_cmpeq_u32 _mm256_cmpeq_epi32 +#define npyv_cmpeq_s32 _mm256_cmpeq_epi32 +#define npyv_cmpeq_u64 _mm256_cmpeq_epi64 +#define npyv_cmpeq_s64 _mm256_cmpeq_epi64 + +// int Not Equal +#define npyv_cmpneq_u8(A, B) npyv_not_u8(_mm256_cmpeq_epi8(A, B)) +#define npyv_cmpneq_s8 npyv_cmpneq_u8 +#define npyv_cmpneq_u16(A, B) npyv_not_u16(_mm256_cmpeq_epi16(A, B)) +#define npyv_cmpneq_s16 npyv_cmpneq_u16 +#define npyv_cmpneq_u32(A, B) npyv_not_u32(_mm256_cmpeq_epi32(A, B)) +#define npyv_cmpneq_s32 npyv_cmpneq_u32 +#define npyv_cmpneq_u64(A, B) npyv_not_u64(_mm256_cmpeq_epi64(A, B)) +#define npyv_cmpneq_s64 npyv_cmpneq_u64 + +// signed greater than +#define npyv_cmpgt_s8 _mm256_cmpgt_epi8 +#define npyv_cmpgt_s16 _mm256_cmpgt_epi16 +#define npyv_cmpgt_s32 _mm256_cmpgt_epi32 +#define npyv_cmpgt_s64 _mm256_cmpgt_epi64 + +// signed greater than or equal +#define npyv_cmpge_s8(A, B) npyv_not_s8(_mm256_cmpgt_epi8(B, A)) +#define npyv_cmpge_s16(A, B) npyv_not_s16(_mm256_cmpgt_epi16(B, A)) +#define npyv_cmpge_s32(A, B) npyv_not_s32(_mm256_cmpgt_epi32(B, A)) +#define npyv_cmpge_s64(A, B) npyv_not_s64(_mm256_cmpgt_epi64(B, A)) + +// unsigned greater than +#define NPYV_IMPL_AVX2_UNSIGNED_GT(LEN, SIGN) \ + NPY_FINLINE __m256i npyv_cmpgt_u##LEN(__m256i a, __m256i b) \ + { \ + const __m256i sbit = _mm256_set1_epi32(SIGN); \ + return _mm256_cmpgt_epi##LEN( \ + _mm256_xor_si256(a, sbit), _mm256_xor_si256(b, sbit) \ + ); \ + } + +NPYV_IMPL_AVX2_UNSIGNED_GT(8, 0x80808080) +NPYV_IMPL_AVX2_UNSIGNED_GT(16, 0x80008000) +NPYV_IMPL_AVX2_UNSIGNED_GT(32, 0x80000000) + +NPY_FINLINE __m256i npyv_cmpgt_u64(__m256i a, __m256i b) +{ + const __m256i sbit = _mm256_set1_epi64x(0x8000000000000000); + return _mm256_cmpgt_epi64(_mm256_xor_si256(a, sbit), _mm256_xor_si256(b, sbit)); +} + +// unsigned greater than or equal +NPY_FINLINE __m256i npyv_cmpge_u8(__m256i a, __m256i b) +{ return _mm256_cmpeq_epi8(a, _mm256_max_epu8(a, b)); } +NPY_FINLINE __m256i npyv_cmpge_u16(__m256i a, __m256i b) +{ return _mm256_cmpeq_epi16(a, _mm256_max_epu16(a, b)); } +NPY_FINLINE __m256i npyv_cmpge_u32(__m256i a, __m256i b) +{ return _mm256_cmpeq_epi32(a, _mm256_max_epu32(a, b)); } +#define npyv_cmpge_u64(A, B) npyv_not_u64(npyv_cmpgt_u64(B, A)) + +// less than +#define npyv_cmplt_u8(A, B) npyv_cmpgt_u8(B, A) +#define npyv_cmplt_s8(A, B) npyv_cmpgt_s8(B, A) +#define npyv_cmplt_u16(A, B) npyv_cmpgt_u16(B, A) +#define npyv_cmplt_s16(A, B) npyv_cmpgt_s16(B, A) +#define npyv_cmplt_u32(A, B) npyv_cmpgt_u32(B, A) +#define npyv_cmplt_s32(A, B) npyv_cmpgt_s32(B, A) +#define npyv_cmplt_u64(A, B) npyv_cmpgt_u64(B, A) +#define npyv_cmplt_s64(A, B) npyv_cmpgt_s64(B, A) + +// less than or equal +#define npyv_cmple_u8(A, B) npyv_cmpge_u8(B, A) +#define npyv_cmple_s8(A, B) npyv_cmpge_s8(B, A) +#define npyv_cmple_u16(A, B) npyv_cmpge_u16(B, A) +#define npyv_cmple_s16(A, B) npyv_cmpge_s16(B, A) +#define npyv_cmple_u32(A, B) npyv_cmpge_u32(B, A) +#define npyv_cmple_s32(A, B) npyv_cmpge_s32(B, A) +#define npyv_cmple_u64(A, B) npyv_cmpge_u64(B, A) +#define npyv_cmple_s64(A, B) npyv_cmpge_s64(B, A) + +// precision comparison (ordered) +#define npyv_cmpeq_f32(A, B) _mm256_castps_si256(_mm256_cmp_ps(A, B, _CMP_EQ_OQ)) +#define npyv_cmpeq_f64(A, B) _mm256_castpd_si256(_mm256_cmp_pd(A, B, _CMP_EQ_OQ)) +#define npyv_cmpneq_f32(A, B) _mm256_castps_si256(_mm256_cmp_ps(A, B, _CMP_NEQ_UQ)) +#define npyv_cmpneq_f64(A, B) _mm256_castpd_si256(_mm256_cmp_pd(A, B, _CMP_NEQ_UQ)) +#define npyv_cmplt_f32(A, B) _mm256_castps_si256(_mm256_cmp_ps(A, B, _CMP_LT_OQ)) +#define npyv_cmplt_f64(A, B) _mm256_castpd_si256(_mm256_cmp_pd(A, B, _CMP_LT_OQ)) +#define npyv_cmple_f32(A, B) _mm256_castps_si256(_mm256_cmp_ps(A, B, _CMP_LE_OQ)) +#define npyv_cmple_f64(A, B) _mm256_castpd_si256(_mm256_cmp_pd(A, B, _CMP_LE_OQ)) +#define npyv_cmpgt_f32(A, B) _mm256_castps_si256(_mm256_cmp_ps(A, B, _CMP_GT_OQ)) +#define npyv_cmpgt_f64(A, B) _mm256_castpd_si256(_mm256_cmp_pd(A, B, _CMP_GT_OQ)) +#define npyv_cmpge_f32(A, B) _mm256_castps_si256(_mm256_cmp_ps(A, B, _CMP_GE_OQ)) +#define npyv_cmpge_f64(A, B) _mm256_castpd_si256(_mm256_cmp_pd(A, B, _CMP_GE_OQ)) + +// check special cases +NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a) +{ return _mm256_castps_si256(_mm256_cmp_ps(a, a, _CMP_ORD_Q)); } +NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a) +{ return _mm256_castpd_si256(_mm256_cmp_pd(a, a, _CMP_ORD_Q)); } + +// Test cross all vector lanes +// any: returns true if any of the elements is not equal to zero +// all: returns true if all elements are not equal to zero +#define NPYV_IMPL_AVX2_ANYALL(SFX) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { return _mm256_movemask_epi8(a) != 0; } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { return _mm256_movemask_epi8(a) == -1; } +NPYV_IMPL_AVX2_ANYALL(b8) +NPYV_IMPL_AVX2_ANYALL(b16) +NPYV_IMPL_AVX2_ANYALL(b32) +NPYV_IMPL_AVX2_ANYALL(b64) +#undef NPYV_IMPL_AVX2_ANYALL + +#define NPYV_IMPL_AVX2_ANYALL(SFX) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { \ + return _mm256_movemask_epi8( \ + npyv_cmpeq_##SFX(a, npyv_zero_##SFX()) \ + ) != -1; \ + } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { \ + return _mm256_movemask_epi8( \ + npyv_cmpeq_##SFX(a, npyv_zero_##SFX()) \ + ) == 0; \ + } +NPYV_IMPL_AVX2_ANYALL(u8) +NPYV_IMPL_AVX2_ANYALL(s8) +NPYV_IMPL_AVX2_ANYALL(u16) +NPYV_IMPL_AVX2_ANYALL(s16) +NPYV_IMPL_AVX2_ANYALL(u32) +NPYV_IMPL_AVX2_ANYALL(s32) +NPYV_IMPL_AVX2_ANYALL(u64) +NPYV_IMPL_AVX2_ANYALL(s64) +#undef NPYV_IMPL_AVX2_ANYALL + +#define NPYV_IMPL_AVX2_ANYALL(SFX, XSFX, MASK) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { \ + return _mm256_movemask_##XSFX( \ + _mm256_cmp_##XSFX(a, npyv_zero_##SFX(), _CMP_EQ_OQ) \ + ) != MASK; \ + } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { \ + return _mm256_movemask_##XSFX( \ + _mm256_cmp_##XSFX(a, npyv_zero_##SFX(), _CMP_EQ_OQ) \ + ) == 0; \ + } +NPYV_IMPL_AVX2_ANYALL(f32, ps, 0xff) +NPYV_IMPL_AVX2_ANYALL(f64, pd, 0xf) +#undef NPYV_IMPL_AVX2_ANYALL + +#endif // _NPY_SIMD_AVX2_OPERATORS_H diff --git a/mkl_umath/src/npyv/avx2/reorder.h b/mkl_umath/src/npyv/avx2/reorder.h new file mode 100644 index 00000000..9ebe0e7f --- /dev/null +++ b/mkl_umath/src/npyv/avx2/reorder.h @@ -0,0 +1,216 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_REORDER_H +#define _NPY_SIMD_AVX2_REORDER_H + +// combine lower part of two vectors +#define npyv_combinel_u8(A, B) _mm256_permute2x128_si256(A, B, 0x20) +#define npyv_combinel_s8 npyv_combinel_u8 +#define npyv_combinel_u16 npyv_combinel_u8 +#define npyv_combinel_s16 npyv_combinel_u8 +#define npyv_combinel_u32 npyv_combinel_u8 +#define npyv_combinel_s32 npyv_combinel_u8 +#define npyv_combinel_u64 npyv_combinel_u8 +#define npyv_combinel_s64 npyv_combinel_u8 +#define npyv_combinel_f32(A, B) _mm256_permute2f128_ps(A, B, 0x20) +#define npyv_combinel_f64(A, B) _mm256_permute2f128_pd(A, B, 0x20) + +// combine higher part of two vectors +#define npyv_combineh_u8(A, B) _mm256_permute2x128_si256(A, B, 0x31) +#define npyv_combineh_s8 npyv_combineh_u8 +#define npyv_combineh_u16 npyv_combineh_u8 +#define npyv_combineh_s16 npyv_combineh_u8 +#define npyv_combineh_u32 npyv_combineh_u8 +#define npyv_combineh_s32 npyv_combineh_u8 +#define npyv_combineh_u64 npyv_combineh_u8 +#define npyv_combineh_s64 npyv_combineh_u8 +#define npyv_combineh_f32(A, B) _mm256_permute2f128_ps(A, B, 0x31) +#define npyv_combineh_f64(A, B) _mm256_permute2f128_pd(A, B, 0x31) + +// combine two vectors from lower and higher parts of two other vectors +NPY_FINLINE npyv_m256ix2 npyv__combine(__m256i a, __m256i b) +{ + npyv_m256ix2 r; + __m256i a1b0 = _mm256_permute2x128_si256(a, b, 0x21); + r.val[0] = _mm256_blend_epi32(a, a1b0, 0xF0); + r.val[1] = _mm256_blend_epi32(b, a1b0, 0xF); + return r; +} +NPY_FINLINE npyv_f32x2 npyv_combine_f32(__m256 a, __m256 b) +{ + npyv_f32x2 r; + __m256 a1b0 = _mm256_permute2f128_ps(a, b, 0x21); + r.val[0] = _mm256_blend_ps(a, a1b0, 0xF0); + r.val[1] = _mm256_blend_ps(b, a1b0, 0xF); + return r; +} +NPY_FINLINE npyv_f64x2 npyv_combine_f64(__m256d a, __m256d b) +{ + npyv_f64x2 r; + __m256d a1b0 = _mm256_permute2f128_pd(a, b, 0x21); + r.val[0] = _mm256_blend_pd(a, a1b0, 0xC); + r.val[1] = _mm256_blend_pd(b, a1b0, 0x3); + return r; +} +#define npyv_combine_u8 npyv__combine +#define npyv_combine_s8 npyv__combine +#define npyv_combine_u16 npyv__combine +#define npyv_combine_s16 npyv__combine +#define npyv_combine_u32 npyv__combine +#define npyv_combine_s32 npyv__combine +#define npyv_combine_u64 npyv__combine +#define npyv_combine_s64 npyv__combine + +// interleave two vectors +#define NPYV_IMPL_AVX2_ZIP_U(T_VEC, LEN) \ + NPY_FINLINE T_VEC##x2 npyv_zip_u##LEN(T_VEC a, T_VEC b) \ + { \ + __m256i ab0 = _mm256_unpacklo_epi##LEN(a, b); \ + __m256i ab1 = _mm256_unpackhi_epi##LEN(a, b); \ + return npyv__combine(ab0, ab1); \ + } + +NPYV_IMPL_AVX2_ZIP_U(npyv_u8, 8) +NPYV_IMPL_AVX2_ZIP_U(npyv_u16, 16) +NPYV_IMPL_AVX2_ZIP_U(npyv_u32, 32) +NPYV_IMPL_AVX2_ZIP_U(npyv_u64, 64) +#define npyv_zip_s8 npyv_zip_u8 +#define npyv_zip_s16 npyv_zip_u16 +#define npyv_zip_s32 npyv_zip_u32 +#define npyv_zip_s64 npyv_zip_u64 + +NPY_FINLINE npyv_f32x2 npyv_zip_f32(__m256 a, __m256 b) +{ + __m256 ab0 = _mm256_unpacklo_ps(a, b); + __m256 ab1 = _mm256_unpackhi_ps(a, b); + return npyv_combine_f32(ab0, ab1); +} +NPY_FINLINE npyv_f64x2 npyv_zip_f64(__m256d a, __m256d b) +{ + __m256d ab0 = _mm256_unpacklo_pd(a, b); + __m256d ab1 = _mm256_unpackhi_pd(a, b); + return npyv_combine_f64(ab0, ab1); +} + +// deinterleave two vectors +NPY_FINLINE npyv_u8x2 npyv_unzip_u8(npyv_u8 ab0, npyv_u8 ab1) +{ + const __m256i idx = _mm256_setr_epi8( + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15, + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 + ); + __m256i ab_03 = _mm256_shuffle_epi8(ab0, idx); + __m256i ab_12 = _mm256_shuffle_epi8(ab1, idx); + npyv_u8x2 ab_lh = npyv_combine_u8(ab_03, ab_12); + npyv_u8x2 r; + r.val[0] = _mm256_unpacklo_epi64(ab_lh.val[0], ab_lh.val[1]); + r.val[1] = _mm256_unpackhi_epi64(ab_lh.val[0], ab_lh.val[1]); + return r; +} +#define npyv_unzip_s8 npyv_unzip_u8 + +NPY_FINLINE npyv_u16x2 npyv_unzip_u16(npyv_u16 ab0, npyv_u16 ab1) +{ + const __m256i idx = _mm256_setr_epi8( + 0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15, + 0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15 + ); + __m256i ab_03 = _mm256_shuffle_epi8(ab0, idx); + __m256i ab_12 = _mm256_shuffle_epi8(ab1, idx); + npyv_u16x2 ab_lh = npyv_combine_u16(ab_03, ab_12); + npyv_u16x2 r; + r.val[0] = _mm256_unpacklo_epi64(ab_lh.val[0], ab_lh.val[1]); + r.val[1] = _mm256_unpackhi_epi64(ab_lh.val[0], ab_lh.val[1]); + return r; +} +#define npyv_unzip_s16 npyv_unzip_u16 + +NPY_FINLINE npyv_u32x2 npyv_unzip_u32(npyv_u32 ab0, npyv_u32 ab1) +{ + const __m256i idx = npyv_set_u32(0, 2, 4, 6, 1, 3, 5, 7); + __m256i abl = _mm256_permutevar8x32_epi32(ab0, idx); + __m256i abh = _mm256_permutevar8x32_epi32(ab1, idx); + return npyv_combine_u32(abl, abh); +} +#define npyv_unzip_s32 npyv_unzip_u32 + +NPY_FINLINE npyv_u64x2 npyv_unzip_u64(npyv_u64 ab0, npyv_u64 ab1) +{ + npyv_u64x2 ab_lh = npyv_combine_u64(ab0, ab1); + npyv_u64x2 r; + r.val[0] = _mm256_unpacklo_epi64(ab_lh.val[0], ab_lh.val[1]); + r.val[1] = _mm256_unpackhi_epi64(ab_lh.val[0], ab_lh.val[1]); + return r; +} +#define npyv_unzip_s64 npyv_unzip_u64 + +NPY_FINLINE npyv_f32x2 npyv_unzip_f32(npyv_f32 ab0, npyv_f32 ab1) +{ + const __m256i idx = npyv_set_u32(0, 2, 4, 6, 1, 3, 5, 7); + __m256 abl = _mm256_permutevar8x32_ps(ab0, idx); + __m256 abh = _mm256_permutevar8x32_ps(ab1, idx); + return npyv_combine_f32(abl, abh); +} + +NPY_FINLINE npyv_f64x2 npyv_unzip_f64(npyv_f64 ab0, npyv_f64 ab1) +{ + npyv_f64x2 ab_lh = npyv_combine_f64(ab0, ab1); + npyv_f64x2 r; + r.val[0] = _mm256_unpacklo_pd(ab_lh.val[0], ab_lh.val[1]); + r.val[1] = _mm256_unpackhi_pd(ab_lh.val[0], ab_lh.val[1]); + return r; +} + +// Reverse elements of each 64-bit lane +NPY_FINLINE npyv_u8 npyv_rev64_u8(npyv_u8 a) +{ + const __m256i idx = _mm256_setr_epi8( + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8 + ); + return _mm256_shuffle_epi8(a, idx); +} +#define npyv_rev64_s8 npyv_rev64_u8 + +NPY_FINLINE npyv_u16 npyv_rev64_u16(npyv_u16 a) +{ + const __m256i idx = _mm256_setr_epi8( + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9, + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9 + ); + return _mm256_shuffle_epi8(a, idx); +} +#define npyv_rev64_s16 npyv_rev64_u16 + +NPY_FINLINE npyv_u32 npyv_rev64_u32(npyv_u32 a) +{ + return _mm256_shuffle_epi32(a, _MM_SHUFFLE(2, 3, 0, 1)); +} +#define npyv_rev64_s32 npyv_rev64_u32 + +NPY_FINLINE npyv_f32 npyv_rev64_f32(npyv_f32 a) +{ + return _mm256_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 0, 1)); +} + +// Permuting the elements of each 128-bit lane by immediate index for +// each element. +#define npyv_permi128_u32(A, E0, E1, E2, E3) \ + _mm256_shuffle_epi32(A, _MM_SHUFFLE(E3, E2, E1, E0)) + +#define npyv_permi128_s32 npyv_permi128_u32 + +#define npyv_permi128_u64(A, E0, E1) \ + _mm256_shuffle_epi32(A, _MM_SHUFFLE(((E1)<<1)+1, ((E1)<<1), ((E0)<<1)+1, ((E0)<<1))) + +#define npyv_permi128_s64 npyv_permi128_u64 + +#define npyv_permi128_f32(A, E0, E1, E2, E3) \ + _mm256_permute_ps(A, _MM_SHUFFLE(E3, E2, E1, E0)) + +#define npyv_permi128_f64(A, E0, E1) \ + _mm256_permute_pd(A, ((E1)<<3) | ((E0)<<2) | ((E1)<<1) | (E0)) + +#endif // _NPY_SIMD_AVX2_REORDER_H diff --git a/mkl_umath/src/npyv/avx2/utils.h b/mkl_umath/src/npyv/avx2/utils.h new file mode 100644 index 00000000..24f1af5d --- /dev/null +++ b/mkl_umath/src/npyv/avx2/utils.h @@ -0,0 +1,21 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX2_UTILS_H +#define _NPY_SIMD_AVX2_UTILS_H + +#define npyv256_shuffle_odd(A) _mm256_permute4x64_epi64(A, _MM_SHUFFLE(3, 1, 2, 0)) +#define npyv256_shuffle_odd_ps(A) _mm256_castsi256_ps(npyv256_shuffle_odd(_mm256_castps_si256(A))) +#define npyv256_shuffle_odd_pd(A) _mm256_permute4x64_pd(A, _MM_SHUFFLE(3, 1, 2, 0)) + +NPY_FINLINE __m256i npyv256_mul_u8(__m256i a, __m256i b) +{ + const __m256i mask = _mm256_set1_epi32(0xFF00FF00); + __m256i even = _mm256_mullo_epi16(a, b); + __m256i odd = _mm256_mullo_epi16(_mm256_srai_epi16(a, 8), _mm256_srai_epi16(b, 8)); + odd = _mm256_slli_epi16(odd, 8); + return _mm256_blendv_epi8(even, odd, mask); +} + +#endif // _NPY_SIMD_AVX2_UTILS_H diff --git a/mkl_umath/src/npyv/avx512/arithmetic.h b/mkl_umath/src/npyv/avx512/arithmetic.h new file mode 100644 index 00000000..a63da87d --- /dev/null +++ b/mkl_umath/src/npyv/avx512/arithmetic.h @@ -0,0 +1,446 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_ARITHMETIC_H +#define _NPY_SIMD_AVX512_ARITHMETIC_H + +#include "../avx2/utils.h" +#include "../sse/utils.h" +/*************************** + * Addition + ***************************/ +// non-saturated +#ifdef NPY_HAVE_AVX512BW + #define npyv_add_u8 _mm512_add_epi8 + #define npyv_add_u16 _mm512_add_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_add_u8, _mm256_add_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_add_u16, _mm256_add_epi16) +#endif +#define npyv_add_s8 npyv_add_u8 +#define npyv_add_s16 npyv_add_u16 +#define npyv_add_u32 _mm512_add_epi32 +#define npyv_add_s32 _mm512_add_epi32 +#define npyv_add_u64 _mm512_add_epi64 +#define npyv_add_s64 _mm512_add_epi64 +#define npyv_add_f32 _mm512_add_ps +#define npyv_add_f64 _mm512_add_pd + +// saturated +#ifdef NPY_HAVE_AVX512BW + #define npyv_adds_u8 _mm512_adds_epu8 + #define npyv_adds_s8 _mm512_adds_epi8 + #define npyv_adds_u16 _mm512_adds_epu16 + #define npyv_adds_s16 _mm512_adds_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_u8, _mm256_adds_epu8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_s8, _mm256_adds_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_u16, _mm256_adds_epu16) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_adds_s16, _mm256_adds_epi16) +#endif +// TODO: rest, after implement Packs intrins + +/*************************** + * Subtraction + ***************************/ +// non-saturated +#ifdef NPY_HAVE_AVX512BW + #define npyv_sub_u8 _mm512_sub_epi8 + #define npyv_sub_u16 _mm512_sub_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_sub_u8, _mm256_sub_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_sub_u16, _mm256_sub_epi16) +#endif +#define npyv_sub_s8 npyv_sub_u8 +#define npyv_sub_s16 npyv_sub_u16 +#define npyv_sub_u32 _mm512_sub_epi32 +#define npyv_sub_s32 _mm512_sub_epi32 +#define npyv_sub_u64 _mm512_sub_epi64 +#define npyv_sub_s64 _mm512_sub_epi64 +#define npyv_sub_f32 _mm512_sub_ps +#define npyv_sub_f64 _mm512_sub_pd + +// saturated +#ifdef NPY_HAVE_AVX512BW + #define npyv_subs_u8 _mm512_subs_epu8 + #define npyv_subs_s8 _mm512_subs_epi8 + #define npyv_subs_u16 _mm512_subs_epu16 + #define npyv_subs_s16 _mm512_subs_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_u8, _mm256_subs_epu8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_s8, _mm256_subs_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_u16, _mm256_subs_epu16) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_subs_s16, _mm256_subs_epi16) +#endif +// TODO: rest, after implement Packs intrins + +/*************************** + * Multiplication + ***************************/ +// non-saturated +#ifdef NPY_HAVE_AVX512BW +NPY_FINLINE __m512i npyv_mul_u8(__m512i a, __m512i b) +{ + __m512i even = _mm512_mullo_epi16(a, b); + __m512i odd = _mm512_mullo_epi16(_mm512_srai_epi16(a, 8), _mm512_srai_epi16(b, 8)); + odd = _mm512_slli_epi16(odd, 8); + return _mm512_mask_blend_epi8(0xAAAAAAAAAAAAAAAA, even, odd); +} +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_mul_u8, npyv256_mul_u8) +#endif + +#ifdef NPY_HAVE_AVX512BW + #define npyv_mul_u16 _mm512_mullo_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_mul_u16, _mm256_mullo_epi16) +#endif +#define npyv_mul_s8 npyv_mul_u8 +#define npyv_mul_s16 npyv_mul_u16 +#define npyv_mul_u32 _mm512_mullo_epi32 +#define npyv_mul_s32 _mm512_mullo_epi32 +#define npyv_mul_f32 _mm512_mul_ps +#define npyv_mul_f64 _mm512_mul_pd + +// saturated +// TODO: after implement Packs intrins + +/*************************** + * Integer Division + ***************************/ +// See simd/intdiv.h for more clarification +// divide each unsigned 8-bit element by divisor +NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]); +#ifdef NPY_HAVE_AVX512BW + const __m512i bmask = _mm512_set1_epi32(0x00FF00FF); + const __m512i shf1b = _mm512_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf1)); + const __m512i shf2b = _mm512_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf2)); + // high part of unsigned multiplication + __m512i mulhi_even = _mm512_mullo_epi16(_mm512_and_si512(a, bmask), divisor.val[0]); + mulhi_even = _mm512_srli_epi16(mulhi_even, 8); + __m512i mulhi_odd = _mm512_mullo_epi16(_mm512_srli_epi16(a, 8), divisor.val[0]); + __m512i mulhi = _mm512_mask_mov_epi8(mulhi_even, 0xAAAAAAAAAAAAAAAA, mulhi_odd); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m512i q = _mm512_sub_epi8(a, mulhi); + q = _mm512_and_si512(_mm512_srl_epi16(q, shf1), shf1b); + q = _mm512_add_epi8(mulhi, q); + q = _mm512_and_si512(_mm512_srl_epi16(q, shf2), shf2b); + return q; +#else + const __m256i bmask = _mm256_set1_epi32(0x00FF00FF); + const __m256i shf1b = _mm256_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf1)); + const __m256i shf2b = _mm256_set1_epi8(0xFFU >> _mm_cvtsi128_si32(shf2)); + const __m512i shf2bw= npyv512_combine_si256(shf2b, shf2b); + const __m256i mulc = npyv512_lower_si256(divisor.val[0]); + //// lower 256-bit + __m256i lo_a = npyv512_lower_si256(a); + // high part of unsigned multiplication + __m256i mulhi_even = _mm256_mullo_epi16(_mm256_and_si256(lo_a, bmask), mulc); + mulhi_even = _mm256_srli_epi16(mulhi_even, 8); + __m256i mulhi_odd = _mm256_mullo_epi16(_mm256_srli_epi16(lo_a, 8), mulc); + __m256i mulhi = _mm256_blendv_epi8(mulhi_odd, mulhi_even, bmask); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m256i lo_q = _mm256_sub_epi8(lo_a, mulhi); + lo_q = _mm256_and_si256(_mm256_srl_epi16(lo_q, shf1), shf1b); + lo_q = _mm256_add_epi8(mulhi, lo_q); + lo_q = _mm256_srl_epi16(lo_q, shf2); // no sign extend + + //// higher 256-bit + __m256i hi_a = npyv512_higher_si256(a); + // high part of unsigned multiplication + mulhi_even = _mm256_mullo_epi16(_mm256_and_si256(hi_a, bmask), mulc); + mulhi_even = _mm256_srli_epi16(mulhi_even, 8); + mulhi_odd = _mm256_mullo_epi16(_mm256_srli_epi16(hi_a, 8), mulc); + mulhi = _mm256_blendv_epi8(mulhi_odd, mulhi_even, bmask); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m256i hi_q = _mm256_sub_epi8(hi_a, mulhi); + hi_q = _mm256_and_si256(_mm256_srl_epi16(hi_q, shf1), shf1b); + hi_q = _mm256_add_epi8(mulhi, hi_q); + hi_q = _mm256_srl_epi16(hi_q, shf2); // no sign extend + return _mm512_and_si512(npyv512_combine_si256(lo_q, hi_q), shf2bw); // extend sign +#endif +} +// divide each signed 8-bit element by divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor); +NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor) +{ + __m512i divc_even = npyv_divc_s16(npyv_shri_s16(npyv_shli_s16(a, 8), 8), divisor); + __m512i divc_odd = npyv_divc_s16(npyv_shri_s16(a, 8), divisor); + divc_odd = npyv_shli_s16(divc_odd, 8); +#ifdef NPY_HAVE_AVX512BW + return _mm512_mask_mov_epi8(divc_even, 0xAAAAAAAAAAAAAAAA, divc_odd); +#else + const __m512i bmask = _mm512_set1_epi32(0x00FF00FF); + return npyv_select_u8(bmask, divc_even, divc_odd); +#endif +} +// divide each unsigned 16-bit element by divisor +NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + #define NPYV__DIVC_U16(RLEN, A, MULC, R) \ + mulhi = _mm##RLEN##_mulhi_epu16(A, MULC); \ + R = _mm##RLEN##_sub_epi16(A, mulhi); \ + R = _mm##RLEN##_srl_epi16(R, shf1); \ + R = _mm##RLEN##_add_epi16(mulhi, R); \ + R = _mm##RLEN##_srl_epi16(R, shf2); + +#ifdef NPY_HAVE_AVX512BW + __m512i mulhi, q; + NPYV__DIVC_U16(512, a, divisor.val[0], q) + return q; +#else + const __m256i m = npyv512_lower_si256(divisor.val[0]); + __m256i lo_a = npyv512_lower_si256(a); + __m256i hi_a = npyv512_higher_si256(a); + + __m256i mulhi, lo_q, hi_q; + NPYV__DIVC_U16(256, lo_a, m, lo_q) + NPYV__DIVC_U16(256, hi_a, m, hi_q) + return npyv512_combine_si256(lo_q, hi_q); +#endif + #undef NPYV__DIVC_U16 +} +// divide each signed 16-bit element by divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + #define NPYV__DIVC_S16(RLEN, A, MULC, DSIGN, R) \ + mulhi = _mm##RLEN##_mulhi_epi16(A, MULC); \ + R = _mm##RLEN##_sra_epi16(_mm##RLEN##_add_epi16(A, mulhi), shf1); \ + R = _mm##RLEN##_sub_epi16(R, _mm##RLEN##_srai_epi16(A, 15)); \ + R = _mm##RLEN##_sub_epi16(_mm##RLEN##_xor_si##RLEN(R, DSIGN), DSIGN); + +#ifdef NPY_HAVE_AVX512BW + __m512i mulhi, q; + NPYV__DIVC_S16(512, a, divisor.val[0], divisor.val[2], q) + return q; +#else + const __m256i m = npyv512_lower_si256(divisor.val[0]); + const __m256i dsign = npyv512_lower_si256(divisor.val[2]); + __m256i lo_a = npyv512_lower_si256(a); + __m256i hi_a = npyv512_higher_si256(a); + + __m256i mulhi, lo_q, hi_q; + NPYV__DIVC_S16(256, lo_a, m, dsign, lo_q) + NPYV__DIVC_S16(256, hi_a, m, dsign, hi_q) + return npyv512_combine_si256(lo_q, hi_q); +#endif + #undef NPYV__DIVC_S16 +} +// divide each unsigned 32-bit element by divisor +NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]); + // high part of unsigned multiplication + __m512i mulhi_even = _mm512_srli_epi64(_mm512_mul_epu32(a, divisor.val[0]), 32); + __m512i mulhi_odd = _mm512_mul_epu32(_mm512_srli_epi64(a, 32), divisor.val[0]); + __m512i mulhi = _mm512_mask_mov_epi32(mulhi_even, 0xAAAA, mulhi_odd); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m512i q = _mm512_sub_epi32(a, mulhi); + q = _mm512_srl_epi32(q, shf1); + q = _mm512_add_epi32(mulhi, q); + q = _mm512_srl_epi32(q, shf2); + return q; +} +// divide each signed 32-bit element by divisor (round towards zero) +NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + // high part of signed multiplication + __m512i mulhi_even = _mm512_srli_epi64(_mm512_mul_epi32(a, divisor.val[0]), 32); + __m512i mulhi_odd = _mm512_mul_epi32(_mm512_srli_epi64(a, 32), divisor.val[0]); + __m512i mulhi = _mm512_mask_mov_epi32(mulhi_even, 0xAAAA, mulhi_odd); + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + __m512i q = _mm512_sra_epi32(_mm512_add_epi32(a, mulhi), shf1); + q = _mm512_sub_epi32(q, _mm512_srai_epi32(a, 31)); + q = _mm512_sub_epi32(_mm512_xor_si512(q, divisor.val[2]), divisor.val[2]); + return q; +} +// returns the high 64 bits of unsigned 64-bit multiplication +// xref https://stackoverflow.com/a/28827013 +NPY_FINLINE npyv_u64 npyv__mullhi_u64(npyv_u64 a, npyv_u64 b) +{ + __m512i lomask = npyv_setall_s64(0xffffffff); + __m512i a_hi = _mm512_srli_epi64(a, 32); // a0l, a0h, a1l, a1h + __m512i b_hi = _mm512_srli_epi64(b, 32); // b0l, b0h, b1l, b1h + // compute partial products + __m512i w0 = _mm512_mul_epu32(a, b); // a0l*b0l, a1l*b1l + __m512i w1 = _mm512_mul_epu32(a, b_hi); // a0l*b0h, a1l*b1h + __m512i w2 = _mm512_mul_epu32(a_hi, b); // a0h*b0l, a1h*b0l + __m512i w3 = _mm512_mul_epu32(a_hi, b_hi); // a0h*b0h, a1h*b1h + // sum partial products + __m512i w0h = _mm512_srli_epi64(w0, 32); + __m512i s1 = _mm512_add_epi64(w1, w0h); + __m512i s1l = _mm512_and_si512(s1, lomask); + __m512i s1h = _mm512_srli_epi64(s1, 32); + + __m512i s2 = _mm512_add_epi64(w2, s1l); + __m512i s2h = _mm512_srli_epi64(s2, 32); + + __m512i hi = _mm512_add_epi64(w3, s1h); + hi = _mm512_add_epi64(hi, s2h); + return hi; +} +// divide each unsigned 64-bit element by a divisor +NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + const __m128i shf2 = _mm512_castsi512_si128(divisor.val[2]); + // high part of unsigned multiplication + __m512i mulhi = npyv__mullhi_u64(a, divisor.val[0]); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m512i q = _mm512_sub_epi64(a, mulhi); + q = _mm512_srl_epi64(q, shf1); + q = _mm512_add_epi64(mulhi, q); + q = _mm512_srl_epi64(q, shf2); + return q; +} +// divide each unsigned 64-bit element by a divisor (round towards zero) +NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor) +{ + const __m128i shf1 = _mm512_castsi512_si128(divisor.val[1]); + // high part of unsigned multiplication + __m512i mulhi = npyv__mullhi_u64(a, divisor.val[0]); + // convert unsigned to signed high multiplication + // mulhi - ((a < 0) ? m : 0) - ((m < 0) ? a : 0); + __m512i asign = _mm512_srai_epi64(a, 63); + __m512i msign = _mm512_srai_epi64(divisor.val[0], 63); + __m512i m_asign = _mm512_and_si512(divisor.val[0], asign); + __m512i a_msign = _mm512_and_si512(a, msign); + mulhi = _mm512_sub_epi64(mulhi, m_asign); + mulhi = _mm512_sub_epi64(mulhi, a_msign); + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + __m512i q = _mm512_sra_epi64(_mm512_add_epi64(a, mulhi), shf1); + q = _mm512_sub_epi64(q, asign); + q = _mm512_sub_epi64(_mm512_xor_si512(q, divisor.val[2]), divisor.val[2]); + return q; +} +/*************************** + * Division + ***************************/ +// TODO: emulate integer division +#define npyv_div_f32 _mm512_div_ps +#define npyv_div_f64 _mm512_div_pd + +/*************************** + * FUSED + ***************************/ +// multiply and add, a*b + c +#define npyv_muladd_f32 _mm512_fmadd_ps +#define npyv_muladd_f64 _mm512_fmadd_pd +// multiply and subtract, a*b - c +#define npyv_mulsub_f32 _mm512_fmsub_ps +#define npyv_mulsub_f64 _mm512_fmsub_pd +// negate multiply and add, -(a*b) + c +#define npyv_nmuladd_f32 _mm512_fnmadd_ps +#define npyv_nmuladd_f64 _mm512_fnmadd_pd +// negate multiply and subtract, -(a*b) - c +#define npyv_nmulsub_f32 _mm512_fnmsub_ps +#define npyv_nmulsub_f64 _mm512_fnmsub_pd +// multiply, add for odd elements and subtract even elements. +// (a * b) -+ c +#define npyv_muladdsub_f32 _mm512_fmaddsub_ps +#define npyv_muladdsub_f64 _mm512_fmaddsub_pd + +/*************************** + * Summation: Calculates the sum of all vector elements. + * there are three ways to implement reduce sum for AVX512: + * 1- split(256) /add /split(128) /add /hadd /hadd /extract + * 2- shuff(cross) /add /shuff(cross) /add /shuff /add /shuff /add /extract + * 3- _mm512_reduce_add_ps/pd + * The first one is been widely used by many projects + * + * the second one is used by Intel Compiler, maybe because the + * latency of hadd increased by (2-3) starting from Skylake-X which makes two + * extra shuffles(non-cross) cheaper. check https://godbolt.org/z/s3G9Er for more info. + * + * The third one is almost the same as the second one but only works for + * intel compiler/GCC 7.1/Clang 4, we still need to support older GCC. + ***************************/ +// reduce sum across vector +#ifdef NPY_HAVE_AVX512F_REDUCE + #define npyv_sum_u32 _mm512_reduce_add_epi32 + #define npyv_sum_u64 _mm512_reduce_add_epi64 + #define npyv_sum_f32 _mm512_reduce_add_ps + #define npyv_sum_f64 _mm512_reduce_add_pd +#else + NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) + { + __m256i half = _mm256_add_epi32(npyv512_lower_si256(a), npyv512_higher_si256(a)); + __m128i quarter = _mm_add_epi32(_mm256_castsi256_si128(half), _mm256_extracti128_si256(half, 1)); + quarter = _mm_hadd_epi32(quarter, quarter); + return _mm_cvtsi128_si32(_mm_hadd_epi32(quarter, quarter)); + } + + NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) + { + __m256i four = _mm256_add_epi64(npyv512_lower_si256(a), npyv512_higher_si256(a)); + __m256i two = _mm256_add_epi64(four, _mm256_shuffle_epi32(four, _MM_SHUFFLE(1, 0, 3, 2))); + __m128i one = _mm_add_epi64(_mm256_castsi256_si128(two), _mm256_extracti128_si256(two, 1)); + return (npy_uint64)npyv128_cvtsi128_si64(one); + } + + NPY_FINLINE float npyv_sum_f32(npyv_f32 a) + { + __m512 h64 = _mm512_shuffle_f32x4(a, a, _MM_SHUFFLE(3, 2, 3, 2)); + __m512 sum32 = _mm512_add_ps(a, h64); + __m512 h32 = _mm512_shuffle_f32x4(sum32, sum32, _MM_SHUFFLE(1, 0, 3, 2)); + __m512 sum16 = _mm512_add_ps(sum32, h32); + __m512 h16 = _mm512_permute_ps(sum16, _MM_SHUFFLE(1, 0, 3, 2)); + __m512 sum8 = _mm512_add_ps(sum16, h16); + __m512 h4 = _mm512_permute_ps(sum8, _MM_SHUFFLE(2, 3, 0, 1)); + __m512 sum4 = _mm512_add_ps(sum8, h4); + return _mm_cvtss_f32(_mm512_castps512_ps128(sum4)); + } + + NPY_FINLINE double npyv_sum_f64(npyv_f64 a) + { + __m512d h64 = _mm512_shuffle_f64x2(a, a, _MM_SHUFFLE(3, 2, 3, 2)); + __m512d sum32 = _mm512_add_pd(a, h64); + __m512d h32 = _mm512_permutex_pd(sum32, _MM_SHUFFLE(1, 0, 3, 2)); + __m512d sum16 = _mm512_add_pd(sum32, h32); + __m512d h16 = _mm512_permute_pd(sum16, _MM_SHUFFLE(2, 3, 0, 1)); + __m512d sum8 = _mm512_add_pd(sum16, h16); + return _mm_cvtsd_f64(_mm512_castpd512_pd128(sum8)); + } + +#endif + +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ +#ifdef NPY_HAVE_AVX512BW + __m512i eight = _mm512_sad_epu8(a, _mm512_setzero_si512()); + __m256i four = _mm256_add_epi16(npyv512_lower_si256(eight), npyv512_higher_si256(eight)); +#else + __m256i lo_four = _mm256_sad_epu8(npyv512_lower_si256(a), _mm256_setzero_si256()); + __m256i hi_four = _mm256_sad_epu8(npyv512_higher_si256(a), _mm256_setzero_si256()); + __m256i four = _mm256_add_epi16(lo_four, hi_four); +#endif + __m128i two = _mm_add_epi16(_mm256_castsi256_si128(four), _mm256_extracti128_si256(four, 1)); + __m128i one = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two)); + return (npy_uint16)_mm_cvtsi128_si32(one); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const npyv_u16 even_mask = _mm512_set1_epi32(0x0000FFFF); + __m512i even = _mm512_and_si512(a, even_mask); + __m512i odd = _mm512_srli_epi32(a, 16); + __m512i ff = _mm512_add_epi32(even, odd); + return npyv_sum_u32(ff); +} + +#endif // _NPY_SIMD_AVX512_ARITHMETIC_H diff --git a/mkl_umath/src/npyv/avx512/avx512.h b/mkl_umath/src/npyv/avx512/avx512.h new file mode 100644 index 00000000..2a4a20b2 --- /dev/null +++ b/mkl_umath/src/npyv/avx512/avx512.h @@ -0,0 +1,82 @@ +#ifndef _NPY_SIMD_H_ + #error "Not a standalone header" +#endif +#define NPY_SIMD 512 +#define NPY_SIMD_WIDTH 64 +#define NPY_SIMD_F32 1 +#define NPY_SIMD_F64 1 +#define NPY_SIMD_FMA3 1 // native support +#define NPY_SIMD_BIGENDIAN 0 +#define NPY_SIMD_CMPSIGNAL 0 +// Enough limit to allow us to use _mm512_i32gather_* and _mm512_i32scatter_* +#define NPY_SIMD_MAXLOAD_STRIDE32 (0x7fffffff / 16) +#define NPY_SIMD_MAXSTORE_STRIDE32 (0x7fffffff / 16) +#define NPY_SIMD_MAXLOAD_STRIDE64 (0x7fffffff / 16) +#define NPY_SIMD_MAXSTORE_STRIDE64 (0x7fffffff / 16) + +typedef __m512i npyv_u8; +typedef __m512i npyv_s8; +typedef __m512i npyv_u16; +typedef __m512i npyv_s16; +typedef __m512i npyv_u32; +typedef __m512i npyv_s32; +typedef __m512i npyv_u64; +typedef __m512i npyv_s64; +typedef __m512 npyv_f32; +typedef __m512d npyv_f64; + +#ifdef NPY_HAVE_AVX512BW +typedef __mmask64 npyv_b8; +typedef __mmask32 npyv_b16; +#else +typedef __m512i npyv_b8; +typedef __m512i npyv_b16; +#endif +typedef __mmask16 npyv_b32; +typedef __mmask8 npyv_b64; + +typedef struct { __m512i val[2]; } npyv_m512ix2; +typedef npyv_m512ix2 npyv_u8x2; +typedef npyv_m512ix2 npyv_s8x2; +typedef npyv_m512ix2 npyv_u16x2; +typedef npyv_m512ix2 npyv_s16x2; +typedef npyv_m512ix2 npyv_u32x2; +typedef npyv_m512ix2 npyv_s32x2; +typedef npyv_m512ix2 npyv_u64x2; +typedef npyv_m512ix2 npyv_s64x2; + +typedef struct { __m512i val[3]; } npyv_m512ix3; +typedef npyv_m512ix3 npyv_u8x3; +typedef npyv_m512ix3 npyv_s8x3; +typedef npyv_m512ix3 npyv_u16x3; +typedef npyv_m512ix3 npyv_s16x3; +typedef npyv_m512ix3 npyv_u32x3; +typedef npyv_m512ix3 npyv_s32x3; +typedef npyv_m512ix3 npyv_u64x3; +typedef npyv_m512ix3 npyv_s64x3; + +typedef struct { __m512 val[2]; } npyv_f32x2; +typedef struct { __m512d val[2]; } npyv_f64x2; +typedef struct { __m512 val[3]; } npyv_f32x3; +typedef struct { __m512d val[3]; } npyv_f64x3; + +#define npyv_nlanes_u8 64 +#define npyv_nlanes_s8 64 +#define npyv_nlanes_u16 32 +#define npyv_nlanes_s16 32 +#define npyv_nlanes_u32 16 +#define npyv_nlanes_s32 16 +#define npyv_nlanes_u64 8 +#define npyv_nlanes_s64 8 +#define npyv_nlanes_f32 16 +#define npyv_nlanes_f64 8 + +#include "utils.h" +#include "memory.h" +#include "misc.h" +#include "reorder.h" +#include "operators.h" +#include "conversion.h" +#include "arithmetic.h" +#include "math.h" +#include "maskop.h" diff --git a/mkl_umath/src/npyv/avx512/conversion.h b/mkl_umath/src/npyv/avx512/conversion.h new file mode 100644 index 00000000..3b29b672 --- /dev/null +++ b/mkl_umath/src/npyv/avx512/conversion.h @@ -0,0 +1,204 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_CVT_H +#define _NPY_SIMD_AVX512_CVT_H + +// convert mask to integer vectors +#ifdef NPY_HAVE_AVX512BW + #define npyv_cvt_u8_b8 _mm512_movm_epi8 + #define npyv_cvt_u16_b16 _mm512_movm_epi16 +#else + #define npyv_cvt_u8_b8(BL) BL + #define npyv_cvt_u16_b16(BL) BL +#endif +#define npyv_cvt_s8_b8 npyv_cvt_u8_b8 +#define npyv_cvt_s16_b16 npyv_cvt_u16_b16 + +#ifdef NPY_HAVE_AVX512DQ + #define npyv_cvt_u32_b32 _mm512_movm_epi32 + #define npyv_cvt_u64_b64 _mm512_movm_epi64 +#else + #define npyv_cvt_u32_b32(BL) _mm512_maskz_set1_epi32(BL, (int)-1) + #define npyv_cvt_u64_b64(BL) _mm512_maskz_set1_epi64(BL, (npy_int64)-1) +#endif +#define npyv_cvt_s32_b32 npyv_cvt_u32_b32 +#define npyv_cvt_s64_b64 npyv_cvt_u64_b64 +#define npyv_cvt_f32_b32(BL) _mm512_castsi512_ps(npyv_cvt_u32_b32(BL)) +#define npyv_cvt_f64_b64(BL) _mm512_castsi512_pd(npyv_cvt_u64_b64(BL)) + +// convert integer vectors to mask +#ifdef NPY_HAVE_AVX512BW + #define npyv_cvt_b8_u8 _mm512_movepi8_mask + #define npyv_cvt_b16_u16 _mm512_movepi16_mask +#else + #define npyv_cvt_b8_u8(A) A + #define npyv_cvt_b16_u16(A) A +#endif +#define npyv_cvt_b8_s8 npyv_cvt_b8_u8 +#define npyv_cvt_b16_s16 npyv_cvt_b16_u16 + +#ifdef NPY_HAVE_AVX512DQ + #define npyv_cvt_b32_u32 _mm512_movepi32_mask + #define npyv_cvt_b64_u64 _mm512_movepi64_mask +#else + #define npyv_cvt_b32_u32(A) _mm512_cmpneq_epu32_mask(A, _mm512_setzero_si512()) + #define npyv_cvt_b64_u64(A) _mm512_cmpneq_epu64_mask(A, _mm512_setzero_si512()) +#endif +#define npyv_cvt_b32_s32 npyv_cvt_b32_u32 +#define npyv_cvt_b64_s64 npyv_cvt_b64_u64 +#define npyv_cvt_b32_f32(A) npyv_cvt_b32_u32(_mm512_castps_si512(A)) +#define npyv_cvt_b64_f64(A) npyv_cvt_b64_u64(_mm512_castpd_si512(A)) + +// expand +NPY_FINLINE npyv_u16x2 npyv_expand_u16_u8(npyv_u8 data) +{ + npyv_u16x2 r; + __m256i lo = npyv512_lower_si256(data); + __m256i hi = npyv512_higher_si256(data); +#ifdef NPY_HAVE_AVX512BW + r.val[0] = _mm512_cvtepu8_epi16(lo); + r.val[1] = _mm512_cvtepu8_epi16(hi); +#else + __m256i loelo = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(lo)); + __m256i loehi = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(lo, 1)); + __m256i hielo = _mm256_cvtepu8_epi16(_mm256_castsi256_si128(hi)); + __m256i hiehi = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(hi, 1)); + r.val[0] = npyv512_combine_si256(loelo, loehi); + r.val[1] = npyv512_combine_si256(hielo, hiehi); +#endif + return r; +} + +NPY_FINLINE npyv_u32x2 npyv_expand_u32_u16(npyv_u16 data) +{ + npyv_u32x2 r; + __m256i lo = npyv512_lower_si256(data); + __m256i hi = npyv512_higher_si256(data); +#ifdef NPY_HAVE_AVX512BW + r.val[0] = _mm512_cvtepu16_epi32(lo); + r.val[1] = _mm512_cvtepu16_epi32(hi); +#else + __m256i loelo = _mm256_cvtepu16_epi32(_mm256_castsi256_si128(lo)); + __m256i loehi = _mm256_cvtepu16_epi32(_mm256_extracti128_si256(lo, 1)); + __m256i hielo = _mm256_cvtepu16_epi32(_mm256_castsi256_si128(hi)); + __m256i hiehi = _mm256_cvtepu16_epi32(_mm256_extracti128_si256(hi, 1)); + r.val[0] = npyv512_combine_si256(loelo, loehi); + r.val[1] = npyv512_combine_si256(hielo, hiehi); +#endif + return r; +} + +// pack two 16-bit boolean into one 8-bit boolean vector +NPY_FINLINE npyv_b8 npyv_pack_b8_b16(npyv_b16 a, npyv_b16 b) { +#ifdef NPY_HAVE_AVX512BW + return _mm512_kunpackd((__mmask64)b, (__mmask64)a); +#else + const __m512i idx = _mm512_setr_epi64(0, 2, 4, 6, 1, 3, 5, 7); + return _mm512_permutexvar_epi64(idx, npyv512_packs_epi16(a, b)); +#endif +} + +// pack four 32-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b32(npyv_b32 a, npyv_b32 b, npyv_b32 c, npyv_b32 d) { +#ifdef NPY_HAVE_AVX512BW + __mmask32 ab = _mm512_kunpackw((__mmask32)b, (__mmask32)a); + __mmask32 cd = _mm512_kunpackw((__mmask32)d, (__mmask32)c); + return npyv_pack_b8_b16(ab, cd); +#else + const __m512i idx = _mm512_setr_epi32( + 0, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15); + __m256i ta = npyv512_pack_lo_hi(npyv_cvt_u32_b32(a)); + __m256i tb = npyv512_pack_lo_hi(npyv_cvt_u32_b32(b)); + __m256i tc = npyv512_pack_lo_hi(npyv_cvt_u32_b32(c)); + __m256i td = npyv512_pack_lo_hi(npyv_cvt_u32_b32(d)); + __m256i ab = _mm256_packs_epi16(ta, tb); + __m256i cd = _mm256_packs_epi16(tc, td); + __m512i abcd = npyv512_combine_si256(ab, cd); + return _mm512_permutexvar_epi32(idx, abcd); +#endif +} + +// pack eight 64-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b64(npyv_b64 a, npyv_b64 b, npyv_b64 c, npyv_b64 d, + npyv_b64 e, npyv_b64 f, npyv_b64 g, npyv_b64 h) { + __mmask16 ab = _mm512_kunpackb((__mmask16)b, (__mmask16)a); + __mmask16 cd = _mm512_kunpackb((__mmask16)d, (__mmask16)c); + __mmask16 ef = _mm512_kunpackb((__mmask16)f, (__mmask16)e); + __mmask16 gh = _mm512_kunpackb((__mmask16)h, (__mmask16)g); + return npyv_pack_b8_b32(ab, cd, ef, gh); +} +/* + * A compiler bug workaround on Intel Compiler Classic. + * The bug manifests specifically when the + * scalar result of _cvtmask64_u64 is compared against the constant -1. This + * comparison uniquely triggers a bug under conditions of equality (==) or + * inequality (!=) checks, which are typically used in reduction operations like + * np.logical_or. + * + * The underlying issue arises from the compiler's optimizer. When the last + * vector comparison instruction operates on zmm, the optimizer erroneously + * emits a duplicate of this instruction but on the lower half register ymm. It + * then performs a bitwise XOR operation between the mask produced by this + * duplicated instruction and the mask from the original comparison instruction. + * This erroneous behavior leads to incorrect results. + * + * See https://github.com/numpy/numpy/issues/26197#issuecomment-2056750975 + */ +#ifdef __INTEL_COMPILER +#define NPYV__VOLATILE_CVTMASK64 volatile +#else +#define NPYV__VOLATILE_CVTMASK64 +#endif +// convert boolean vectors to integer bitfield +NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) { +#ifdef NPY_HAVE_AVX512BW_MASK + npy_uint64 NPYV__VOLATILE_CVTMASK64 t = (npy_uint64)_cvtmask64_u64(a); + return t; +#elif defined(NPY_HAVE_AVX512BW) + npy_uint64 NPYV__VOLATILE_CVTMASK64 t = (npy_uint64)a; + return t; +#else + int mask_lo = _mm256_movemask_epi8(npyv512_lower_si256(a)); + int mask_hi = _mm256_movemask_epi8(npyv512_higher_si256(a)); + return (unsigned)mask_lo | ((npy_uint64)(unsigned)mask_hi << 32); +#endif +} +#undef NPYV__VOLATILE_CVTMASK64 + +NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a) +{ +#ifdef NPY_HAVE_AVX512BW_MASK + return (npy_uint32)_cvtmask32_u32(a); +#elif defined(NPY_HAVE_AVX512BW) + return (npy_uint32)a; +#else + __m256i pack = _mm256_packs_epi16( + npyv512_lower_si256(a), npyv512_higher_si256(a) + ); + return (npy_uint32)_mm256_movemask_epi8(_mm256_permute4x64_epi64(pack, _MM_SHUFFLE(3, 1, 2, 0))); +#endif +} +NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a) +{ return (npy_uint16)a; } +NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a) +{ +#ifdef NPY_HAVE_AVX512DQ_MASK + return _cvtmask8_u32(a); +#else + return (npy_uint8)a; +#endif +} + +// round to nearest integer (assuming even) +#define npyv_round_s32_f32 _mm512_cvtps_epi32 +NPY_FINLINE npyv_s32 npyv_round_s32_f64(npyv_f64 a, npyv_f64 b) +{ + __m256i lo = _mm512_cvtpd_epi32(a), hi = _mm512_cvtpd_epi32(b); + return npyv512_combine_si256(lo, hi); +} + +#endif // _NPY_SIMD_AVX512_CVT_H diff --git a/mkl_umath/src/npyv/avx512/maskop.h b/mkl_umath/src/npyv/avx512/maskop.h new file mode 100644 index 00000000..88fa4a68 --- /dev/null +++ b/mkl_umath/src/npyv/avx512/maskop.h @@ -0,0 +1,67 @@ +#ifndef NPY_SIMD + #error "Not a standalone header, use simd/simd.h instead" +#endif + +#ifndef _NPY_SIMD_AVX512_MASKOP_H +#define _NPY_SIMD_AVX512_MASKOP_H + +/** + * Implements conditional addition and subtraction. + * e.g. npyv_ifadd_f32(m, a, b, c) -> m ? a + b : c + * e.g. npyv_ifsub_f32(m, a, b, c) -> m ? a - b : c + */ +#define NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(SFX, BSFX) \ + NPY_FINLINE npyv_##SFX npyv_ifadd_##SFX \ + (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \ + { \ + npyv_##SFX add = npyv_add_##SFX(a, b); \ + return npyv_select_##SFX(m, add, c); \ + } \ + NPY_FINLINE npyv_##SFX npyv_ifsub_##SFX \ + (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \ + { \ + npyv_##SFX sub = npyv_sub_##SFX(a, b); \ + return npyv_select_##SFX(m, sub, c); \ + } + +#define NPYV_IMPL_AVX512_MASK_ADDSUB(SFX, BSFX, ZSFX) \ + NPY_FINLINE npyv_##SFX npyv_ifadd_##SFX \ + (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \ + { return _mm512_mask_add_##ZSFX(c, m, a, b); } \ + NPY_FINLINE npyv_##SFX npyv_ifsub_##SFX \ + (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \ + { return _mm512_mask_sub_##ZSFX(c, m, a, b); } + +#ifdef NPY_HAVE_AVX512BW + NPYV_IMPL_AVX512_MASK_ADDSUB(u8, b8, epi8) + NPYV_IMPL_AVX512_MASK_ADDSUB(s8, b8, epi8) + NPYV_IMPL_AVX512_MASK_ADDSUB(u16, b16, epi16) + NPYV_IMPL_AVX512_MASK_ADDSUB(s16, b16, epi16) +#else + NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(u8, b8) + NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(s8, b8) + NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(u16, b16) + NPYV_IMPL_AVX512_EMULATE_MASK_ADDSUB(s16, b16) +#endif + +NPYV_IMPL_AVX512_MASK_ADDSUB(u32, b32, epi32) +NPYV_IMPL_AVX512_MASK_ADDSUB(s32, b32, epi32) +NPYV_IMPL_AVX512_MASK_ADDSUB(u64, b64, epi64) +NPYV_IMPL_AVX512_MASK_ADDSUB(s64, b64, epi64) +NPYV_IMPL_AVX512_MASK_ADDSUB(f32, b32, ps) +NPYV_IMPL_AVX512_MASK_ADDSUB(f64, b64, pd) + +// division, m ? a / b : c +NPY_FINLINE npyv_f32 npyv_ifdiv_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b, npyv_f32 c) +{ return _mm512_mask_div_ps(c, m, a, b); } +// conditional division, m ? a / b : 0 +NPY_FINLINE npyv_f32 npyv_ifdivz_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b) +{ return _mm512_maskz_div_ps(m, a, b); } +// division, m ? a / b : c +NPY_FINLINE npyv_f64 npyv_ifdiv_f64(npyv_b32 m, npyv_f64 a, npyv_f64 b, npyv_f64 c) +{ return _mm512_mask_div_pd(c, m, a, b); } +// conditional division, m ? a / b : 0 +NPY_FINLINE npyv_f64 npyv_ifdivz_f64(npyv_b32 m, npyv_f64 a, npyv_f64 b) +{ return _mm512_maskz_div_pd(m, a, b); } + +#endif // _NPY_SIMD_AVX512_MASKOP_H diff --git a/mkl_umath/src/npyv/avx512/math.h b/mkl_umath/src/npyv/avx512/math.h new file mode 100644 index 00000000..97fd2d64 --- /dev/null +++ b/mkl_umath/src/npyv/avx512/math.h @@ -0,0 +1,309 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_MATH_H +#define _NPY_SIMD_AVX512_MATH_H + +/*************************** + * Elementary + ***************************/ +// Square root +#define npyv_sqrt_f32 _mm512_sqrt_ps +#define npyv_sqrt_f64 _mm512_sqrt_pd + +// Reciprocal +NPY_FINLINE npyv_f32 npyv_recip_f32(npyv_f32 a) +{ return _mm512_div_ps(_mm512_set1_ps(1.0f), a); } +NPY_FINLINE npyv_f64 npyv_recip_f64(npyv_f64 a) +{ return _mm512_div_pd(_mm512_set1_pd(1.0), a); } + +// Absolute +NPY_FINLINE npyv_f32 npyv_abs_f32(npyv_f32 a) +{ +#if 0 // def NPY_HAVE_AVX512DQ + return _mm512_range_ps(a, a, 8); +#else + return npyv_and_f32( + a, _mm512_castsi512_ps(_mm512_set1_epi32(0x7fffffff)) + ); +#endif +} +NPY_FINLINE npyv_f64 npyv_abs_f64(npyv_f64 a) +{ +#if 0 // def NPY_HAVE_AVX512DQ + return _mm512_range_pd(a, a, 8); +#else + return npyv_and_f64( + a, _mm512_castsi512_pd(npyv_setall_s64(0x7fffffffffffffffLL)) + ); +#endif +} + +// Square +NPY_FINLINE npyv_f32 npyv_square_f32(npyv_f32 a) +{ return _mm512_mul_ps(a, a); } +NPY_FINLINE npyv_f64 npyv_square_f64(npyv_f64 a) +{ return _mm512_mul_pd(a, a); } + +// Maximum, natively mapping with no guarantees to handle NaN. +#define npyv_max_f32 _mm512_max_ps +#define npyv_max_f64 _mm512_max_pd +// Maximum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_maxp_f32(npyv_f32 a, npyv_f32 b) +{ + __mmask16 nn = _mm512_cmp_ps_mask(b, b, _CMP_ORD_Q); + return _mm512_mask_max_ps(a, nn, a, b); +} +NPY_FINLINE npyv_f64 npyv_maxp_f64(npyv_f64 a, npyv_f64 b) +{ + __mmask8 nn = _mm512_cmp_pd_mask(b, b, _CMP_ORD_Q); + return _mm512_mask_max_pd(a, nn, a, b); +} +// Maximum, propagates NaNs +// If any of corresponded element is NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_maxn_f32(npyv_f32 a, npyv_f32 b) +{ + __mmask16 nn = _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q); + return _mm512_mask_max_ps(a, nn, a, b); +} +NPY_FINLINE npyv_f64 npyv_maxn_f64(npyv_f64 a, npyv_f64 b) +{ + __mmask8 nn = _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q); + return _mm512_mask_max_pd(a, nn, a, b); +} +// Maximum, integer operations +#ifdef NPY_HAVE_AVX512BW + #define npyv_max_u8 _mm512_max_epu8 + #define npyv_max_s8 _mm512_max_epi8 + #define npyv_max_u16 _mm512_max_epu16 + #define npyv_max_s16 _mm512_max_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_u8, _mm256_max_epu8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_s8, _mm256_max_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_u16, _mm256_max_epu16) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_max_s16, _mm256_max_epi16) +#endif +#define npyv_max_u32 _mm512_max_epu32 +#define npyv_max_s32 _mm512_max_epi32 +#define npyv_max_u64 _mm512_max_epu64 +#define npyv_max_s64 _mm512_max_epi64 + +// Minimum, natively mapping with no guarantees to handle NaN. +#define npyv_min_f32 _mm512_min_ps +#define npyv_min_f64 _mm512_min_pd +// Minimum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_minp_f32(npyv_f32 a, npyv_f32 b) +{ + __mmask16 nn = _mm512_cmp_ps_mask(b, b, _CMP_ORD_Q); + return _mm512_mask_min_ps(a, nn, a, b); +} +NPY_FINLINE npyv_f64 npyv_minp_f64(npyv_f64 a, npyv_f64 b) +{ + __mmask8 nn = _mm512_cmp_pd_mask(b, b, _CMP_ORD_Q); + return _mm512_mask_min_pd(a, nn, a, b); +} +// Minimum, propagates NaNs +// If any of corresponded element is NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_minn_f32(npyv_f32 a, npyv_f32 b) +{ + __mmask16 nn = _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q); + return _mm512_mask_min_ps(a, nn, a, b); +} +NPY_FINLINE npyv_f64 npyv_minn_f64(npyv_f64 a, npyv_f64 b) +{ + __mmask8 nn = _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q); + return _mm512_mask_min_pd(a, nn, a, b); +} +// Minimum, integer operations +#ifdef NPY_HAVE_AVX512BW + #define npyv_min_u8 _mm512_min_epu8 + #define npyv_min_s8 _mm512_min_epi8 + #define npyv_min_u16 _mm512_min_epu16 + #define npyv_min_s16 _mm512_min_epi16 +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_u8, _mm256_min_epu8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_s8, _mm256_min_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_u16, _mm256_min_epu16) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_min_s16, _mm256_min_epi16) +#endif +#define npyv_min_u32 _mm512_min_epu32 +#define npyv_min_s32 _mm512_min_epi32 +#define npyv_min_u64 _mm512_min_epu64 +#define npyv_min_s64 _mm512_min_epi64 + +#ifdef NPY_HAVE_AVX512F_REDUCE + #define npyv_reduce_min_u32 _mm512_reduce_min_epu32 + #define npyv_reduce_min_s32 _mm512_reduce_min_epi32 + #define npyv_reduce_min_u64 _mm512_reduce_min_epu64 + #define npyv_reduce_min_s64 _mm512_reduce_min_epi64 + #define npyv_reduce_min_f32 _mm512_reduce_min_ps + #define npyv_reduce_min_f64 _mm512_reduce_min_pd + #define npyv_reduce_max_u32 _mm512_reduce_max_epu32 + #define npyv_reduce_max_s32 _mm512_reduce_max_epi32 + #define npyv_reduce_max_u64 _mm512_reduce_max_epu64 + #define npyv_reduce_max_s64 _mm512_reduce_max_epi64 + #define npyv_reduce_max_f32 _mm512_reduce_max_ps + #define npyv_reduce_max_f64 _mm512_reduce_max_pd +#else + // reduce min&max for 32&64-bits + #define NPY_IMPL_AVX512_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN) \ + NPY_FINLINE STYPE##32 npyv_reduce_##INTRIN##32(__m512i a) \ + { \ + __m256i v256 = _mm256_##VINTRIN##32(npyv512_lower_si256(a), \ + npyv512_higher_si256(a)); \ + __m128i v128 = _mm_##VINTRIN##32(_mm256_castsi256_si128(v256), \ + _mm256_extracti128_si256(v256, 1)); \ + __m128i v64 = _mm_##VINTRIN##32(v128, _mm_shuffle_epi32(v128, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = _mm_##VINTRIN##32(v64, _mm_shuffle_epi32(v64, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + return (STYPE##32)_mm_cvtsi128_si32(v32); \ + } \ + NPY_FINLINE STYPE##64 npyv_reduce_##INTRIN##64(__m512i a) \ + { \ + __m512i v256 = _mm512_##VINTRIN##64(a, \ + _mm512_shuffle_i64x2(a, a, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2))); \ + __m512i v128 = _mm512_##VINTRIN##64(v256, \ + _mm512_shuffle_i64x2(v256, v256, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + __m512i v64 = _mm512_##VINTRIN##64(v128, \ + _mm512_shuffle_epi32(v128, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2))); \ + return (STYPE##64)npyv_extract0_u64(v64); \ + } + + NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, min_u, min_epu) + NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int, min_s, min_epi) + NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, max_u, max_epu) + NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int, max_s, max_epi) + #undef NPY_IMPL_AVX512_REDUCE_MINMAX + // reduce min&max for ps & pd + #define NPY_IMPL_AVX512_REDUCE_MINMAX(INTRIN) \ + NPY_FINLINE float npyv_reduce_##INTRIN##_f32(npyv_f32 a) \ + { \ + __m256 v256 = _mm256_##INTRIN##_ps( \ + npyv512_lower_ps256(a), npyv512_higher_ps256(a)); \ + __m128 v128 = _mm_##INTRIN##_ps( \ + _mm256_castps256_ps128(v256), _mm256_extractf128_ps(v256, 1)); \ + __m128 v64 = _mm_##INTRIN##_ps(v128, \ + _mm_shuffle_ps(v128, v128, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2))); \ + __m128 v32 = _mm_##INTRIN##_ps(v64, \ + _mm_shuffle_ps(v64, v64, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + return _mm_cvtss_f32(v32); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##_f64(npyv_f64 a) \ + { \ + __m256d v256 = _mm256_##INTRIN##_pd( \ + npyv512_lower_pd256(a), npyv512_higher_pd256(a)); \ + __m128d v128 = _mm_##INTRIN##_pd( \ + _mm256_castpd256_pd128(v256), _mm256_extractf128_pd(v256, 1)); \ + __m128d v64 = _mm_##INTRIN##_pd(v128, \ + _mm_shuffle_pd(v128, v128, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + return _mm_cvtsd_f64(v64); \ + } + + NPY_IMPL_AVX512_REDUCE_MINMAX(min) + NPY_IMPL_AVX512_REDUCE_MINMAX(max) + #undef NPY_IMPL_AVX512_REDUCE_MINMAX +#endif +#define NPY_IMPL_AVX512_REDUCE_MINMAX(INTRIN, INF, INF64) \ + NPY_FINLINE float npyv_reduce_##INTRIN##p_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_any_b32(notnan))) { \ + return _mm_cvtss_f32(_mm512_castps512_ps128(a)); \ + } \ + a = npyv_select_f32(notnan, a, \ + npyv_reinterpret_f32_u32(npyv_setall_u32(INF))); \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##p_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_any_b64(notnan))) { \ + return _mm_cvtsd_f64(_mm512_castpd512_pd128(a)); \ + } \ + a = npyv_select_f64(notnan, a, \ + npyv_reinterpret_f64_u64(npyv_setall_u64(INF64))); \ + return npyv_reduce_##INTRIN##_f64(a); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##n_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_all_b32(notnan))) { \ + const union { npy_uint32 i; float f;} pnan = { \ + 0x7fc00000ul \ + }; \ + return pnan.f; \ + } \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##n_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_all_b64(notnan))) { \ + const union { npy_uint64 i; double d;} pnan = { \ + 0x7ff8000000000000ull \ + }; \ + return pnan.d; \ + } \ + return npyv_reduce_##INTRIN##_f64(a); \ + } + +NPY_IMPL_AVX512_REDUCE_MINMAX(min, 0x7f800000, 0x7ff0000000000000) +NPY_IMPL_AVX512_REDUCE_MINMAX(max, 0xff800000, 0xfff0000000000000) +#undef NPY_IMPL_AVX512_REDUCE_MINMAX + +// reduce min&max for 8&16-bits +#define NPY_IMPL_AVX512_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN) \ + NPY_FINLINE STYPE##16 npyv_reduce_##INTRIN##16(__m512i a) \ + { \ + __m256i v256 = _mm256_##VINTRIN##16(npyv512_lower_si256(a), npyv512_higher_si256(a)); \ + __m128i v128 = _mm_##VINTRIN##16(_mm256_castsi256_si128(v256), _mm256_extracti128_si256(v256, 1)); \ + __m128i v64 = _mm_##VINTRIN##16(v128, _mm_shuffle_epi32(v128, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = _mm_##VINTRIN##16(v64, _mm_shuffle_epi32(v64, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v16 = _mm_##VINTRIN##16(v32, _mm_shufflelo_epi16(v32, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + return (STYPE##16)_mm_cvtsi128_si32(v16); \ + } \ + NPY_FINLINE STYPE##8 npyv_reduce_##INTRIN##8(__m512i a) \ + { \ + __m256i v256 = _mm256_##VINTRIN##8(npyv512_lower_si256(a), npyv512_higher_si256(a)); \ + __m128i v128 = _mm_##VINTRIN##8(_mm256_castsi256_si128(v256), _mm256_extracti128_si256(v256, 1)); \ + __m128i v64 = _mm_##VINTRIN##8(v128, _mm_shuffle_epi32(v128, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = _mm_##VINTRIN##8(v64, _mm_shuffle_epi32(v64, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v16 = _mm_##VINTRIN##8(v32, _mm_shufflelo_epi16(v32, \ + (_MM_PERM_ENUM)_MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v8 = _mm_##VINTRIN##8(v16, _mm_srli_epi16(v16, 8)); \ + return (STYPE##16)_mm_cvtsi128_si32(v8); \ + } +NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, min_u, min_epu) +NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int, min_s, min_epi) +NPY_IMPL_AVX512_REDUCE_MINMAX(npy_uint, max_u, max_epu) +NPY_IMPL_AVX512_REDUCE_MINMAX(npy_int, max_s, max_epi) +#undef NPY_IMPL_AVX512_REDUCE_MINMAX + +// round to nearest integer even +#define npyv_rint_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_NEAREST_INT) +#define npyv_rint_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_NEAREST_INT) + +// ceil +#define npyv_ceil_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_POS_INF) +#define npyv_ceil_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_POS_INF) + +// trunc +#define npyv_trunc_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_ZERO) +#define npyv_trunc_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_ZERO) + +// floor +#define npyv_floor_f32(A) _mm512_roundscale_ps(A, _MM_FROUND_TO_NEG_INF) +#define npyv_floor_f64(A) _mm512_roundscale_pd(A, _MM_FROUND_TO_NEG_INF) + +#endif // _NPY_SIMD_AVX512_MATH_H diff --git a/mkl_umath/src/npyv/avx512/memory.h b/mkl_umath/src/npyv/avx512/memory.h new file mode 100644 index 00000000..e981ef8f --- /dev/null +++ b/mkl_umath/src/npyv/avx512/memory.h @@ -0,0 +1,715 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_MEMORY_H +#define _NPY_SIMD_AVX512_MEMORY_H + +#include "misc.h" + +/*************************** + * load/store + ***************************/ +#if defined(__GNUC__) + // GCC expect pointer argument type to be `void*` instead of `const void *`, + // which cause a massive warning. + #define npyv__loads(PTR) _mm512_stream_load_si512((__m512i*)(PTR)) +#else + #define npyv__loads(PTR) _mm512_stream_load_si512((const __m512i*)(PTR)) +#endif +#if defined(_MSC_VER) && defined(_M_IX86) + // workaround msvc(32bit) overflow bug, reported at + // https://developercommunity.visualstudio.com/content/problem/911872/u.html + NPY_FINLINE __m512i npyv__loadl(const __m256i *ptr) + { + __m256i a = _mm256_loadu_si256(ptr); + return _mm512_inserti64x4(_mm512_castsi256_si512(a), a, 0); + } +#else + #define npyv__loadl(PTR) \ + _mm512_castsi256_si512(_mm256_loadu_si256(PTR)) +#endif +#define NPYV_IMPL_AVX512_MEM_INT(CTYPE, SFX) \ + NPY_FINLINE npyv_##SFX npyv_load_##SFX(const CTYPE *ptr) \ + { return _mm512_loadu_si512((const __m512i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loada_##SFX(const CTYPE *ptr) \ + { return _mm512_load_si512((const __m512i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loads_##SFX(const CTYPE *ptr) \ + { return npyv__loads(ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loadl_##SFX(const CTYPE *ptr) \ + { return npyv__loadl((const __m256i *)ptr); } \ + NPY_FINLINE void npyv_store_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm512_storeu_si512((__m512i*)ptr, vec); } \ + NPY_FINLINE void npyv_storea_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm512_store_si512((__m512i*)ptr, vec); } \ + NPY_FINLINE void npyv_stores_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm512_stream_si512((__m512i*)ptr, vec); } \ + NPY_FINLINE void npyv_storel_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm256_storeu_si256((__m256i*)ptr, npyv512_lower_si256(vec)); } \ + NPY_FINLINE void npyv_storeh_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm256_storeu_si256((__m256i*)(ptr), npyv512_higher_si256(vec)); } + +NPYV_IMPL_AVX512_MEM_INT(npy_uint8, u8) +NPYV_IMPL_AVX512_MEM_INT(npy_int8, s8) +NPYV_IMPL_AVX512_MEM_INT(npy_uint16, u16) +NPYV_IMPL_AVX512_MEM_INT(npy_int16, s16) +NPYV_IMPL_AVX512_MEM_INT(npy_uint32, u32) +NPYV_IMPL_AVX512_MEM_INT(npy_int32, s32) +NPYV_IMPL_AVX512_MEM_INT(npy_uint64, u64) +NPYV_IMPL_AVX512_MEM_INT(npy_int64, s64) + +// unaligned load +#define npyv_load_f32(PTR) _mm512_loadu_ps((const __m512*)(PTR)) +#define npyv_load_f64(PTR) _mm512_loadu_pd((const __m512d*)(PTR)) +// aligned load +#define npyv_loada_f32(PTR) _mm512_load_ps((const __m512*)(PTR)) +#define npyv_loada_f64(PTR) _mm512_load_pd((const __m512d*)(PTR)) +// load lower part +#if defined(_MSC_VER) && defined(_M_IX86) + #define npyv_loadl_f32(PTR) _mm512_castsi512_ps(npyv__loadl((const __m256i *)(PTR))) + #define npyv_loadl_f64(PTR) _mm512_castsi512_pd(npyv__loadl((const __m256i *)(PTR))) +#else + #define npyv_loadl_f32(PTR) _mm512_castps256_ps512(_mm256_loadu_ps(PTR)) + #define npyv_loadl_f64(PTR) _mm512_castpd256_pd512(_mm256_loadu_pd(PTR)) +#endif +// stream load +#define npyv_loads_f32(PTR) _mm512_castsi512_ps(npyv__loads(PTR)) +#define npyv_loads_f64(PTR) _mm512_castsi512_pd(npyv__loads(PTR)) +// unaligned store +#define npyv_store_f32 _mm512_storeu_ps +#define npyv_store_f64 _mm512_storeu_pd +// aligned store +#define npyv_storea_f32 _mm512_store_ps +#define npyv_storea_f64 _mm512_store_pd +// stream store +#define npyv_stores_f32 _mm512_stream_ps +#define npyv_stores_f64 _mm512_stream_pd +// store lower part +#define npyv_storel_f32(PTR, VEC) _mm256_storeu_ps(PTR, npyv512_lower_ps256(VEC)) +#define npyv_storel_f64(PTR, VEC) _mm256_storeu_pd(PTR, npyv512_lower_pd256(VEC)) +// store higher part +#define npyv_storeh_f32(PTR, VEC) _mm256_storeu_ps(PTR, npyv512_higher_ps256(VEC)) +#define npyv_storeh_f64(PTR, VEC) _mm256_storeu_pd(PTR, npyv512_higher_pd256(VEC)) +/*************************** + * Non-contiguous Load + ***************************/ +//// 32 +NPY_FINLINE npyv_u32 npyv_loadn_u32(const npy_uint32 *ptr, npy_intp stride) +{ + assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE32); + const __m512i steps = npyv_set_s32( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride)); + return _mm512_i32gather_epi32(idx, (const __m512i*)ptr, 4); +} +NPY_FINLINE npyv_s32 npyv_loadn_s32(const npy_int32 *ptr, npy_intp stride) +{ return npyv_loadn_u32((const npy_uint32*)ptr, stride); } +NPY_FINLINE npyv_f32 npyv_loadn_f32(const float *ptr, npy_intp stride) +{ return _mm512_castsi512_ps(npyv_loadn_u32((const npy_uint32*)ptr, stride)); } +//// 64 +NPY_FINLINE npyv_u64 npyv_loadn_u64(const npy_uint64 *ptr, npy_intp stride) +{ + const __m512i idx = npyv_set_s64( + 0*stride, 1*stride, 2*stride, 3*stride, + 4*stride, 5*stride, 6*stride, 7*stride + ); + return _mm512_i64gather_epi64(idx, (const __m512i*)ptr, 8); +} +NPY_FINLINE npyv_s64 npyv_loadn_s64(const npy_int64 *ptr, npy_intp stride) +{ return npyv_loadn_u64((const npy_uint64*)ptr, stride); } +NPY_FINLINE npyv_f64 npyv_loadn_f64(const double *ptr, npy_intp stride) +{ return _mm512_castsi512_pd(npyv_loadn_u64((const npy_uint64*)ptr, stride)); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_u32 npyv_loadn2_u32(const npy_uint32 *ptr, npy_intp stride) +{ + __m128d a = _mm_loadh_pd( + _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)ptr)), + (const double*)(ptr + stride) + ); + __m128d b = _mm_loadh_pd( + _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*2))), + (const double*)(ptr + stride*3) + ); + __m128d c = _mm_loadh_pd( + _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*4))), + (const double*)(ptr + stride*5) + ); + __m128d d = _mm_loadh_pd( + _mm_castsi128_pd(_mm_loadl_epi64((const __m128i*)(ptr + stride*6))), + (const double*)(ptr + stride*7) + ); + return _mm512_castpd_si512(npyv512_combine_pd256( + _mm256_insertf128_pd(_mm256_castpd128_pd256(a), b, 1), + _mm256_insertf128_pd(_mm256_castpd128_pd256(c), d, 1) + )); +} +NPY_FINLINE npyv_s32 npyv_loadn2_s32(const npy_int32 *ptr, npy_intp stride) +{ return npyv_loadn2_u32((const npy_uint32*)ptr, stride); } +NPY_FINLINE npyv_f32 npyv_loadn2_f32(const float *ptr, npy_intp stride) +{ return _mm512_castsi512_ps(npyv_loadn2_u32((const npy_uint32*)ptr, stride)); } + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_f64 npyv_loadn2_f64(const double *ptr, npy_intp stride) +{ + __m128d a = _mm_loadu_pd(ptr); + __m128d b = _mm_loadu_pd(ptr + stride); + __m128d c = _mm_loadu_pd(ptr + stride * 2); + __m128d d = _mm_loadu_pd(ptr + stride * 3); + return npyv512_combine_pd256( + _mm256_insertf128_pd(_mm256_castpd128_pd256(a), b, 1), + _mm256_insertf128_pd(_mm256_castpd128_pd256(c), d, 1) + ); +} +NPY_FINLINE npyv_u64 npyv_loadn2_u64(const npy_uint64 *ptr, npy_intp stride) +{ return npyv_reinterpret_u64_f64(npyv_loadn2_f64((const double*)ptr, stride)); } +NPY_FINLINE npyv_s64 npyv_loadn2_s64(const npy_int64 *ptr, npy_intp stride) +{ return npyv_loadn2_u64((const npy_uint64*)ptr, stride); } +/*************************** + * Non-contiguous Store + ***************************/ +//// 32 +NPY_FINLINE void npyv_storen_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ + assert(llabs(stride) <= NPY_SIMD_MAXSTORE_STRIDE32); + const __m512i steps = _mm512_setr_epi32( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride)); + _mm512_i32scatter_epi32((__m512i*)ptr, idx, a, 4); +} +NPY_FINLINE void npyv_storen_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen_u32((npy_uint32*)ptr, stride, a); } +NPY_FINLINE void npyv_storen_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen_u32((npy_uint32*)ptr, stride, _mm512_castps_si512(a)); } +//// 64 +NPY_FINLINE void npyv_storen_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ + const __m512i idx = npyv_set_s64( + 0*stride, 1*stride, 2*stride, 3*stride, + 4*stride, 5*stride, 6*stride, 7*stride + ); + _mm512_i64scatter_epi64((__m512i*)ptr, idx, a, 8); +} +NPY_FINLINE void npyv_storen_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ npyv_storen_u64((npy_uint64*)ptr, stride, a); } +NPY_FINLINE void npyv_storen_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ npyv_storen_u64((npy_uint64*)ptr, stride, _mm512_castpd_si512(a)); } + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ + __m256d lo = _mm512_castpd512_pd256(_mm512_castsi512_pd(a)); + __m256d hi = _mm512_extractf64x4_pd(_mm512_castsi512_pd(a), 1); + __m128d e0 = _mm256_castpd256_pd128(lo); + __m128d e1 = _mm256_extractf128_pd(lo, 1); + __m128d e2 = _mm256_castpd256_pd128(hi); + __m128d e3 = _mm256_extractf128_pd(hi, 1); + _mm_storel_pd((double*)(ptr + stride * 0), e0); + _mm_storeh_pd((double*)(ptr + stride * 1), e0); + _mm_storel_pd((double*)(ptr + stride * 2), e1); + _mm_storeh_pd((double*)(ptr + stride * 3), e1); + _mm_storel_pd((double*)(ptr + stride * 4), e2); + _mm_storeh_pd((double*)(ptr + stride * 5), e2); + _mm_storel_pd((double*)(ptr + stride * 6), e3); + _mm_storeh_pd((double*)(ptr + stride * 7), e3); +} +NPY_FINLINE void npyv_storen2_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, a); } +NPY_FINLINE void npyv_storen2_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, _mm512_castps_si512(a)); } + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ + __m256i lo = npyv512_lower_si256(a); + __m256i hi = npyv512_higher_si256(a); + __m128i e0 = _mm256_castsi256_si128(lo); + __m128i e1 = _mm256_extracti128_si256(lo, 1); + __m128i e2 = _mm256_castsi256_si128(hi); + __m128i e3 = _mm256_extracti128_si256(hi, 1); + _mm_storeu_si128((__m128i*)(ptr + stride * 0), e0); + _mm_storeu_si128((__m128i*)(ptr + stride * 1), e1); + _mm_storeu_si128((__m128i*)(ptr + stride * 2), e2); + _mm_storeu_si128((__m128i*)(ptr + stride * 3), e3); +} +NPY_FINLINE void npyv_storen2_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ npyv_storen2_u64((npy_uint64*)ptr, stride, a); } +NPY_FINLINE void npyv_storen2_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ npyv_storen2_u64((npy_uint64*)ptr, stride, _mm512_castpd_si512(a)); } + +/********************************* + * Partial Load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 npyv_load_till_s32(const npy_int32 *ptr, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + const __m512i vfill = _mm512_set1_epi32(fill); + const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_mask_loadu_epi32(vfill, mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_maskz_loadu_epi32(mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +//// 64 +NPY_FINLINE npyv_s64 npyv_load_till_s64(const npy_int64 *ptr, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + const __m512i vfill = npyv_setall_s64(fill); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_mask_loadu_epi64(vfill, mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_load_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_maskz_loadu_epi64(mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} + +//// 64-bit nlane +NPY_FINLINE npyv_s32 npyv_load2_till_s32(const npy_int32 *ptr, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + const __m512i vfill = _mm512_set4_epi32(fill_hi, fill_lo, fill_hi, fill_lo); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_mask_loadu_epi64(vfill, mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load2_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ return npyv_load_tillz_s64((const npy_int64*)ptr, nlane); } + +//// 128-bit nlane +NPY_FINLINE npyv_u64 npyv_load2_till_s64(const npy_int64 *ptr, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ + assert(nlane > 0); + const __m512i vfill = _mm512_set4_epi64(fill_hi, fill_lo, fill_hi, fill_lo); + const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1; + __m512i ret = _mm512_mask_loadu_epi64(vfill, mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_load2_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1; + __m512i ret = _mm512_maskz_loadu_epi64(mask, (const __m512i*)ptr); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +/********************************* + * Non-contiguous partial load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 +npyv_loadn_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + assert(llabs(stride) <= NPY_SIMD_MAXLOAD_STRIDE32); + const __m512i steps = npyv_set_s32( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride)); + const __m512i vfill = _mm512_set1_epi32(fill); + const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_mask_i32gather_epi32(vfill, mask, idx, (const __m512i*)ptr, 4); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 +npyv_loadn_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s32(ptr, stride, nlane, 0); } +//// 64 +NPY_FINLINE npyv_s64 +npyv_loadn_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + const __m512i idx = npyv_set_s64( + 0*stride, 1*stride, 2*stride, 3*stride, + 4*stride, 5*stride, 6*stride, 7*stride + ); + const __m512i vfill = npyv_setall_s64(fill); + const __mmask8 mask = nlane > 15 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_mask_i64gather_epi64(vfill, mask, idx, (const __m512i*)ptr, 8); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 +npyv_loadn_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s64(ptr, stride, nlane, 0); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + const __m512i idx = npyv_set_s64( + 0*stride, 1*stride, 2*stride, 3*stride, + 4*stride, 5*stride, 6*stride, 7*stride + ); + const __m512i vfill = _mm512_set4_epi32(fill_hi, fill_lo, fill_hi, fill_lo); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + __m512i ret = _mm512_mask_i64gather_epi64(vfill, mask, idx, (const __m512i*)ptr, 4); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_loadn2_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn2_till_s32(ptr, stride, nlane, 0, 0); } + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ + assert(nlane > 0); + const __m512i idx = npyv_set_s64( + 0, 1, stride, stride+1, + stride*2, stride*2+1, stride*3, stride*3+1 + ); + const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1; + const __m512i vfill = _mm512_set4_epi64(fill_hi, fill_lo, fill_hi, fill_lo); + __m512i ret = _mm512_mask_i64gather_epi64(vfill, mask, idx, (const __m512i*)ptr, 8); +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m512i workaround = ret; + ret = _mm512_or_si512(workaround, ret); +#endif + return ret; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_loadn2_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn2_till_s64(ptr, stride, nlane, 0, 0); } + +/********************************* + * Partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_store_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1; + _mm512_mask_storeu_epi32((__m512i*)ptr, mask, a); +} +//// 64 +NPY_FINLINE void npyv_store_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + _mm512_mask_storeu_epi64((__m512i*)ptr, mask, a); +} + +//// 64-bit nlane +NPY_FINLINE void npyv_store2_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + _mm512_mask_storeu_epi64((__m512i*)ptr, mask, a); +} + +//// 128-bit nlane +NPY_FINLINE void npyv_store2_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1; + _mm512_mask_storeu_epi64((__m512i*)ptr, mask, a); +} +/********************************* + * Non-contiguous partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_storen_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + assert(llabs(stride) <= NPY_SIMD_MAXSTORE_STRIDE32); + const __m512i steps = _mm512_setr_epi32( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + const __m512i idx = _mm512_mullo_epi32(steps, _mm512_set1_epi32((int)stride)); + const __mmask16 mask = nlane > 15 ? -1 : (1 << nlane) - 1; + _mm512_mask_i32scatter_epi32((__m512i*)ptr, mask, idx, a, 4); +} +//// 64 +NPY_FINLINE void npyv_storen_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + const __m512i idx = npyv_set_s64( + 0*stride, 1*stride, 2*stride, 3*stride, + 4*stride, 5*stride, 6*stride, 7*stride + ); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + _mm512_mask_i64scatter_epi64((__m512i*)ptr, mask, idx, a, 8); +} + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + const __m512i idx = npyv_set_s64( + 0*stride, 1*stride, 2*stride, 3*stride, + 4*stride, 5*stride, 6*stride, 7*stride + ); + const __mmask8 mask = nlane > 7 ? -1 : (1 << nlane) - 1; + _mm512_mask_i64scatter_epi64((__m512i*)ptr, mask, idx, a, 4); +} + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + const __m512i idx = npyv_set_s64( + 0, 1, stride, stride+1, + 2*stride, 2*stride+1, 3*stride, 3*stride+1 + ); + const __mmask8 mask = nlane > 3 ? -1 : (1 << (nlane*2)) - 1; + _mm512_mask_i64scatter_epi64((__m512i*)ptr, mask, idx, a, 8); +} + +/***************************************************************************** + * Implement partial load/store for u32/f32/u64/f64... via reinterpret cast + *****************************************************************************/ +#define NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(u32, s32) +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(f32, s32) +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(u64, s64) +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES(f64, s64) + +// 128-bit/64-bit stride (pair load/store) +#define NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun_lo.to_##T_SFX, pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun_lo.to_##T_SFX, \ + pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(u32, s32) +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(f32, s32) +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(u64, s64) +NPYV_IMPL_AVX512_REST_PARTIAL_TYPES_PAIR(f64, s64) + +/************************************************************ + * de-interlave load / interleave contiguous store + ************************************************************/ +// two channels +#define NPYV_IMPL_AVX512_MEM_INTERLEAVE(SFX, ZSFX) \ + NPY_FINLINE npyv_##ZSFX##x2 npyv_zip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX); \ + NPY_FINLINE npyv_##ZSFX##x2 npyv_unzip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX); \ + NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2( \ + const npyv_lanetype_##SFX *ptr \ + ) { \ + return npyv_unzip_##ZSFX( \ + npyv_load_##SFX(ptr), npyv_load_##SFX(ptr+npyv_nlanes_##SFX) \ + ); \ + } \ + NPY_FINLINE void npyv_store_##SFX##x2( \ + npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v \ + ) { \ + npyv_##SFX##x2 zip = npyv_zip_##ZSFX(v.val[0], v.val[1]); \ + npyv_store_##SFX(ptr, zip.val[0]); \ + npyv_store_##SFX(ptr + npyv_nlanes_##SFX, zip.val[1]); \ + } + +NPYV_IMPL_AVX512_MEM_INTERLEAVE(u8, u8) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(s8, u8) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(u16, u16) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(s16, u16) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(u32, u32) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(s32, u32) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(u64, u64) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(s64, u64) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(f32, f32) +NPYV_IMPL_AVX512_MEM_INTERLEAVE(f64, f64) + +/************************************************** + * Lookup table + *************************************************/ +// uses vector as indexes into a table +// that contains 32 elements of float32. +NPY_FINLINE npyv_f32 npyv_lut32_f32(const float *table, npyv_u32 idx) +{ + const npyv_f32 table0 = npyv_load_f32(table); + const npyv_f32 table1 = npyv_load_f32(table + 16); + return _mm512_permutex2var_ps(table0, idx, table1); +} +NPY_FINLINE npyv_u32 npyv_lut32_u32(const npy_uint32 *table, npyv_u32 idx) +{ return npyv_reinterpret_u32_f32(npyv_lut32_f32((const float*)table, idx)); } +NPY_FINLINE npyv_s32 npyv_lut32_s32(const npy_int32 *table, npyv_u32 idx) +{ return npyv_reinterpret_s32_f32(npyv_lut32_f32((const float*)table, idx)); } + +// uses vector as indexes into a table +// that contains 16 elements of float64. +NPY_FINLINE npyv_f64 npyv_lut16_f64(const double *table, npyv_u64 idx) +{ + const npyv_f64 table0 = npyv_load_f64(table); + const npyv_f64 table1 = npyv_load_f64(table + 8); + return _mm512_permutex2var_pd(table0, idx, table1); +} +NPY_FINLINE npyv_u64 npyv_lut16_u64(const npy_uint64 *table, npyv_u64 idx) +{ return npyv_reinterpret_u64_f64(npyv_lut16_f64((const double*)table, idx)); } +NPY_FINLINE npyv_s64 npyv_lut16_s64(const npy_int64 *table, npyv_u64 idx) +{ return npyv_reinterpret_s64_f64(npyv_lut16_f64((const double*)table, idx)); } + +#endif // _NPY_SIMD_AVX512_MEMORY_H diff --git a/mkl_umath/src/npyv/avx512/misc.h b/mkl_umath/src/npyv/avx512/misc.h new file mode 100644 index 00000000..d9190870 --- /dev/null +++ b/mkl_umath/src/npyv/avx512/misc.h @@ -0,0 +1,292 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_MISC_H +#define _NPY_SIMD_AVX512_MISC_H + +// set all lanes to zero +#define npyv_zero_u8 _mm512_setzero_si512 +#define npyv_zero_s8 _mm512_setzero_si512 +#define npyv_zero_u16 _mm512_setzero_si512 +#define npyv_zero_s16 _mm512_setzero_si512 +#define npyv_zero_u32 _mm512_setzero_si512 +#define npyv_zero_s32 _mm512_setzero_si512 +#define npyv_zero_u64 _mm512_setzero_si512 +#define npyv_zero_s64 _mm512_setzero_si512 +#define npyv_zero_f32 _mm512_setzero_ps +#define npyv_zero_f64 _mm512_setzero_pd + +// set all lanes to same value +#define npyv_setall_u8(VAL) _mm512_set1_epi8((char)VAL) +#define npyv_setall_s8(VAL) _mm512_set1_epi8((char)VAL) +#define npyv_setall_u16(VAL) _mm512_set1_epi16((short)VAL) +#define npyv_setall_s16(VAL) _mm512_set1_epi16((short)VAL) +#define npyv_setall_u32(VAL) _mm512_set1_epi32((int)VAL) +#define npyv_setall_s32(VAL) _mm512_set1_epi32(VAL) +#define npyv_setall_f32(VAL) _mm512_set1_ps(VAL) +#define npyv_setall_f64(VAL) _mm512_set1_pd(VAL) + +NPY_FINLINE __m512i npyv__setr_epi64( + npy_int64, npy_int64, npy_int64, npy_int64, + npy_int64, npy_int64, npy_int64, npy_int64 +); +NPY_FINLINE npyv_u64 npyv_setall_u64(npy_uint64 a) +{ + npy_int64 ai = (npy_int64)a; +#if defined(_MSC_VER) && defined(_M_IX86) + return npyv__setr_epi64(ai, ai, ai, ai, ai, ai, ai, ai); +#else + return _mm512_set1_epi64(ai); +#endif +} +NPY_FINLINE npyv_s64 npyv_setall_s64(npy_int64 a) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return npyv__setr_epi64(a, a, a, a, a, a, a, a); +#else + return _mm512_set1_epi64(a); +#endif +} +/** + * vector with specific values set to each lane and + * set a specific value to all remained lanes + * + * _mm512_set_epi8 and _mm512_set_epi16 are missing in many compilers + */ +NPY_FINLINE __m512i npyv__setr_epi8( + char i0, char i1, char i2, char i3, char i4, char i5, char i6, char i7, + char i8, char i9, char i10, char i11, char i12, char i13, char i14, char i15, + char i16, char i17, char i18, char i19, char i20, char i21, char i22, char i23, + char i24, char i25, char i26, char i27, char i28, char i29, char i30, char i31, + char i32, char i33, char i34, char i35, char i36, char i37, char i38, char i39, + char i40, char i41, char i42, char i43, char i44, char i45, char i46, char i47, + char i48, char i49, char i50, char i51, char i52, char i53, char i54, char i55, + char i56, char i57, char i58, char i59, char i60, char i61, char i62, char i63) +{ + const char NPY_DECL_ALIGNED(64) data[64] = { + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, + i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31, + i32, i33, i34, i35, i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, + i48, i49, i50, i51, i52, i53, i54, i55, i56, i57, i58, i59, i60, i61, i62, i63 + }; + return _mm512_load_si512((const void*)data); +} +NPY_FINLINE __m512i npyv__setr_epi16( + short i0, short i1, short i2, short i3, short i4, short i5, short i6, short i7, + short i8, short i9, short i10, short i11, short i12, short i13, short i14, short i15, + short i16, short i17, short i18, short i19, short i20, short i21, short i22, short i23, + short i24, short i25, short i26, short i27, short i28, short i29, short i30, short i31) +{ + const short NPY_DECL_ALIGNED(64) data[32] = { + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, + i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31 + }; + return _mm512_load_si512((const void*)data); +} +// args that generated by NPYV__SET_FILL_* not going to expand if +// _mm512_setr_* are defined as macros. +NPY_FINLINE __m512i npyv__setr_epi32( + int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, + int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15) +{ + return _mm512_setr_epi32(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15); +} +NPY_FINLINE __m512i npyv__setr_epi64(npy_int64 i0, npy_int64 i1, npy_int64 i2, npy_int64 i3, + npy_int64 i4, npy_int64 i5, npy_int64 i6, npy_int64 i7) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return _mm512_setr_epi32( + (int)i0, (int)(i0 >> 32), (int)i1, (int)(i1 >> 32), + (int)i2, (int)(i2 >> 32), (int)i3, (int)(i3 >> 32), + (int)i4, (int)(i4 >> 32), (int)i5, (int)(i5 >> 32), + (int)i6, (int)(i6 >> 32), (int)i7, (int)(i7 >> 32) + ); +#else + return _mm512_setr_epi64(i0, i1, i2, i3, i4, i5, i6, i7); +#endif +} + +NPY_FINLINE __m512 npyv__setr_ps( + float i0, float i1, float i2, float i3, float i4, float i5, float i6, float i7, + float i8, float i9, float i10, float i11, float i12, float i13, float i14, float i15) +{ + return _mm512_setr_ps(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15); +} +NPY_FINLINE __m512d npyv__setr_pd(double i0, double i1, double i2, double i3, + double i4, double i5, double i6, double i7) +{ + return _mm512_setr_pd(i0, i1, i2, i3, i4, i5, i6, i7); +} +#define npyv_setf_u8(FILL, ...) npyv__setr_epi8(NPYV__SET_FILL_64(char, FILL, __VA_ARGS__)) +#define npyv_setf_s8(FILL, ...) npyv__setr_epi8(NPYV__SET_FILL_64(char, FILL, __VA_ARGS__)) +#define npyv_setf_u16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_32(short, FILL, __VA_ARGS__)) +#define npyv_setf_s16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_32(short, FILL, __VA_ARGS__)) +#define npyv_setf_u32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_16(int, FILL, __VA_ARGS__)) +#define npyv_setf_s32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_16(int, FILL, __VA_ARGS__)) +#define npyv_setf_u64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_8(npy_int64, FILL, __VA_ARGS__)) +#define npyv_setf_s64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_8(npy_int64, FILL, __VA_ARGS__)) +#define npyv_setf_f32(FILL, ...) npyv__setr_ps(NPYV__SET_FILL_16(float, FILL, __VA_ARGS__)) +#define npyv_setf_f64(FILL, ...) npyv__setr_pd(NPYV__SET_FILL_8(double, FILL, __VA_ARGS__)) + +// vector with specific values set to each lane and +// set zero to all remained lanes +#define npyv_set_u8(...) npyv_setf_u8(0, __VA_ARGS__) +#define npyv_set_s8(...) npyv_setf_s8(0, __VA_ARGS__) +#define npyv_set_u16(...) npyv_setf_u16(0, __VA_ARGS__) +#define npyv_set_s16(...) npyv_setf_s16(0, __VA_ARGS__) +#define npyv_set_u32(...) npyv_setf_u32(0, __VA_ARGS__) +#define npyv_set_s32(...) npyv_setf_s32(0, __VA_ARGS__) +#define npyv_set_u64(...) npyv_setf_u64(0, __VA_ARGS__) +#define npyv_set_s64(...) npyv_setf_s64(0, __VA_ARGS__) +#define npyv_set_f32(...) npyv_setf_f32(0, __VA_ARGS__) +#define npyv_set_f64(...) npyv_setf_f64(0, __VA_ARGS__) + +// per lane select +#ifdef NPY_HAVE_AVX512BW + #define npyv_select_u8(MASK, A, B) _mm512_mask_blend_epi8(MASK, B, A) + #define npyv_select_u16(MASK, A, B) _mm512_mask_blend_epi16(MASK, B, A) +#else + NPY_FINLINE __m512i npyv_select_u8(__m512i mask, __m512i a, __m512i b) + { return _mm512_xor_si512(b, _mm512_and_si512(_mm512_xor_si512(b, a), mask)); } + #define npyv_select_u16 npyv_select_u8 +#endif +#define npyv_select_s8 npyv_select_u8 +#define npyv_select_s16 npyv_select_u16 +#define npyv_select_u32(MASK, A, B) _mm512_mask_blend_epi32(MASK, B, A) +#define npyv_select_s32 npyv_select_u32 +#define npyv_select_u64(MASK, A, B) _mm512_mask_blend_epi64(MASK, B, A) +#define npyv_select_s64 npyv_select_u64 +#define npyv_select_f32(MASK, A, B) _mm512_mask_blend_ps(MASK, B, A) +#define npyv_select_f64(MASK, A, B) _mm512_mask_blend_pd(MASK, B, A) + +// extract the first vector's lane +#define npyv_extract0_u8(A) ((npy_uint8)_mm_cvtsi128_si32(_mm512_castsi512_si128(A))) +#define npyv_extract0_s8(A) ((npy_int8)_mm_cvtsi128_si32(_mm512_castsi512_si128(A))) +#define npyv_extract0_u16(A) ((npy_uint16)_mm_cvtsi128_si32(_mm512_castsi512_si128(A))) +#define npyv_extract0_s16(A) ((npy_int16)_mm_cvtsi128_si32(_mm512_castsi512_si128(A))) +#define npyv_extract0_u32(A) ((npy_uint32)_mm_cvtsi128_si32(_mm512_castsi512_si128(A))) +#define npyv_extract0_s32(A) ((npy_int32)_mm_cvtsi128_si32(_mm512_castsi512_si128(A))) +#define npyv_extract0_u64(A) ((npy_uint64)npyv128_cvtsi128_si64(_mm512_castsi512_si128(A))) +#define npyv_extract0_s64(A) ((npy_int64)npyv128_cvtsi128_si64(_mm512_castsi512_si128(A))) +#define npyv_extract0_f32(A) _mm_cvtss_f32(_mm512_castps512_ps128(A)) +#define npyv_extract0_f64(A) _mm_cvtsd_f64(_mm512_castpd512_pd128(A)) + +// reinterpret +#define npyv_reinterpret_u8_u8(X) X +#define npyv_reinterpret_u8_s8(X) X +#define npyv_reinterpret_u8_u16(X) X +#define npyv_reinterpret_u8_s16(X) X +#define npyv_reinterpret_u8_u32(X) X +#define npyv_reinterpret_u8_s32(X) X +#define npyv_reinterpret_u8_u64(X) X +#define npyv_reinterpret_u8_s64(X) X +#define npyv_reinterpret_u8_f32 _mm512_castps_si512 +#define npyv_reinterpret_u8_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_s8_s8(X) X +#define npyv_reinterpret_s8_u8(X) X +#define npyv_reinterpret_s8_u16(X) X +#define npyv_reinterpret_s8_s16(X) X +#define npyv_reinterpret_s8_u32(X) X +#define npyv_reinterpret_s8_s32(X) X +#define npyv_reinterpret_s8_u64(X) X +#define npyv_reinterpret_s8_s64(X) X +#define npyv_reinterpret_s8_f32 _mm512_castps_si512 +#define npyv_reinterpret_s8_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_u16_u16(X) X +#define npyv_reinterpret_u16_u8(X) X +#define npyv_reinterpret_u16_s8(X) X +#define npyv_reinterpret_u16_s16(X) X +#define npyv_reinterpret_u16_u32(X) X +#define npyv_reinterpret_u16_s32(X) X +#define npyv_reinterpret_u16_u64(X) X +#define npyv_reinterpret_u16_s64(X) X +#define npyv_reinterpret_u16_f32 _mm512_castps_si512 +#define npyv_reinterpret_u16_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_s16_s16(X) X +#define npyv_reinterpret_s16_u8(X) X +#define npyv_reinterpret_s16_s8(X) X +#define npyv_reinterpret_s16_u16(X) X +#define npyv_reinterpret_s16_u32(X) X +#define npyv_reinterpret_s16_s32(X) X +#define npyv_reinterpret_s16_u64(X) X +#define npyv_reinterpret_s16_s64(X) X +#define npyv_reinterpret_s16_f32 _mm512_castps_si512 +#define npyv_reinterpret_s16_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_u32_u32(X) X +#define npyv_reinterpret_u32_u8(X) X +#define npyv_reinterpret_u32_s8(X) X +#define npyv_reinterpret_u32_u16(X) X +#define npyv_reinterpret_u32_s16(X) X +#define npyv_reinterpret_u32_s32(X) X +#define npyv_reinterpret_u32_u64(X) X +#define npyv_reinterpret_u32_s64(X) X +#define npyv_reinterpret_u32_f32 _mm512_castps_si512 +#define npyv_reinterpret_u32_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_s32_s32(X) X +#define npyv_reinterpret_s32_u8(X) X +#define npyv_reinterpret_s32_s8(X) X +#define npyv_reinterpret_s32_u16(X) X +#define npyv_reinterpret_s32_s16(X) X +#define npyv_reinterpret_s32_u32(X) X +#define npyv_reinterpret_s32_u64(X) X +#define npyv_reinterpret_s32_s64(X) X +#define npyv_reinterpret_s32_f32 _mm512_castps_si512 +#define npyv_reinterpret_s32_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_u64_u64(X) X +#define npyv_reinterpret_u64_u8(X) X +#define npyv_reinterpret_u64_s8(X) X +#define npyv_reinterpret_u64_u16(X) X +#define npyv_reinterpret_u64_s16(X) X +#define npyv_reinterpret_u64_u32(X) X +#define npyv_reinterpret_u64_s32(X) X +#define npyv_reinterpret_u64_s64(X) X +#define npyv_reinterpret_u64_f32 _mm512_castps_si512 +#define npyv_reinterpret_u64_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_s64_s64(X) X +#define npyv_reinterpret_s64_u8(X) X +#define npyv_reinterpret_s64_s8(X) X +#define npyv_reinterpret_s64_u16(X) X +#define npyv_reinterpret_s64_s16(X) X +#define npyv_reinterpret_s64_u32(X) X +#define npyv_reinterpret_s64_s32(X) X +#define npyv_reinterpret_s64_u64(X) X +#define npyv_reinterpret_s64_f32 _mm512_castps_si512 +#define npyv_reinterpret_s64_f64 _mm512_castpd_si512 + +#define npyv_reinterpret_f32_f32(X) X +#define npyv_reinterpret_f32_u8 _mm512_castsi512_ps +#define npyv_reinterpret_f32_s8 _mm512_castsi512_ps +#define npyv_reinterpret_f32_u16 _mm512_castsi512_ps +#define npyv_reinterpret_f32_s16 _mm512_castsi512_ps +#define npyv_reinterpret_f32_u32 _mm512_castsi512_ps +#define npyv_reinterpret_f32_s32 _mm512_castsi512_ps +#define npyv_reinterpret_f32_u64 _mm512_castsi512_ps +#define npyv_reinterpret_f32_s64 _mm512_castsi512_ps +#define npyv_reinterpret_f32_f64 _mm512_castpd_ps + +#define npyv_reinterpret_f64_f64(X) X +#define npyv_reinterpret_f64_u8 _mm512_castsi512_pd +#define npyv_reinterpret_f64_s8 _mm512_castsi512_pd +#define npyv_reinterpret_f64_u16 _mm512_castsi512_pd +#define npyv_reinterpret_f64_s16 _mm512_castsi512_pd +#define npyv_reinterpret_f64_u32 _mm512_castsi512_pd +#define npyv_reinterpret_f64_s32 _mm512_castsi512_pd +#define npyv_reinterpret_f64_u64 _mm512_castsi512_pd +#define npyv_reinterpret_f64_s64 _mm512_castsi512_pd +#define npyv_reinterpret_f64_f32 _mm512_castps_pd + +#ifdef NPY_HAVE_AVX512_KNL + #define npyv_cleanup() ((void)0) +#else + #define npyv_cleanup _mm256_zeroall +#endif + +#endif // _NPY_SIMD_AVX512_MISC_H diff --git a/mkl_umath/src/npyv/avx512/operators.h b/mkl_umath/src/npyv/avx512/operators.h new file mode 100644 index 00000000..c70932d5 --- /dev/null +++ b/mkl_umath/src/npyv/avx512/operators.h @@ -0,0 +1,380 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_OPERATORS_H +#define _NPY_SIMD_AVX512_OPERATORS_H + +#include "conversion.h" // tobits + +/*************************** + * Shifting + ***************************/ + +// left +#ifdef NPY_HAVE_AVX512BW + #define npyv_shl_u16(A, C) _mm512_sll_epi16(A, _mm_cvtsi32_si128(C)) +#else + #define NPYV_IMPL_AVX512_SHIFT(FN, INTRIN) \ + NPY_FINLINE __m512i npyv_##FN(__m512i a, int c) \ + { \ + __m256i l = npyv512_lower_si256(a); \ + __m256i h = npyv512_higher_si256(a); \ + __m128i cv = _mm_cvtsi32_si128(c); \ + l = _mm256_##INTRIN(l, cv); \ + h = _mm256_##INTRIN(h, cv); \ + return npyv512_combine_si256(l, h); \ + } + + NPYV_IMPL_AVX512_SHIFT(shl_u16, sll_epi16) +#endif +#define npyv_shl_s16 npyv_shl_u16 +#define npyv_shl_u32(A, C) _mm512_sll_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s32(A, C) _mm512_sll_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_u64(A, C) _mm512_sll_epi64(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s64(A, C) _mm512_sll_epi64(A, _mm_cvtsi32_si128(C)) + +// left by an immediate constant +#ifdef NPY_HAVE_AVX512BW + #define npyv_shli_u16 _mm512_slli_epi16 +#else + #define npyv_shli_u16 npyv_shl_u16 +#endif +#define npyv_shli_s16 npyv_shl_u16 +#define npyv_shli_u32 _mm512_slli_epi32 +#define npyv_shli_s32 _mm512_slli_epi32 +#define npyv_shli_u64 _mm512_slli_epi64 +#define npyv_shli_s64 _mm512_slli_epi64 + +// right +#ifdef NPY_HAVE_AVX512BW + #define npyv_shr_u16(A, C) _mm512_srl_epi16(A, _mm_cvtsi32_si128(C)) + #define npyv_shr_s16(A, C) _mm512_sra_epi16(A, _mm_cvtsi32_si128(C)) +#else + NPYV_IMPL_AVX512_SHIFT(shr_u16, srl_epi16) + NPYV_IMPL_AVX512_SHIFT(shr_s16, sra_epi16) +#endif +#define npyv_shr_u32(A, C) _mm512_srl_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_s32(A, C) _mm512_sra_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_u64(A, C) _mm512_srl_epi64(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_s64(A, C) _mm512_sra_epi64(A, _mm_cvtsi32_si128(C)) + +// right by an immediate constant +#ifdef NPY_HAVE_AVX512BW + #define npyv_shri_u16 _mm512_srli_epi16 + #define npyv_shri_s16 _mm512_srai_epi16 +#else + #define npyv_shri_u16 npyv_shr_u16 + #define npyv_shri_s16 npyv_shr_s16 +#endif +#define npyv_shri_u32 _mm512_srli_epi32 +#define npyv_shri_s32 _mm512_srai_epi32 +#define npyv_shri_u64 _mm512_srli_epi64 +#define npyv_shri_s64 _mm512_srai_epi64 + +/*************************** + * Logical + ***************************/ + +// AND +#define npyv_and_u8 _mm512_and_si512 +#define npyv_and_s8 _mm512_and_si512 +#define npyv_and_u16 _mm512_and_si512 +#define npyv_and_s16 _mm512_and_si512 +#define npyv_and_u32 _mm512_and_si512 +#define npyv_and_s32 _mm512_and_si512 +#define npyv_and_u64 _mm512_and_si512 +#define npyv_and_s64 _mm512_and_si512 +#ifdef NPY_HAVE_AVX512DQ + #define npyv_and_f32 _mm512_and_ps + #define npyv_and_f64 _mm512_and_pd +#else + NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(npyv_and_f32, _mm512_and_si512) + NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(npyv_and_f64, _mm512_and_si512) +#endif +// OR +#define npyv_or_u8 _mm512_or_si512 +#define npyv_or_s8 _mm512_or_si512 +#define npyv_or_u16 _mm512_or_si512 +#define npyv_or_s16 _mm512_or_si512 +#define npyv_or_u32 _mm512_or_si512 +#define npyv_or_s32 _mm512_or_si512 +#define npyv_or_u64 _mm512_or_si512 +#define npyv_or_s64 _mm512_or_si512 +#ifdef NPY_HAVE_AVX512DQ + #define npyv_or_f32 _mm512_or_ps + #define npyv_or_f64 _mm512_or_pd +#else + NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(npyv_or_f32, _mm512_or_si512) + NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(npyv_or_f64, _mm512_or_si512) +#endif + +// XOR +#define npyv_xor_u8 _mm512_xor_si512 +#define npyv_xor_s8 _mm512_xor_si512 +#define npyv_xor_u16 _mm512_xor_si512 +#define npyv_xor_s16 _mm512_xor_si512 +#define npyv_xor_u32 _mm512_xor_si512 +#define npyv_xor_s32 _mm512_xor_si512 +#define npyv_xor_u64 _mm512_xor_si512 +#define npyv_xor_s64 _mm512_xor_si512 +#ifdef NPY_HAVE_AVX512DQ + #define npyv_xor_f32 _mm512_xor_ps + #define npyv_xor_f64 _mm512_xor_pd +#else + NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(npyv_xor_f32, _mm512_xor_si512) + NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(npyv_xor_f64, _mm512_xor_si512) +#endif +// NOT +#define npyv_not_u8(A) _mm512_xor_si512(A, _mm512_set1_epi32(-1)) +#define npyv_not_s8 npyv_not_u8 +#define npyv_not_u16 npyv_not_u8 +#define npyv_not_s16 npyv_not_u8 +#define npyv_not_u32 npyv_not_u8 +#define npyv_not_s32 npyv_not_u8 +#define npyv_not_u64 npyv_not_u8 +#define npyv_not_s64 npyv_not_u8 +#ifdef NPY_HAVE_AVX512DQ + #define npyv_not_f32(A) _mm512_xor_ps(A, _mm512_castsi512_ps(_mm512_set1_epi32(-1))) + #define npyv_not_f64(A) _mm512_xor_pd(A, _mm512_castsi512_pd(_mm512_set1_epi32(-1))) +#else + #define npyv_not_f32(A) _mm512_castsi512_ps(npyv_not_u32(_mm512_castps_si512(A))) + #define npyv_not_f64(A) _mm512_castsi512_pd(npyv_not_u64(_mm512_castpd_si512(A))) +#endif + +// ANDC +#define npyv_andc_u8(A, B) _mm512_andnot_si512(B, A) + +/*************************** + * Logical (boolean) + ***************************/ +#ifdef NPY_HAVE_AVX512BW_MASK + #define npyv_and_b8 _kand_mask64 + #define npyv_and_b16 _kand_mask32 + #define npyv_or_b8 _kor_mask64 + #define npyv_or_b16 _kor_mask32 + #define npyv_xor_b8 _kxor_mask64 + #define npyv_xor_b16 _kxor_mask32 + #define npyv_not_b8 _knot_mask64 + #define npyv_not_b16 _knot_mask32 + #define npyv_andc_b8(A, B) _kandn_mask64(B, A) + #define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A) + #define npyv_xnor_b8 _kxnor_mask64 +#elif defined(NPY_HAVE_AVX512BW) + NPY_FINLINE npyv_b8 npyv_and_b8(npyv_b8 a, npyv_b8 b) + { return a & b; } + NPY_FINLINE npyv_b16 npyv_and_b16(npyv_b16 a, npyv_b16 b) + { return a & b; } + NPY_FINLINE npyv_b8 npyv_or_b8(npyv_b8 a, npyv_b8 b) + { return a | b; } + NPY_FINLINE npyv_b16 npyv_or_b16(npyv_b16 a, npyv_b16 b) + { return a | b; } + NPY_FINLINE npyv_b8 npyv_xor_b8(npyv_b8 a, npyv_b8 b) + { return a ^ b; } + NPY_FINLINE npyv_b16 npyv_xor_b16(npyv_b16 a, npyv_b16 b) + { return a ^ b; } + NPY_FINLINE npyv_b8 npyv_not_b8(npyv_b8 a) + { return ~a; } + NPY_FINLINE npyv_b16 npyv_not_b16(npyv_b16 a) + { return ~a; } + NPY_FINLINE npyv_b8 npyv_andc_b8(npyv_b8 a, npyv_b8 b) + { return a & (~b); } + NPY_FINLINE npyv_b8 npyv_orc_b8(npyv_b8 a, npyv_b8 b) + { return a | (~b); } + NPY_FINLINE npyv_b8 npyv_xnor_b8(npyv_b8 a, npyv_b8 b) + { return ~(a ^ b); } +#else + #define npyv_and_b8 _mm512_and_si512 + #define npyv_and_b16 _mm512_and_si512 + #define npyv_or_b8 _mm512_or_si512 + #define npyv_or_b16 _mm512_or_si512 + #define npyv_xor_b8 _mm512_xor_si512 + #define npyv_xor_b16 _mm512_xor_si512 + #define npyv_not_b8 npyv_not_u8 + #define npyv_not_b16 npyv_not_u8 + #define npyv_andc_b8(A, B) _mm512_andnot_si512(B, A) + #define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A) + #define npyv_xnor_b8(A, B) npyv_not_b8(npyv_xor_b8(A, B)) +#endif + +#define npyv_and_b32 _mm512_kand +#define npyv_or_b32 _mm512_kor +#define npyv_xor_b32 _mm512_kxor +#define npyv_not_b32 _mm512_knot + +#ifdef NPY_HAVE_AVX512DQ_MASK + #define npyv_and_b64 _kand_mask8 + #define npyv_or_b64 _kor_mask8 + #define npyv_xor_b64 _kxor_mask8 + #define npyv_not_b64 _knot_mask8 +#else + NPY_FINLINE npyv_b64 npyv_and_b64(npyv_b64 a, npyv_b64 b) + { return (npyv_b64)_mm512_kand((npyv_b32)a, (npyv_b32)b); } + NPY_FINLINE npyv_b64 npyv_or_b64(npyv_b64 a, npyv_b64 b) + { return (npyv_b64)_mm512_kor((npyv_b32)a, (npyv_b32)b); } + NPY_FINLINE npyv_b64 npyv_xor_b64(npyv_b64 a, npyv_b64 b) + { return (npyv_b64)_mm512_kxor((npyv_b32)a, (npyv_b32)b); } + NPY_FINLINE npyv_b64 npyv_not_b64(npyv_b64 a) + { return (npyv_b64)_mm512_knot((npyv_b32)a); } +#endif + +/*************************** + * Comparison + ***************************/ + +// int Equal +#ifdef NPY_HAVE_AVX512BW + #define npyv_cmpeq_u8 _mm512_cmpeq_epu8_mask + #define npyv_cmpeq_s8 _mm512_cmpeq_epi8_mask + #define npyv_cmpeq_u16 _mm512_cmpeq_epu16_mask + #define npyv_cmpeq_s16 _mm512_cmpeq_epi16_mask +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpeq_u8, _mm256_cmpeq_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpeq_u16, _mm256_cmpeq_epi16) + #define npyv_cmpeq_s8 npyv_cmpeq_u8 + #define npyv_cmpeq_s16 npyv_cmpeq_u16 +#endif +#define npyv_cmpeq_u32 _mm512_cmpeq_epu32_mask +#define npyv_cmpeq_s32 _mm512_cmpeq_epi32_mask +#define npyv_cmpeq_u64 _mm512_cmpeq_epu64_mask +#define npyv_cmpeq_s64 _mm512_cmpeq_epi64_mask + +// int not equal +#ifdef NPY_HAVE_AVX512BW + #define npyv_cmpneq_u8 _mm512_cmpneq_epu8_mask + #define npyv_cmpneq_s8 _mm512_cmpneq_epi8_mask + #define npyv_cmpneq_u16 _mm512_cmpneq_epu16_mask + #define npyv_cmpneq_s16 _mm512_cmpneq_epi16_mask +#else + #define npyv_cmpneq_u8(A, B) npyv_not_u8(npyv_cmpeq_u8(A, B)) + #define npyv_cmpneq_u16(A, B) npyv_not_u16(npyv_cmpeq_u16(A, B)) + #define npyv_cmpneq_s8 npyv_cmpneq_u8 + #define npyv_cmpneq_s16 npyv_cmpneq_u16 +#endif +#define npyv_cmpneq_u32 _mm512_cmpneq_epu32_mask +#define npyv_cmpneq_s32 _mm512_cmpneq_epi32_mask +#define npyv_cmpneq_u64 _mm512_cmpneq_epu64_mask +#define npyv_cmpneq_s64 _mm512_cmpneq_epi64_mask + +// greater than +#ifdef NPY_HAVE_AVX512BW + #define npyv_cmpgt_u8 _mm512_cmpgt_epu8_mask + #define npyv_cmpgt_s8 _mm512_cmpgt_epi8_mask + #define npyv_cmpgt_u16 _mm512_cmpgt_epu16_mask + #define npyv_cmpgt_s16 _mm512_cmpgt_epi16_mask +#else + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpgt_s8, _mm256_cmpgt_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv_cmpgt_s16, _mm256_cmpgt_epi16) + NPY_FINLINE __m512i npyv_cmpgt_u8(__m512i a, __m512i b) + { + const __m512i sbit = _mm512_set1_epi32(0x80808080); + return npyv_cmpgt_s8(_mm512_xor_si512(a, sbit), _mm512_xor_si512(b, sbit)); + } + NPY_FINLINE __m512i npyv_cmpgt_u16(__m512i a, __m512i b) + { + const __m512i sbit = _mm512_set1_epi32(0x80008000); + return npyv_cmpgt_s16(_mm512_xor_si512(a, sbit), _mm512_xor_si512(b, sbit)); + } +#endif +#define npyv_cmpgt_u32 _mm512_cmpgt_epu32_mask +#define npyv_cmpgt_s32 _mm512_cmpgt_epi32_mask +#define npyv_cmpgt_u64 _mm512_cmpgt_epu64_mask +#define npyv_cmpgt_s64 _mm512_cmpgt_epi64_mask + +// greater than or equal +#ifdef NPY_HAVE_AVX512BW + #define npyv_cmpge_u8 _mm512_cmpge_epu8_mask + #define npyv_cmpge_s8 _mm512_cmpge_epi8_mask + #define npyv_cmpge_u16 _mm512_cmpge_epu16_mask + #define npyv_cmpge_s16 _mm512_cmpge_epi16_mask +#else + #define npyv_cmpge_u8(A, B) npyv_not_u8(npyv_cmpgt_u8(B, A)) + #define npyv_cmpge_s8(A, B) npyv_not_s8(npyv_cmpgt_s8(B, A)) + #define npyv_cmpge_u16(A, B) npyv_not_u16(npyv_cmpgt_u16(B, A)) + #define npyv_cmpge_s16(A, B) npyv_not_s16(npyv_cmpgt_s16(B, A)) +#endif +#define npyv_cmpge_u32 _mm512_cmpge_epu32_mask +#define npyv_cmpge_s32 _mm512_cmpge_epi32_mask +#define npyv_cmpge_u64 _mm512_cmpge_epu64_mask +#define npyv_cmpge_s64 _mm512_cmpge_epi64_mask + +// less than +#define npyv_cmplt_u8(A, B) npyv_cmpgt_u8(B, A) +#define npyv_cmplt_s8(A, B) npyv_cmpgt_s8(B, A) +#define npyv_cmplt_u16(A, B) npyv_cmpgt_u16(B, A) +#define npyv_cmplt_s16(A, B) npyv_cmpgt_s16(B, A) +#define npyv_cmplt_u32(A, B) npyv_cmpgt_u32(B, A) +#define npyv_cmplt_s32(A, B) npyv_cmpgt_s32(B, A) +#define npyv_cmplt_u64(A, B) npyv_cmpgt_u64(B, A) +#define npyv_cmplt_s64(A, B) npyv_cmpgt_s64(B, A) + +// less than or equal +#define npyv_cmple_u8(A, B) npyv_cmpge_u8(B, A) +#define npyv_cmple_s8(A, B) npyv_cmpge_s8(B, A) +#define npyv_cmple_u16(A, B) npyv_cmpge_u16(B, A) +#define npyv_cmple_s16(A, B) npyv_cmpge_s16(B, A) +#define npyv_cmple_u32(A, B) npyv_cmpge_u32(B, A) +#define npyv_cmple_s32(A, B) npyv_cmpge_s32(B, A) +#define npyv_cmple_u64(A, B) npyv_cmpge_u64(B, A) +#define npyv_cmple_s64(A, B) npyv_cmpge_s64(B, A) + +// precision comparison +#define npyv_cmpeq_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_EQ_OQ) +#define npyv_cmpeq_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_EQ_OQ) +#define npyv_cmpneq_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_NEQ_UQ) +#define npyv_cmpneq_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_NEQ_UQ) +#define npyv_cmplt_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_LT_OQ) +#define npyv_cmplt_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_LT_OQ) +#define npyv_cmple_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_LE_OQ) +#define npyv_cmple_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_LE_OQ) +#define npyv_cmpgt_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_GT_OQ) +#define npyv_cmpgt_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_GT_OQ) +#define npyv_cmpge_f32(A, B) _mm512_cmp_ps_mask(A, B, _CMP_GE_OQ) +#define npyv_cmpge_f64(A, B) _mm512_cmp_pd_mask(A, B, _CMP_GE_OQ) + +// check special cases +NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a) +{ return _mm512_cmp_ps_mask(a, a, _CMP_ORD_Q); } +NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a) +{ return _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q); } + +// Test cross all vector lanes +// any: returns true if any of the elements is not equal to zero +// all: returns true if all elements are not equal to zero +#define NPYV_IMPL_AVX512_ANYALL(SFX, MASK) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { return npyv_tobits_##SFX(a) != 0; } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { return npyv_tobits_##SFX(a) == MASK; } +NPYV_IMPL_AVX512_ANYALL(b8, 0xffffffffffffffffull) +NPYV_IMPL_AVX512_ANYALL(b16, 0xfffffffful) +NPYV_IMPL_AVX512_ANYALL(b32, 0xffff) +NPYV_IMPL_AVX512_ANYALL(b64, 0xff) +#undef NPYV_IMPL_AVX512_ANYALL + +#define NPYV_IMPL_AVX512_ANYALL(SFX, BSFX, MASK) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { \ + return npyv_tobits_##BSFX( \ + npyv_cmpeq_##SFX(a, npyv_zero_##SFX()) \ + ) != MASK; \ + } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { \ + return npyv_tobits_##BSFX( \ + npyv_cmpeq_##SFX(a, npyv_zero_##SFX()) \ + ) == 0; \ + } +NPYV_IMPL_AVX512_ANYALL(u8, b8, 0xffffffffffffffffull) +NPYV_IMPL_AVX512_ANYALL(s8, b8, 0xffffffffffffffffull) +NPYV_IMPL_AVX512_ANYALL(u16, b16, 0xfffffffful) +NPYV_IMPL_AVX512_ANYALL(s16, b16, 0xfffffffful) +NPYV_IMPL_AVX512_ANYALL(u32, b32, 0xffff) +NPYV_IMPL_AVX512_ANYALL(s32, b32, 0xffff) +NPYV_IMPL_AVX512_ANYALL(u64, b64, 0xff) +NPYV_IMPL_AVX512_ANYALL(s64, b64, 0xff) +NPYV_IMPL_AVX512_ANYALL(f32, b32, 0xffff) +NPYV_IMPL_AVX512_ANYALL(f64, b64, 0xff) +#undef NPYV_IMPL_AVX512_ANYALL + +#endif // _NPY_SIMD_AVX512_OPERATORS_H diff --git a/mkl_umath/src/npyv/avx512/reorder.h b/mkl_umath/src/npyv/avx512/reorder.h new file mode 100644 index 00000000..27e66b5e --- /dev/null +++ b/mkl_umath/src/npyv/avx512/reorder.h @@ -0,0 +1,378 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_REORDER_H +#define _NPY_SIMD_AVX512_REORDER_H + +// combine lower part of two vectors +#define npyv_combinel_u8(A, B) _mm512_inserti64x4(A, _mm512_castsi512_si256(B), 1) +#define npyv_combinel_s8 npyv_combinel_u8 +#define npyv_combinel_u16 npyv_combinel_u8 +#define npyv_combinel_s16 npyv_combinel_u8 +#define npyv_combinel_u32 npyv_combinel_u8 +#define npyv_combinel_s32 npyv_combinel_u8 +#define npyv_combinel_u64 npyv_combinel_u8 +#define npyv_combinel_s64 npyv_combinel_u8 +#define npyv_combinel_f64(A, B) _mm512_insertf64x4(A, _mm512_castpd512_pd256(B), 1) +#ifdef NPY_HAVE_AVX512DQ + #define npyv_combinel_f32(A, B) \ + _mm512_insertf32x8(A, _mm512_castps512_ps256(B), 1) +#else + #define npyv_combinel_f32(A, B) \ + _mm512_castsi512_ps(npyv_combinel_u8(_mm512_castps_si512(A), _mm512_castps_si512(B))) +#endif + +// combine higher part of two vectors +#define npyv_combineh_u8(A, B) _mm512_inserti64x4(B, _mm512_extracti64x4_epi64(A, 1), 0) +#define npyv_combineh_s8 npyv_combineh_u8 +#define npyv_combineh_u16 npyv_combineh_u8 +#define npyv_combineh_s16 npyv_combineh_u8 +#define npyv_combineh_u32 npyv_combineh_u8 +#define npyv_combineh_s32 npyv_combineh_u8 +#define npyv_combineh_u64 npyv_combineh_u8 +#define npyv_combineh_s64 npyv_combineh_u8 +#define npyv_combineh_f64(A, B) _mm512_insertf64x4(B, _mm512_extractf64x4_pd(A, 1), 0) +#ifdef NPY_HAVE_AVX512DQ + #define npyv_combineh_f32(A, B) \ + _mm512_insertf32x8(B, _mm512_extractf32x8_ps(A, 1), 0) +#else + #define npyv_combineh_f32(A, B) \ + _mm512_castsi512_ps(npyv_combineh_u8(_mm512_castps_si512(A), _mm512_castps_si512(B))) +#endif + +// combine two vectors from lower and higher parts of two other vectors +NPY_FINLINE npyv_m512ix2 npyv__combine(__m512i a, __m512i b) +{ + npyv_m512ix2 r; + r.val[0] = npyv_combinel_u8(a, b); + r.val[1] = npyv_combineh_u8(a, b); + return r; +} +NPY_FINLINE npyv_f32x2 npyv_combine_f32(__m512 a, __m512 b) +{ + npyv_f32x2 r; + r.val[0] = npyv_combinel_f32(a, b); + r.val[1] = npyv_combineh_f32(a, b); + return r; +} +NPY_FINLINE npyv_f64x2 npyv_combine_f64(__m512d a, __m512d b) +{ + npyv_f64x2 r; + r.val[0] = npyv_combinel_f64(a, b); + r.val[1] = npyv_combineh_f64(a, b); + return r; +} +#define npyv_combine_u8 npyv__combine +#define npyv_combine_s8 npyv__combine +#define npyv_combine_u16 npyv__combine +#define npyv_combine_s16 npyv__combine +#define npyv_combine_u32 npyv__combine +#define npyv_combine_s32 npyv__combine +#define npyv_combine_u64 npyv__combine +#define npyv_combine_s64 npyv__combine + +// interleave two vectors +#ifndef NPY_HAVE_AVX512BW + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpacklo_epi8, _mm256_unpacklo_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpackhi_epi8, _mm256_unpackhi_epi8) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpacklo_epi16, _mm256_unpacklo_epi16) + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv__unpackhi_epi16, _mm256_unpackhi_epi16) +#endif + +NPY_FINLINE npyv_u64x2 npyv_zip_u64(__m512i a, __m512i b) +{ + npyv_u64x2 r; + r.val[0] = _mm512_permutex2var_epi64(a, npyv_set_u64(0, 8, 1, 9, 2, 10, 3, 11), b); + r.val[1] = _mm512_permutex2var_epi64(a, npyv_set_u64(4, 12, 5, 13, 6, 14, 7, 15), b); + return r; +} +#define npyv_zip_s64 npyv_zip_u64 + +NPY_FINLINE npyv_u8x2 npyv_zip_u8(__m512i a, __m512i b) +{ + npyv_u8x2 r; +#ifdef NPY_HAVE_AVX512VBMI + r.val[0] = _mm512_permutex2var_epi8(a, + npyv_set_u8(0, 64, 1, 65, 2, 66, 3, 67, 4, 68, 5, 69, 6, 70, 7, 71, + 8, 72, 9, 73, 10, 74, 11, 75, 12, 76, 13, 77, 14, 78, 15, 79, + 16, 80, 17, 81, 18, 82, 19, 83, 20, 84, 21, 85, 22, 86, 23, 87, + 24, 88, 25, 89, 26, 90, 27, 91, 28, 92, 29, 93, 30, 94, 31, 95), b); + r.val[1] = _mm512_permutex2var_epi8(a, + npyv_set_u8(32, 96, 33, 97, 34, 98, 35, 99, 36, 100, 37, 101, 38, 102, 39, 103, + 40, 104, 41, 105, 42, 106, 43, 107, 44, 108, 45, 109, 46, 110, 47, 111, + 48, 112, 49, 113, 50, 114, 51, 115, 52, 116, 53, 117, 54, 118, 55, 119, + 56, 120, 57, 121, 58, 122, 59, 123, 60, 124, 61, 125, 62, 126, 63, 127), b); +#else + #ifdef NPY_HAVE_AVX512BW + __m512i ab0 = _mm512_unpacklo_epi8(a, b); + __m512i ab1 = _mm512_unpackhi_epi8(a, b); + #else + __m512i ab0 = npyv__unpacklo_epi8(a, b); + __m512i ab1 = npyv__unpackhi_epi8(a, b); + #endif + r.val[0] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(0, 1, 8, 9, 2, 3, 10, 11), ab1); + r.val[1] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(4, 5, 12, 13, 6, 7, 14, 15), ab1); +#endif + return r; +} +#define npyv_zip_s8 npyv_zip_u8 + +NPY_FINLINE npyv_u16x2 npyv_zip_u16(__m512i a, __m512i b) +{ + npyv_u16x2 r; +#ifdef NPY_HAVE_AVX512BW + r.val[0] = _mm512_permutex2var_epi16(a, + npyv_set_u16(0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39, + 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47), b); + r.val[1] = _mm512_permutex2var_epi16(a, + npyv_set_u16(16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55, + 24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63), b); +#else + __m512i ab0 = npyv__unpacklo_epi16(a, b); + __m512i ab1 = npyv__unpackhi_epi16(a, b); + r.val[0] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(0, 1, 8, 9, 2, 3, 10, 11), ab1); + r.val[1] = _mm512_permutex2var_epi64(ab0, npyv_set_u64(4, 5, 12, 13, 6, 7, 14, 15), ab1); +#endif + return r; +} +#define npyv_zip_s16 npyv_zip_u16 + +NPY_FINLINE npyv_u32x2 npyv_zip_u32(__m512i a, __m512i b) +{ + npyv_u32x2 r; + r.val[0] = _mm512_permutex2var_epi32(a, + npyv_set_u32(0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23), b); + r.val[1] = _mm512_permutex2var_epi32(a, + npyv_set_u32(8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31), b); + return r; +} +#define npyv_zip_s32 npyv_zip_u32 + +NPY_FINLINE npyv_f32x2 npyv_zip_f32(__m512 a, __m512 b) +{ + npyv_f32x2 r; + r.val[0] = _mm512_permutex2var_ps(a, + npyv_set_u32(0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23), b); + r.val[1] = _mm512_permutex2var_ps(a, + npyv_set_u32(8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31), b); + return r; +} + +NPY_FINLINE npyv_f64x2 npyv_zip_f64(__m512d a, __m512d b) +{ + npyv_f64x2 r; + r.val[0] = _mm512_permutex2var_pd(a, npyv_set_u64(0, 8, 1, 9, 2, 10, 3, 11), b); + r.val[1] = _mm512_permutex2var_pd(a, npyv_set_u64(4, 12, 5, 13, 6, 14, 7, 15), b); + return r; +} + +// deinterleave two vectors +NPY_FINLINE npyv_u8x2 npyv_unzip_u8(npyv_u8 ab0, npyv_u8 ab1) +{ + npyv_u8x2 r; +#ifdef NPY_HAVE_AVX512VBMI + const __m512i idx_a = npyv_set_u8( + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, + 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126 + ); + const __m512i idx_b = npyv_set_u8( + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127 + ); + r.val[0] = _mm512_permutex2var_epi8(ab0, idx_a, ab1); + r.val[1] = _mm512_permutex2var_epi8(ab0, idx_b, ab1); +#else + #ifdef NPY_HAVE_AVX512BW + const __m512i idx = npyv_set_u8( + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15, + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15, + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15, + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 + ); + __m512i abl = _mm512_shuffle_epi8(ab0, idx); + __m512i abh = _mm512_shuffle_epi8(ab1, idx); + #else + const __m256i idx = _mm256_setr_epi8( + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15, + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 + ); + __m256i abl_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab0), idx); + __m256i abl_hi = _mm256_shuffle_epi8(npyv512_higher_si256(ab0), idx); + __m256i abh_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab1), idx); + __m256i abh_hi = _mm256_shuffle_epi8(npyv512_higher_si256(ab1), idx); + __m512i abl = npyv512_combine_si256(abl_lo, abl_hi); + __m512i abh = npyv512_combine_si256(abh_lo, abh_hi); + #endif + const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14); + const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15); + r.val[0] = _mm512_permutex2var_epi64(abl, idx_a, abh); + r.val[1] = _mm512_permutex2var_epi64(abl, idx_b, abh); +#endif + return r; +} +#define npyv_unzip_s8 npyv_unzip_u8 + +NPY_FINLINE npyv_u16x2 npyv_unzip_u16(npyv_u16 ab0, npyv_u16 ab1) +{ + npyv_u16x2 r; +#ifdef NPY_HAVE_AVX512BW + const __m512i idx_a = npyv_set_u16( + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 + ); + const __m512i idx_b = npyv_set_u16( + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63 + ); + r.val[0] = _mm512_permutex2var_epi16(ab0, idx_a, ab1); + r.val[1] = _mm512_permutex2var_epi16(ab0, idx_b, ab1); +#else + const __m256i idx = _mm256_setr_epi8( + 0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15, + 0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15 + ); + __m256i abl_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab0), idx); + __m256i abl_hi = _mm256_shuffle_epi8(npyv512_higher_si256(ab0), idx); + __m256i abh_lo = _mm256_shuffle_epi8(npyv512_lower_si256(ab1), idx); + __m256i abh_hi = _mm256_shuffle_epi8(npyv512_higher_si256(ab1), idx); + __m512i abl = npyv512_combine_si256(abl_lo, abl_hi); + __m512i abh = npyv512_combine_si256(abh_lo, abh_hi); + + const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14); + const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15); + r.val[0] = _mm512_permutex2var_epi64(abl, idx_a, abh); + r.val[1] = _mm512_permutex2var_epi64(abl, idx_b, abh); +#endif + return r; +} +#define npyv_unzip_s16 npyv_unzip_u16 + +NPY_FINLINE npyv_u32x2 npyv_unzip_u32(npyv_u32 ab0, npyv_u32 ab1) +{ + const __m512i idx_a = npyv_set_u32( + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + ); + const __m512i idx_b = npyv_set_u32( + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + ); + npyv_u32x2 r; + r.val[0] = _mm512_permutex2var_epi32(ab0, idx_a, ab1); + r.val[1] = _mm512_permutex2var_epi32(ab0, idx_b, ab1); + return r; +} +#define npyv_unzip_s32 npyv_unzip_u32 + +NPY_FINLINE npyv_u64x2 npyv_unzip_u64(npyv_u64 ab0, npyv_u64 ab1) +{ + const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14); + const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15); + npyv_u64x2 r; + r.val[0] = _mm512_permutex2var_epi64(ab0, idx_a, ab1); + r.val[1] = _mm512_permutex2var_epi64(ab0, idx_b, ab1); + return r; +} +#define npyv_unzip_s64 npyv_unzip_u64 + +NPY_FINLINE npyv_f32x2 npyv_unzip_f32(npyv_f32 ab0, npyv_f32 ab1) +{ + const __m512i idx_a = npyv_set_u32( + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + ); + const __m512i idx_b = npyv_set_u32( + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + ); + npyv_f32x2 r; + r.val[0] = _mm512_permutex2var_ps(ab0, idx_a, ab1); + r.val[1] = _mm512_permutex2var_ps(ab0, idx_b, ab1); + return r; +} +NPY_FINLINE npyv_f64x2 npyv_unzip_f64(npyv_f64 ab0, npyv_f64 ab1) +{ + const __m512i idx_a = npyv_set_u64(0, 2, 4, 6, 8, 10, 12, 14); + const __m512i idx_b = npyv_set_u64(1, 3, 5, 7, 9, 11, 13, 15); + npyv_f64x2 r; + r.val[0] = _mm512_permutex2var_pd(ab0, idx_a, ab1); + r.val[1] = _mm512_permutex2var_pd(ab0, idx_b, ab1); + return r; +} + +// Reverse elements of each 64-bit lane +NPY_FINLINE npyv_u8 npyv_rev64_u8(npyv_u8 a) +{ +#ifdef NPY_HAVE_AVX512BW + const __m512i idx = npyv_set_u8( + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8 + ); + return _mm512_shuffle_epi8(a, idx); +#else + const __m256i idx = _mm256_setr_epi8( + 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 + ); + __m256i lo = _mm256_shuffle_epi8(npyv512_lower_si256(a), idx); + __m256i hi = _mm256_shuffle_epi8(npyv512_higher_si256(a), idx); + return npyv512_combine_si256(lo, hi); +#endif +} +#define npyv_rev64_s8 npyv_rev64_u8 + +NPY_FINLINE npyv_u16 npyv_rev64_u16(npyv_u16 a) +{ +#ifdef NPY_HAVE_AVX512BW + const __m512i idx = npyv_set_u8( + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9, + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9, + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9, + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9 + ); + return _mm512_shuffle_epi8(a, idx); +#else + const __m256i idx = _mm256_setr_epi8( + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9, + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9 + ); + __m256i lo = _mm256_shuffle_epi8(npyv512_lower_si256(a), idx); + __m256i hi = _mm256_shuffle_epi8(npyv512_higher_si256(a), idx); + return npyv512_combine_si256(lo, hi); +#endif +} +#define npyv_rev64_s16 npyv_rev64_u16 + +NPY_FINLINE npyv_u32 npyv_rev64_u32(npyv_u32 a) +{ + return _mm512_shuffle_epi32(a, (_MM_PERM_ENUM)_MM_SHUFFLE(2, 3, 0, 1)); +} +#define npyv_rev64_s32 npyv_rev64_u32 + +NPY_FINLINE npyv_f32 npyv_rev64_f32(npyv_f32 a) +{ + return _mm512_shuffle_ps(a, a, (_MM_PERM_ENUM)_MM_SHUFFLE(2, 3, 0, 1)); +} + +// Permuting the elements of each 128-bit lane by immediate index for +// each element. +#define npyv_permi128_u32(A, E0, E1, E2, E3) \ + _mm512_shuffle_epi32(A, _MM_SHUFFLE(E3, E2, E1, E0)) + +#define npyv_permi128_s32 npyv_permi128_u32 + +#define npyv_permi128_u64(A, E0, E1) \ + _mm512_shuffle_epi32(A, _MM_SHUFFLE(((E1)<<1)+1, ((E1)<<1), ((E0)<<1)+1, ((E0)<<1))) + +#define npyv_permi128_s64 npyv_permi128_u64 + +#define npyv_permi128_f32(A, E0, E1, E2, E3) \ + _mm512_permute_ps(A, _MM_SHUFFLE(E3, E2, E1, E0)) + +#define npyv_permi128_f64(A, E0, E1) \ + _mm512_permute_pd(A, (((E1)<<7) | ((E0)<<6) | ((E1)<<5) | ((E0)<<4) | ((E1)<<3) | ((E0)<<2) | ((E1)<<1) | (E0))) + +#endif // _NPY_SIMD_AVX512_REORDER_H diff --git a/mkl_umath/src/npyv/avx512/utils.h b/mkl_umath/src/npyv/avx512/utils.h new file mode 100644 index 00000000..ced3bfef --- /dev/null +++ b/mkl_umath/src/npyv/avx512/utils.h @@ -0,0 +1,102 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_AVX512_UTILS_H +#define _NPY_SIMD_AVX512_UTILS_H + +#define npyv512_lower_si256 _mm512_castsi512_si256 +#define npyv512_lower_ps256 _mm512_castps512_ps256 +#define npyv512_lower_pd256 _mm512_castpd512_pd256 + +#define npyv512_higher_si256(A) _mm512_extracti64x4_epi64(A, 1) +#define npyv512_higher_pd256(A) _mm512_extractf64x4_pd(A, 1) + +#ifdef NPY_HAVE_AVX512DQ + #define npyv512_higher_ps256(A) _mm512_extractf32x8_ps(A, 1) +#else + #define npyv512_higher_ps256(A) \ + _mm256_castsi256_ps(_mm512_extracti64x4_epi64(_mm512_castps_si512(A), 1)) +#endif + +#define npyv512_combine_si256(A, B) _mm512_inserti64x4(_mm512_castsi256_si512(A), B, 1) +#define npyv512_combine_pd256(A, B) _mm512_insertf64x4(_mm512_castpd256_pd512(A), B, 1) + +#ifdef NPY_HAVE_AVX512DQ + #define npyv512_combine_ps256(A, B) _mm512_insertf32x8(_mm512_castps256_ps512(A), B, 1) +#else + #define npyv512_combine_ps256(A, B) \ + _mm512_castsi512_ps(npyv512_combine_si256(_mm256_castps_si256(A), _mm256_castps_si256(B))) +#endif + +#define NPYV_IMPL_AVX512_FROM_AVX2_1ARG(FN_NAME, INTRIN) \ + NPY_FINLINE __m512i FN_NAME(__m512i a) \ + { \ + __m256i l_a = npyv512_lower_si256(a); \ + __m256i h_a = npyv512_higher_si256(a); \ + l_a = INTRIN(l_a); \ + h_a = INTRIN(h_a); \ + return npyv512_combine_si256(l_a, h_a); \ + } + +#define NPYV_IMPL_AVX512_FROM_AVX2_PS_1ARG(FN_NAME, INTRIN) \ + NPY_FINLINE __m512 FN_NAME(__m512 a) \ + { \ + __m256 l_a = npyv512_lower_ps256(a); \ + __m256 h_a = npyv512_higher_ps256(a); \ + l_a = INTRIN(l_a); \ + h_a = INTRIN(h_a); \ + return npyv512_combine_ps256(l_a, h_a); \ + } + +#define NPYV_IMPL_AVX512_FROM_AVX2_PD_1ARG(FN_NAME, INTRIN) \ + NPY_FINLINE __m512d FN_NAME(__m512d a) \ + { \ + __m256d l_a = npyv512_lower_pd256(a); \ + __m256d h_a = npyv512_higher_pd256(a); \ + l_a = INTRIN(l_a); \ + h_a = INTRIN(h_a); \ + return npyv512_combine_pd256(l_a, h_a); \ + } + +#define NPYV_IMPL_AVX512_FROM_AVX2_2ARG(FN_NAME, INTRIN) \ + NPY_FINLINE __m512i FN_NAME(__m512i a, __m512i b) \ + { \ + __m256i l_a = npyv512_lower_si256(a); \ + __m256i h_a = npyv512_higher_si256(a); \ + __m256i l_b = npyv512_lower_si256(b); \ + __m256i h_b = npyv512_higher_si256(b); \ + l_a = INTRIN(l_a, l_b); \ + h_a = INTRIN(h_a, h_b); \ + return npyv512_combine_si256(l_a, h_a); \ + } + +#define NPYV_IMPL_AVX512_FROM_SI512_PS_2ARG(FN_NAME, INTRIN) \ + NPY_FINLINE __m512 FN_NAME(__m512 a, __m512 b) \ + { \ + return _mm512_castsi512_ps(INTRIN( \ + _mm512_castps_si512(a), _mm512_castps_si512(b) \ + )); \ + } + +#define NPYV_IMPL_AVX512_FROM_SI512_PD_2ARG(FN_NAME, INTRIN) \ + NPY_FINLINE __m512d FN_NAME(__m512d a, __m512d b) \ + { \ + return _mm512_castsi512_pd(INTRIN( \ + _mm512_castpd_si512(a), _mm512_castpd_si512(b) \ + )); \ + } + +#ifndef NPY_HAVE_AVX512BW + NPYV_IMPL_AVX512_FROM_AVX2_2ARG(npyv512_packs_epi16, _mm256_packs_epi16) +#else + #define npyv512_packs_epi16 _mm512_packs_epi16 +#endif + +NPY_FINLINE __m256i npyv512_pack_lo_hi(__m512i a) { + __m256i lo = npyv512_lower_si256(a); + __m256i hi = npyv512_higher_si256(a); + return _mm256_packs_epi32(lo, hi); +} + +#endif // _NPY_SIMD_AVX512_UTILS_H diff --git a/mkl_umath/src/npyv/binop_override.h b/mkl_umath/src/npyv/binop_override.h new file mode 100644 index 00000000..ec3d0467 --- /dev/null +++ b/mkl_umath/src/npyv/binop_override.h @@ -0,0 +1,215 @@ +#ifndef NUMPY_CORE_SRC_COMMON_BINOP_OVERRIDE_H_ +#define NUMPY_CORE_SRC_COMMON_BINOP_OVERRIDE_H_ + +#include +#include +#include "numpy/arrayobject.h" + +#include "get_attr_string.h" + +/* + * Logic for deciding when binops should return NotImplemented versus when + * they should go ahead and call a ufunc (or similar). + * + * The interaction between binop methods (ndarray.__add__ and friends) and + * ufuncs (which dispatch to __array_ufunc__) is both complicated in its own + * right, and also has complicated historical constraints. + * + * In the very old days, the rules were: + * - If the other argument has a higher __array_priority__, then return + * NotImplemented + * - Otherwise, call the corresponding ufunc. + * - And the ufunc might return NotImplemented based on some complex + * criteria that I won't reproduce here. + * + * Ufuncs no longer return NotImplemented (except in a few marginal situations + * which are being phased out -- see https://github.com/numpy/numpy/pull/5864) + * + * So as of 1.9, the effective rules were: + * - If the other argument has a higher __array_priority__, and is *not* a + * subclass of ndarray, then return NotImplemented. (If it is a subclass, + * the regular Python rules have already given it a chance to run; so if we + * are running, then it means the other argument has already returned + * NotImplemented and is basically asking us to take care of things.) + * - Otherwise call the corresponding ufunc. + * + * We would like to get rid of __array_priority__, and __array_ufunc__ + * provides a large part of a replacement for it. Once __array_ufunc__ is + * widely available, the simplest dispatch rules that might possibly work + * would be: + * - Always call the corresponding ufunc. + * + * But: + * - Doing this immediately would break backwards compatibility -- there's a + * lot of code using __array_priority__ out there. + * - It's not at all clear whether __array_ufunc__ actually is sufficient for + * all use cases. (See https://github.com/numpy/numpy/issues/5844 for lots + * of discussion of this, and in particular + * https://github.com/numpy/numpy/issues/5844#issuecomment-112014014 + * for a summary of some conclusions.) Also, python 3.6 defines a standard + * where setting a special-method name to None is a signal that that method + * cannot be used. + * + * So for 1.13, we are going to try the following rules. + * + * For binops like a.__add__(b): + * - If b does not define __array_ufunc__, apply the legacy rule: + * - If not isinstance(b, a.__class__), and b.__array_priority__ is higher + * than a.__array_priority__, return NotImplemented + * - If b does define __array_ufunc__ but it is None, return NotImplemented + * - Otherwise, call the corresponding ufunc. + * + * For in-place operations like a.__iadd__(b) + * - If b does not define __array_ufunc__, apply the legacy rule: + * - If not isinstance(b, a.__class__), and b.__array_priority__ is higher + * than a.__array_priority__, return NotImplemented + * - Otherwise, call the corresponding ufunc. + * + * For reversed operations like b.__radd__(a) we call the corresponding ufunc. + * + * Rationale for __radd__: This is because by the time the reversed operation + * is called, there are only two possibilities: The first possibility is that + * the current class is a strict subclass of the other class. In practice, the + * only way this will happen is if b is a strict subclass of a, and a is + * ndarray or a subclass of ndarray, and neither a nor b has actually + * overridden this method. In this case, Python will never call a.__add__ + * (because it's identical to b.__radd__), so we have no-one to defer to; + * there's no reason to return NotImplemented. The second possibility is that + * b.__add__ has already been called and returned NotImplemented. Again, in + * this case there is no point in returning NotImplemented. + * + * Rationale for __iadd__: In-place operations do not take all the trouble + * above, because if __iadd__ returns NotImplemented then Python will silently + * convert the operation into an out-of-place operation, i.e. 'a += b' will + * silently become 'a = a + b'. We don't want to allow this for arrays, + * because it will create unexpected memory allocations, break views, etc. + * However, backwards compatibility requires that we follow the rules of + * __array_priority__ for arrays that define it. For classes that use the new + * __array_ufunc__ mechanism we simply defer to the ufunc. That has the effect + * that when the other array has__array_ufunc = None a TypeError will be raised. + * + * In the future we might change these rules further. For example, we plan to + * eventually deprecate __array_priority__ in cases where __array_ufunc__ is + * not present. + */ + +static int +binop_should_defer(PyObject *self, PyObject *other, int inplace) +{ + /* + * This function assumes that self.__binop__(other) is underway and + * implements the rules described above. Python's C API is funny, and + * makes it tricky to tell whether a given slot is called for __binop__ + * ("forward") or __rbinop__ ("reversed"). You are responsible for + * determining this before calling this function; it only provides the + * logic for forward binop implementations. + */ + + /* + * NB: there's another copy of this code in + * numpy.ma.core.MaskedArray._delegate_binop + * which should possibly be updated when this is. + */ + + PyObject *attr; + double self_prio, other_prio; + int defer; + /* + * attribute check is expensive for scalar operations, avoid if possible + */ + if (other == NULL || + self == NULL || + Py_TYPE(self) == Py_TYPE(other) || + PyArray_CheckExact(other) || + PyArray_CheckAnyScalarExact(other)) { + return 0; + } + /* + * Classes with __array_ufunc__ are living in the future, and only need to + * check whether __array_ufunc__ equals None. + */ + attr = PyArray_LookupSpecial(other, npy_um_str_array_ufunc); + if (attr != NULL) { + defer = !inplace && (attr == Py_None); + Py_DECREF(attr); + return defer; + } + else if (PyErr_Occurred()) { + PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */ + } + /* + * Otherwise, we need to check for the legacy __array_priority__. But if + * other.__class__ is a subtype of self.__class__, then it's already had + * a chance to run, so no need to defer to it. + */ + if(PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) { + return 0; + } + self_prio = PyArray_GetPriority((PyObject *)self, NPY_SCALAR_PRIORITY); + other_prio = PyArray_GetPriority((PyObject *)other, NPY_SCALAR_PRIORITY); + return self_prio < other_prio; +} + +/* + * A CPython slot like ->tp_as_number->nb_add gets called for *both* forward + * and reversed operations. E.g. + * a + b + * may call + * a->tp_as_number->nb_add(a, b) + * and + * b + a + * may call + * a->tp_as_number->nb_add(b, a) + * and the only way to tell which is which is for a slot implementation 'f' to + * check + * arg1->tp_as_number->nb_add == f + * arg2->tp_as_number->nb_add == f + * If both are true, then CPython will as a special case only call the + * operation once (i.e., it performs both the forward and reversed binops + * simultaneously). This function is mostly intended for figuring out + * whether we are a forward binop that might want to return NotImplemented, + * and in the both-at-once case we never want to return NotImplemented, so in + * that case BINOP_IS_FORWARD returns false. + * + * This is modeled on the checks in CPython's typeobject.c SLOT1BINFULL + * macro. + */ +#define BINOP_IS_FORWARD(m1, m2, SLOT_NAME, test_func) \ + (Py_TYPE(m2)->tp_as_number != NULL && \ + (void*)(Py_TYPE(m2)->tp_as_number->SLOT_NAME) != (void*)(test_func)) + +#define BINOP_GIVE_UP_IF_NEEDED(m1, m2, slot_expr, test_func) \ + do { \ + if (BINOP_IS_FORWARD(m1, m2, slot_expr, test_func) && \ + binop_should_defer((PyObject*)m1, (PyObject*)m2, 0)) { \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ + } while (0) + +#define INPLACE_GIVE_UP_IF_NEEDED(m1, m2, slot_expr, test_func) \ + do { \ + if (BINOP_IS_FORWARD(m1, m2, slot_expr, test_func) && \ + binop_should_defer((PyObject*)m1, (PyObject*)m2, 1)) { \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ + } while (0) + +/* + * For rich comparison operations, it's impossible to distinguish + * between a forward comparison and a reversed/reflected + * comparison. So we assume they are all forward. This only works because the + * logic in binop_override_forward_binop_should_defer is essentially + * asymmetric -- you can never have two duck-array types that each decide to + * defer to the other. + */ +#define RICHCMP_GIVE_UP_IF_NEEDED(m1, m2) \ + do { \ + if (binop_should_defer((PyObject*)m1, (PyObject*)m2, 0)) { \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ + } while (0) + +#endif /* NUMPY_CORE_SRC_COMMON_BINOP_OVERRIDE_H_ */ diff --git a/mkl_umath/src/npyv/cblasfuncs.h b/mkl_umath/src/npyv/cblasfuncs.h new file mode 100644 index 00000000..71c533f3 --- /dev/null +++ b/mkl_umath/src/npyv/cblasfuncs.h @@ -0,0 +1,7 @@ +#ifndef NUMPY_CORE_SRC_COMMON_CBLASFUNCS_H_ +#define NUMPY_CORE_SRC_COMMON_CBLASFUNCS_H_ + +NPY_NO_EXPORT PyObject * +cblas_matrixproduct(int, PyArrayObject *, PyArrayObject *, PyArrayObject *); + +#endif /* NUMPY_CORE_SRC_COMMON_CBLASFUNCS_H_ */ diff --git a/mkl_umath/src/npyv/emulate_maskop.h b/mkl_umath/src/npyv/emulate_maskop.h new file mode 100644 index 00000000..0a3a164f --- /dev/null +++ b/mkl_umath/src/npyv/emulate_maskop.h @@ -0,0 +1,80 @@ +/** + * This header is used internally by all current supported SIMD extensions, + * except for AVX512. + */ +#ifndef NPY_SIMD + #error "Not a standalone header, use simd/simd.h instead" +#endif + +#ifndef _NPY_SIMD_EMULATE_MASKOP_H +#define _NPY_SIMD_EMULATE_MASKOP_H + +/** + * Implements conditional addition and subtraction. + * e.g. npyv_ifadd_f32(mask, a, b, c) -> mask ? a + b : c + * e.g. npyv_ifsub_f32(mask, a, b, c) -> mask ? a - b : c + */ +#define NPYV_IMPL_EMULATE_MASK_ADDSUB(SFX, BSFX) \ + NPY_FINLINE npyv_##SFX npyv_ifadd_##SFX \ + (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \ + { \ + npyv_##SFX add = npyv_add_##SFX(a, b); \ + return npyv_select_##SFX(m, add, c); \ + } \ + NPY_FINLINE npyv_##SFX npyv_ifsub_##SFX \ + (npyv_##BSFX m, npyv_##SFX a, npyv_##SFX b, npyv_##SFX c) \ + { \ + npyv_##SFX sub = npyv_sub_##SFX(a, b); \ + return npyv_select_##SFX(m, sub, c); \ + } + +NPYV_IMPL_EMULATE_MASK_ADDSUB(u8, b8) +NPYV_IMPL_EMULATE_MASK_ADDSUB(s8, b8) +NPYV_IMPL_EMULATE_MASK_ADDSUB(u16, b16) +NPYV_IMPL_EMULATE_MASK_ADDSUB(s16, b16) +NPYV_IMPL_EMULATE_MASK_ADDSUB(u32, b32) +NPYV_IMPL_EMULATE_MASK_ADDSUB(s32, b32) +NPYV_IMPL_EMULATE_MASK_ADDSUB(u64, b64) +NPYV_IMPL_EMULATE_MASK_ADDSUB(s64, b64) +#if NPY_SIMD_F32 + NPYV_IMPL_EMULATE_MASK_ADDSUB(f32, b32) +#endif +#if NPY_SIMD_F64 + NPYV_IMPL_EMULATE_MASK_ADDSUB(f64, b64) +#endif +#if NPY_SIMD_F32 + // conditional division, m ? a / b : c + NPY_FINLINE npyv_f32 + npyv_ifdiv_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b, npyv_f32 c) + { + const npyv_f32 one = npyv_setall_f32(1.0f); + npyv_f32 div = npyv_div_f32(a, npyv_select_f32(m, b, one)); + return npyv_select_f32(m, div, c); + } + // conditional division, m ? a / b : 0 + NPY_FINLINE npyv_f32 + npyv_ifdivz_f32(npyv_b32 m, npyv_f32 a, npyv_f32 b) + { + const npyv_f32 zero = npyv_zero_f32(); + return npyv_ifdiv_f32(m, a, b, zero); + } +#endif +#if NPY_SIMD_F64 + // conditional division, m ? a / b : c + NPY_FINLINE npyv_f64 + npyv_ifdiv_f64(npyv_b64 m, npyv_f64 a, npyv_f64 b, npyv_f64 c) + { + const npyv_f64 one = npyv_setall_f64(1.0); + npyv_f64 div = npyv_div_f64(a, npyv_select_f64(m, b, one)); + return npyv_select_f64(m, div, c); + } + // conditional division, m ? a / b : 0 + NPY_FINLINE npyv_f64 + npyv_ifdivz_f64(npyv_b64 m, npyv_f64 a, npyv_f64 b) + { + const npyv_f64 zero = npyv_zero_f64(); + return npyv_ifdiv_f64(m, a, b, zero); + } +#endif + +#endif // _NPY_SIMD_EMULATE_MASKOP_H diff --git a/mkl_umath/src/npyv/get_attr_string.h b/mkl_umath/src/npyv/get_attr_string.h new file mode 100644 index 00000000..36d39189 --- /dev/null +++ b/mkl_umath/src/npyv/get_attr_string.h @@ -0,0 +1,95 @@ +#ifndef NUMPY_CORE_SRC_COMMON_GET_ATTR_STRING_H_ +#define NUMPY_CORE_SRC_COMMON_GET_ATTR_STRING_H_ + +#include +#include "ufunc_object.h" + +static inline npy_bool +_is_basic_python_type(PyTypeObject *tp) +{ + return ( + /* Basic number types */ + tp == &PyBool_Type || + tp == &PyLong_Type || + tp == &PyFloat_Type || + tp == &PyComplex_Type || + + /* Basic sequence types */ + tp == &PyList_Type || + tp == &PyTuple_Type || + tp == &PyDict_Type || + tp == &PySet_Type || + tp == &PyFrozenSet_Type || + tp == &PyUnicode_Type || + tp == &PyBytes_Type || + + /* other builtins */ + tp == &PySlice_Type || + tp == Py_TYPE(Py_None) || + tp == Py_TYPE(Py_Ellipsis) || + tp == Py_TYPE(Py_NotImplemented) || + + /* TODO: ndarray, but we can't see PyArray_Type here */ + + /* sentinel to swallow trailing || */ + NPY_FALSE + ); +} + + +/* + * Lookup a special method, following the python approach of looking up + * on the type object, rather than on the instance itself. + * + * Assumes that the special method is a numpy-specific one, so does not look + * at builtin types. It does check base ndarray and numpy scalar types. + * + * In future, could be made more like _Py_LookupSpecial + */ +static inline PyObject * +PyArray_LookupSpecial(PyObject *obj, PyObject *name_unicode) +{ + PyTypeObject *tp = Py_TYPE(obj); + + /* We do not need to check for special attributes on trivial types */ + if (_is_basic_python_type(tp)) { + return NULL; + } + PyObject *res = PyObject_GetAttr((PyObject *)tp, name_unicode); + + if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + + return res; +} + + +/* + * PyArray_LookupSpecial_OnInstance: + * + * Implements incorrect special method lookup rules, that break the python + * convention, and looks on the instance, not the type. + * + * Kept for backwards compatibility. In future, we should deprecate this. + */ +static inline PyObject * +PyArray_LookupSpecial_OnInstance(PyObject *obj, PyObject *name_unicode) +{ + PyTypeObject *tp = Py_TYPE(obj); + + /* We do not need to check for special attributes on trivial types */ + if (_is_basic_python_type(tp)) { + return NULL; + } + + PyObject *res = PyObject_GetAttr(obj, name_unicode); + + if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + + return res; +} + +#endif /* NUMPY_CORE_SRC_COMMON_GET_ATTR_STRING_H_ */ diff --git a/mkl_umath/src/npyv/gil_utils.h b/mkl_umath/src/npyv/gil_utils.h new file mode 100644 index 00000000..fd77fa60 --- /dev/null +++ b/mkl_umath/src/npyv/gil_utils.h @@ -0,0 +1,15 @@ +#ifndef NUMPY_CORE_SRC_COMMON_GIL_UTILS_H_ +#define NUMPY_CORE_SRC_COMMON_GIL_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +NPY_NO_EXPORT void +npy_gil_error(PyObject *type, const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_SRC_COMMON_GIL_UTILS_H_ */ diff --git a/mkl_umath/src/npyv/intdiv.h b/mkl_umath/src/npyv/intdiv.h new file mode 100644 index 00000000..d843eaf4 --- /dev/null +++ b/mkl_umath/src/npyv/intdiv.h @@ -0,0 +1,475 @@ +/** + * This header implements `npyv_divisor_*` intrinsics used for computing the parameters + * of fast integer division, while division intrinsics `npyv_divc_*` are defined in + * {extension}/arithmetic.h. + */ +#ifndef NPY_SIMD + #error "Not a standalone header, use simd/simd.h instead" +#endif +#ifndef _NPY_SIMD_INTDIV_H +#define _NPY_SIMD_INTDIV_H +/********************************************************************************** + ** Integer division + ********************************************************************************** + * Almost all architecture (except Power10) doesn't support integer vector division, + * also the cost of scalar division in architectures like x86 is too high it can take + * 30 to 40 cycles on modern chips and up to 100 on old ones. + * + * Therefore we are using division by multiplying with precomputed reciprocal technique, + * the method that been used in this implementation is based on T. Granlund and P. L. Montgomery + * “Division by invariant integers using multiplication(see [Figure 4.1, 5.1] + * https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.2556) + * + * It shows a good impact for all architectures especially on X86, + * however computing divisor parameters is kind of expensive so this implementation + * should only works when divisor is a scalar and used multiple of times. + * + * The division process is separated into two intrinsics for each data type + * + * 1- npyv_{dtype}x3 npyv_divisor_{dtype} ({dtype} divisor); + * For computing the divisor parameters (multiplier + shifters + sign of divisor(signed only)) + * + * 2- npyv_{dtype} npyv_divisor_{dtype} (npyv_{dtype} dividend, npyv_{dtype}x3 divisor_parms); + * For performing the final division. + * + ** For example: + * int vstep = npyv_nlanes_s32; // number of lanes + * int x = 0x6e70; + * npyv_s32x3 divisor = npyv_divisor_s32(x); // init divisor params + * for (; len >= vstep; src += vstep, dst += vstep, len -= vstep) { + * npyv_s32 a = npyv_load_s32(*src); // load s32 vector from memory + * a = npyv_divc_s32(a, divisor); // divide all elements by x + * npyv_store_s32(dst, a); // store s32 vector into memory + * } + * + ** NOTES: + * - For 64-bit division on Aarch64 and IBM/Power, we fall-back to the scalar division + * since emulating multiply-high is expensive and both architectures have very fast dividers. + * + *************************************************************** + ** Figure 4.1: Unsigned division by run–time invariant divisor + *************************************************************** + * Initialization (given uword d with 1 ≤ d < 2^N): + * int l = ceil(log2(d)); + * uword m = 2^N * (2^l− d) / d + 1; + * int sh1 = min(l, 1); + * int sh2 = max(l − 1, 0); + * + * For q = FLOOR(a/d), all uword: + * uword t1 = MULUH(m, a); + * q = SRL(t1 + SRL(a − t1, sh1), sh2); + * + ************************************************************************************ + ** Figure 5.1: Signed division by run–time invariant divisor, rounded towards zero + ************************************************************************************ + * Initialization (given constant sword d with d !=0): + * int l = max(ceil(log2(abs(d))), 1); + * udword m0 = 1 + (2^(N+l-1)) / abs(d); + * sword m = m0 − 2^N; + * sword dsign = XSIGN(d); + * int sh = l − 1; + * + * For q = TRUNC(a/d), all sword: + * sword q0 = a + MULSH(m, a); + * q0 = SRA(q0, sh) − XSIGN(a); + * q = EOR(q0, dsign) − dsign; + */ +/** + * bit-scan reverse for non-zeros. returns the index of the highest set bit. + * equivalent to floor(log2(a)) + */ +#ifdef _MSC_VER + #include // _BitScanReverse +#endif +NPY_FINLINE unsigned npyv__bitscan_revnz_u32(npy_uint32 a) +{ + assert(a > 0); // due to use __builtin_clz + unsigned r; +#if defined(NPY_HAVE_SSE2) && defined(_MSC_VER) + unsigned long rl; + (void)_BitScanReverse(&rl, (unsigned long)a); + r = (unsigned)rl; + +#elif defined(NPY_HAVE_SSE2) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) \ + && (defined(NPY_CPU_X86) || defined(NPY_CPU_AMD64)) + __asm__("bsr %1, %0" : "=r" (r) : "r"(a)); +#elif defined(__GNUC__) || defined(__clang__) + r = 31 - __builtin_clz(a); // performs on arm -> clz, ppc -> cntlzw +#else + r = 0; + while (a >>= 1) { + r++; + } +#endif + return r; +} +NPY_FINLINE unsigned npyv__bitscan_revnz_u64(npy_uint64 a) +{ + assert(a > 0); // due to use __builtin_clzll +#if defined(_M_AMD64) && defined(_MSC_VER) + unsigned long rl; + (void)_BitScanReverse64(&rl, a); + return (unsigned)rl; +#elif defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) + npy_uint64 r; + __asm__("bsrq %1, %0" : "=r"(r) : "r"(a)); + return (unsigned)r; +#elif defined(__GNUC__) || defined(__clang__) + return 63 - __builtin_clzll(a); +#else + npy_uint64 a_hi = a >> 32; + if (a_hi == 0) { + return npyv__bitscan_revnz_u32((npy_uint32)a); + } + return 32 + npyv__bitscan_revnz_u32((npy_uint32)a_hi); +#endif +} +/** + * Divides 128-bit unsigned integer by a 64-bit when the lower + * 64-bit of the dividend is zero. + * + * This function is needed to calculate the multiplier of 64-bit integer division + * see npyv_divisor_u64/npyv_divisor_s64. + */ +NPY_FINLINE npy_uint64 npyv__divh128_u64(npy_uint64 high, npy_uint64 divisor) +{ + assert(divisor > 1); + npy_uint64 quotient; +#if defined(_M_X64) && defined(_MSC_VER) && _MSC_VER >= 1920 && !defined(__clang__) + npy_uint64 remainder; + quotient = _udiv128(high, 0, divisor, &remainder); + (void)remainder; +#elif defined(__x86_64__) && (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) + __asm__("divq %[d]" : "=a"(quotient) : [d] "r"(divisor), "a"(0), "d"(high)); +#elif defined(__SIZEOF_INT128__) + quotient = (npy_uint64)((((__uint128_t)high) << 64) / divisor); +#else + /** + * Minified version based on Donald Knuth’s Algorithm D (Division of nonnegative integers), + * and Generic implementation in Hacker’s Delight. + * + * See https://skanthak.homepage.t-online.de/division.html + * with respect to the license of the Hacker's Delight book + * (https://web.archive.org/web/20190408122508/http://www.hackersdelight.org/permissions.htm) + */ + // shift amount for normalize + unsigned ldz = 63 - npyv__bitscan_revnz_u64(divisor); + // normalize divisor + divisor <<= ldz; + high <<= ldz; + // break divisor up into two 32-bit digits + npy_uint32 divisor_hi = divisor >> 32; + npy_uint32 divisor_lo = divisor & 0xFFFFFFFF; + // compute high quotient digit + npy_uint64 quotient_hi = high / divisor_hi; + npy_uint64 remainder = high - divisor_hi * quotient_hi; + npy_uint64 base32 = 1ULL << 32; + while (quotient_hi >= base32 || quotient_hi*divisor_lo > base32*remainder) { + --quotient_hi; + remainder += divisor_hi; + if (remainder >= base32) { + break; + } + } + // compute dividend digit pairs + npy_uint64 dividend_pairs = base32*high - divisor*quotient_hi; + // compute second quotient digit for lower zeros + npy_uint32 quotient_lo = (npy_uint32)(dividend_pairs / divisor_hi); + quotient = base32*quotient_hi + quotient_lo; +#endif + return quotient; +} +// Initializing divisor parameters for unsigned 8-bit division +NPY_FINLINE npyv_u8x3 npyv_divisor_u8(npy_uint8 d) +{ + unsigned l, l2, sh1, sh2, m; + switch (d) { + case 0: // LCOV_EXCL_LINE + // for potential divide by zero, On x86 GCC inserts `ud2` instruction + // instead of letting the HW/CPU trap it which leads to illegal instruction exception. + // 'volatile' should suppress this behavior and allow us to raise HW/CPU + // arithmetic exception. + m = sh1 = sh2 = 1 / ((npy_uint8 volatile *)&d)[0]; + break; + case 1: + m = 1; sh1 = sh2 = 0; + break; + case 2: + m = 1; sh1 = 1; sh2 = 0; + break; + default: + l = npyv__bitscan_revnz_u32(d - 1) + 1; // ceil(log2(d)) + l2 = (npy_uint8)(1 << l); // 2^l, overflow to 0 if l = 8 + m = ((npy_uint16)((l2 - d) << 8)) / d + 1; // multiplier + sh1 = 1; sh2 = l - 1; // shift counts + } + npyv_u8x3 divisor; +#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[0] = npyv_setall_u16(m); + divisor.val[1] = npyv_set_u8(sh1); + divisor.val[2] = npyv_set_u8(sh2); +#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) + divisor.val[0] = npyv_setall_u8(m); + divisor.val[1] = npyv_setall_u8(sh1); + divisor.val[2] = npyv_setall_u8(sh2); +#elif defined(NPY_HAVE_NEON) + divisor.val[0] = npyv_setall_u8(m); + divisor.val[1] = npyv_reinterpret_u8_s8(npyv_setall_s8(-sh1)); + divisor.val[2] = npyv_reinterpret_u8_s8(npyv_setall_s8(-sh2)); +#else + #error "please initialize the shifting operand for the new architecture" +#endif + return divisor; +} +// Initializing divisor parameters for signed 8-bit division +NPY_FINLINE npyv_s16x3 npyv_divisor_s16(npy_int16 d); +NPY_FINLINE npyv_s8x3 npyv_divisor_s8(npy_int8 d) +{ +#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + npyv_s16x3 p = npyv_divisor_s16(d); + npyv_s8x3 r; + r.val[0] = npyv_reinterpret_s8_s16(p.val[0]); + r.val[1] = npyv_reinterpret_s8_s16(p.val[1]); + r.val[2] = npyv_reinterpret_s8_s16(p.val[2]); + return r; +#else + int d1 = abs(d); + int sh, m; + if (d1 > 1) { + sh = (int)npyv__bitscan_revnz_u32(d1-1); // ceil(log2(abs(d))) - 1 + m = (1 << (8 + sh)) / d1 + 1; // multiplier + } + else if (d1 == 1) { + sh = 0; m = 1; + } + else { + // raise arithmetic exception for d == 0 + sh = m = 1 / ((npy_int8 volatile *)&d)[0]; // LCOV_EXCL_LINE + } + npyv_s8x3 divisor; + divisor.val[0] = npyv_setall_s8(m); + divisor.val[2] = npyv_setall_s8(d < 0 ? -1 : 0); + #if defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) + divisor.val[1] = npyv_setall_s8(sh); + #elif defined(NPY_HAVE_NEON) + divisor.val[1] = npyv_setall_s8(-sh); + #else + #error "please initialize the shifting operand for the new architecture" + #endif + return divisor; +#endif +} +// Initializing divisor parameters for unsigned 16-bit division +NPY_FINLINE npyv_u16x3 npyv_divisor_u16(npy_uint16 d) +{ + unsigned l, l2, sh1, sh2, m; + switch (d) { + case 0: // LCOV_EXCL_LINE + // raise arithmetic exception for d == 0 + m = sh1 = sh2 = 1 / ((npy_uint16 volatile *)&d)[0]; + break; + case 1: + m = 1; sh1 = sh2 = 0; + break; + case 2: + m = 1; sh1 = 1; sh2 = 0; + break; + default: + l = npyv__bitscan_revnz_u32(d - 1) + 1; // ceil(log2(d)) + l2 = (npy_uint16)(1 << l); // 2^l, overflow to 0 if l = 16 + m = ((l2 - d) << 16) / d + 1; // multiplier + sh1 = 1; sh2 = l - 1; // shift counts + } + npyv_u16x3 divisor; + divisor.val[0] = npyv_setall_u16(m); +#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[1] = npyv_set_u16(sh1); + divisor.val[2] = npyv_set_u16(sh2); +#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) + divisor.val[1] = npyv_setall_u16(sh1); + divisor.val[2] = npyv_setall_u16(sh2); +#elif defined(NPY_HAVE_NEON) + divisor.val[1] = npyv_reinterpret_u16_s16(npyv_setall_s16(-sh1)); + divisor.val[2] = npyv_reinterpret_u16_s16(npyv_setall_s16(-sh2)); +#else + #error "please initialize the shifting operand for the new architecture" +#endif + return divisor; +} +// Initializing divisor parameters for signed 16-bit division +NPY_FINLINE npyv_s16x3 npyv_divisor_s16(npy_int16 d) +{ + int d1 = abs(d); + int sh, m; + if (d1 > 1) { + sh = (int)npyv__bitscan_revnz_u32(d1 - 1); // ceil(log2(abs(d))) - 1 + m = (1 << (16 + sh)) / d1 + 1; // multiplier + } + else if (d1 == 1) { + sh = 0; m = 1; + } + else { + // raise arithmetic exception for d == 0 + sh = m = 1 / ((npy_int16 volatile *)&d)[0]; // LCOV_EXCL_LINE + } + npyv_s16x3 divisor; + divisor.val[0] = npyv_setall_s16(m); + divisor.val[2] = npyv_setall_s16(d < 0 ? -1 : 0); // sign of divisor +#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[1] = npyv_set_s16(sh); +#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) + divisor.val[1] = npyv_setall_s16(sh); +#elif defined(NPY_HAVE_NEON) + divisor.val[1] = npyv_setall_s16(-sh); +#else + #error "please initialize the shifting operand for the new architecture" +#endif + return divisor; +} +// Initializing divisor parameters for unsigned 32-bit division +NPY_FINLINE npyv_u32x3 npyv_divisor_u32(npy_uint32 d) +{ + npy_uint32 l, l2, sh1, sh2, m; + switch (d) { + case 0: // LCOV_EXCL_LINE + // raise arithmetic exception for d == 0 + m = sh1 = sh2 = 1 / ((npy_uint32 volatile *)&d)[0]; // LCOV_EXCL_LINE + break; + case 1: + m = 1; sh1 = sh2 = 0; + break; + case 2: + m = 1; sh1 = 1; sh2 = 0; + break; + default: + l = npyv__bitscan_revnz_u32(d - 1) + 1; // ceil(log2(d)) + l2 = (npy_uint32)(1ULL << l); // 2^l, overflow to 0 if l = 32 + m = ((npy_uint64)(l2 - d) << 32) / d + 1; // multiplier + sh1 = 1; sh2 = l - 1; // shift counts + } + npyv_u32x3 divisor; + divisor.val[0] = npyv_setall_u32(m); +#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[1] = npyv_set_u32(sh1); + divisor.val[2] = npyv_set_u32(sh2); +#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) + divisor.val[1] = npyv_setall_u32(sh1); + divisor.val[2] = npyv_setall_u32(sh2); +#elif defined(NPY_HAVE_NEON) + divisor.val[1] = npyv_reinterpret_u32_s32(npyv_setall_s32(-sh1)); + divisor.val[2] = npyv_reinterpret_u32_s32(npyv_setall_s32(-sh2)); +#else + #error "please initialize the shifting operand for the new architecture" +#endif + return divisor; +} +// Initializing divisor parameters for signed 32-bit division +NPY_FINLINE npyv_s32x3 npyv_divisor_s32(npy_int32 d) +{ + npy_int32 d1 = abs(d); + npy_int32 sh, m; + // Handle abs overflow + if ((npy_uint32)d == 0x80000000U) { + m = 0x80000001; + sh = 30; + } + else if (d1 > 1) { + sh = npyv__bitscan_revnz_u32(d1 - 1); // ceil(log2(abs(d))) - 1 + m = (1ULL << (32 + sh)) / d1 + 1; // multiplier + } + else if (d1 == 1) { + sh = 0; m = 1; + } + else { + // raise arithmetic exception for d == 0 + sh = m = 1 / ((npy_int32 volatile *)&d)[0]; // LCOV_EXCL_LINE + } + npyv_s32x3 divisor; + divisor.val[0] = npyv_setall_s32(m); + divisor.val[2] = npyv_setall_s32(d < 0 ? -1 : 0); // sign of divisor +#ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[1] = npyv_set_s32(sh); +#elif defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) + divisor.val[1] = npyv_setall_s32(sh); +#elif defined(NPY_HAVE_NEON) + divisor.val[1] = npyv_setall_s32(-sh); +#else + #error "please initialize the shifting operand for the new architecture" +#endif + return divisor; +} +// Initializing divisor parameters for unsigned 64-bit division +NPY_FINLINE npyv_u64x3 npyv_divisor_u64(npy_uint64 d) +{ + npyv_u64x3 divisor; +#if defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) || defined(NPY_HAVE_NEON) + divisor.val[0] = npyv_setall_u64(d); +#else + npy_uint64 l, l2, sh1, sh2, m; + switch (d) { + case 0: // LCOV_EXCL_LINE + // raise arithmetic exception for d == 0 + m = sh1 = sh2 = 1 / ((npy_uint64 volatile *)&d)[0]; // LCOV_EXCL_LINE + break; + case 1: + m = 1; sh1 = sh2 = 0; + break; + case 2: + m = 1; sh1 = 1; sh2 = 0; + break; + default: + l = npyv__bitscan_revnz_u64(d - 1) + 1; // ceil(log2(d)) + l2 = l < 64 ? 1ULL << l : 0; // 2^l + m = npyv__divh128_u64(l2 - d, d) + 1; // multiplier + sh1 = 1; sh2 = l - 1; // shift counts + } + divisor.val[0] = npyv_setall_u64(m); + #ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[1] = npyv_set_u64(sh1); + divisor.val[2] = npyv_set_u64(sh2); + #else + #error "please initialize the shifting operand for the new architecture" + #endif +#endif + return divisor; +} +// Initializing divisor parameters for signed 64-bit division +NPY_FINLINE npyv_s64x3 npyv_divisor_s64(npy_int64 d) +{ + npyv_s64x3 divisor; +#if defined(NPY_HAVE_VSX2) || defined(NPY_HAVE_VX) || defined(NPY_HAVE_NEON) + divisor.val[0] = npyv_setall_s64(d); + divisor.val[1] = npyv_cvt_s64_b64( + npyv_cmpeq_s64(npyv_setall_s64(-1), divisor.val[0]) + ); +#else + npy_int64 d1 = llabs(d); + npy_int64 sh, m; + // Handle abs overflow + if ((npy_uint64)d == 0x8000000000000000ULL) { + m = 0x8000000000000001LL; + sh = 62; + } + else if (d1 > 1) { + sh = npyv__bitscan_revnz_u64(d1 - 1); // ceil(log2(abs(d))) - 1 + m = npyv__divh128_u64(1ULL << sh, d1) + 1; // multiplier + } + else if (d1 == 1) { + sh = 0; m = 1; + } + else { + // raise arithmetic exception for d == 0 + sh = m = 1 / ((npy_int64 volatile *)&d)[0]; // LCOV_EXCL_LINE + } + divisor.val[0] = npyv_setall_s64(m); + divisor.val[2] = npyv_setall_s64(d < 0 ? -1 : 0); // sign of divisor + #ifdef NPY_HAVE_SSE2 // SSE/AVX2/AVX512 + divisor.val[1] = npyv_set_s64(sh); + #else + #error "please initialize the shifting operand for the new architecture" + #endif +#endif + return divisor; +} + +#endif // _NPY_SIMD_INTDIV_H diff --git a/mkl_umath/src/npyv/lowlevel_strided_loops.h b/mkl_umath/src/npyv/lowlevel_strided_loops.h new file mode 100644 index 00000000..9bcfcf2d --- /dev/null +++ b/mkl_umath/src/npyv/lowlevel_strided_loops.h @@ -0,0 +1,790 @@ +#ifndef NUMPY_CORE_SRC_COMMON_LOWLEVEL_STRIDED_LOOPS_H_ +#define NUMPY_CORE_SRC_COMMON_LOWLEVEL_STRIDED_LOOPS_H_ +#include "common.h" +#include "npy_config.h" +#include "array_method.h" +#include "dtype_transfer.h" +#include "mem_overlap.h" +#include "mapping.h" + +/* For PyArray_ macros used below */ +#include "numpy/ndarrayobject.h" + +/* + * NOTE: This API should remain private for the time being, to allow + * for further refinement. I think the 'aligned' mechanism + * needs changing, for example. + * + * Note: Updated in 2018 to distinguish "true" from "uint" alignment. + */ + +/* + * This function pointer is for unary operations that input an + * arbitrarily strided one-dimensional array segment and output + * an arbitrarily strided array segment of the same size. + * It may be a fully general function, or a specialized function + * when the strides or item size have particular known values. + * + * Examples of unary operations are a straight copy, a byte-swap, + * and a casting operation, + * + * The 'transferdata' parameter is slightly special, following a + * generic auxiliary data pattern defined in ndarraytypes.h + * Use NPY_AUXDATA_CLONE and NPY_AUXDATA_FREE to deal with this data. + * + */ +// TODO: FIX! That comment belongs to something now in array-method + +/* + * This is for pointers to functions which behave exactly as + * for PyArrayMethod_StridedLoop, but with an additional mask controlling + * which values are transformed. + * + * TODO: We should move this mask "capability" to the ArrayMethod itself + * probably. Although for NumPy internal things this works decently, + * and exposing it there should be well thought out to be useful beyond + * NumPy if possible. + * + * In particular, the 'i'-th element is operated on if and only if + * mask[i*mask_stride] is true. + */ +typedef int (PyArray_MaskedStridedUnaryOp)( + PyArrayMethod_Context *context, char *const *args, + const npy_intp *dimensions, const npy_intp *strides, + npy_bool *mask, npy_intp mask_stride, + NpyAuxData *auxdata); + +/* + * Gives back a function pointer to a specialized function for copying + * strided memory. Returns NULL if there is a problem with the inputs. + * + * aligned: + * Should be 1 if the src and dst pointers always point to + * locations at which a uint of equal size to dtype->elsize + * would be aligned, 0 otherwise. + * src_stride: + * Should be the src stride if it will always be the same, + * NPY_MAX_INTP otherwise. + * dst_stride: + * Should be the dst stride if it will always be the same, + * NPY_MAX_INTP otherwise. + * itemsize: + * Should be the item size if it will always be the same, 0 otherwise. + * + */ +NPY_NO_EXPORT PyArrayMethod_StridedLoop * +PyArray_GetStridedCopyFn(int aligned, + npy_intp src_stride, npy_intp dst_stride, + npy_intp itemsize); + +/* + * Gives back a function pointer to a specialized function for copying + * and swapping strided memory. This assumes each element is a single + * value to be swapped. + * + * For information on the 'aligned', 'src_stride' and 'dst_stride' parameters + * see above. + * + * Parameters are as for PyArray_GetStridedCopyFn. + */ +NPY_NO_EXPORT PyArrayMethod_StridedLoop * +PyArray_GetStridedCopySwapFn(int aligned, + npy_intp src_stride, npy_intp dst_stride, + npy_intp itemsize); + +/* + * Gives back a function pointer to a specialized function for copying + * and swapping strided memory. This assumes each element is a pair + * of values, each of which needs to be swapped. + * + * For information on the 'aligned', 'src_stride' and 'dst_stride' parameters + * see above. + * + * Parameters are as for PyArray_GetStridedCopyFn. + */ +NPY_NO_EXPORT PyArrayMethod_StridedLoop * +PyArray_GetStridedCopySwapPairFn(int aligned, + npy_intp src_stride, npy_intp dst_stride, + npy_intp itemsize); + +/* + * Gives back a transfer function and transfer data pair which copies + * the data from source to dest, truncating it if the data doesn't + * fit, and padding with zero bytes if there's too much space. + * + * For information on the 'aligned', 'src_stride' and 'dst_stride' parameters + * see above. + * + * Returns NPY_SUCCEED or NPY_FAIL + */ +NPY_NO_EXPORT int +PyArray_GetStridedZeroPadCopyFn(int aligned, int unicode_swap, + npy_intp src_stride, npy_intp dst_stride, + npy_intp src_itemsize, npy_intp dst_itemsize, + PyArrayMethod_StridedLoop **outstransfer, + NpyAuxData **outtransferdata); + +/* + * For casts between built-in numeric types, + * this produces a function pointer for casting from src_type_num + * to dst_type_num. If a conversion is unsupported, returns NULL + * without setting a Python exception. + */ +NPY_NO_EXPORT PyArrayMethod_StridedLoop * +PyArray_GetStridedNumericCastFn(int aligned, + npy_intp src_stride, npy_intp dst_stride, + int src_type_num, int dst_type_num); + +/* + * Gets an operation which copies elements of the given dtype, + * swapping if the dtype isn't in NBO. + * + * Returns NPY_SUCCEED or NPY_FAIL + */ +NPY_NO_EXPORT int +PyArray_GetDTypeCopySwapFn(int aligned, + npy_intp src_stride, npy_intp dst_stride, + PyArray_Descr *dtype, + PyArrayMethod_StridedLoop **outstransfer, + NpyAuxData **outtransferdata); + +/* + * If it's possible, gives back a transfer function which casts and/or + * byte swaps data with the dtype 'src_dtype' into data with the dtype + * 'dst_dtype'. If the outtransferdata is populated with a non-NULL value, + * it must be deallocated with the NPY_AUXDATA_FREE + * function when the transfer function is no longer required. + * + * aligned: + * Should be 1 if the src and dst pointers always point to + * locations at which a uint of equal size to dtype->elsize + * would be aligned, 0 otherwise. + * src_stride: + * Should be the src stride if it will always be the same, + * NPY_MAX_INTP otherwise. + * dst_stride: + * Should be the dst stride if it will always be the same, + * NPY_MAX_INTP otherwise. + * src_dtype: + * The data type of source data. Must not be NULL. + * dst_dtype: + * The data type of destination data. If this is NULL and + * move_references is 1, a transfer function which decrements + * source data references is produced. + * move_references: + * If 0, the destination data gets new reference ownership. + * If 1, the references from the source data are moved to + * the destination data. + * cast_info: + * A pointer to an (uninitialized) `NPY_cast_info` struct, the caller + * must call `NPY_cast_info_xfree` on it (except on error) and handle + * its memory livespan. + * out_needs_api: + * If this is non-NULL, and the transfer function produced needs + * to call into the (Python) API, this gets set to 1. This + * remains untouched if no API access is required. + * + * WARNING: If you set move_references to 1, it is best that src_stride is + * never zero when calling the transfer function. Otherwise, the + * first destination reference will get the value and all the rest + * will get NULL. + * + * Returns NPY_SUCCEED or NPY_FAIL. + */ +NPY_NO_EXPORT int +PyArray_GetDTypeTransferFunction(int aligned, + npy_intp src_stride, npy_intp dst_stride, + PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, + int move_references, + NPY_cast_info *cast_info, + NPY_ARRAYMETHOD_FLAGS *out_flags); + +NPY_NO_EXPORT int +get_fields_transfer_function(int aligned, + npy_intp src_stride, npy_intp dst_stride, + PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, + int move_references, + PyArrayMethod_StridedLoop **out_stransfer, + NpyAuxData **out_transferdata, + NPY_ARRAYMETHOD_FLAGS *out_flags); + +NPY_NO_EXPORT int +get_subarray_transfer_function(int aligned, + npy_intp src_stride, npy_intp dst_stride, + PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, + int move_references, + PyArrayMethod_StridedLoop **out_stransfer, + NpyAuxData **out_transferdata, + NPY_ARRAYMETHOD_FLAGS *out_flags); + +/* + * This is identical to PyArray_GetDTypeTransferFunction, but returns a + * transfer function which also takes a mask as a parameter. The mask is used + * to determine which values to copy, and data is transferred exactly when + * mask[i*mask_stride] is true. + * + * If move_references is true, values which are not copied to the + * destination will still have their source reference decremented. + * + * If mask_dtype is NPY_BOOL or NPY_UINT8, each full element is either + * transferred or not according to the mask as described above. If + * dst_dtype and mask_dtype are both struct dtypes, their names must + * match exactly, and the dtype of each leaf field in mask_dtype must + * be either NPY_BOOL or NPY_UINT8. + */ +NPY_NO_EXPORT int +PyArray_GetMaskedDTypeTransferFunction(int aligned, + npy_intp src_stride, + npy_intp dst_stride, + npy_intp mask_stride, + PyArray_Descr *src_dtype, + PyArray_Descr *dst_dtype, + PyArray_Descr *mask_dtype, + int move_references, + NPY_cast_info *cast_info, + NPY_ARRAYMETHOD_FLAGS *out_flags); + +/* + * Casts the specified number of elements from 'src' with data type + * 'src_dtype' to 'dst' with 'dst_dtype'. See + * PyArray_GetDTypeTransferFunction for more details. + * + * Returns NPY_SUCCEED or NPY_FAIL. + */ +NPY_NO_EXPORT int +PyArray_CastRawArrays(npy_intp count, + char *src, char *dst, + npy_intp src_stride, npy_intp dst_stride, + PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype, + int move_references); + +/* + * These two functions copy or convert the data of an n-dimensional array + * to/from a 1-dimensional strided buffer. These functions will only call + * 'stransfer' with the provided dst_stride/src_stride and + * dst_strides[0]/src_strides[0], so the caller can use those values to + * specialize the function. + * Note that even if ndim == 0, everything needs to be set as if ndim == 1. + * + * The return value is the number of elements it couldn't copy. A return value + * of 0 means all elements were copied, a larger value means the end of + * the n-dimensional array was reached before 'count' elements were copied. + * A negative return value indicates an error occurred. + * + * ndim: + * The number of dimensions of the n-dimensional array. + * dst/src/mask: + * The destination, source or mask starting pointer. + * dst_stride/src_stride/mask_stride: + * The stride of the 1-dimensional strided buffer + * dst_strides/src_strides: + * The strides of the n-dimensional array. + * dst_strides_inc/src_strides_inc: + * How much to add to the ..._strides pointer to get to the next stride. + * coords: + * The starting coordinates in the n-dimensional array. + * coords_inc: + * How much to add to the coords pointer to get to the next coordinate. + * shape: + * The shape of the n-dimensional array. + * shape_inc: + * How much to add to the shape pointer to get to the next shape entry. + * count: + * How many elements to transfer + * src_itemsize: + * How big each element is. If transferring between elements of different + * sizes, for example a casting operation, the 'stransfer' function + * should be specialized for that, in which case 'stransfer' will use + * this parameter as the source item size. + * cast_info: + * Pointer to the NPY_cast_info struct which summarizes all information + * necessary to perform a cast. + */ +NPY_NO_EXPORT npy_intp +PyArray_TransferNDimToStrided(npy_intp ndim, + char *dst, npy_intp dst_stride, + char *src, npy_intp const *src_strides, npy_intp src_strides_inc, + npy_intp const *coords, npy_intp coords_inc, + npy_intp const *shape, npy_intp shape_inc, + npy_intp count, npy_intp src_itemsize, + NPY_cast_info *cast_info); + +NPY_NO_EXPORT npy_intp +PyArray_TransferStridedToNDim(npy_intp ndim, + char *dst, npy_intp const *dst_strides, npy_intp dst_strides_inc, + char *src, npy_intp src_stride, + npy_intp const *coords, npy_intp coords_inc, + npy_intp const *shape, npy_intp shape_inc, + npy_intp count, npy_intp src_itemsize, + NPY_cast_info *cast_info); + +NPY_NO_EXPORT npy_intp +PyArray_TransferMaskedStridedToNDim(npy_intp ndim, + char *dst, npy_intp const *dst_strides, npy_intp dst_strides_inc, + char *src, npy_intp src_stride, + npy_bool *mask, npy_intp mask_stride, + npy_intp const *coords, npy_intp coords_inc, + npy_intp const *shape, npy_intp shape_inc, + npy_intp count, npy_intp src_itemsize, + NPY_cast_info *cast_info); + +NPY_NO_EXPORT int +mapiter_trivial_get( + PyArrayObject *self, PyArrayObject *ind, PyArrayObject *result, + int is_aligned, NPY_cast_info *cast_info); + +NPY_NO_EXPORT int +mapiter_trivial_set( + PyArrayObject *self, PyArrayObject *ind, PyArrayObject *result, + int is_aligned, NPY_cast_info *cast_info); + +NPY_NO_EXPORT int +mapiter_get( + PyArrayMapIterObject *mit, NPY_cast_info *cast_info, + NPY_ARRAYMETHOD_FLAGS flags, int is_aligned); + +NPY_NO_EXPORT int +mapiter_set( + PyArrayMapIterObject *mit, NPY_cast_info *cast_info, + NPY_ARRAYMETHOD_FLAGS flags, int is_aligned); + +/* + * Prepares shape and strides for a simple raw array iteration. + * This sorts the strides into FORTRAN order, reverses any negative + * strides, then coalesces axes where possible. The results are + * filled in the output parameters. + * + * This is intended for simple, lightweight iteration over arrays + * where no buffering of any kind is needed, and the array may + * not be stored as a PyArrayObject. + * + * You can use this together with NPY_RAW_ITER_START and + * NPY_RAW_ITER_ONE_NEXT to handle the looping boilerplate of everything + * but the innermost loop (which is for idim == 0). + * + * Returns 0 on success, -1 on failure. + */ +NPY_NO_EXPORT int +PyArray_PrepareOneRawArrayIter(int ndim, npy_intp const *shape, + char *data, npy_intp const *strides, + int *out_ndim, npy_intp *out_shape, + char **out_data, npy_intp *out_strides); + +/* + * The same as PyArray_PrepareOneRawArrayIter, but for two + * operands instead of one. Any broadcasting of the two operands + * should have already been done before calling this function, + * as the ndim and shape is only specified once for both operands. + * + * Only the strides of the first operand are used to reorder + * the dimensions, no attempt to consider all the strides together + * is made, as is done in the NpyIter object. + * + * You can use this together with NPY_RAW_ITER_START and + * NPY_RAW_ITER_TWO_NEXT to handle the looping boilerplate of everything + * but the innermost loop (which is for idim == 0). + * + * Returns 0 on success, -1 on failure. + */ +NPY_NO_EXPORT int +PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp const *shape, + char *dataA, npy_intp const *stridesA, + char *dataB, npy_intp const *stridesB, + int *out_ndim, npy_intp *out_shape, + char **out_dataA, npy_intp *out_stridesA, + char **out_dataB, npy_intp *out_stridesB); + +/* + * The same as PyArray_PrepareOneRawArrayIter, but for three + * operands instead of one. Any broadcasting of the three operands + * should have already been done before calling this function, + * as the ndim and shape is only specified once for all operands. + * + * Only the strides of the first operand are used to reorder + * the dimensions, no attempt to consider all the strides together + * is made, as is done in the NpyIter object. + * + * You can use this together with NPY_RAW_ITER_START and + * NPY_RAW_ITER_THREE_NEXT to handle the looping boilerplate of everything + * but the innermost loop (which is for idim == 0). + * + * Returns 0 on success, -1 on failure. + */ +NPY_NO_EXPORT int +PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp const *shape, + char *dataA, npy_intp const *stridesA, + char *dataB, npy_intp const *stridesB, + char *dataC, npy_intp const *stridesC, + int *out_ndim, npy_intp *out_shape, + char **out_dataA, npy_intp *out_stridesA, + char **out_dataB, npy_intp *out_stridesB, + char **out_dataC, npy_intp *out_stridesC); + +/* + * Return number of elements that must be peeled from the start of 'addr' with + * 'nvals' elements of size 'esize' in order to reach blockable alignment. + * The required alignment in bytes is passed as the 'alignment' argument and + * must be a power of two. This function is used to prepare an array for + * blocking. See the 'npy_blocked_end' function documentation below for an + * example of how this function is used. + */ +static inline npy_intp +npy_aligned_block_offset(const void * addr, const npy_uintp esize, + const npy_uintp alignment, const npy_uintp nvals) +{ + npy_uintp offset, peel; + + offset = (npy_uintp)addr & (alignment - 1); + peel = offset ? (alignment - offset) / esize : 0; + peel = (peel <= nvals) ? peel : nvals; + assert(peel <= NPY_MAX_INTP); + return (npy_intp)peel; +} + +/* + * Return upper loop bound for an array of 'nvals' elements + * of size 'esize' peeled by 'offset' elements and blocking to + * a vector size of 'vsz' in bytes + * + * example usage: + * npy_intp i; + * double v[101]; + * npy_intp esize = sizeof(v[0]); + * npy_intp peel = npy_aligned_block_offset(v, esize, 16, n); + * // peel to alignment 16 + * for (i = 0; i < peel; i++) + * + * // simd vectorized operation + * for (; i < npy_blocked_end(peel, esize, 16, n); i += 16 / esize) + * + * // handle scalar rest + * for(; i < n; i++) + * + */ +static inline npy_intp +npy_blocked_end(const npy_uintp peel, const npy_uintp esize, + const npy_uintp vsz, const npy_uintp nvals) +{ + npy_uintp ndiff = nvals - peel; + npy_uintp res = (ndiff - ndiff % (vsz / esize)); + + assert(nvals >= peel); + assert(res <= NPY_MAX_INTP); + return (npy_intp)(res); +} + + +/* byte swapping functions */ +static inline npy_uint16 +npy_bswap2(npy_uint16 x) +{ + return ((x & 0xffu) << 8) | (x >> 8); +} + +/* + * treat as int16 and byteswap unaligned memory, + * some cpus don't support unaligned access + */ +static inline void +npy_bswap2_unaligned(char * x) +{ + char a = x[0]; + x[0] = x[1]; + x[1] = a; +} + +static inline npy_uint32 +npy_bswap4(npy_uint32 x) +{ +#ifdef HAVE___BUILTIN_BSWAP32 + return __builtin_bswap32(x); +#else + return ((x & 0xffu) << 24) | ((x & 0xff00u) << 8) | + ((x & 0xff0000u) >> 8) | (x >> 24); +#endif +} + +static inline void +npy_bswap4_unaligned(char * x) +{ + char a = x[0]; + x[0] = x[3]; + x[3] = a; + a = x[1]; + x[1] = x[2]; + x[2] = a; +} + +static inline npy_uint64 +npy_bswap8(npy_uint64 x) +{ +#ifdef HAVE___BUILTIN_BSWAP64 + return __builtin_bswap64(x); +#else + return ((x & 0xffULL) << 56) | + ((x & 0xff00ULL) << 40) | + ((x & 0xff0000ULL) << 24) | + ((x & 0xff000000ULL) << 8) | + ((x & 0xff00000000ULL) >> 8) | + ((x & 0xff0000000000ULL) >> 24) | + ((x & 0xff000000000000ULL) >> 40) | + ( x >> 56); +#endif +} + +static inline void +npy_bswap8_unaligned(char * x) +{ + char a = x[0]; x[0] = x[7]; x[7] = a; + a = x[1]; x[1] = x[6]; x[6] = a; + a = x[2]; x[2] = x[5]; x[5] = a; + a = x[3]; x[3] = x[4]; x[4] = a; +} + + +/* Start raw iteration */ +#define NPY_RAW_ITER_START(idim, ndim, coord, shape) \ + memset((coord), 0, (ndim) * sizeof(coord[0])); \ + do { + +/* Increment to the next n-dimensional coordinate for one raw array */ +#define NPY_RAW_ITER_ONE_NEXT(idim, ndim, coord, shape, data, strides) \ + for ((idim) = 1; (idim) < (ndim); ++(idim)) { \ + if (++(coord)[idim] == (shape)[idim]) { \ + (coord)[idim] = 0; \ + (data) -= ((shape)[idim] - 1) * (strides)[idim]; \ + } \ + else { \ + (data) += (strides)[idim]; \ + break; \ + } \ + } \ + } while ((idim) < (ndim)) + +/* Increment to the next n-dimensional coordinate for two raw arrays */ +#define NPY_RAW_ITER_TWO_NEXT(idim, ndim, coord, shape, \ + dataA, stridesA, dataB, stridesB) \ + for ((idim) = 1; (idim) < (ndim); ++(idim)) { \ + if (++(coord)[idim] == (shape)[idim]) { \ + (coord)[idim] = 0; \ + (dataA) -= ((shape)[idim] - 1) * (stridesA)[idim]; \ + (dataB) -= ((shape)[idim] - 1) * (stridesB)[idim]; \ + } \ + else { \ + (dataA) += (stridesA)[idim]; \ + (dataB) += (stridesB)[idim]; \ + break; \ + } \ + } \ + } while ((idim) < (ndim)) + +/* Increment to the next n-dimensional coordinate for three raw arrays */ +#define NPY_RAW_ITER_THREE_NEXT(idim, ndim, coord, shape, \ + dataA, stridesA, \ + dataB, stridesB, \ + dataC, stridesC) \ + for ((idim) = 1; (idim) < (ndim); ++(idim)) { \ + if (++(coord)[idim] == (shape)[idim]) { \ + (coord)[idim] = 0; \ + (dataA) -= ((shape)[idim] - 1) * (stridesA)[idim]; \ + (dataB) -= ((shape)[idim] - 1) * (stridesB)[idim]; \ + (dataC) -= ((shape)[idim] - 1) * (stridesC)[idim]; \ + } \ + else { \ + (dataA) += (stridesA)[idim]; \ + (dataB) += (stridesB)[idim]; \ + (dataC) += (stridesC)[idim]; \ + break; \ + } \ + } \ + } while ((idim) < (ndim)) + +/* Increment to the next n-dimensional coordinate for four raw arrays */ +#define NPY_RAW_ITER_FOUR_NEXT(idim, ndim, coord, shape, \ + dataA, stridesA, \ + dataB, stridesB, \ + dataC, stridesC, \ + dataD, stridesD) \ + for ((idim) = 1; (idim) < (ndim); ++(idim)) { \ + if (++(coord)[idim] == (shape)[idim]) { \ + (coord)[idim] = 0; \ + (dataA) -= ((shape)[idim] - 1) * (stridesA)[idim]; \ + (dataB) -= ((shape)[idim] - 1) * (stridesB)[idim]; \ + (dataC) -= ((shape)[idim] - 1) * (stridesC)[idim]; \ + (dataD) -= ((shape)[idim] - 1) * (stridesD)[idim]; \ + } \ + else { \ + (dataA) += (stridesA)[idim]; \ + (dataB) += (stridesB)[idim]; \ + (dataC) += (stridesC)[idim]; \ + (dataD) += (stridesD)[idim]; \ + break; \ + } \ + } \ + } while ((idim) < (ndim)) + + +/* + * TRIVIAL ITERATION + * + * In some cases when the iteration order isn't important, iteration over + * arrays is trivial. This is the case when: + * * The array has 0 or 1 dimensions. + * * The array is C or Fortran contiguous. + * Use of an iterator can be skipped when this occurs. These macros assist + * in detecting and taking advantage of the situation. Note that it may + * be worthwhile to further check if the stride is a contiguous stride + * and take advantage of that. + * + * Here is example code for a single array: + * + * if (PyArray_TRIVIALLY_ITERABLE(self)) { + * char *data; + * npy_intp count, stride; + * + * PyArray_PREPARE_TRIVIAL_ITERATION(self, count, data, stride); + * + * while (count--) { + * // Use the data pointer + * + * data += stride; + * } + * } + * else { + * // Create iterator, etc... + * } + * + */ + +/* + * Note: Equivalently iterable macro requires one of arr1 or arr2 be + * trivially iterable to be valid. + */ + +/** + * Determine whether two arrays are safe for trivial iteration in cases where + * some of the arrays may be modified. + * + * In-place iteration is safe if one of the following is true: + * + * - Both arrays are read-only + * - The arrays do not have overlapping memory (based on a check that may be too + * strict) + * - The strides match, and the non-read-only array base addresses are equal or + * before the read-only one, ensuring correct data dependency. + */ + +#define PyArray_TRIVIALLY_ITERABLE_OP_NOREAD 0 +#define PyArray_TRIVIALLY_ITERABLE_OP_READ 1 + +#define PyArray_TRIVIALLY_ITERABLE(arr) ( \ + PyArray_NDIM(arr) <= 1 || \ + PyArray_CHKFLAGS(arr, NPY_ARRAY_C_CONTIGUOUS) || \ + PyArray_CHKFLAGS(arr, NPY_ARRAY_F_CONTIGUOUS) \ + ) + +#define PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size, arr) ( \ + assert(PyArray_TRIVIALLY_ITERABLE(arr)), \ + size == 1 ? 0 : ((PyArray_NDIM(arr) == 1) ? \ + PyArray_STRIDE(arr, 0) : PyArray_ITEMSIZE(arr))) + +static inline int +PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK(PyArrayObject *arr1, PyArrayObject *arr2, + int arr1_read, int arr2_read) +{ + npy_intp size1, size2, stride1, stride2; + int arr1_ahead = 0, arr2_ahead = 0; + + if (arr1_read && arr2_read) { + return 1; + } + + size1 = PyArray_SIZE(arr1); + stride1 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size1, arr1); + + /* + * arr1 == arr2 is common for in-place operations, so we fast-path it here. + * TODO: The stride1 != 0 check rejects broadcast arrays. This may affect + * self-overlapping arrays, but seems only necessary due to + * `try_trivial_single_output_loop` not rejecting broadcast outputs. + */ + if (arr1 == arr2 && stride1 != 0) { + return 1; + } + + if (solve_may_share_memory(arr1, arr2, 1) == 0) { + return 1; + } + + /* + * Arrays overlapping in memory may be equivalently iterable if input + * arrays stride ahead faster than output arrays. + */ + + size2 = PyArray_SIZE(arr2); + stride2 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size2, arr2); + + /* + * Arrays with zero stride are never "ahead" since the element is reused + * (at this point we know the array extents overlap). + */ + + if (stride1 > 0) { + arr1_ahead = (stride1 >= stride2 && + PyArray_BYTES(arr1) >= PyArray_BYTES(arr2)); + } + else if (stride1 < 0) { + arr1_ahead = (stride1 <= stride2 && + PyArray_BYTES(arr1) <= PyArray_BYTES(arr2)); + } + + if (stride2 > 0) { + arr2_ahead = (stride2 >= stride1 && + PyArray_BYTES(arr2) >= PyArray_BYTES(arr1)); + } + else if (stride2 < 0) { + arr2_ahead = (stride2 <= stride1 && + PyArray_BYTES(arr2) <= PyArray_BYTES(arr1)); + } + + return (!arr1_read || arr1_ahead) && (!arr2_read || arr2_ahead); +} + +#define PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr2) ( \ + PyArray_NDIM(arr1) == PyArray_NDIM(arr2) && \ + PyArray_CompareLists(PyArray_DIMS(arr1), \ + PyArray_DIMS(arr2), \ + PyArray_NDIM(arr1)) && \ + (PyArray_FLAGS(arr1)&(NPY_ARRAY_C_CONTIGUOUS| \ + NPY_ARRAY_F_CONTIGUOUS)) & \ + (PyArray_FLAGS(arr2)&(NPY_ARRAY_C_CONTIGUOUS| \ + NPY_ARRAY_F_CONTIGUOUS)) \ + ) + +#define PyArray_EQUIVALENTLY_ITERABLE(arr1, arr2, arr1_read, arr2_read) ( \ + PyArray_EQUIVALENTLY_ITERABLE_BASE(arr1, arr2) && \ + PyArray_EQUIVALENTLY_ITERABLE_OVERLAP_OK( \ + arr1, arr2, arr1_read, arr2_read)) + +#define PyArray_PREPARE_TRIVIAL_ITERATION(arr, count, data, stride) \ + count = PyArray_SIZE(arr); \ + data = PyArray_BYTES(arr); \ + stride = ((PyArray_NDIM(arr) == 0) ? 0 : \ + ((PyArray_NDIM(arr) == 1) ? \ + PyArray_STRIDE(arr, 0) : \ + PyArray_ITEMSIZE(arr))); + +#define PyArray_PREPARE_TRIVIAL_PAIR_ITERATION(arr1, arr2, \ + count, \ + data1, data2, \ + stride1, stride2) { \ + npy_intp size1 = PyArray_SIZE(arr1); \ + npy_intp size2 = PyArray_SIZE(arr2); \ + count = ((size1 > size2) || size1 == 0) ? size1 : size2; \ + data1 = PyArray_BYTES(arr1); \ + data2 = PyArray_BYTES(arr2); \ + stride1 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size1, arr1); \ + stride2 = PyArray_TRIVIAL_PAIR_ITERATION_STRIDE(size2, arr2); \ + } + +#endif /* NUMPY_CORE_SRC_COMMON_LOWLEVEL_STRIDED_LOOPS_H_ */ diff --git a/mkl_umath/src/npyv/mem_overlap.h b/mkl_umath/src/npyv/mem_overlap.h new file mode 100644 index 00000000..3aa4f798 --- /dev/null +++ b/mkl_umath/src/npyv/mem_overlap.h @@ -0,0 +1,49 @@ +#ifndef NUMPY_CORE_SRC_COMMON_MEM_OVERLAP_H_ +#define NUMPY_CORE_SRC_COMMON_MEM_OVERLAP_H_ + +#include "npy_config.h" +#include "numpy/ndarraytypes.h" + + +/* Bounds check only */ +#define NPY_MAY_SHARE_BOUNDS 0 + +/* Exact solution */ +#define NPY_MAY_SHARE_EXACT -1 + + +typedef enum { + MEM_OVERLAP_NO = 0, /* no solution exists */ + MEM_OVERLAP_YES = 1, /* solution found */ + MEM_OVERLAP_TOO_HARD = -1, /* max_work exceeded */ + MEM_OVERLAP_OVERFLOW = -2, /* algorithm failed due to integer overflow */ + MEM_OVERLAP_ERROR = -3 /* invalid input */ +} mem_overlap_t; + + +typedef struct { + npy_int64 a; + npy_int64 ub; +} diophantine_term_t; + +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_diophantine(unsigned int n, diophantine_term_t *E, + npy_int64 b, Py_ssize_t max_work, int require_nontrivial, + npy_int64 *x); + +NPY_VISIBILITY_HIDDEN int +diophantine_simplify(unsigned int *n, diophantine_term_t *E, npy_int64 b); + +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_may_share_memory(PyArrayObject *a, PyArrayObject *b, + Py_ssize_t max_work); + +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_may_have_internal_overlap(PyArrayObject *a, Py_ssize_t max_work); + +NPY_VISIBILITY_HIDDEN void +offset_bounds_from_strides(const int itemsize, const int nd, + const npy_intp *dims, const npy_intp *strides, + npy_intp *lower_offset, npy_intp *upper_offset); + +#endif /* NUMPY_CORE_SRC_COMMON_MEM_OVERLAP_H_ */ diff --git a/mkl_umath/src/npyv/neon/arithmetic.h b/mkl_umath/src/npyv/neon/arithmetic.h new file mode 100644 index 00000000..68362011 --- /dev/null +++ b/mkl_umath/src/npyv/neon/arithmetic.h @@ -0,0 +1,343 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_ARITHMETIC_H +#define _NPY_SIMD_NEON_ARITHMETIC_H + +/*************************** + * Addition + ***************************/ +// non-saturated +#define npyv_add_u8 vaddq_u8 +#define npyv_add_s8 vaddq_s8 +#define npyv_add_u16 vaddq_u16 +#define npyv_add_s16 vaddq_s16 +#define npyv_add_u32 vaddq_u32 +#define npyv_add_s32 vaddq_s32 +#define npyv_add_u64 vaddq_u64 +#define npyv_add_s64 vaddq_s64 +#define npyv_add_f32 vaddq_f32 +#define npyv_add_f64 vaddq_f64 + +// saturated +#define npyv_adds_u8 vqaddq_u8 +#define npyv_adds_s8 vqaddq_s8 +#define npyv_adds_u16 vqaddq_u16 +#define npyv_adds_s16 vqaddq_s16 + +/*************************** + * Subtraction + ***************************/ +// non-saturated +#define npyv_sub_u8 vsubq_u8 +#define npyv_sub_s8 vsubq_s8 +#define npyv_sub_u16 vsubq_u16 +#define npyv_sub_s16 vsubq_s16 +#define npyv_sub_u32 vsubq_u32 +#define npyv_sub_s32 vsubq_s32 +#define npyv_sub_u64 vsubq_u64 +#define npyv_sub_s64 vsubq_s64 +#define npyv_sub_f32 vsubq_f32 +#define npyv_sub_f64 vsubq_f64 + +// saturated +#define npyv_subs_u8 vqsubq_u8 +#define npyv_subs_s8 vqsubq_s8 +#define npyv_subs_u16 vqsubq_u16 +#define npyv_subs_s16 vqsubq_s16 + +/*************************** + * Multiplication + ***************************/ +// non-saturated +#define npyv_mul_u8 vmulq_u8 +#define npyv_mul_s8 vmulq_s8 +#define npyv_mul_u16 vmulq_u16 +#define npyv_mul_s16 vmulq_s16 +#define npyv_mul_u32 vmulq_u32 +#define npyv_mul_s32 vmulq_s32 +#define npyv_mul_f32 vmulq_f32 +#define npyv_mul_f64 vmulq_f64 + +/*************************** + * Integer Division + ***************************/ +// See simd/intdiv.h for more clarification +// divide each unsigned 8-bit element by a precomputed divisor +NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor) +{ + const uint8x8_t mulc_lo = vget_low_u8(divisor.val[0]); + // high part of unsigned multiplication + uint16x8_t mull_lo = vmull_u8(vget_low_u8(a), mulc_lo); +#if NPY_SIMD_F64 + uint16x8_t mull_hi = vmull_high_u8(a, divisor.val[0]); + // get the high unsigned bytes + uint8x16_t mulhi = vuzp2q_u8(vreinterpretq_u8_u16(mull_lo), vreinterpretq_u8_u16(mull_hi)); +#else + const uint8x8_t mulc_hi = vget_high_u8(divisor.val[0]); + uint16x8_t mull_hi = vmull_u8(vget_high_u8(a), mulc_hi); + uint8x16_t mulhi = vuzpq_u8(vreinterpretq_u8_u16(mull_lo), vreinterpretq_u8_u16(mull_hi)).val[1]; +#endif + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + uint8x16_t q = vsubq_u8(a, mulhi); + q = vshlq_u8(q, vreinterpretq_s8_u8(divisor.val[1])); + q = vaddq_u8(mulhi, q); + q = vshlq_u8(q, vreinterpretq_s8_u8(divisor.val[2])); + return q; +} +// divide each signed 8-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor) +{ + const int8x8_t mulc_lo = vget_low_s8(divisor.val[0]); + // high part of signed multiplication + int16x8_t mull_lo = vmull_s8(vget_low_s8(a), mulc_lo); +#if NPY_SIMD_F64 + int16x8_t mull_hi = vmull_high_s8(a, divisor.val[0]); + // get the high unsigned bytes + int8x16_t mulhi = vuzp2q_s8(vreinterpretq_s8_s16(mull_lo), vreinterpretq_s8_s16(mull_hi)); +#else + const int8x8_t mulc_hi = vget_high_s8(divisor.val[0]); + int16x8_t mull_hi = vmull_s8(vget_high_s8(a), mulc_hi); + int8x16_t mulhi = vuzpq_s8(vreinterpretq_s8_s16(mull_lo), vreinterpretq_s8_s16(mull_hi)).val[1]; +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + int8x16_t q = vshlq_s8(vaddq_s8(a, mulhi), divisor.val[1]); + q = vsubq_s8(q, vshrq_n_s8(a, 7)); + q = vsubq_s8(veorq_s8(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 16-bit element by a precomputed divisor +NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor) +{ + const uint16x4_t mulc_lo = vget_low_u16(divisor.val[0]); + // high part of unsigned multiplication + uint32x4_t mull_lo = vmull_u16(vget_low_u16(a), mulc_lo); +#if NPY_SIMD_F64 + uint32x4_t mull_hi = vmull_high_u16(a, divisor.val[0]); + // get the high unsigned bytes + uint16x8_t mulhi = vuzp2q_u16(vreinterpretq_u16_u32(mull_lo), vreinterpretq_u16_u32(mull_hi)); +#else + const uint16x4_t mulc_hi = vget_high_u16(divisor.val[0]); + uint32x4_t mull_hi = vmull_u16(vget_high_u16(a), mulc_hi); + uint16x8_t mulhi = vuzpq_u16(vreinterpretq_u16_u32(mull_lo), vreinterpretq_u16_u32(mull_hi)).val[1]; +#endif + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + uint16x8_t q = vsubq_u16(a, mulhi); + q = vshlq_u16(q, vreinterpretq_s16_u16(divisor.val[1])); + q = vaddq_u16(mulhi, q); + q = vshlq_u16(q, vreinterpretq_s16_u16(divisor.val[2])); + return q; +} +// divide each signed 16-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor) +{ + const int16x4_t mulc_lo = vget_low_s16(divisor.val[0]); + // high part of signed multiplication + int32x4_t mull_lo = vmull_s16(vget_low_s16(a), mulc_lo); +#if NPY_SIMD_F64 + int32x4_t mull_hi = vmull_high_s16(a, divisor.val[0]); + // get the high unsigned bytes + int16x8_t mulhi = vuzp2q_s16(vreinterpretq_s16_s32(mull_lo), vreinterpretq_s16_s32(mull_hi)); +#else + const int16x4_t mulc_hi = vget_high_s16(divisor.val[0]); + int32x4_t mull_hi = vmull_s16(vget_high_s16(a), mulc_hi); + int16x8_t mulhi = vuzpq_s16(vreinterpretq_s16_s32(mull_lo), vreinterpretq_s16_s32(mull_hi)).val[1]; +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + int16x8_t q = vshlq_s16(vaddq_s16(a, mulhi), divisor.val[1]); + q = vsubq_s16(q, vshrq_n_s16(a, 15)); + q = vsubq_s16(veorq_s16(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 32-bit element by a precomputed divisor +NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor) +{ + const uint32x2_t mulc_lo = vget_low_u32(divisor.val[0]); + // high part of unsigned multiplication + uint64x2_t mull_lo = vmull_u32(vget_low_u32(a), mulc_lo); +#if NPY_SIMD_F64 + uint64x2_t mull_hi = vmull_high_u32(a, divisor.val[0]); + // get the high unsigned bytes + uint32x4_t mulhi = vuzp2q_u32(vreinterpretq_u32_u64(mull_lo), vreinterpretq_u32_u64(mull_hi)); +#else + const uint32x2_t mulc_hi = vget_high_u32(divisor.val[0]); + uint64x2_t mull_hi = vmull_u32(vget_high_u32(a), mulc_hi); + uint32x4_t mulhi = vuzpq_u32(vreinterpretq_u32_u64(mull_lo), vreinterpretq_u32_u64(mull_hi)).val[1]; +#endif + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + uint32x4_t q = vsubq_u32(a, mulhi); + q = vshlq_u32(q, vreinterpretq_s32_u32(divisor.val[1])); + q = vaddq_u32(mulhi, q); + q = vshlq_u32(q, vreinterpretq_s32_u32(divisor.val[2])); + return q; +} +// divide each signed 32-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor) +{ + const int32x2_t mulc_lo = vget_low_s32(divisor.val[0]); + // high part of signed multiplication + int64x2_t mull_lo = vmull_s32(vget_low_s32(a), mulc_lo); +#if NPY_SIMD_F64 + int64x2_t mull_hi = vmull_high_s32(a, divisor.val[0]); + // get the high unsigned bytes + int32x4_t mulhi = vuzp2q_s32(vreinterpretq_s32_s64(mull_lo), vreinterpretq_s32_s64(mull_hi)); +#else + const int32x2_t mulc_hi = vget_high_s32(divisor.val[0]); + int64x2_t mull_hi = vmull_s32(vget_high_s32(a), mulc_hi); + int32x4_t mulhi = vuzpq_s32(vreinterpretq_s32_s64(mull_lo), vreinterpretq_s32_s64(mull_hi)).val[1]; +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + int32x4_t q = vshlq_s32(vaddq_s32(a, mulhi), divisor.val[1]); + q = vsubq_s32(q, vshrq_n_s32(a, 31)); + q = vsubq_s32(veorq_s32(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 64-bit element by a divisor +NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor) +{ + const uint64_t d = vgetq_lane_u64(divisor.val[0], 0); + return npyv_set_u64(vgetq_lane_u64(a, 0) / d, vgetq_lane_u64(a, 1) / d); +} +// returns the high 64 bits of signed 64-bit multiplication +NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor) +{ + const int64_t d = vgetq_lane_s64(divisor.val[0], 0); + return npyv_set_s64(vgetq_lane_s64(a, 0) / d, vgetq_lane_s64(a, 1) / d); +} +/*************************** + * Division + ***************************/ +#if NPY_SIMD_F64 + #define npyv_div_f32 vdivq_f32 +#else + NPY_FINLINE npyv_f32 npyv_div_f32(npyv_f32 a, npyv_f32 b) + { + // Based on ARM doc, see https://developer.arm.com/documentation/dui0204/j/CIHDIACI + // estimate to 1/b + npyv_f32 recipe = vrecpeq_f32(b); + /** + * Newton-Raphson iteration: + * x[n+1] = x[n] * (2-d * x[n]) + * converges to (1/d) if x0 is the result of VRECPE applied to d. + * + * NOTE: at least 3 iterations is needed to improve precision + */ + recipe = vmulq_f32(vrecpsq_f32(b, recipe), recipe); + recipe = vmulq_f32(vrecpsq_f32(b, recipe), recipe); + recipe = vmulq_f32(vrecpsq_f32(b, recipe), recipe); + // a/b = a*recip(b) + return vmulq_f32(a, recipe); + } +#endif +#define npyv_div_f64 vdivq_f64 + +/*************************** + * FUSED F32 + ***************************/ +#ifdef NPY_HAVE_NEON_VFPV4 // FMA + // multiply and add, a*b + c + NPY_FINLINE npyv_f32 npyv_muladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vfmaq_f32(c, a, b); } + // multiply and subtract, a*b - c + NPY_FINLINE npyv_f32 npyv_mulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vfmaq_f32(vnegq_f32(c), a, b); } + // negate multiply and add, -(a*b) + c + NPY_FINLINE npyv_f32 npyv_nmuladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vfmsq_f32(c, a, b); } + // negate multiply and subtract, -(a*b) - c + NPY_FINLINE npyv_f32 npyv_nmulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vfmsq_f32(vnegq_f32(c), a, b); } +#else + // multiply and add, a*b + c + NPY_FINLINE npyv_f32 npyv_muladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vmlaq_f32(c, a, b); } + // multiply and subtract, a*b - c + NPY_FINLINE npyv_f32 npyv_mulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vmlaq_f32(vnegq_f32(c), a, b); } + // negate multiply and add, -(a*b) + c + NPY_FINLINE npyv_f32 npyv_nmuladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vmlsq_f32(c, a, b); } + // negate multiply and subtract, -(a*b) - c + NPY_FINLINE npyv_f32 npyv_nmulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return vmlsq_f32(vnegq_f32(c), a, b); } +#endif +// multiply, add for odd elements and subtract even elements. +// (a * b) -+ c +NPY_FINLINE npyv_f32 npyv_muladdsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) +{ + const npyv_f32 msign = npyv_set_f32(-0.0f, 0.0f, -0.0f, 0.0f); + return npyv_muladd_f32(a, b, npyv_xor_f32(msign, c)); +} + +/*************************** + * FUSED F64 + ***************************/ +#if NPY_SIMD_F64 + NPY_FINLINE npyv_f64 npyv_muladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return vfmaq_f64(c, a, b); } + NPY_FINLINE npyv_f64 npyv_mulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return vfmaq_f64(vnegq_f64(c), a, b); } + NPY_FINLINE npyv_f64 npyv_nmuladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return vfmsq_f64(c, a, b); } + NPY_FINLINE npyv_f64 npyv_nmulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return vfmsq_f64(vnegq_f64(c), a, b); } + NPY_FINLINE npyv_f64 npyv_muladdsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { + const npyv_f64 msign = npyv_set_f64(-0.0, 0.0); + return npyv_muladd_f64(a, b, npyv_xor_f64(msign, c)); + } +#endif // NPY_SIMD_F64 + +/*************************** + * Summation + ***************************/ +// reduce sum across vector +#if NPY_SIMD_F64 + #define npyv_sum_u32 vaddvq_u32 + #define npyv_sum_u64 vaddvq_u64 + #define npyv_sum_f32 vaddvq_f32 + #define npyv_sum_f64 vaddvq_f64 +#else + NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) + { + return vget_lane_u64(vadd_u64(vget_low_u64(a), vget_high_u64(a)),0); + } + + NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) + { + uint32x2_t a0 = vpadd_u32(vget_low_u32(a), vget_high_u32(a)); + return (unsigned)vget_lane_u32(vpadd_u32(a0, vget_high_u32(a)),0); + } + + NPY_FINLINE float npyv_sum_f32(npyv_f32 a) + { + float32x2_t r = vadd_f32(vget_high_f32(a), vget_low_f32(a)); + return vget_lane_f32(vpadd_f32(r, r), 0); + } +#endif + +// expand the source vector and performs sum reduce +#if NPY_SIMD_F64 + #define npyv_sumup_u8 vaddlvq_u8 + #define npyv_sumup_u16 vaddlvq_u16 +#else + NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) + { + uint32x4_t t0 = vpaddlq_u16(vpaddlq_u8(a)); + uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0)); + return vget_lane_u32(vpadd_u32(t1, t1), 0); + } + + NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) + { + uint32x4_t t0 = vpaddlq_u16(a); + uint32x2_t t1 = vpadd_u32(vget_low_u32(t0), vget_high_u32(t0)); + return vget_lane_u32(vpadd_u32(t1, t1), 0); + } +#endif + +#endif // _NPY_SIMD_NEON_ARITHMETIC_H diff --git a/mkl_umath/src/npyv/neon/conversion.h b/mkl_umath/src/npyv/neon/conversion.h new file mode 100644 index 00000000..03a5259f --- /dev/null +++ b/mkl_umath/src/npyv/neon/conversion.h @@ -0,0 +1,150 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_CVT_H +#define _NPY_SIMD_NEON_CVT_H + +// convert boolean vectors to integer vectors +#define npyv_cvt_u8_b8(A) A +#define npyv_cvt_s8_b8 vreinterpretq_s8_u8 +#define npyv_cvt_u16_b16(A) A +#define npyv_cvt_s16_b16 vreinterpretq_s16_u16 +#define npyv_cvt_u32_b32(A) A +#define npyv_cvt_s32_b32 vreinterpretq_s32_u32 +#define npyv_cvt_u64_b64(A) A +#define npyv_cvt_s64_b64 vreinterpretq_s64_u64 +#define npyv_cvt_f32_b32 vreinterpretq_f32_u32 +#define npyv_cvt_f64_b64 vreinterpretq_f64_u64 + +// convert integer vectors to boolean vectors +#define npyv_cvt_b8_u8(BL) BL +#define npyv_cvt_b8_s8 vreinterpretq_u8_s8 +#define npyv_cvt_b16_u16(BL) BL +#define npyv_cvt_b16_s16 vreinterpretq_u16_s16 +#define npyv_cvt_b32_u32(BL) BL +#define npyv_cvt_b32_s32 vreinterpretq_u32_s32 +#define npyv_cvt_b64_u64(BL) BL +#define npyv_cvt_b64_s64 vreinterpretq_u64_s64 +#define npyv_cvt_b32_f32 vreinterpretq_u32_f32 +#define npyv_cvt_b64_f64 vreinterpretq_u64_f64 + +// convert boolean vector to integer bitfield +NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) +{ + const npyv_u8 scale = npyv_set_u8(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128); + npyv_u8 seq_scale = vandq_u8(a, scale); +#if defined(__aarch64__) + const npyv_u8 byteOrder = {0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15}; + npyv_u8 v0 = vqtbl1q_u8(seq_scale, byteOrder); + return vaddlvq_u16(vreinterpretq_u16_u8(v0)); +#else + npyv_u64 sumh = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(seq_scale))); + return vgetq_lane_u64(sumh, 0) + ((int)vgetq_lane_u64(sumh, 1) << 8); +#endif +} +NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a) +{ + const npyv_u16 scale = npyv_set_u16(1, 2, 4, 8, 16, 32, 64, 128); + npyv_u16 seq_scale = vandq_u16(a, scale); +#if NPY_SIMD_F64 + return vaddvq_u16(seq_scale); +#else + npyv_u64 sumh = vpaddlq_u32(vpaddlq_u16(seq_scale)); + return vgetq_lane_u64(sumh, 0) + vgetq_lane_u64(sumh, 1); +#endif +} +NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a) +{ + const npyv_u32 scale = npyv_set_u32(1, 2, 4, 8); + npyv_u32 seq_scale = vandq_u32(a, scale); +#if NPY_SIMD_F64 + return vaddvq_u32(seq_scale); +#else + npyv_u64 sumh = vpaddlq_u32(seq_scale); + return vgetq_lane_u64(sumh, 0) + vgetq_lane_u64(sumh, 1); +#endif +} +NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a) +{ + uint64_t lo = vgetq_lane_u64(a, 0); + uint64_t hi = vgetq_lane_u64(a, 1); + return ((hi & 0x2) | (lo & 0x1)); +} + +//expand +NPY_FINLINE npyv_u16x2 npyv_expand_u16_u8(npyv_u8 data) { + npyv_u16x2 r; + r.val[0] = vmovl_u8(vget_low_u8(data)); + r.val[1] = vmovl_u8(vget_high_u8(data)); + return r; +} + +NPY_FINLINE npyv_u32x2 npyv_expand_u32_u16(npyv_u16 data) { + npyv_u32x2 r; + r.val[0] = vmovl_u16(vget_low_u16(data)); + r.val[1] = vmovl_u16(vget_high_u16(data)); + return r; +} + +// pack two 16-bit boolean into one 8-bit boolean vector +NPY_FINLINE npyv_b8 npyv_pack_b8_b16(npyv_b16 a, npyv_b16 b) { +#if defined(__aarch64__) + return vuzp1q_u8((uint8x16_t)a, (uint8x16_t)b); +#else + return vcombine_u8(vmovn_u16(a), vmovn_u16(b)); +#endif +} + +// pack four 32-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b32(npyv_b32 a, npyv_b32 b, npyv_b32 c, npyv_b32 d) { +#if defined(__aarch64__) + npyv_b16 ab = vuzp1q_u16((uint16x8_t)a, (uint16x8_t)b); + npyv_b16 cd = vuzp1q_u16((uint16x8_t)c, (uint16x8_t)d); +#else + npyv_b16 ab = vcombine_u16(vmovn_u32(a), vmovn_u32(b)); + npyv_b16 cd = vcombine_u16(vmovn_u32(c), vmovn_u32(d)); +#endif + return npyv_pack_b8_b16(ab, cd); +} + +// pack eight 64-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b64(npyv_b64 a, npyv_b64 b, npyv_b64 c, npyv_b64 d, + npyv_b64 e, npyv_b64 f, npyv_b64 g, npyv_b64 h) { +#if defined(__aarch64__) + npyv_b32 ab = vuzp1q_u32((uint32x4_t)a, (uint32x4_t)b); + npyv_b32 cd = vuzp1q_u32((uint32x4_t)c, (uint32x4_t)d); + npyv_b32 ef = vuzp1q_u32((uint32x4_t)e, (uint32x4_t)f); + npyv_u32 gh = vuzp1q_u32((uint32x4_t)g, (uint32x4_t)h); +#else + npyv_b32 ab = vcombine_u32(vmovn_u64(a), vmovn_u64(b)); + npyv_b32 cd = vcombine_u32(vmovn_u64(c), vmovn_u64(d)); + npyv_b32 ef = vcombine_u32(vmovn_u64(e), vmovn_u64(f)); + npyv_b32 gh = vcombine_u32(vmovn_u64(g), vmovn_u64(h)); +#endif + return npyv_pack_b8_b32(ab, cd, ef, gh); +} + +// round to nearest integer +#if NPY_SIMD_F64 + #define npyv_round_s32_f32 vcvtnq_s32_f32 + NPY_FINLINE npyv_s32 npyv_round_s32_f64(npyv_f64 a, npyv_f64 b) + { + npyv_s64 lo = vcvtnq_s64_f64(a), hi = vcvtnq_s64_f64(b); + return vcombine_s32(vmovn_s64(lo), vmovn_s64(hi)); + } +#else + NPY_FINLINE npyv_s32 npyv_round_s32_f32(npyv_f32 a) + { + // halves will be rounded up. it's very costly + // to obey IEEE standard on arm7. tests should pass +-1 difference + const npyv_u32 sign = vdupq_n_u32(0x80000000); + const npyv_f32 half = vdupq_n_f32(0.5f); + npyv_f32 sign_half = vbslq_f32(sign, a, half); + return vcvtq_s32_f32(vaddq_f32(a, sign_half)); + } +#endif + +#endif // _NPY_SIMD_NEON_CVT_H diff --git a/mkl_umath/src/npyv/neon/math.h b/mkl_umath/src/npyv/neon/math.h new file mode 100644 index 00000000..58d14809 --- /dev/null +++ b/mkl_umath/src/npyv/neon/math.h @@ -0,0 +1,416 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_MATH_H +#define _NPY_SIMD_NEON_MATH_H + +/*************************** + * Elementary + ***************************/ +// Absolute +#define npyv_abs_f32 vabsq_f32 +#define npyv_abs_f64 vabsq_f64 + +// Square +NPY_FINLINE npyv_f32 npyv_square_f32(npyv_f32 a) +{ return vmulq_f32(a, a); } +#if NPY_SIMD_F64 + NPY_FINLINE npyv_f64 npyv_square_f64(npyv_f64 a) + { return vmulq_f64(a, a); } +#endif + +// Square root +#if NPY_SIMD_F64 + #define npyv_sqrt_f32 vsqrtq_f32 + #define npyv_sqrt_f64 vsqrtq_f64 +#else + // Based on ARM doc, see https://developer.arm.com/documentation/dui0204/j/CIHDIACI + NPY_FINLINE npyv_f32 npyv_sqrt_f32(npyv_f32 a) + { + const npyv_f32 zero = vdupq_n_f32(0.0f); + const npyv_u32 pinf = vdupq_n_u32(0x7f800000); + npyv_u32 is_zero = vceqq_f32(a, zero), is_inf = vceqq_u32(vreinterpretq_u32_f32(a), pinf); + // guard against floating-point division-by-zero error + npyv_f32 guard_byz = vbslq_f32(is_zero, vreinterpretq_f32_u32(pinf), a); + // estimate to (1/√a) + npyv_f32 rsqrte = vrsqrteq_f32(guard_byz); + /** + * Newton-Raphson iteration: + * x[n+1] = x[n] * (3-d * (x[n]*x[n]) )/2) + * converges to (1/√d)if x0 is the result of VRSQRTE applied to d. + * + * NOTE: at least 3 iterations is needed to improve precision + */ + rsqrte = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a, rsqrte), rsqrte), rsqrte); + rsqrte = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a, rsqrte), rsqrte), rsqrte); + rsqrte = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a, rsqrte), rsqrte), rsqrte); + // a * (1/√a) + npyv_f32 sqrt = vmulq_f32(a, rsqrte); + // return zero if the a is zero + // - return zero if a is zero. + // - return positive infinity if a is positive infinity + return vbslq_f32(vorrq_u32(is_zero, is_inf), a, sqrt); + } +#endif // NPY_SIMD_F64 + +// Reciprocal +NPY_FINLINE npyv_f32 npyv_recip_f32(npyv_f32 a) +{ +#if NPY_SIMD_F64 + const npyv_f32 one = vdupq_n_f32(1.0f); + return npyv_div_f32(one, a); +#else + npyv_f32 recipe = vrecpeq_f32(a); + /** + * Newton-Raphson iteration: + * x[n+1] = x[n] * (2-d * x[n]) + * converges to (1/d) if x0 is the result of VRECPE applied to d. + * + * NOTE: at least 3 iterations is needed to improve precision + */ + recipe = vmulq_f32(vrecpsq_f32(a, recipe), recipe); + recipe = vmulq_f32(vrecpsq_f32(a, recipe), recipe); + recipe = vmulq_f32(vrecpsq_f32(a, recipe), recipe); + return recipe; +#endif +} +#if NPY_SIMD_F64 + NPY_FINLINE npyv_f64 npyv_recip_f64(npyv_f64 a) + { + const npyv_f64 one = vdupq_n_f64(1.0); + return npyv_div_f64(one, a); + } +#endif // NPY_SIMD_F64 + +// Maximum, natively mapping with no guarantees to handle NaN. +#define npyv_max_f32 vmaxq_f32 +#define npyv_max_f64 vmaxq_f64 +// Maximum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +#ifdef NPY_HAVE_ASIMD + #define npyv_maxp_f32 vmaxnmq_f32 +#else + NPY_FINLINE npyv_f32 npyv_maxp_f32(npyv_f32 a, npyv_f32 b) + { + npyv_u32 nn_a = vceqq_f32(a, a); + npyv_u32 nn_b = vceqq_f32(b, b); + return vmaxq_f32(vbslq_f32(nn_a, a, b), vbslq_f32(nn_b, b, a)); + } +#endif +// Max, propagates NaNs +// If any of corresponded element is NaN, NaN is set. +#define npyv_maxn_f32 vmaxq_f32 +#if NPY_SIMD_F64 + #define npyv_maxp_f64 vmaxnmq_f64 + #define npyv_maxn_f64 vmaxq_f64 +#endif // NPY_SIMD_F64 +// Maximum, integer operations +#define npyv_max_u8 vmaxq_u8 +#define npyv_max_s8 vmaxq_s8 +#define npyv_max_u16 vmaxq_u16 +#define npyv_max_s16 vmaxq_s16 +#define npyv_max_u32 vmaxq_u32 +#define npyv_max_s32 vmaxq_s32 +NPY_FINLINE npyv_u64 npyv_max_u64(npyv_u64 a, npyv_u64 b) +{ + return vbslq_u64(npyv_cmpgt_u64(a, b), a, b); +} +NPY_FINLINE npyv_s64 npyv_max_s64(npyv_s64 a, npyv_s64 b) +{ + return vbslq_s64(npyv_cmpgt_s64(a, b), a, b); +} + +// Minimum, natively mapping with no guarantees to handle NaN. +#define npyv_min_f32 vminq_f32 +#define npyv_min_f64 vminq_f64 +// Minimum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +#ifdef NPY_HAVE_ASIMD + #define npyv_minp_f32 vminnmq_f32 +#else + NPY_FINLINE npyv_f32 npyv_minp_f32(npyv_f32 a, npyv_f32 b) + { + npyv_u32 nn_a = vceqq_f32(a, a); + npyv_u32 nn_b = vceqq_f32(b, b); + return vminq_f32(vbslq_f32(nn_a, a, b), vbslq_f32(nn_b, b, a)); + } +#endif +// Min, propagates NaNs +// If any of corresponded element is NaN, NaN is set. +#define npyv_minn_f32 vminq_f32 +#if NPY_SIMD_F64 + #define npyv_minp_f64 vminnmq_f64 + #define npyv_minn_f64 vminq_f64 +#endif // NPY_SIMD_F64 + +// Minimum, integer operations +#define npyv_min_u8 vminq_u8 +#define npyv_min_s8 vminq_s8 +#define npyv_min_u16 vminq_u16 +#define npyv_min_s16 vminq_s16 +#define npyv_min_u32 vminq_u32 +#define npyv_min_s32 vminq_s32 +NPY_FINLINE npyv_u64 npyv_min_u64(npyv_u64 a, npyv_u64 b) +{ + return vbslq_u64(npyv_cmplt_u64(a, b), a, b); +} +NPY_FINLINE npyv_s64 npyv_min_s64(npyv_s64 a, npyv_s64 b) +{ + return vbslq_s64(npyv_cmplt_s64(a, b), a, b); +} +// reduce min/max for all data types +#if NPY_SIMD_F64 + #define npyv_reduce_max_u8 vmaxvq_u8 + #define npyv_reduce_max_s8 vmaxvq_s8 + #define npyv_reduce_max_u16 vmaxvq_u16 + #define npyv_reduce_max_s16 vmaxvq_s16 + #define npyv_reduce_max_u32 vmaxvq_u32 + #define npyv_reduce_max_s32 vmaxvq_s32 + + #define npyv_reduce_max_f32 vmaxvq_f32 + #define npyv_reduce_max_f64 vmaxvq_f64 + #define npyv_reduce_maxn_f32 vmaxvq_f32 + #define npyv_reduce_maxn_f64 vmaxvq_f64 + #define npyv_reduce_maxp_f32 vmaxnmvq_f32 + #define npyv_reduce_maxp_f64 vmaxnmvq_f64 + + #define npyv_reduce_min_u8 vminvq_u8 + #define npyv_reduce_min_s8 vminvq_s8 + #define npyv_reduce_min_u16 vminvq_u16 + #define npyv_reduce_min_s16 vminvq_s16 + #define npyv_reduce_min_u32 vminvq_u32 + #define npyv_reduce_min_s32 vminvq_s32 + + #define npyv_reduce_min_f32 vminvq_f32 + #define npyv_reduce_min_f64 vminvq_f64 + #define npyv_reduce_minn_f32 vminvq_f32 + #define npyv_reduce_minn_f64 vminvq_f64 + #define npyv_reduce_minp_f32 vminnmvq_f32 + #define npyv_reduce_minp_f64 vminnmvq_f64 +#else + #define NPY_IMPL_NEON_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + STYPE##x8_t r = vp##INTRIN##_##SFX(vget_low_##SFX(a), vget_high_##SFX(a)); \ + r = vp##INTRIN##_##SFX(r, r); \ + r = vp##INTRIN##_##SFX(r, r); \ + r = vp##INTRIN##_##SFX(r, r); \ + return (npy_##STYPE)vget_lane_##SFX(r, 0); \ + } + NPY_IMPL_NEON_REDUCE_MINMAX(min, uint8, u8) + NPY_IMPL_NEON_REDUCE_MINMAX(max, uint8, u8) + NPY_IMPL_NEON_REDUCE_MINMAX(min, int8, s8) + NPY_IMPL_NEON_REDUCE_MINMAX(max, int8, s8) + #undef NPY_IMPL_NEON_REDUCE_MINMAX + + #define NPY_IMPL_NEON_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + STYPE##x4_t r = vp##INTRIN##_##SFX(vget_low_##SFX(a), vget_high_##SFX(a)); \ + r = vp##INTRIN##_##SFX(r, r); \ + r = vp##INTRIN##_##SFX(r, r); \ + return (npy_##STYPE)vget_lane_##SFX(r, 0); \ + } + NPY_IMPL_NEON_REDUCE_MINMAX(min, uint16, u16) + NPY_IMPL_NEON_REDUCE_MINMAX(max, uint16, u16) + NPY_IMPL_NEON_REDUCE_MINMAX(min, int16, s16) + NPY_IMPL_NEON_REDUCE_MINMAX(max, int16, s16) + #undef NPY_IMPL_NEON_REDUCE_MINMAX + + #define NPY_IMPL_NEON_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + STYPE##x2_t r = vp##INTRIN##_##SFX(vget_low_##SFX(a), vget_high_##SFX(a)); \ + r = vp##INTRIN##_##SFX(r, r); \ + return (npy_##STYPE)vget_lane_##SFX(r, 0); \ + } + NPY_IMPL_NEON_REDUCE_MINMAX(min, uint32, u32) + NPY_IMPL_NEON_REDUCE_MINMAX(max, uint32, u32) + NPY_IMPL_NEON_REDUCE_MINMAX(min, int32, s32) + NPY_IMPL_NEON_REDUCE_MINMAX(max, int32, s32) + #undef NPY_IMPL_NEON_REDUCE_MINMAX + + #define NPY_IMPL_NEON_REDUCE_MINMAX(INTRIN, INF) \ + NPY_FINLINE float npyv_reduce_##INTRIN##_f32(npyv_f32 a) \ + { \ + float32x2_t r = vp##INTRIN##_f32(vget_low_f32(a), vget_high_f32(a));\ + r = vp##INTRIN##_f32(r, r); \ + return vget_lane_f32(r, 0); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##p_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_any_b32(notnan))) { \ + return vgetq_lane_f32(a, 0); \ + } \ + a = npyv_select_f32(notnan, a, \ + npyv_reinterpret_f32_u32(npyv_setall_u32(INF))); \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##n_f32(npyv_f32 a) \ + { \ + return npyv_reduce_##INTRIN##_f32(a); \ + } + NPY_IMPL_NEON_REDUCE_MINMAX(min, 0x7f800000) + NPY_IMPL_NEON_REDUCE_MINMAX(max, 0xff800000) + #undef NPY_IMPL_NEON_REDUCE_MINMAX +#endif // NPY_SIMD_F64 +#define NPY_IMPL_NEON_REDUCE_MINMAX(INTRIN, STYPE, SFX, OP) \ + NPY_FINLINE STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + STYPE al = (STYPE)vget_low_##SFX(a); \ + STYPE ah = (STYPE)vget_high_##SFX(a); \ + return al OP ah ? al : ah; \ + } +NPY_IMPL_NEON_REDUCE_MINMAX(max, npy_uint64, u64, >) +NPY_IMPL_NEON_REDUCE_MINMAX(max, npy_int64, s64, >) +NPY_IMPL_NEON_REDUCE_MINMAX(min, npy_uint64, u64, <) +NPY_IMPL_NEON_REDUCE_MINMAX(min, npy_int64, s64, <) +#undef NPY_IMPL_NEON_REDUCE_MINMAX + +// round to nearest integer even +NPY_FINLINE npyv_f32 npyv_rint_f32(npyv_f32 a) +{ +#ifdef NPY_HAVE_ASIMD + return vrndnq_f32(a); +#else + // ARMv7 NEON only supports fp to int truncate conversion. + // a magic trick of adding 1.5 * 2^23 is used for rounding + // to nearest even and then subtract this magic number to get + // the integer. + // + const npyv_u32 szero = vreinterpretq_u32_f32(vdupq_n_f32(-0.0f)); + const npyv_u32 sign_mask = vandq_u32(vreinterpretq_u32_f32(a), szero); + const npyv_f32 two_power_23 = vdupq_n_f32(8388608.0); // 2^23 + const npyv_f32 two_power_23h = vdupq_n_f32(12582912.0f); // 1.5 * 2^23 + npyv_u32 nnan_mask = vceqq_f32(a, a); + // eliminate nans to avoid invalid fp errors + npyv_f32 abs_x = vabsq_f32(vreinterpretq_f32_u32(vandq_u32(nnan_mask, vreinterpretq_u32_f32(a)))); + // round by add magic number 1.5 * 2^23 + npyv_f32 round = vsubq_f32(vaddq_f32(two_power_23h, abs_x), two_power_23h); + // copysign + round = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(round), sign_mask )); + // a if |a| >= 2^23 or a == NaN + npyv_u32 mask = vcleq_f32(abs_x, two_power_23); + mask = vandq_u32(mask, nnan_mask); + return vbslq_f32(mask, round, a); +#endif +} +#if NPY_SIMD_F64 + #define npyv_rint_f64 vrndnq_f64 +#endif // NPY_SIMD_F64 + +// ceil +#ifdef NPY_HAVE_ASIMD + #define npyv_ceil_f32 vrndpq_f32 +#else + NPY_FINLINE npyv_f32 npyv_ceil_f32(npyv_f32 a) + { + const npyv_u32 one = vreinterpretq_u32_f32(vdupq_n_f32(1.0f)); + const npyv_u32 szero = vreinterpretq_u32_f32(vdupq_n_f32(-0.0f)); + const npyv_u32 sign_mask = vandq_u32(vreinterpretq_u32_f32(a), szero); + const npyv_f32 two_power_23 = vdupq_n_f32(8388608.0); // 2^23 + const npyv_f32 two_power_23h = vdupq_n_f32(12582912.0f); // 1.5 * 2^23 + npyv_u32 nnan_mask = vceqq_f32(a, a); + npyv_f32 x = vreinterpretq_f32_u32(vandq_u32(nnan_mask, vreinterpretq_u32_f32(a))); + // eliminate nans to avoid invalid fp errors + npyv_f32 abs_x = vabsq_f32(x); + // round by add magic number 1.5 * 2^23 + npyv_f32 round = vsubq_f32(vaddq_f32(two_power_23h, abs_x), two_power_23h); + // copysign + round = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(round), sign_mask)); + npyv_f32 ceil = vaddq_f32(round, vreinterpretq_f32_u32( + vandq_u32(vcltq_f32(round, x), one)) + ); + // respects signed zero + ceil = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(ceil), sign_mask)); + // a if |a| >= 2^23 or a == NaN + npyv_u32 mask = vcleq_f32(abs_x, two_power_23); + mask = vandq_u32(mask, nnan_mask); + return vbslq_f32(mask, ceil, a); + } +#endif +#if NPY_SIMD_F64 + #define npyv_ceil_f64 vrndpq_f64 +#endif // NPY_SIMD_F64 + +// trunc +#ifdef NPY_HAVE_ASIMD + #define npyv_trunc_f32 vrndq_f32 +#else + NPY_FINLINE npyv_f32 npyv_trunc_f32(npyv_f32 a) + { + const npyv_s32 max_int = vdupq_n_s32(0x7fffffff); + const npyv_u32 exp_mask = vdupq_n_u32(0xff000000); + const npyv_s32 szero = vreinterpretq_s32_f32(vdupq_n_f32(-0.0f)); + const npyv_u32 sign_mask = vandq_u32( + vreinterpretq_u32_f32(a), vreinterpretq_u32_s32(szero)); + + npyv_u32 nfinite_mask = vshlq_n_u32(vreinterpretq_u32_f32(a), 1); + nfinite_mask = vandq_u32(nfinite_mask, exp_mask); + nfinite_mask = vceqq_u32(nfinite_mask, exp_mask); + // eliminate nans/inf to avoid invalid fp errors + npyv_f32 x = vreinterpretq_f32_u32( + veorq_u32(nfinite_mask, vreinterpretq_u32_f32(a))); + /** + * On armv7, vcvtq.f32 handles special cases as follows: + * NaN return 0 + * +inf or +outrange return 0x80000000(-0.0f) + * -inf or -outrange return 0x7fffffff(nan) + */ + npyv_s32 trunci = vcvtq_s32_f32(x); + npyv_f32 trunc = vcvtq_f32_s32(trunci); + // respect signed zero, e.g. -0.5 -> -0.0 + trunc = vreinterpretq_f32_u32( + vorrq_u32(vreinterpretq_u32_f32(trunc), sign_mask)); + // if overflow return a + npyv_u32 overflow_mask = vorrq_u32( + vceqq_s32(trunci, szero), vceqq_s32(trunci, max_int) + ); + // a if a overflow or nonfinite + return vbslq_f32(vorrq_u32(nfinite_mask, overflow_mask), a, trunc); + } +#endif +#if NPY_SIMD_F64 + #define npyv_trunc_f64 vrndq_f64 +#endif // NPY_SIMD_F64 + +// floor +#ifdef NPY_HAVE_ASIMD + #define npyv_floor_f32 vrndmq_f32 +#else + NPY_FINLINE npyv_f32 npyv_floor_f32(npyv_f32 a) + { + const npyv_u32 one = vreinterpretq_u32_f32(vdupq_n_f32(1.0f)); + const npyv_u32 szero = vreinterpretq_u32_f32(vdupq_n_f32(-0.0f)); + const npyv_u32 sign_mask = vandq_u32(vreinterpretq_u32_f32(a), szero); + const npyv_f32 two_power_23 = vdupq_n_f32(8388608.0); // 2^23 + const npyv_f32 two_power_23h = vdupq_n_f32(12582912.0f); // 1.5 * 2^23 + + npyv_u32 nnan_mask = vceqq_f32(a, a); + npyv_f32 x = vreinterpretq_f32_u32(vandq_u32(nnan_mask, vreinterpretq_u32_f32(a))); + // eliminate nans to avoid invalid fp errors + npyv_f32 abs_x = vabsq_f32(x); + // round by add magic number 1.5 * 2^23 + npyv_f32 round = vsubq_f32(vaddq_f32(two_power_23h, abs_x), two_power_23h); + // copysign + round = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(round), sign_mask)); + npyv_f32 floor = vsubq_f32(round, vreinterpretq_f32_u32( + vandq_u32(vcgtq_f32(round, x), one) + )); + // respects signed zero + floor = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(floor), sign_mask)); + // a if |a| >= 2^23 or a == NaN + npyv_u32 mask = vcleq_f32(abs_x, two_power_23); + mask = vandq_u32(mask, nnan_mask); + return vbslq_f32(mask, floor, a); + } +#endif // NPY_HAVE_ASIMD +#if NPY_SIMD_F64 + #define npyv_floor_f64 vrndmq_f64 +#endif // NPY_SIMD_F64 + +#endif // _NPY_SIMD_NEON_MATH_H diff --git a/mkl_umath/src/npyv/neon/memory.h b/mkl_umath/src/npyv/neon/memory.h new file mode 100644 index 00000000..e7503b82 --- /dev/null +++ b/mkl_umath/src/npyv/neon/memory.h @@ -0,0 +1,678 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_MEMORY_H +#define _NPY_SIMD_NEON_MEMORY_H + +#include "misc.h" + +/*************************** + * load/store + ***************************/ +// GCC requires literal type definitions for pointers types otherwise it causes ambiguous errors +#define NPYV_IMPL_NEON_MEM(SFX, CTYPE) \ + NPY_FINLINE npyv_##SFX npyv_load_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return vld1q_##SFX((const CTYPE*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loada_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return vld1q_##SFX((const CTYPE*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loads_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return vld1q_##SFX((const CTYPE*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loadl_##SFX(const npyv_lanetype_##SFX *ptr) \ + { \ + return vcombine_##SFX( \ + vld1_##SFX((const CTYPE*)ptr), vdup_n_##SFX(0) \ + ); \ + } \ + NPY_FINLINE void npyv_store_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { vst1q_##SFX((CTYPE*)ptr, vec); } \ + NPY_FINLINE void npyv_storea_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { vst1q_##SFX((CTYPE*)ptr, vec); } \ + NPY_FINLINE void npyv_stores_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { vst1q_##SFX((CTYPE*)ptr, vec); } \ + NPY_FINLINE void npyv_storel_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { vst1_##SFX((CTYPE*)ptr, vget_low_##SFX(vec)); } \ + NPY_FINLINE void npyv_storeh_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { vst1_##SFX((CTYPE*)ptr, vget_high_##SFX(vec)); } + +NPYV_IMPL_NEON_MEM(u8, uint8_t) +NPYV_IMPL_NEON_MEM(s8, int8_t) +NPYV_IMPL_NEON_MEM(u16, uint16_t) +NPYV_IMPL_NEON_MEM(s16, int16_t) +NPYV_IMPL_NEON_MEM(u32, uint32_t) +NPYV_IMPL_NEON_MEM(s32, int32_t) +NPYV_IMPL_NEON_MEM(u64, uint64_t) +NPYV_IMPL_NEON_MEM(s64, int64_t) +NPYV_IMPL_NEON_MEM(f32, float) +#if NPY_SIMD_F64 +NPYV_IMPL_NEON_MEM(f64, double) +#endif +/*************************** + * Non-contiguous Load + ***************************/ +NPY_FINLINE npyv_s32 npyv_loadn_s32(const npy_int32 *ptr, npy_intp stride) +{ + int32x4_t a = vdupq_n_s32(0); + a = vld1q_lane_s32((const int32_t*)ptr, a, 0); + a = vld1q_lane_s32((const int32_t*)ptr + stride, a, 1); + a = vld1q_lane_s32((const int32_t*)ptr + stride*2, a, 2); + a = vld1q_lane_s32((const int32_t*)ptr + stride*3, a, 3); + return a; +} + +NPY_FINLINE npyv_u32 npyv_loadn_u32(const npy_uint32 *ptr, npy_intp stride) +{ + return npyv_reinterpret_u32_s32( + npyv_loadn_s32((const npy_int32*)ptr, stride) + ); +} +NPY_FINLINE npyv_f32 npyv_loadn_f32(const float *ptr, npy_intp stride) +{ + return npyv_reinterpret_f32_s32( + npyv_loadn_s32((const npy_int32*)ptr, stride) + ); +} +//// 64 +NPY_FINLINE npyv_s64 npyv_loadn_s64(const npy_int64 *ptr, npy_intp stride) +{ + return vcombine_s64( + vld1_s64((const int64_t*)ptr), vld1_s64((const int64_t*)ptr + stride) + ); +} +NPY_FINLINE npyv_u64 npyv_loadn_u64(const npy_uint64 *ptr, npy_intp stride) +{ + return npyv_reinterpret_u64_s64( + npyv_loadn_s64((const npy_int64*)ptr, stride) + ); +} +#if NPY_SIMD_F64 +NPY_FINLINE npyv_f64 npyv_loadn_f64(const double *ptr, npy_intp stride) +{ + return npyv_reinterpret_f64_s64( + npyv_loadn_s64((const npy_int64*)ptr, stride) + ); +} +#endif + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_u32 npyv_loadn2_u32(const npy_uint32 *ptr, npy_intp stride) +{ + return vcombine_u32( + vld1_u32((const uint32_t*)ptr), vld1_u32((const uint32_t*)ptr + stride) + ); +} +NPY_FINLINE npyv_s32 npyv_loadn2_s32(const npy_int32 *ptr, npy_intp stride) +{ return npyv_reinterpret_s32_u32(npyv_loadn2_u32((const npy_uint32*)ptr, stride)); } +NPY_FINLINE npyv_f32 npyv_loadn2_f32(const float *ptr, npy_intp stride) +{ return npyv_reinterpret_f32_u32(npyv_loadn2_u32((const npy_uint32*)ptr, stride)); } + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_u64 npyv_loadn2_u64(const npy_uint64 *ptr, npy_intp stride) +{ (void)stride; return npyv_load_u64(ptr); } +NPY_FINLINE npyv_s64 npyv_loadn2_s64(const npy_int64 *ptr, npy_intp stride) +{ (void)stride; return npyv_load_s64(ptr); } +#if NPY_SIMD_F64 +NPY_FINLINE npyv_f64 npyv_loadn2_f64(const double *ptr, npy_intp stride) +{ (void)stride; return npyv_load_f64(ptr); } +#endif + +/*************************** + * Non-contiguous Store + ***************************/ +//// 32 +NPY_FINLINE void npyv_storen_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ + vst1q_lane_s32((int32_t*)ptr, a, 0); + vst1q_lane_s32((int32_t*)ptr + stride, a, 1); + vst1q_lane_s32((int32_t*)ptr + stride*2, a, 2); + vst1q_lane_s32((int32_t*)ptr + stride*3, a, 3); +} +NPY_FINLINE void npyv_storen_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ npyv_storen_s32((npy_int32*)ptr, stride, npyv_reinterpret_s32_u32(a)); } +NPY_FINLINE void npyv_storen_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen_s32((npy_int32*)ptr, stride, npyv_reinterpret_s32_f32(a)); } +//// 64 +NPY_FINLINE void npyv_storen_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ + vst1q_lane_s64((int64_t*)ptr, a, 0); + vst1q_lane_s64((int64_t*)ptr + stride, a, 1); +} +NPY_FINLINE void npyv_storen_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ npyv_storen_s64((npy_int64*)ptr, stride, npyv_reinterpret_s64_u64(a)); } + +#if NPY_SIMD_F64 +NPY_FINLINE void npyv_storen_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ npyv_storen_s64((npy_int64*)ptr, stride, npyv_reinterpret_s64_f64(a)); } +#endif + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ +#if NPY_SIMD_F64 + vst1q_lane_u64((uint64_t*)ptr, npyv_reinterpret_u64_u32(a), 0); + vst1q_lane_u64((uint64_t*)(ptr + stride), npyv_reinterpret_u64_u32(a), 1); +#else + // armhf strict to alignment + vst1_u32((uint32_t*)ptr, vget_low_u32(a)); + vst1_u32((uint32_t*)ptr + stride, vget_high_u32(a)); +#endif +} +NPY_FINLINE void npyv_storen2_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, npyv_reinterpret_u32_s32(a)); } +NPY_FINLINE void npyv_storen2_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, npyv_reinterpret_u32_f32(a)); } + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ (void)stride; npyv_store_u64(ptr, a); } +NPY_FINLINE void npyv_storen2_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ (void)stride; npyv_store_s64(ptr, a); } +#if NPY_SIMD_F64 +NPY_FINLINE void npyv_storen2_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ (void)stride; npyv_store_f64(ptr, a); } +#endif +/********************************* + * Partial Load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 npyv_load_till_s32(const npy_int32 *ptr, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + npyv_s32 a; + switch(nlane) { + case 1: + a = vld1q_lane_s32((const int32_t*)ptr, vdupq_n_s32(fill), 0); + break; + case 2: + a = vcombine_s32(vld1_s32((const int32_t*)ptr), vdup_n_s32(fill)); + break; + case 3: + a = vcombine_s32( + vld1_s32((const int32_t*)ptr), + vld1_lane_s32((const int32_t*)ptr + 2, vdup_n_s32(fill), 0) + ); + break; + default: + return npyv_load_s32(ptr); + } +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = a; + a = vorrq_s32(workaround, a); +#endif + return a; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ return npyv_load_till_s32(ptr, nlane, 0); } +//// 64 +NPY_FINLINE npyv_s64 npyv_load_till_s64(const npy_int64 *ptr, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_s64 a = vcombine_s64(vld1_s64((const int64_t*)ptr), vdup_n_s64(fill)); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s64 workaround = a; + a = vorrq_s64(workaround, a); + #endif + return a; + } + return npyv_load_s64(ptr); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_load_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ return npyv_load_till_s64(ptr, nlane, 0); } + +//// 64-bit nlane +NPY_FINLINE npyv_s32 npyv_load2_till_s32(const npy_int32 *ptr, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + if (nlane == 1) { + const int32_t NPY_DECL_ALIGNED(16) fill[2] = {fill_lo, fill_hi}; + npyv_s32 a = vcombine_s32(vld1_s32((const int32_t*)ptr), vld1_s32(fill)); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = a; + a = vorrq_s32(workaround, a); + #endif + return a; + } + return npyv_load_s32(ptr); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load2_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ return vreinterpretq_s32_s64(npyv_load_tillz_s64((const npy_int64*)ptr, nlane)); } + +//// 128-bit nlane +NPY_FINLINE npyv_s64 npyv_load2_till_s64(const npy_int64 *ptr, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ (void)nlane; (void)fill_lo; (void)fill_hi; return npyv_load_s64(ptr); } + +NPY_FINLINE npyv_s64 npyv_load2_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ (void)nlane; return npyv_load_s64(ptr); } + +/********************************* + * Non-contiguous partial load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 +npyv_loadn_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + int32x4_t vfill = vdupq_n_s32(fill); + switch(nlane) { + case 3: + vfill = vld1q_lane_s32((const int32_t*)ptr + stride*2, vfill, 2); + case 2: + vfill = vld1q_lane_s32((const int32_t*)ptr + stride, vfill, 1); + case 1: + vfill = vld1q_lane_s32((const int32_t*)ptr, vfill, 0); + break; + default: + return npyv_loadn_s32(ptr, stride); + } +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = vfill; + vfill = vorrq_s32(workaround, vfill); +#endif + return vfill; +} +NPY_FINLINE npyv_s32 +npyv_loadn_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s32(ptr, stride, nlane, 0); } + +NPY_FINLINE npyv_s64 +npyv_loadn_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + if (nlane == 1) { + return npyv_load_till_s64(ptr, 1, fill); + } + return npyv_loadn_s64(ptr, stride); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_loadn_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s64(ptr, stride, nlane, 0); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_s32 npyv_loadn2_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + if (nlane == 1) { + const int32_t NPY_DECL_ALIGNED(16) fill[2] = {fill_lo, fill_hi}; + npyv_s32 a = vcombine_s32(vld1_s32((const int32_t*)ptr), vld1_s32(fill)); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = a; + a = vorrq_s32(workaround, a); + #endif + return a; + } + return npyv_loadn2_s32(ptr, stride); +} +NPY_FINLINE npyv_s32 npyv_loadn2_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_s32 a = vcombine_s32(vld1_s32((const int32_t*)ptr), vdup_n_s32(0)); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = a; + a = vorrq_s32(workaround, a); + #endif + return a; + } + return npyv_loadn2_s32(ptr, stride); +} + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ assert(nlane > 0); (void)stride; (void)nlane; (void)fill_lo; (void)fill_hi; return npyv_load_s64(ptr); } + +NPY_FINLINE npyv_s64 npyv_loadn2_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ assert(nlane > 0); (void)stride; (void)nlane; return npyv_load_s64(ptr); } + +/********************************* + * Partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_store_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + switch(nlane) { + case 1: + vst1q_lane_s32((int32_t*)ptr, a, 0); + break; + case 2: + vst1_s32((int32_t*)ptr, vget_low_s32(a)); + break; + case 3: + vst1_s32((int32_t*)ptr, vget_low_s32(a)); + vst1q_lane_s32((int32_t*)ptr + 2, a, 2); + break; + default: + npyv_store_s32(ptr, a); + } +} +//// 64 +NPY_FINLINE void npyv_store_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + if (nlane == 1) { + vst1q_lane_s64((int64_t*)ptr, a, 0); + return; + } + npyv_store_s64(ptr, a); +} + +//// 64-bit nlane +NPY_FINLINE void npyv_store2_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + if (nlane == 1) { + // armhf strict to alignment, may cause bus error + #if NPY_SIMD_F64 + vst1q_lane_s64((int64_t*)ptr, npyv_reinterpret_s64_s32(a), 0); + #else + npyv_storel_s32(ptr, a); + #endif + return; + } + npyv_store_s32(ptr, a); +} + +//// 128-bit nlane +NPY_FINLINE void npyv_store2_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); (void)nlane; + npyv_store_s64(ptr, a); +} + +/********************************* + * Non-contiguous partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_storen_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + vst1q_lane_s32((int32_t*)ptr, a, 0); + switch(nlane) { + case 1: + return; + case 2: + vst1q_lane_s32((int32_t*)ptr + stride, a, 1); + return; + case 3: + vst1q_lane_s32((int32_t*)ptr + stride, a, 1); + vst1q_lane_s32((int32_t*)ptr + stride*2, a, 2); + return; + default: + vst1q_lane_s32((int32_t*)ptr + stride, a, 1); + vst1q_lane_s32((int32_t*)ptr + stride*2, a, 2); + vst1q_lane_s32((int32_t*)ptr + stride*3, a, 3); + } +} +//// 64 +NPY_FINLINE void npyv_storen_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + if (nlane == 1) { + vst1q_lane_s64((int64_t*)ptr, a, 0); + return; + } + npyv_storen_s64(ptr, stride, a); +} + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); +#if NPY_SIMD_F64 + vst1q_lane_s64((int64_t*)ptr, npyv_reinterpret_s64_s32(a), 0); + if (nlane > 1) { + vst1q_lane_s64((int64_t*)(ptr + stride), npyv_reinterpret_s64_s32(a), 1); + } +#else + npyv_storel_s32(ptr, a); + if (nlane > 1) { + npyv_storeh_s32(ptr + stride, a); + } +#endif +} + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ assert(nlane > 0); (void)stride; (void)nlane; npyv_store_s64(ptr, a); } + +/***************************************************************** + * Implement partial load/store for u32/f32/u64/f64... via casting + *****************************************************************/ +#define NPYV_IMPL_NEON_REST_PARTIAL_TYPES(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_NEON_REST_PARTIAL_TYPES(u32, s32) +NPYV_IMPL_NEON_REST_PARTIAL_TYPES(f32, s32) +NPYV_IMPL_NEON_REST_PARTIAL_TYPES(u64, s64) +#if NPY_SIMD_F64 +NPYV_IMPL_NEON_REST_PARTIAL_TYPES(f64, s64) +#endif + +// 128-bit/64-bit stride +#define NPYV_IMPL_NEON_REST_PARTIAL_TYPES_PAIR(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun_lo.to_##T_SFX, pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun_lo.to_##T_SFX, \ + pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_NEON_REST_PARTIAL_TYPES_PAIR(u32, s32) +NPYV_IMPL_NEON_REST_PARTIAL_TYPES_PAIR(f32, s32) +NPYV_IMPL_NEON_REST_PARTIAL_TYPES_PAIR(u64, s64) +#if NPY_SIMD_F64 +NPYV_IMPL_NEON_REST_PARTIAL_TYPES_PAIR(f64, s64) +#endif + +/************************************************************ + * de-interlave load / interleave contiguous store + ************************************************************/ +// two channels +#define NPYV_IMPL_NEON_MEM_INTERLEAVE(SFX, T_PTR) \ + NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2( \ + const npyv_lanetype_##SFX *ptr \ + ) { \ + return vld2q_##SFX((const T_PTR*)ptr); \ + } \ + NPY_FINLINE void npyv_store_##SFX##x2( \ + npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v \ + ) { \ + vst2q_##SFX((T_PTR*)ptr, v); \ + } + +NPYV_IMPL_NEON_MEM_INTERLEAVE(u8, uint8_t) +NPYV_IMPL_NEON_MEM_INTERLEAVE(s8, int8_t) +NPYV_IMPL_NEON_MEM_INTERLEAVE(u16, uint16_t) +NPYV_IMPL_NEON_MEM_INTERLEAVE(s16, int16_t) +NPYV_IMPL_NEON_MEM_INTERLEAVE(u32, uint32_t) +NPYV_IMPL_NEON_MEM_INTERLEAVE(s32, int32_t) +NPYV_IMPL_NEON_MEM_INTERLEAVE(f32, float) + +#if NPY_SIMD_F64 + NPYV_IMPL_NEON_MEM_INTERLEAVE(f64, double) + NPYV_IMPL_NEON_MEM_INTERLEAVE(u64, uint64_t) + NPYV_IMPL_NEON_MEM_INTERLEAVE(s64, int64_t) +#else + #define NPYV_IMPL_NEON_MEM_INTERLEAVE_64(SFX) \ + NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2( \ + const npyv_lanetype_##SFX *ptr) \ + { \ + npyv_##SFX a = npyv_load_##SFX(ptr); \ + npyv_##SFX b = npyv_load_##SFX(ptr + 2); \ + npyv_##SFX##x2 r; \ + r.val[0] = vcombine_##SFX(vget_low_##SFX(a), vget_low_##SFX(b)); \ + r.val[1] = vcombine_##SFX(vget_high_##SFX(a), vget_high_##SFX(b)); \ + return r; \ + } \ + NPY_FINLINE void npyv_store_##SFX##x2( \ + npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v) \ + { \ + npyv_store_##SFX(ptr, vcombine_##SFX( \ + vget_low_##SFX(v.val[0]), vget_low_##SFX(v.val[1]))); \ + npyv_store_##SFX(ptr + 2, vcombine_##SFX( \ + vget_high_##SFX(v.val[0]), vget_high_##SFX(v.val[1]))); \ + } + NPYV_IMPL_NEON_MEM_INTERLEAVE_64(u64) + NPYV_IMPL_NEON_MEM_INTERLEAVE_64(s64) +#endif +/********************************* + * Lookup table + *********************************/ +// uses vector as indexes into a table +// that contains 32 elements of uint32. +NPY_FINLINE npyv_u32 npyv_lut32_u32(const npy_uint32 *table, npyv_u32 idx) +{ + const unsigned i0 = vgetq_lane_u32(idx, 0); + const unsigned i1 = vgetq_lane_u32(idx, 1); + const unsigned i2 = vgetq_lane_u32(idx, 2); + const unsigned i3 = vgetq_lane_u32(idx, 3); + + uint32x2_t low = vcreate_u32(table[i0]); + low = vld1_lane_u32((const uint32_t*)table + i1, low, 1); + uint32x2_t high = vcreate_u32(table[i2]); + high = vld1_lane_u32((const uint32_t*)table + i3, high, 1); + return vcombine_u32(low, high); +} +NPY_FINLINE npyv_s32 npyv_lut32_s32(const npy_int32 *table, npyv_u32 idx) +{ return npyv_reinterpret_s32_u32(npyv_lut32_u32((const npy_uint32*)table, idx)); } +NPY_FINLINE npyv_f32 npyv_lut32_f32(const float *table, npyv_u32 idx) +{ return npyv_reinterpret_f32_u32(npyv_lut32_u32((const npy_uint32*)table, idx)); } + +// uses vector as indexes into a table +// that contains 16 elements of uint64. +NPY_FINLINE npyv_u64 npyv_lut16_u64(const npy_uint64 *table, npyv_u64 idx) +{ + const unsigned i0 = vgetq_lane_u32(vreinterpretq_u32_u64(idx), 0); + const unsigned i1 = vgetq_lane_u32(vreinterpretq_u32_u64(idx), 2); + return vcombine_u64( + vld1_u64((const uint64_t*)table + i0), + vld1_u64((const uint64_t*)table + i1) + ); +} +NPY_FINLINE npyv_s64 npyv_lut16_s64(const npy_int64 *table, npyv_u64 idx) +{ return npyv_reinterpret_s64_u64(npyv_lut16_u64((const npy_uint64*)table, idx)); } +#if NPY_SIMD_F64 +NPY_FINLINE npyv_f64 npyv_lut16_f64(const double *table, npyv_u64 idx) +{ return npyv_reinterpret_f64_u64(npyv_lut16_u64((const npy_uint64*)table, idx)); } +#endif + +#endif // _NPY_SIMD_NEON_MEMORY_H diff --git a/mkl_umath/src/npyv/neon/misc.h b/mkl_umath/src/npyv/neon/misc.h new file mode 100644 index 00000000..9dac0cfa --- /dev/null +++ b/mkl_umath/src/npyv/neon/misc.h @@ -0,0 +1,275 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_MISC_H +#define _NPY_SIMD_NEON_MISC_H + +// vector with zero lanes +#define npyv_zero_u8() vreinterpretq_u8_s32(npyv_zero_s32()) +#define npyv_zero_s8() vreinterpretq_s8_s32(npyv_zero_s32()) +#define npyv_zero_u16() vreinterpretq_u16_s32(npyv_zero_s32()) +#define npyv_zero_s16() vreinterpretq_s16_s32(npyv_zero_s32()) +#define npyv_zero_u32() vdupq_n_u32((unsigned)0) +#define npyv_zero_s32() vdupq_n_s32((int)0) +#define npyv_zero_u64() vreinterpretq_u64_s32(npyv_zero_s32()) +#define npyv_zero_s64() vreinterpretq_s64_s32(npyv_zero_s32()) +#define npyv_zero_f32() vdupq_n_f32(0.0f) +#define npyv_zero_f64() vdupq_n_f64(0.0) + +// vector with a specific value set to all lanes +#define npyv_setall_u8 vdupq_n_u8 +#define npyv_setall_s8 vdupq_n_s8 +#define npyv_setall_u16 vdupq_n_u16 +#define npyv_setall_s16 vdupq_n_s16 +#define npyv_setall_u32 vdupq_n_u32 +#define npyv_setall_s32 vdupq_n_s32 +#define npyv_setall_u64 vdupq_n_u64 +#define npyv_setall_s64 vdupq_n_s64 +#define npyv_setall_f32 vdupq_n_f32 +#define npyv_setall_f64 vdupq_n_f64 + +// vector with specific values set to each lane and +// set a specific value to all remained lanes +#if defined(__clang__) || defined(__GNUC__) + #define npyv_setf_u8(FILL, ...) ((uint8x16_t){NPYV__SET_FILL_16(uint8_t, FILL, __VA_ARGS__)}) + #define npyv_setf_s8(FILL, ...) ((int8x16_t){NPYV__SET_FILL_16(int8_t, FILL, __VA_ARGS__)}) + #define npyv_setf_u16(FILL, ...) ((uint16x8_t){NPYV__SET_FILL_8(uint16_t, FILL, __VA_ARGS__)}) + #define npyv_setf_s16(FILL, ...) ((int16x8_t){NPYV__SET_FILL_8(int16_t, FILL, __VA_ARGS__)}) + #define npyv_setf_u32(FILL, ...) ((uint32x4_t){NPYV__SET_FILL_4(uint32_t, FILL, __VA_ARGS__)}) + #define npyv_setf_s32(FILL, ...) ((int32x4_t){NPYV__SET_FILL_4(int32_t, FILL, __VA_ARGS__)}) + #define npyv_setf_u64(FILL, ...) ((uint64x2_t){NPYV__SET_FILL_2(uint64_t, FILL, __VA_ARGS__)}) + #define npyv_setf_s64(FILL, ...) ((int64x2_t){NPYV__SET_FILL_2(int64_t, FILL, __VA_ARGS__)}) + #define npyv_setf_f32(FILL, ...) ((float32x4_t){NPYV__SET_FILL_4(float, FILL, __VA_ARGS__)}) + #if NPY_SIMD_F64 + #define npyv_setf_f64(FILL, ...) ((float64x2_t){NPYV__SET_FILL_2(double, FILL, __VA_ARGS__)}) + #endif +#else + NPY_FINLINE uint8x16_t npyv__set_u8(npy_uint8 i0, npy_uint8 i1, npy_uint8 i2, npy_uint8 i3, + npy_uint8 i4, npy_uint8 i5, npy_uint8 i6, npy_uint8 i7, npy_uint8 i8, npy_uint8 i9, + npy_uint8 i10, npy_uint8 i11, npy_uint8 i12, npy_uint8 i13, npy_uint8 i14, npy_uint8 i15) + { + const uint8_t NPY_DECL_ALIGNED(16) data[16] = { + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15 + }; + return vld1q_u8(data); + } + NPY_FINLINE int8x16_t npyv__set_s8(npy_int8 i0, npy_int8 i1, npy_int8 i2, npy_int8 i3, + npy_int8 i4, npy_int8 i5, npy_int8 i6, npy_int8 i7, npy_int8 i8, npy_int8 i9, + npy_int8 i10, npy_int8 i11, npy_int8 i12, npy_int8 i13, npy_int8 i14, npy_int8 i15) + { + const int8_t NPY_DECL_ALIGNED(16) data[16] = { + i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15 + }; + return vld1q_s8(data); + } + NPY_FINLINE uint16x8_t npyv__set_u16(npy_uint16 i0, npy_uint16 i1, npy_uint16 i2, npy_uint16 i3, + npy_uint16 i4, npy_uint16 i5, npy_uint16 i6, npy_uint16 i7) + { + const uint16_t NPY_DECL_ALIGNED(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7}; + return vld1q_u16(data); + } + NPY_FINLINE int16x8_t npyv__set_s16(npy_int16 i0, npy_int16 i1, npy_int16 i2, npy_int16 i3, + npy_int16 i4, npy_int16 i5, npy_int16 i6, npy_int16 i7) + { + const int16_t NPY_DECL_ALIGNED(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7}; + return vld1q_s16(data); + } + NPY_FINLINE uint32x4_t npyv__set_u32(npy_uint32 i0, npy_uint32 i1, npy_uint32 i2, npy_uint32 i3) + { + const uint32_t NPY_DECL_ALIGNED(16) data[4] = {i0, i1, i2, i3}; + return vld1q_u32(data); + } + NPY_FINLINE int32x4_t npyv__set_s32(npy_int32 i0, npy_int32 i1, npy_int32 i2, npy_int32 i3) + { + const int32_t NPY_DECL_ALIGNED(16) data[4] = {i0, i1, i2, i3}; + return vld1q_s32(data); + } + NPY_FINLINE uint64x2_t npyv__set_u64(npy_uint64 i0, npy_uint64 i1) + { + const uint64_t NPY_DECL_ALIGNED(16) data[2] = {i0, i1}; + return vld1q_u64(data); + } + NPY_FINLINE int64x2_t npyv__set_s64(npy_int64 i0, npy_int64 i1) + { + const int64_t NPY_DECL_ALIGNED(16) data[2] = {i0, i1}; + return vld1q_s64(data); + } + NPY_FINLINE float32x4_t npyv__set_f32(float i0, float i1, float i2, float i3) + { + const float NPY_DECL_ALIGNED(16) data[4] = {i0, i1, i2, i3}; + return vld1q_f32(data); + } + #if NPY_SIMD_F64 + NPY_FINLINE float64x2_t npyv__set_f64(double i0, double i1) + { + const double NPY_DECL_ALIGNED(16) data[2] = {i0, i1}; + return vld1q_f64(data); + } + #endif + #define npyv_setf_u8(FILL, ...) npyv__set_u8(NPYV__SET_FILL_16(npy_uint8, FILL, __VA_ARGS__)) + #define npyv_setf_s8(FILL, ...) npyv__set_s8(NPYV__SET_FILL_16(npy_int8, FILL, __VA_ARGS__)) + #define npyv_setf_u16(FILL, ...) npyv__set_u16(NPYV__SET_FILL_8(npy_uint16, FILL, __VA_ARGS__)) + #define npyv_setf_s16(FILL, ...) npyv__set_s16(NPYV__SET_FILL_8(npy_int16, FILL, __VA_ARGS__)) + #define npyv_setf_u32(FILL, ...) npyv__set_u32(NPYV__SET_FILL_4(npy_uint32, FILL, __VA_ARGS__)) + #define npyv_setf_s32(FILL, ...) npyv__set_s32(NPYV__SET_FILL_4(npy_int32, FILL, __VA_ARGS__)) + #define npyv_setf_u64(FILL, ...) npyv__set_u64(NPYV__SET_FILL_2(npy_uint64, FILL, __VA_ARGS__)) + #define npyv_setf_s64(FILL, ...) npyv__set_s64(NPYV__SET_FILL_2(npy_int64, FILL, __VA_ARGS__)) + #define npyv_setf_f32(FILL, ...) npyv__set_f32(NPYV__SET_FILL_4(float, FILL, __VA_ARGS__)) + #if NPY_SIMD_F64 + #define npyv_setf_f64(FILL, ...) npyv__set_f64(NPYV__SET_FILL_2(double, FILL, __VA_ARGS__)) + #endif +#endif + +// vector with specific values set to each lane and +// set zero to all remained lanes +#define npyv_set_u8(...) npyv_setf_u8(0, __VA_ARGS__) +#define npyv_set_s8(...) npyv_setf_s8(0, __VA_ARGS__) +#define npyv_set_u16(...) npyv_setf_u16(0, __VA_ARGS__) +#define npyv_set_s16(...) npyv_setf_s16(0, __VA_ARGS__) +#define npyv_set_u32(...) npyv_setf_u32(0, __VA_ARGS__) +#define npyv_set_s32(...) npyv_setf_s32(0, __VA_ARGS__) +#define npyv_set_u64(...) npyv_setf_u64(0, __VA_ARGS__) +#define npyv_set_s64(...) npyv_setf_s64(0, __VA_ARGS__) +#define npyv_set_f32(...) npyv_setf_f32(0, __VA_ARGS__) +#define npyv_set_f64(...) npyv_setf_f64(0, __VA_ARGS__) + +// Per lane select +#define npyv_select_u8 vbslq_u8 +#define npyv_select_s8 vbslq_s8 +#define npyv_select_u16 vbslq_u16 +#define npyv_select_s16 vbslq_s16 +#define npyv_select_u32 vbslq_u32 +#define npyv_select_s32 vbslq_s32 +#define npyv_select_u64 vbslq_u64 +#define npyv_select_s64 vbslq_s64 +#define npyv_select_f32 vbslq_f32 +#define npyv_select_f64 vbslq_f64 + +// extract the first vector's lane +#define npyv_extract0_u8(A) ((npy_uint8)vgetq_lane_u8(A, 0)) +#define npyv_extract0_s8(A) ((npy_int8)vgetq_lane_s8(A, 0)) +#define npyv_extract0_u16(A) ((npy_uint16)vgetq_lane_u16(A, 0)) +#define npyv_extract0_s16(A) ((npy_int16)vgetq_lane_s16(A, 0)) +#define npyv_extract0_u32(A) ((npy_uint32)vgetq_lane_u32(A, 0)) +#define npyv_extract0_s32(A) ((npy_int32)vgetq_lane_s32(A, 0)) +#define npyv_extract0_u64(A) ((npy_uint64)vgetq_lane_u64(A, 0)) +#define npyv_extract0_s64(A) ((npy_int64)vgetq_lane_s64(A, 0)) +#define npyv_extract0_f32(A) vgetq_lane_f32(A, 0) +#define npyv_extract0_f64(A) vgetq_lane_f64(A, 0) + +// Reinterpret +#define npyv_reinterpret_u8_u8(X) X +#define npyv_reinterpret_u8_s8 vreinterpretq_u8_s8 +#define npyv_reinterpret_u8_u16 vreinterpretq_u8_u16 +#define npyv_reinterpret_u8_s16 vreinterpretq_u8_s16 +#define npyv_reinterpret_u8_u32 vreinterpretq_u8_u32 +#define npyv_reinterpret_u8_s32 vreinterpretq_u8_s32 +#define npyv_reinterpret_u8_u64 vreinterpretq_u8_u64 +#define npyv_reinterpret_u8_s64 vreinterpretq_u8_s64 +#define npyv_reinterpret_u8_f32 vreinterpretq_u8_f32 +#define npyv_reinterpret_u8_f64 vreinterpretq_u8_f64 + +#define npyv_reinterpret_s8_s8(X) X +#define npyv_reinterpret_s8_u8 vreinterpretq_s8_u8 +#define npyv_reinterpret_s8_u16 vreinterpretq_s8_u16 +#define npyv_reinterpret_s8_s16 vreinterpretq_s8_s16 +#define npyv_reinterpret_s8_u32 vreinterpretq_s8_u32 +#define npyv_reinterpret_s8_s32 vreinterpretq_s8_s32 +#define npyv_reinterpret_s8_u64 vreinterpretq_s8_u64 +#define npyv_reinterpret_s8_s64 vreinterpretq_s8_s64 +#define npyv_reinterpret_s8_f32 vreinterpretq_s8_f32 +#define npyv_reinterpret_s8_f64 vreinterpretq_s8_f64 + +#define npyv_reinterpret_u16_u16(X) X +#define npyv_reinterpret_u16_u8 vreinterpretq_u16_u8 +#define npyv_reinterpret_u16_s8 vreinterpretq_u16_s8 +#define npyv_reinterpret_u16_s16 vreinterpretq_u16_s16 +#define npyv_reinterpret_u16_u32 vreinterpretq_u16_u32 +#define npyv_reinterpret_u16_s32 vreinterpretq_u16_s32 +#define npyv_reinterpret_u16_u64 vreinterpretq_u16_u64 +#define npyv_reinterpret_u16_s64 vreinterpretq_u16_s64 +#define npyv_reinterpret_u16_f32 vreinterpretq_u16_f32 +#define npyv_reinterpret_u16_f64 vreinterpretq_u16_f64 + +#define npyv_reinterpret_s16_s16(X) X +#define npyv_reinterpret_s16_u8 vreinterpretq_s16_u8 +#define npyv_reinterpret_s16_s8 vreinterpretq_s16_s8 +#define npyv_reinterpret_s16_u16 vreinterpretq_s16_u16 +#define npyv_reinterpret_s16_u32 vreinterpretq_s16_u32 +#define npyv_reinterpret_s16_s32 vreinterpretq_s16_s32 +#define npyv_reinterpret_s16_u64 vreinterpretq_s16_u64 +#define npyv_reinterpret_s16_s64 vreinterpretq_s16_s64 +#define npyv_reinterpret_s16_f32 vreinterpretq_s16_f32 +#define npyv_reinterpret_s16_f64 vreinterpretq_s16_f64 + +#define npyv_reinterpret_u32_u32(X) X +#define npyv_reinterpret_u32_u8 vreinterpretq_u32_u8 +#define npyv_reinterpret_u32_s8 vreinterpretq_u32_s8 +#define npyv_reinterpret_u32_u16 vreinterpretq_u32_u16 +#define npyv_reinterpret_u32_s16 vreinterpretq_u32_s16 +#define npyv_reinterpret_u32_s32 vreinterpretq_u32_s32 +#define npyv_reinterpret_u32_u64 vreinterpretq_u32_u64 +#define npyv_reinterpret_u32_s64 vreinterpretq_u32_s64 +#define npyv_reinterpret_u32_f32 vreinterpretq_u32_f32 +#define npyv_reinterpret_u32_f64 vreinterpretq_u32_f64 + +#define npyv_reinterpret_s32_s32(X) X +#define npyv_reinterpret_s32_u8 vreinterpretq_s32_u8 +#define npyv_reinterpret_s32_s8 vreinterpretq_s32_s8 +#define npyv_reinterpret_s32_u16 vreinterpretq_s32_u16 +#define npyv_reinterpret_s32_s16 vreinterpretq_s32_s16 +#define npyv_reinterpret_s32_u32 vreinterpretq_s32_u32 +#define npyv_reinterpret_s32_u64 vreinterpretq_s32_u64 +#define npyv_reinterpret_s32_s64 vreinterpretq_s32_s64 +#define npyv_reinterpret_s32_f32 vreinterpretq_s32_f32 +#define npyv_reinterpret_s32_f64 vreinterpretq_s32_f64 + +#define npyv_reinterpret_u64_u64(X) X +#define npyv_reinterpret_u64_u8 vreinterpretq_u64_u8 +#define npyv_reinterpret_u64_s8 vreinterpretq_u64_s8 +#define npyv_reinterpret_u64_u16 vreinterpretq_u64_u16 +#define npyv_reinterpret_u64_s16 vreinterpretq_u64_s16 +#define npyv_reinterpret_u64_u32 vreinterpretq_u64_u32 +#define npyv_reinterpret_u64_s32 vreinterpretq_u64_s32 +#define npyv_reinterpret_u64_s64 vreinterpretq_u64_s64 +#define npyv_reinterpret_u64_f32 vreinterpretq_u64_f32 +#define npyv_reinterpret_u64_f64 vreinterpretq_u64_f64 + +#define npyv_reinterpret_s64_s64(X) X +#define npyv_reinterpret_s64_u8 vreinterpretq_s64_u8 +#define npyv_reinterpret_s64_s8 vreinterpretq_s64_s8 +#define npyv_reinterpret_s64_u16 vreinterpretq_s64_u16 +#define npyv_reinterpret_s64_s16 vreinterpretq_s64_s16 +#define npyv_reinterpret_s64_u32 vreinterpretq_s64_u32 +#define npyv_reinterpret_s64_s32 vreinterpretq_s64_s32 +#define npyv_reinterpret_s64_u64 vreinterpretq_s64_u64 +#define npyv_reinterpret_s64_f32 vreinterpretq_s64_f32 +#define npyv_reinterpret_s64_f64 vreinterpretq_s64_f64 + +#define npyv_reinterpret_f32_f32(X) X +#define npyv_reinterpret_f32_u8 vreinterpretq_f32_u8 +#define npyv_reinterpret_f32_s8 vreinterpretq_f32_s8 +#define npyv_reinterpret_f32_u16 vreinterpretq_f32_u16 +#define npyv_reinterpret_f32_s16 vreinterpretq_f32_s16 +#define npyv_reinterpret_f32_u32 vreinterpretq_f32_u32 +#define npyv_reinterpret_f32_s32 vreinterpretq_f32_s32 +#define npyv_reinterpret_f32_u64 vreinterpretq_f32_u64 +#define npyv_reinterpret_f32_s64 vreinterpretq_f32_s64 +#define npyv_reinterpret_f32_f64 vreinterpretq_f32_f64 + +#define npyv_reinterpret_f64_f64(X) X +#define npyv_reinterpret_f64_u8 vreinterpretq_f64_u8 +#define npyv_reinterpret_f64_s8 vreinterpretq_f64_s8 +#define npyv_reinterpret_f64_u16 vreinterpretq_f64_u16 +#define npyv_reinterpret_f64_s16 vreinterpretq_f64_s16 +#define npyv_reinterpret_f64_u32 vreinterpretq_f64_u32 +#define npyv_reinterpret_f64_s32 vreinterpretq_f64_s32 +#define npyv_reinterpret_f64_u64 vreinterpretq_f64_u64 +#define npyv_reinterpret_f64_s64 vreinterpretq_f64_s64 +#define npyv_reinterpret_f64_f32 vreinterpretq_f64_f32 + +// Only required by AVX2/AVX512 +#define npyv_cleanup() ((void)0) + +#endif // _NPY_SIMD_NEON_MISC_H diff --git a/mkl_umath/src/npyv/neon/neon.h b/mkl_umath/src/npyv/neon/neon.h new file mode 100644 index 00000000..49c35c41 --- /dev/null +++ b/mkl_umath/src/npyv/neon/neon.h @@ -0,0 +1,82 @@ +#ifndef _NPY_SIMD_H_ + #error "Not a standalone header" +#endif + +#define NPY_SIMD 128 +#define NPY_SIMD_WIDTH 16 +#define NPY_SIMD_F32 1 +#ifdef __aarch64__ + #define NPY_SIMD_F64 1 +#else + #define NPY_SIMD_F64 0 +#endif +#ifdef NPY_HAVE_NEON_VFPV4 + #define NPY_SIMD_FMA3 1 // native support +#else + #define NPY_SIMD_FMA3 0 // HW emulated +#endif +#define NPY_SIMD_BIGENDIAN 0 +#define NPY_SIMD_CMPSIGNAL 1 + +typedef uint8x16_t npyv_u8; +typedef int8x16_t npyv_s8; +typedef uint16x8_t npyv_u16; +typedef int16x8_t npyv_s16; +typedef uint32x4_t npyv_u32; +typedef int32x4_t npyv_s32; +typedef uint64x2_t npyv_u64; +typedef int64x2_t npyv_s64; +typedef float32x4_t npyv_f32; +#if NPY_SIMD_F64 +typedef float64x2_t npyv_f64; +#endif + +typedef uint8x16_t npyv_b8; +typedef uint16x8_t npyv_b16; +typedef uint32x4_t npyv_b32; +typedef uint64x2_t npyv_b64; + +typedef uint8x16x2_t npyv_u8x2; +typedef int8x16x2_t npyv_s8x2; +typedef uint16x8x2_t npyv_u16x2; +typedef int16x8x2_t npyv_s16x2; +typedef uint32x4x2_t npyv_u32x2; +typedef int32x4x2_t npyv_s32x2; +typedef uint64x2x2_t npyv_u64x2; +typedef int64x2x2_t npyv_s64x2; +typedef float32x4x2_t npyv_f32x2; +#if NPY_SIMD_F64 +typedef float64x2x2_t npyv_f64x2; +#endif + +typedef uint8x16x3_t npyv_u8x3; +typedef int8x16x3_t npyv_s8x3; +typedef uint16x8x3_t npyv_u16x3; +typedef int16x8x3_t npyv_s16x3; +typedef uint32x4x3_t npyv_u32x3; +typedef int32x4x3_t npyv_s32x3; +typedef uint64x2x3_t npyv_u64x3; +typedef int64x2x3_t npyv_s64x3; +typedef float32x4x3_t npyv_f32x3; +#if NPY_SIMD_F64 +typedef float64x2x3_t npyv_f64x3; +#endif + +#define npyv_nlanes_u8 16 +#define npyv_nlanes_s8 16 +#define npyv_nlanes_u16 8 +#define npyv_nlanes_s16 8 +#define npyv_nlanes_u32 4 +#define npyv_nlanes_s32 4 +#define npyv_nlanes_u64 2 +#define npyv_nlanes_s64 2 +#define npyv_nlanes_f32 4 +#define npyv_nlanes_f64 2 + +#include "memory.h" +#include "misc.h" +#include "reorder.h" +#include "operators.h" +#include "conversion.h" +#include "arithmetic.h" +#include "math.h" diff --git a/mkl_umath/src/npyv/neon/operators.h b/mkl_umath/src/npyv/neon/operators.h new file mode 100644 index 00000000..e18ea94b --- /dev/null +++ b/mkl_umath/src/npyv/neon/operators.h @@ -0,0 +1,399 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_OPERATORS_H +#define _NPY_SIMD_NEON_OPERATORS_H + +/*************************** + * Shifting + ***************************/ + +// left +#define npyv_shl_u16(A, C) vshlq_u16(A, npyv_setall_s16(C)) +#define npyv_shl_s16(A, C) vshlq_s16(A, npyv_setall_s16(C)) +#define npyv_shl_u32(A, C) vshlq_u32(A, npyv_setall_s32(C)) +#define npyv_shl_s32(A, C) vshlq_s32(A, npyv_setall_s32(C)) +#define npyv_shl_u64(A, C) vshlq_u64(A, npyv_setall_s64(C)) +#define npyv_shl_s64(A, C) vshlq_s64(A, npyv_setall_s64(C)) + +// left by an immediate constant +#define npyv_shli_u16 vshlq_n_u16 +#define npyv_shli_s16 vshlq_n_s16 +#define npyv_shli_u32 vshlq_n_u32 +#define npyv_shli_s32 vshlq_n_s32 +#define npyv_shli_u64 vshlq_n_u64 +#define npyv_shli_s64 vshlq_n_s64 + +// right +#define npyv_shr_u16(A, C) vshlq_u16(A, npyv_setall_s16(-(C))) +#define npyv_shr_s16(A, C) vshlq_s16(A, npyv_setall_s16(-(C))) +#define npyv_shr_u32(A, C) vshlq_u32(A, npyv_setall_s32(-(C))) +#define npyv_shr_s32(A, C) vshlq_s32(A, npyv_setall_s32(-(C))) +#define npyv_shr_u64(A, C) vshlq_u64(A, npyv_setall_s64(-(C))) +#define npyv_shr_s64(A, C) vshlq_s64(A, npyv_setall_s64(-(C))) + +// right by an immediate constant +#define npyv_shri_u16 vshrq_n_u16 +#define npyv_shri_s16 vshrq_n_s16 +#define npyv_shri_u32 vshrq_n_u32 +#define npyv_shri_s32 vshrq_n_s32 +#define npyv_shri_u64 vshrq_n_u64 +#define npyv_shri_s64 vshrq_n_s64 + +/*************************** + * Logical + ***************************/ + +// AND +#define npyv_and_u8 vandq_u8 +#define npyv_and_s8 vandq_s8 +#define npyv_and_u16 vandq_u16 +#define npyv_and_s16 vandq_s16 +#define npyv_and_u32 vandq_u32 +#define npyv_and_s32 vandq_s32 +#define npyv_and_u64 vandq_u64 +#define npyv_and_s64 vandq_s64 +#define npyv_and_f32(A, B) \ + vreinterpretq_f32_u8(vandq_u8(vreinterpretq_u8_f32(A), vreinterpretq_u8_f32(B))) +#define npyv_and_f64(A, B) \ + vreinterpretq_f64_u8(vandq_u8(vreinterpretq_u8_f64(A), vreinterpretq_u8_f64(B))) +#define npyv_and_b8 vandq_u8 +#define npyv_and_b16 vandq_u16 +#define npyv_and_b32 vandq_u32 +#define npyv_and_b64 vandq_u64 + +// OR +#define npyv_or_u8 vorrq_u8 +#define npyv_or_s8 vorrq_s8 +#define npyv_or_u16 vorrq_u16 +#define npyv_or_s16 vorrq_s16 +#define npyv_or_u32 vorrq_u32 +#define npyv_or_s32 vorrq_s32 +#define npyv_or_u64 vorrq_u64 +#define npyv_or_s64 vorrq_s64 +#define npyv_or_f32(A, B) \ + vreinterpretq_f32_u8(vorrq_u8(vreinterpretq_u8_f32(A), vreinterpretq_u8_f32(B))) +#define npyv_or_f64(A, B) \ + vreinterpretq_f64_u8(vorrq_u8(vreinterpretq_u8_f64(A), vreinterpretq_u8_f64(B))) +#define npyv_or_b8 vorrq_u8 +#define npyv_or_b16 vorrq_u16 +#define npyv_or_b32 vorrq_u32 +#define npyv_or_b64 vorrq_u64 + + +// XOR +#define npyv_xor_u8 veorq_u8 +#define npyv_xor_s8 veorq_s8 +#define npyv_xor_u16 veorq_u16 +#define npyv_xor_s16 veorq_s16 +#define npyv_xor_u32 veorq_u32 +#define npyv_xor_s32 veorq_s32 +#define npyv_xor_u64 veorq_u64 +#define npyv_xor_s64 veorq_s64 +#define npyv_xor_f32(A, B) \ + vreinterpretq_f32_u8(veorq_u8(vreinterpretq_u8_f32(A), vreinterpretq_u8_f32(B))) +#define npyv_xor_f64(A, B) \ + vreinterpretq_f64_u8(veorq_u8(vreinterpretq_u8_f64(A), vreinterpretq_u8_f64(B))) +#define npyv_xor_b8 veorq_u8 +#define npyv_xor_b16 veorq_u16 +#define npyv_xor_b32 veorq_u32 +#define npyv_xor_b64 veorq_u64 + +// NOT +#define npyv_not_u8 vmvnq_u8 +#define npyv_not_s8 vmvnq_s8 +#define npyv_not_u16 vmvnq_u16 +#define npyv_not_s16 vmvnq_s16 +#define npyv_not_u32 vmvnq_u32 +#define npyv_not_s32 vmvnq_s32 +#define npyv_not_u64(A) vreinterpretq_u64_u8(vmvnq_u8(vreinterpretq_u8_u64(A))) +#define npyv_not_s64(A) vreinterpretq_s64_u8(vmvnq_u8(vreinterpretq_u8_s64(A))) +#define npyv_not_f32(A) vreinterpretq_f32_u8(vmvnq_u8(vreinterpretq_u8_f32(A))) +#define npyv_not_f64(A) vreinterpretq_f64_u8(vmvnq_u8(vreinterpretq_u8_f64(A))) +#define npyv_not_b8 vmvnq_u8 +#define npyv_not_b16 vmvnq_u16 +#define npyv_not_b32 vmvnq_u32 +#define npyv_not_b64 npyv_not_u64 + +// ANDC, ORC and XNOR +#define npyv_andc_u8 vbicq_u8 +#define npyv_andc_b8 vbicq_u8 +#define npyv_orc_b8 vornq_u8 +#define npyv_xnor_b8 vceqq_u8 + +/*************************** + * Comparison + ***************************/ + +// equal +#define npyv_cmpeq_u8 vceqq_u8 +#define npyv_cmpeq_s8 vceqq_s8 +#define npyv_cmpeq_u16 vceqq_u16 +#define npyv_cmpeq_s16 vceqq_s16 +#define npyv_cmpeq_u32 vceqq_u32 +#define npyv_cmpeq_s32 vceqq_s32 +#define npyv_cmpeq_f32 vceqq_f32 +#define npyv_cmpeq_f64 vceqq_f64 + +#ifdef __aarch64__ + #define npyv_cmpeq_u64 vceqq_u64 + #define npyv_cmpeq_s64 vceqq_s64 +#else + NPY_FINLINE uint64x2_t npyv_cmpeq_u64(uint64x2_t a, uint64x2_t b) + { + uint64x2_t cmpeq = vreinterpretq_u64_u32(vceqq_u32( + vreinterpretq_u32_u64(a), vreinterpretq_u32_u64(b) + )); + uint64x2_t cmpeq_h = vshlq_n_u64(cmpeq, 32); + uint64x2_t test = vandq_u64(cmpeq, cmpeq_h); + return vreinterpretq_u64_s64(vshrq_n_s64(vreinterpretq_s64_u64(test), 32)); + } + #define npyv_cmpeq_s64(A, B) \ + npyv_cmpeq_u64(vreinterpretq_u64_s64(A), vreinterpretq_u64_s64(B)) +#endif + +// not Equal +#define npyv_cmpneq_u8(A, B) vmvnq_u8(vceqq_u8(A, B)) +#define npyv_cmpneq_s8(A, B) vmvnq_u8(vceqq_s8(A, B)) +#define npyv_cmpneq_u16(A, B) vmvnq_u16(vceqq_u16(A, B)) +#define npyv_cmpneq_s16(A, B) vmvnq_u16(vceqq_s16(A, B)) +#define npyv_cmpneq_u32(A, B) vmvnq_u32(vceqq_u32(A, B)) +#define npyv_cmpneq_s32(A, B) vmvnq_u32(vceqq_s32(A, B)) +#define npyv_cmpneq_u64(A, B) npyv_not_u64(npyv_cmpeq_u64(A, B)) +#define npyv_cmpneq_s64(A, B) npyv_not_u64(npyv_cmpeq_s64(A, B)) +#define npyv_cmpneq_f32(A, B) vmvnq_u32(vceqq_f32(A, B)) +#define npyv_cmpneq_f64(A, B) npyv_not_u64(vceqq_f64(A, B)) + +// greater than +#define npyv_cmpgt_u8 vcgtq_u8 +#define npyv_cmpgt_s8 vcgtq_s8 +#define npyv_cmpgt_u16 vcgtq_u16 +#define npyv_cmpgt_s16 vcgtq_s16 +#define npyv_cmpgt_u32 vcgtq_u32 +#define npyv_cmpgt_s32 vcgtq_s32 +#define npyv_cmpgt_f32 vcgtq_f32 +#define npyv_cmpgt_f64 vcgtq_f64 + +#ifdef __aarch64__ + #define npyv_cmpgt_u64 vcgtq_u64 + #define npyv_cmpgt_s64 vcgtq_s64 +#else + NPY_FINLINE uint64x2_t npyv_cmpgt_s64(int64x2_t a, int64x2_t b) + { + int64x2_t sub = vsubq_s64(b, a); + uint64x2_t nsame_sbit = vreinterpretq_u64_s64(veorq_s64(a, b)); + int64x2_t test = vbslq_s64(nsame_sbit, b, sub); + int64x2_t extend_sbit = vshrq_n_s64(test, 63); + return vreinterpretq_u64_s64(extend_sbit); + } + NPY_FINLINE uint64x2_t npyv_cmpgt_u64(uint64x2_t a, uint64x2_t b) + { + const uint64x2_t sbit = npyv_setall_u64(0x8000000000000000); + a = npyv_xor_u64(a, sbit); + b = npyv_xor_u64(b, sbit); + return npyv_cmpgt_s64(vreinterpretq_s64_u64(a), vreinterpretq_s64_u64(b)); + } +#endif + +// greater than or equal +#define npyv_cmpge_u8 vcgeq_u8 +#define npyv_cmpge_s8 vcgeq_s8 +#define npyv_cmpge_u16 vcgeq_u16 +#define npyv_cmpge_s16 vcgeq_s16 +#define npyv_cmpge_u32 vcgeq_u32 +#define npyv_cmpge_s32 vcgeq_s32 +#define npyv_cmpge_f32 vcgeq_f32 +#define npyv_cmpge_f64 vcgeq_f64 + +#ifdef __aarch64__ + #define npyv_cmpge_u64 vcgeq_u64 + #define npyv_cmpge_s64 vcgeq_s64 +#else + #define npyv_cmpge_u64(A, B) npyv_not_u64(npyv_cmpgt_u64(B, A)) + #define npyv_cmpge_s64(A, B) npyv_not_u64(npyv_cmpgt_s64(B, A)) +#endif + +// less than +#define npyv_cmplt_u8(A, B) npyv_cmpgt_u8(B, A) +#define npyv_cmplt_s8(A, B) npyv_cmpgt_s8(B, A) +#define npyv_cmplt_u16(A, B) npyv_cmpgt_u16(B, A) +#define npyv_cmplt_s16(A, B) npyv_cmpgt_s16(B, A) +#define npyv_cmplt_u32(A, B) npyv_cmpgt_u32(B, A) +#define npyv_cmplt_s32(A, B) npyv_cmpgt_s32(B, A) +#define npyv_cmplt_u64(A, B) npyv_cmpgt_u64(B, A) +#define npyv_cmplt_s64(A, B) npyv_cmpgt_s64(B, A) +#define npyv_cmplt_f32(A, B) npyv_cmpgt_f32(B, A) +#define npyv_cmplt_f64(A, B) npyv_cmpgt_f64(B, A) + +// less than or equal +#define npyv_cmple_u8(A, B) npyv_cmpge_u8(B, A) +#define npyv_cmple_s8(A, B) npyv_cmpge_s8(B, A) +#define npyv_cmple_u16(A, B) npyv_cmpge_u16(B, A) +#define npyv_cmple_s16(A, B) npyv_cmpge_s16(B, A) +#define npyv_cmple_u32(A, B) npyv_cmpge_u32(B, A) +#define npyv_cmple_s32(A, B) npyv_cmpge_s32(B, A) +#define npyv_cmple_u64(A, B) npyv_cmpge_u64(B, A) +#define npyv_cmple_s64(A, B) npyv_cmpge_s64(B, A) +#define npyv_cmple_f32(A, B) npyv_cmpge_f32(B, A) +#define npyv_cmple_f64(A, B) npyv_cmpge_f64(B, A) + +// check special cases +NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a) +{ +#if defined(__clang__) +/** + * To avoid signaling qNaN, workaround for clang symmetric inputs bug + * check https://github.com/numpy/numpy/issues/22933, + * for more clarification. + */ + npyv_b32 ret; + #if NPY_SIMD_F64 + __asm("fcmeq %0.4s, %1.4s, %1.4s" : "=w" (ret) : "w" (a)); + #else + __asm("vceq.f32 %q0, %q1, %q1" : "=w" (ret) : "w" (a)); + #endif + return ret; +#else + return vceqq_f32(a, a); +#endif +} +#if NPY_SIMD_F64 + NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a) + { + #if defined(__clang__) + npyv_b64 ret; + __asm("fcmeq %0.2d, %1.2d, %1.2d" : "=w" (ret) : "w" (a)); + return ret; + #else + return vceqq_f64(a, a); + #endif + } +#endif + +// Test cross all vector lanes +// any: returns true if any of the elements is not equal to zero +// all: returns true if all elements are not equal to zero +#if NPY_SIMD_F64 + #define NPYV_IMPL_NEON_ANYALL(LEN) \ + NPY_FINLINE bool npyv_any_b##LEN(npyv_b##LEN a) \ + { return vmaxvq_u##LEN(a) != 0; } \ + NPY_FINLINE bool npyv_all_b##LEN(npyv_b##LEN a) \ + { return vminvq_u##LEN(a) != 0; } + NPYV_IMPL_NEON_ANYALL(8) + NPYV_IMPL_NEON_ANYALL(16) + NPYV_IMPL_NEON_ANYALL(32) + #undef NPYV_IMPL_NEON_ANYALL + + #define NPYV_IMPL_NEON_ANYALL(SFX, USFX, BSFX) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { return npyv_any_##BSFX(npyv_reinterpret_##USFX##_##SFX(a)); } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { return npyv_all_##BSFX(npyv_reinterpret_##USFX##_##SFX(a)); } + NPYV_IMPL_NEON_ANYALL(u8, u8, b8) + NPYV_IMPL_NEON_ANYALL(s8, u8, b8) + NPYV_IMPL_NEON_ANYALL(u16, u16, b16) + NPYV_IMPL_NEON_ANYALL(s16, u16, b16) + NPYV_IMPL_NEON_ANYALL(u32, u32, b32) + NPYV_IMPL_NEON_ANYALL(s32, u32, b32) + #undef NPYV_IMPL_NEON_ANYALL + + NPY_FINLINE bool npyv_any_b64(npyv_b64 a) + { return vmaxvq_u32(vreinterpretq_u32_u64(a)) != 0; } + NPY_FINLINE bool npyv_all_b64(npyv_b64 a) + { return vminvq_u32(vreinterpretq_u32_u64(a)) != 0; } + #define npyv_any_u64 npyv_any_b64 + NPY_FINLINE bool npyv_all_u64(npyv_u64 a) + { + uint32x4_t a32 = vreinterpretq_u32_u64(a); + a32 = vorrq_u32(a32, vrev64q_u32(a32)); + return vminvq_u32(a32) != 0; + } + NPY_FINLINE bool npyv_any_s64(npyv_s64 a) + { return npyv_any_u64(vreinterpretq_u64_s64(a)); } + NPY_FINLINE bool npyv_all_s64(npyv_s64 a) + { return npyv_all_u64(vreinterpretq_u64_s64(a)); } + + #define NPYV_IMPL_NEON_ANYALL(SFX, BSFX) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { return !npyv_all_##BSFX(npyv_cmpeq_##SFX(a, npyv_zero_##SFX())); } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { return !npyv_any_##BSFX(npyv_cmpeq_##SFX(a, npyv_zero_##SFX())); } + NPYV_IMPL_NEON_ANYALL(f32, b32) + NPYV_IMPL_NEON_ANYALL(f64, b64) + #undef NPYV_IMPL_NEON_ANYALL +#else + #define NPYV_IMPL_NEON_ANYALL(LEN) \ + NPY_FINLINE bool npyv_any_b##LEN(npyv_b##LEN a) \ + { \ + int64x2_t a64 = vreinterpretq_s64_u##LEN(a); \ + return ( \ + vgetq_lane_s64(a64, 0) | \ + vgetq_lane_s64(a64, 1) \ + ) != 0; \ + } \ + NPY_FINLINE bool npyv_all_b##LEN(npyv_b##LEN a) \ + { \ + int64x2_t a64 = vreinterpretq_s64_u##LEN(a); \ + return ( \ + vgetq_lane_s64(a64, 0) & \ + vgetq_lane_s64(a64, 1) \ + ) == -1; \ + } + NPYV_IMPL_NEON_ANYALL(8) + NPYV_IMPL_NEON_ANYALL(16) + NPYV_IMPL_NEON_ANYALL(32) + NPYV_IMPL_NEON_ANYALL(64) + #undef NPYV_IMPL_NEON_ANYALL + + #define NPYV_IMPL_NEON_ANYALL(SFX, USFX) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { \ + int64x2_t a64 = vreinterpretq_s64_##SFX(a); \ + return ( \ + vgetq_lane_s64(a64, 0) | \ + vgetq_lane_s64(a64, 1) \ + ) != 0; \ + } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { \ + npyv_##USFX tz = npyv_cmpeq_##SFX( \ + a, npyv_zero_##SFX() \ + ); \ + int64x2_t a64 = vreinterpretq_s64_##USFX(tz); \ + return ( \ + vgetq_lane_s64(a64, 0) | \ + vgetq_lane_s64(a64, 1) \ + ) == 0; \ + } + NPYV_IMPL_NEON_ANYALL(u8, u8) + NPYV_IMPL_NEON_ANYALL(s8, u8) + NPYV_IMPL_NEON_ANYALL(u16, u16) + NPYV_IMPL_NEON_ANYALL(s16, u16) + NPYV_IMPL_NEON_ANYALL(u32, u32) + NPYV_IMPL_NEON_ANYALL(s32, u32) + #undef NPYV_IMPL_NEON_ANYALL + + NPY_FINLINE bool npyv_any_f32(npyv_f32 a) + { + uint32x4_t tz = npyv_cmpeq_f32(a, npyv_zero_f32()); + int64x2_t a64 = vreinterpretq_s64_u32(tz); + return (vgetq_lane_s64(a64, 0) & vgetq_lane_s64(a64, 1)) != -1ll; + } + NPY_FINLINE bool npyv_all_f32(npyv_f32 a) + { + uint32x4_t tz = npyv_cmpeq_f32(a, npyv_zero_f32()); + int64x2_t a64 = vreinterpretq_s64_u32(tz); + return (vgetq_lane_s64(a64, 0) | vgetq_lane_s64(a64, 1)) == 0; + } + NPY_FINLINE bool npyv_any_s64(npyv_s64 a) + { return (vgetq_lane_s64(a, 0) | vgetq_lane_s64(a, 1)) != 0; } + NPY_FINLINE bool npyv_all_s64(npyv_s64 a) + { return vgetq_lane_s64(a, 0) && vgetq_lane_s64(a, 1); } + NPY_FINLINE bool npyv_any_u64(npyv_u64 a) + { return (vgetq_lane_u64(a, 0) | vgetq_lane_u64(a, 1)) != 0; } + NPY_FINLINE bool npyv_all_u64(npyv_u64 a) + { return vgetq_lane_u64(a, 0) && vgetq_lane_u64(a, 1); } +#endif // NPY_SIMD_F64 + +#endif // _NPY_SIMD_NEON_OPERATORS_H diff --git a/mkl_umath/src/npyv/neon/reorder.h b/mkl_umath/src/npyv/neon/reorder.h new file mode 100644 index 00000000..8bf68f5b --- /dev/null +++ b/mkl_umath/src/npyv/neon/reorder.h @@ -0,0 +1,189 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_NEON_REORDER_H +#define _NPY_SIMD_NEON_REORDER_H + +// combine lower part of two vectors +#ifdef __aarch64__ + #define npyv_combinel_u8(A, B) vreinterpretq_u8_u64(vzip1q_u64(vreinterpretq_u64_u8(A), vreinterpretq_u64_u8(B))) + #define npyv_combinel_s8(A, B) vreinterpretq_s8_u64(vzip1q_u64(vreinterpretq_u64_s8(A), vreinterpretq_u64_s8(B))) + #define npyv_combinel_u16(A, B) vreinterpretq_u16_u64(vzip1q_u64(vreinterpretq_u64_u16(A), vreinterpretq_u64_u16(B))) + #define npyv_combinel_s16(A, B) vreinterpretq_s16_u64(vzip1q_u64(vreinterpretq_u64_s16(A), vreinterpretq_u64_s16(B))) + #define npyv_combinel_u32(A, B) vreinterpretq_u32_u64(vzip1q_u64(vreinterpretq_u64_u32(A), vreinterpretq_u64_u32(B))) + #define npyv_combinel_s32(A, B) vreinterpretq_s32_u64(vzip1q_u64(vreinterpretq_u64_s32(A), vreinterpretq_u64_s32(B))) + #define npyv_combinel_u64 vzip1q_u64 + #define npyv_combinel_s64 vzip1q_s64 + #define npyv_combinel_f32(A, B) vreinterpretq_f32_u64(vzip1q_u64(vreinterpretq_u64_f32(A), vreinterpretq_u64_f32(B))) + #define npyv_combinel_f64 vzip1q_f64 +#else + #define npyv_combinel_u8(A, B) vcombine_u8(vget_low_u8(A), vget_low_u8(B)) + #define npyv_combinel_s8(A, B) vcombine_s8(vget_low_s8(A), vget_low_s8(B)) + #define npyv_combinel_u16(A, B) vcombine_u16(vget_low_u16(A), vget_low_u16(B)) + #define npyv_combinel_s16(A, B) vcombine_s16(vget_low_s16(A), vget_low_s16(B)) + #define npyv_combinel_u32(A, B) vcombine_u32(vget_low_u32(A), vget_low_u32(B)) + #define npyv_combinel_s32(A, B) vcombine_s32(vget_low_s32(A), vget_low_s32(B)) + #define npyv_combinel_u64(A, B) vcombine_u64(vget_low_u64(A), vget_low_u64(B)) + #define npyv_combinel_s64(A, B) vcombine_s64(vget_low_s64(A), vget_low_s64(B)) + #define npyv_combinel_f32(A, B) vcombine_f32(vget_low_f32(A), vget_low_f32(B)) +#endif + +// combine higher part of two vectors +#ifdef __aarch64__ + #define npyv_combineh_u8(A, B) vreinterpretq_u8_u64(vzip2q_u64(vreinterpretq_u64_u8(A), vreinterpretq_u64_u8(B))) + #define npyv_combineh_s8(A, B) vreinterpretq_s8_u64(vzip2q_u64(vreinterpretq_u64_s8(A), vreinterpretq_u64_s8(B))) + #define npyv_combineh_u16(A, B) vreinterpretq_u16_u64(vzip2q_u64(vreinterpretq_u64_u16(A), vreinterpretq_u64_u16(B))) + #define npyv_combineh_s16(A, B) vreinterpretq_s16_u64(vzip2q_u64(vreinterpretq_u64_s16(A), vreinterpretq_u64_s16(B))) + #define npyv_combineh_u32(A, B) vreinterpretq_u32_u64(vzip2q_u64(vreinterpretq_u64_u32(A), vreinterpretq_u64_u32(B))) + #define npyv_combineh_s32(A, B) vreinterpretq_s32_u64(vzip2q_u64(vreinterpretq_u64_s32(A), vreinterpretq_u64_s32(B))) + #define npyv_combineh_u64 vzip2q_u64 + #define npyv_combineh_s64 vzip2q_s64 + #define npyv_combineh_f32(A, B) vreinterpretq_f32_u64(vzip2q_u64(vreinterpretq_u64_f32(A), vreinterpretq_u64_f32(B))) + #define npyv_combineh_f64 vzip2q_f64 +#else + #define npyv_combineh_u8(A, B) vcombine_u8(vget_high_u8(A), vget_high_u8(B)) + #define npyv_combineh_s8(A, B) vcombine_s8(vget_high_s8(A), vget_high_s8(B)) + #define npyv_combineh_u16(A, B) vcombine_u16(vget_high_u16(A), vget_high_u16(B)) + #define npyv_combineh_s16(A, B) vcombine_s16(vget_high_s16(A), vget_high_s16(B)) + #define npyv_combineh_u32(A, B) vcombine_u32(vget_high_u32(A), vget_high_u32(B)) + #define npyv_combineh_s32(A, B) vcombine_s32(vget_high_s32(A), vget_high_s32(B)) + #define npyv_combineh_u64(A, B) vcombine_u64(vget_high_u64(A), vget_high_u64(B)) + #define npyv_combineh_s64(A, B) vcombine_s64(vget_high_s64(A), vget_high_s64(B)) + #define npyv_combineh_f32(A, B) vcombine_f32(vget_high_f32(A), vget_high_f32(B)) +#endif + +// combine two vectors from lower and higher parts of two other vectors +#define NPYV_IMPL_NEON_COMBINE(T_VEC, SFX) \ + NPY_FINLINE T_VEC##x2 npyv_combine_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC##x2 r; \ + r.val[0] = NPY_CAT(npyv_combinel_, SFX)(a, b); \ + r.val[1] = NPY_CAT(npyv_combineh_, SFX)(a, b); \ + return r; \ + } + +NPYV_IMPL_NEON_COMBINE(npyv_u8, u8) +NPYV_IMPL_NEON_COMBINE(npyv_s8, s8) +NPYV_IMPL_NEON_COMBINE(npyv_u16, u16) +NPYV_IMPL_NEON_COMBINE(npyv_s16, s16) +NPYV_IMPL_NEON_COMBINE(npyv_u32, u32) +NPYV_IMPL_NEON_COMBINE(npyv_s32, s32) +NPYV_IMPL_NEON_COMBINE(npyv_u64, u64) +NPYV_IMPL_NEON_COMBINE(npyv_s64, s64) +NPYV_IMPL_NEON_COMBINE(npyv_f32, f32) +#ifdef __aarch64__ +NPYV_IMPL_NEON_COMBINE(npyv_f64, f64) +#endif + +// interleave & deinterleave two vectors +#ifdef __aarch64__ + #define NPYV_IMPL_NEON_ZIP(T_VEC, SFX) \ + NPY_FINLINE T_VEC##x2 npyv_zip_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC##x2 r; \ + r.val[0] = vzip1q_##SFX(a, b); \ + r.val[1] = vzip2q_##SFX(a, b); \ + return r; \ + } \ + NPY_FINLINE T_VEC##x2 npyv_unzip_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC##x2 r; \ + r.val[0] = vuzp1q_##SFX(a, b); \ + r.val[1] = vuzp2q_##SFX(a, b); \ + return r; \ + } +#else + #define NPYV_IMPL_NEON_ZIP(T_VEC, SFX) \ + NPY_FINLINE T_VEC##x2 npyv_zip_##SFX(T_VEC a, T_VEC b) \ + { return vzipq_##SFX(a, b); } \ + NPY_FINLINE T_VEC##x2 npyv_unzip_##SFX(T_VEC a, T_VEC b) \ + { return vuzpq_##SFX(a, b); } +#endif + +NPYV_IMPL_NEON_ZIP(npyv_u8, u8) +NPYV_IMPL_NEON_ZIP(npyv_s8, s8) +NPYV_IMPL_NEON_ZIP(npyv_u16, u16) +NPYV_IMPL_NEON_ZIP(npyv_s16, s16) +NPYV_IMPL_NEON_ZIP(npyv_u32, u32) +NPYV_IMPL_NEON_ZIP(npyv_s32, s32) +NPYV_IMPL_NEON_ZIP(npyv_f32, f32) + +#define npyv_zip_u64 npyv_combine_u64 +#define npyv_zip_s64 npyv_combine_s64 +#define npyv_zip_f64 npyv_combine_f64 +#define npyv_unzip_u64 npyv_combine_u64 +#define npyv_unzip_s64 npyv_combine_s64 +#define npyv_unzip_f64 npyv_combine_f64 + +// Reverse elements of each 64-bit lane +#define npyv_rev64_u8 vrev64q_u8 +#define npyv_rev64_s8 vrev64q_s8 +#define npyv_rev64_u16 vrev64q_u16 +#define npyv_rev64_s16 vrev64q_s16 +#define npyv_rev64_u32 vrev64q_u32 +#define npyv_rev64_s32 vrev64q_s32 +#define npyv_rev64_f32 vrev64q_f32 + +// Permuting the elements of each 128-bit lane by immediate index for +// each element. +#ifdef __clang__ + #define npyv_permi128_u32(A, E0, E1, E2, E3) \ + __builtin_shufflevector(A, A, E0, E1, E2, E3) +#elif defined(__GNUC__) + #define npyv_permi128_u32(A, E0, E1, E2, E3) \ + __builtin_shuffle(A, npyv_set_u32(E0, E1, E2, E3)) +#else + #define npyv_permi128_u32(A, E0, E1, E2, E3) \ + npyv_set_u32( \ + vgetq_lane_u32(A, E0), vgetq_lane_u32(A, E1), \ + vgetq_lane_u32(A, E2), vgetq_lane_u32(A, E3) \ + ) + #define npyv_permi128_s32(A, E0, E1, E2, E3) \ + npyv_set_s32( \ + vgetq_lane_s32(A, E0), vgetq_lane_s32(A, E1), \ + vgetq_lane_s32(A, E2), vgetq_lane_s32(A, E3) \ + ) + #define npyv_permi128_f32(A, E0, E1, E2, E3) \ + npyv_set_f32( \ + vgetq_lane_f32(A, E0), vgetq_lane_f32(A, E1), \ + vgetq_lane_f32(A, E2), vgetq_lane_f32(A, E3) \ + ) +#endif + +#if defined(__clang__) || defined(__GNUC__) + #define npyv_permi128_s32 npyv_permi128_u32 + #define npyv_permi128_f32 npyv_permi128_u32 +#endif + +#ifdef __clang__ + #define npyv_permi128_u64(A, E0, E1) \ + __builtin_shufflevector(A, A, E0, E1) +#elif defined(__GNUC__) + #define npyv_permi128_u64(A, E0, E1) \ + __builtin_shuffle(A, npyv_set_u64(E0, E1)) +#else + #define npyv_permi128_u64(A, E0, E1) \ + npyv_set_u64( \ + vgetq_lane_u64(A, E0), vgetq_lane_u64(A, E1) \ + ) + #define npyv_permi128_s64(A, E0, E1) \ + npyv_set_s64( \ + vgetq_lane_s64(A, E0), vgetq_lane_s64(A, E1) \ + ) + #define npyv_permi128_f64(A, E0, E1) \ + npyv_set_f64( \ + vgetq_lane_f64(A, E0), vgetq_lane_f64(A, E1) \ + ) +#endif + +#if defined(__clang__) || defined(__GNUC__) + #define npyv_permi128_s64 npyv_permi128_u64 + #define npyv_permi128_f64 npyv_permi128_u64 +#endif + +#if !NPY_SIMD_F64 + #undef npyv_permi128_f64 +#endif + +#endif // _NPY_SIMD_NEON_REORDER_H diff --git a/mkl_umath/src/npyv/npy_argparse.h b/mkl_umath/src/npyv/npy_argparse.h new file mode 100644 index 00000000..f4122103 --- /dev/null +++ b/mkl_umath/src/npyv/npy_argparse.h @@ -0,0 +1,96 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_ARGPARSE_H +#define NUMPY_CORE_SRC_COMMON_NPY_ARGPARSE_H + +#include +#include "numpy/ndarraytypes.h" + +/* + * This file defines macros to help with keyword argument parsing. + * This solves two issues as of now: + * 1. Pythons C-API PyArg_* keyword argument parsers are slow, due to + * not caching the strings they use. + * 2. It allows the use of METH_ARGPARSE (and `tp_vectorcall`) + * when available in Python, which removes a large chunk of overhead. + * + * Internally CPython achieves similar things by using a code generator + * argument clinic. NumPy may well decide to use argument clinic or a different + * solution in the future. + */ + +NPY_NO_EXPORT int +PyArray_PythonPyIntFromInt(PyObject *obj, int *value); + + +#define _NPY_MAX_KWARGS 15 + +typedef struct { + int npositional; + int nargs; + int npositional_only; + int nrequired; + /* Null terminated list of keyword argument name strings */ + PyObject *kw_strings[_NPY_MAX_KWARGS+1]; +} _NpyArgParserCache; + + +/* + * The sole purpose of this macro is to hide the argument parsing cache. + * Since this cache must be static, this also removes a source of error. + */ +#define NPY_PREPARE_ARGPARSER static _NpyArgParserCache __argparse_cache = {-1} + +/** + * Macro to help with argument parsing. + * + * The pattern for using this macro is by defining the method as: + * + * @code + * static PyObject * + * my_method(PyObject *self, + * PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames) + * { + * NPY_PREPARE_ARGPARSER; + * + * PyObject *argument1, *argument3; + * int argument2 = -1; + * if (npy_parse_arguments("method", args, len_args, kwnames), + * "argument1", NULL, &argument1, + * "|argument2", &PyArray_PythonPyIntFromInt, &argument2, + * "$argument3", NULL, &argument3, + * NULL, NULL, NULL) < 0) { + * return NULL; + * } + * } + * @endcode + * + * The `NPY_PREPARE_ARGPARSER` macro sets up a static cache variable necessary + * to hold data for speeding up the parsing. `npy_parse_arguments` must be + * used in cunjunction with the macro defined in the same scope. + * (No two `npy_parse_arguments` may share a single `NPY_PREPARE_ARGPARSER`.) + * + * @param funcname + * @param args Python passed args (METH_FASTCALL) + * @param len_args Number of arguments (not flagged) + * @param kwnames Tuple as passed by METH_FASTCALL or NULL. + * @param ... List of arguments must be param1_name, param1_converter, + * *param1_outvalue, param2_name, ..., NULL, NULL, NULL. + * Where name is ``char *``, ``converter`` a python converter + * function or NULL and ``outvalue`` is the ``void *`` passed to + * the converter (holding the converted data or a borrowed + * reference if converter is NULL). + * + * @return Returns 0 on success and -1 on failure. + */ +NPY_NO_EXPORT int +_npy_parse_arguments(const char *funcname, + /* cache_ptr is a NULL initialized persistent storage for data */ + _NpyArgParserCache *cache_ptr, + PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames, + /* va_list is NULL, NULL, NULL terminated: name, converter, value */ + ...) NPY_GCC_NONNULL(1); + +#define npy_parse_arguments(funcname, args, len_args, kwnames, ...) \ + _npy_parse_arguments(funcname, &__argparse_cache, \ + args, len_args, kwnames, __VA_ARGS__) + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_ARGPARSE_H */ diff --git a/mkl_umath/src/npyv/npy_binsearch.h b/mkl_umath/src/npyv/npy_binsearch.h new file mode 100644 index 00000000..8d2f0714 --- /dev/null +++ b/mkl_umath/src/npyv/npy_binsearch.h @@ -0,0 +1,31 @@ +#ifndef __NPY_BINSEARCH_H__ +#define __NPY_BINSEARCH_H__ + +#include "npy_sort.h" +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (PyArray_BinSearchFunc)(const char*, const char*, char*, + npy_intp, npy_intp, + npy_intp, npy_intp, npy_intp, + PyArrayObject*); + +typedef int (PyArray_ArgBinSearchFunc)(const char*, const char*, + const char*, char*, + npy_intp, npy_intp, npy_intp, + npy_intp, npy_intp, npy_intp, + PyArrayObject*); + +NPY_NO_EXPORT PyArray_BinSearchFunc* get_binsearch_func(PyArray_Descr *dtype, NPY_SEARCHSIDE side); +NPY_NO_EXPORT PyArray_ArgBinSearchFunc* get_argbinsearch_func(PyArray_Descr *dtype, NPY_SEARCHSIDE side); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mkl_umath/src/npyv/npy_cblas.h b/mkl_umath/src/npyv/npy_cblas.h new file mode 100644 index 00000000..596a7c68 --- /dev/null +++ b/mkl_umath/src/npyv/npy_cblas.h @@ -0,0 +1,129 @@ +/* + * This header provides numpy a consistent interface to CBLAS code. It is needed + * because not all providers of cblas provide cblas.h. For instance, MKL provides + * mkl_cblas.h and also typedefs the CBLAS_XXX enums. + */ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CBLAS_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CBLAS_H_ + +#include + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * Enumerated and derived types + */ +enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; +enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; +enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; +enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; +enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; + +#define CBLAS_INDEX size_t /* this may vary between platforms */ + +#ifdef ACCELERATE_NEW_LAPACK + #if __MAC_OS_X_VERSION_MAX_ALLOWED < 130300 + #ifdef HAVE_BLAS_ILP64 + #error "Accelerate ILP64 support is only available with macOS 13.3 SDK or later" + #endif + #else + #define NO_APPEND_FORTRAN + #ifdef HAVE_BLAS_ILP64 + #define BLAS_SYMBOL_SUFFIX $NEWLAPACK$ILP64 + #else + #define BLAS_SYMBOL_SUFFIX $NEWLAPACK + #endif + #endif +#endif + +#ifdef NO_APPEND_FORTRAN +#define BLAS_FORTRAN_SUFFIX +#else +#define BLAS_FORTRAN_SUFFIX _ +#endif + +#ifndef BLAS_SYMBOL_PREFIX +#define BLAS_SYMBOL_PREFIX +#endif + +#ifndef BLAS_SYMBOL_SUFFIX +#define BLAS_SYMBOL_SUFFIX +#endif + +#define BLAS_FUNC_CONCAT(name,prefix,suffix,suffix2) prefix ## name ## suffix ## suffix2 +#define BLAS_FUNC_EXPAND(name,prefix,suffix,suffix2) BLAS_FUNC_CONCAT(name,prefix,suffix,suffix2) + +/* + * Use either the OpenBLAS scheme with the `64_` suffix behind the Fortran + * compiler symbol mangling, or the MKL scheme (and upcoming + * reference-lapack#666) which does it the other way around and uses `_64`. + */ +#ifdef OPENBLAS_ILP64_NAMING_SCHEME +#define BLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,BLAS_FORTRAN_SUFFIX,BLAS_SYMBOL_SUFFIX) +#else +#define BLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,BLAS_SYMBOL_SUFFIX,BLAS_FORTRAN_SUFFIX) +#endif +/* + * Note that CBLAS doesn't include Fortran compiler symbol mangling, so ends up + * being the same in both schemes + */ +#define CBLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,,BLAS_SYMBOL_SUFFIX) + +#ifdef HAVE_BLAS_ILP64 +#define CBLAS_INT npy_int64 +#define CBLAS_INT_MAX NPY_MAX_INT64 +#else +#define CBLAS_INT int +#define CBLAS_INT_MAX INT_MAX +#endif + +#define BLASNAME(name) CBLAS_FUNC(name) +#define BLASINT CBLAS_INT + +#include "npy_cblas_base.h" + +#undef BLASINT +#undef BLASNAME + + +/* + * Convert NumPy stride to BLAS stride. Returns 0 if conversion cannot be done + * (BLAS won't handle negative or zero strides the way we want). + */ +static inline CBLAS_INT +blas_stride(npy_intp stride, unsigned itemsize) +{ + /* + * Should probably check pointer alignment also, but this may cause + * problems if we require complex to be 16 byte aligned. + */ + if (stride > 0 && (stride % itemsize) == 0) { + stride /= itemsize; + if (stride <= CBLAS_INT_MAX) { + return stride; + } + } + return 0; +} + +/* + * Define a chunksize for CBLAS. + * + * The chunksize is the greatest power of two less than CBLAS_INT_MAX. + */ +#if NPY_MAX_INTP > CBLAS_INT_MAX +# define NPY_CBLAS_CHUNK (CBLAS_INT_MAX / 2 + 1) +#else +# define NPY_CBLAS_CHUNK NPY_MAX_INTP +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_CBLAS_H_ */ diff --git a/mkl_umath/src/npyv/npy_cblas_base.h b/mkl_umath/src/npyv/npy_cblas_base.h new file mode 100644 index 00000000..12dfb2e7 --- /dev/null +++ b/mkl_umath/src/npyv/npy_cblas_base.h @@ -0,0 +1,562 @@ +/* + * This header provides numpy a consistent interface to CBLAS code. It is needed + * because not all providers of cblas provide cblas.h. For instance, MKL provides + * mkl_cblas.h and also typedefs the CBLAS_XXX enums. + */ + +/* + * =========================================================================== + * Prototypes for level 1 BLAS functions (complex are recast as routines) + * =========================================================================== + */ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CBLAS_BASE_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CBLAS_BASE_H_ + +float BLASNAME(cblas_sdsdot)(const BLASINT N, const float alpha, const float *X, + const BLASINT incX, const float *Y, const BLASINT incY); +double BLASNAME(cblas_dsdot)(const BLASINT N, const float *X, const BLASINT incX, const float *Y, + const BLASINT incY); +float BLASNAME(cblas_sdot)(const BLASINT N, const float *X, const BLASINT incX, + const float *Y, const BLASINT incY); +double BLASNAME(cblas_ddot)(const BLASINT N, const double *X, const BLASINT incX, + const double *Y, const BLASINT incY); + +/* + * Functions having prefixes Z and C only + */ +void BLASNAME(cblas_cdotu_sub)(const BLASINT N, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *dotu); +void BLASNAME(cblas_cdotc_sub)(const BLASINT N, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *dotc); + +void BLASNAME(cblas_zdotu_sub)(const BLASINT N, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *dotu); +void BLASNAME(cblas_zdotc_sub)(const BLASINT N, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *dotc); + + +/* + * Functions having prefixes S D SC DZ + */ +float BLASNAME(cblas_snrm2)(const BLASINT N, const float *X, const BLASINT incX); +float BLASNAME(cblas_sasum)(const BLASINT N, const float *X, const BLASINT incX); + +double BLASNAME(cblas_dnrm2)(const BLASINT N, const double *X, const BLASINT incX); +double BLASNAME(cblas_dasum)(const BLASINT N, const double *X, const BLASINT incX); + +float BLASNAME(cblas_scnrm2)(const BLASINT N, const void *X, const BLASINT incX); +float BLASNAME(cblas_scasum)(const BLASINT N, const void *X, const BLASINT incX); + +double BLASNAME(cblas_dznrm2)(const BLASINT N, const void *X, const BLASINT incX); +double BLASNAME(cblas_dzasum)(const BLASINT N, const void *X, const BLASINT incX); + + +/* + * Functions having standard 4 prefixes (S D C Z) + */ +CBLAS_INDEX BLASNAME(cblas_isamax)(const BLASINT N, const float *X, const BLASINT incX); +CBLAS_INDEX BLASNAME(cblas_idamax)(const BLASINT N, const double *X, const BLASINT incX); +CBLAS_INDEX BLASNAME(cblas_icamax)(const BLASINT N, const void *X, const BLASINT incX); +CBLAS_INDEX BLASNAME(cblas_izamax)(const BLASINT N, const void *X, const BLASINT incX); + +/* + * =========================================================================== + * Prototypes for level 1 BLAS routines + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (s, d, c, z) + */ +void BLASNAME(cblas_sswap)(const BLASINT N, float *X, const BLASINT incX, + float *Y, const BLASINT incY); +void BLASNAME(cblas_scopy)(const BLASINT N, const float *X, const BLASINT incX, + float *Y, const BLASINT incY); +void BLASNAME(cblas_saxpy)(const BLASINT N, const float alpha, const float *X, + const BLASINT incX, float *Y, const BLASINT incY); + +void BLASNAME(cblas_dswap)(const BLASINT N, double *X, const BLASINT incX, + double *Y, const BLASINT incY); +void BLASNAME(cblas_dcopy)(const BLASINT N, const double *X, const BLASINT incX, + double *Y, const BLASINT incY); +void BLASNAME(cblas_daxpy)(const BLASINT N, const double alpha, const double *X, + const BLASINT incX, double *Y, const BLASINT incY); + +void BLASNAME(cblas_cswap)(const BLASINT N, void *X, const BLASINT incX, + void *Y, const BLASINT incY); +void BLASNAME(cblas_ccopy)(const BLASINT N, const void *X, const BLASINT incX, + void *Y, const BLASINT incY); +void BLASNAME(cblas_caxpy)(const BLASINT N, const void *alpha, const void *X, + const BLASINT incX, void *Y, const BLASINT incY); + +void BLASNAME(cblas_zswap)(const BLASINT N, void *X, const BLASINT incX, + void *Y, const BLASINT incY); +void BLASNAME(cblas_zcopy)(const BLASINT N, const void *X, const BLASINT incX, + void *Y, const BLASINT incY); +void BLASNAME(cblas_zaxpy)(const BLASINT N, const void *alpha, const void *X, + const BLASINT incX, void *Y, const BLASINT incY); + + +/* + * Routines with S and D prefix only + */ +void BLASNAME(cblas_srotg)(float *a, float *b, float *c, float *s); +void BLASNAME(cblas_srotmg)(float *d1, float *d2, float *b1, const float b2, float *P); +void BLASNAME(cblas_srot)(const BLASINT N, float *X, const BLASINT incX, + float *Y, const BLASINT incY, const float c, const float s); +void BLASNAME(cblas_srotm)(const BLASINT N, float *X, const BLASINT incX, + float *Y, const BLASINT incY, const float *P); + +void BLASNAME(cblas_drotg)(double *a, double *b, double *c, double *s); +void BLASNAME(cblas_drotmg)(double *d1, double *d2, double *b1, const double b2, double *P); +void BLASNAME(cblas_drot)(const BLASINT N, double *X, const BLASINT incX, + double *Y, const BLASINT incY, const double c, const double s); +void BLASNAME(cblas_drotm)(const BLASINT N, double *X, const BLASINT incX, + double *Y, const BLASINT incY, const double *P); + + +/* + * Routines with S D C Z CS and ZD prefixes + */ +void BLASNAME(cblas_sscal)(const BLASINT N, const float alpha, float *X, const BLASINT incX); +void BLASNAME(cblas_dscal)(const BLASINT N, const double alpha, double *X, const BLASINT incX); +void BLASNAME(cblas_cscal)(const BLASINT N, const void *alpha, void *X, const BLASINT incX); +void BLASNAME(cblas_zscal)(const BLASINT N, const void *alpha, void *X, const BLASINT incX); +void BLASNAME(cblas_csscal)(const BLASINT N, const float alpha, void *X, const BLASINT incX); +void BLASNAME(cblas_zdscal)(const BLASINT N, const double alpha, void *X, const BLASINT incX); + +/* + * =========================================================================== + * Prototypes for level 2 BLAS + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (S, D, C, Z) + */ +void BLASNAME(cblas_sgemv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const float alpha, const float *A, const BLASINT lda, + const float *X, const BLASINT incX, const float beta, + float *Y, const BLASINT incY); +void BLASNAME(cblas_sgbmv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const BLASINT KL, const BLASINT KU, const float alpha, + const float *A, const BLASINT lda, const float *X, + const BLASINT incX, const float beta, float *Y, const BLASINT incY); +void BLASNAME(cblas_strmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const float *A, const BLASINT lda, + float *X, const BLASINT incX); +void BLASNAME(cblas_stbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const float *A, const BLASINT lda, + float *X, const BLASINT incX); +void BLASNAME(cblas_stpmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const float *Ap, float *X, const BLASINT incX); +void BLASNAME(cblas_strsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const float *A, const BLASINT lda, float *X, + const BLASINT incX); +void BLASNAME(cblas_stbsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const float *A, const BLASINT lda, + float *X, const BLASINT incX); +void BLASNAME(cblas_stpsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const float *Ap, float *X, const BLASINT incX); + +void BLASNAME(cblas_dgemv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const double alpha, const double *A, const BLASINT lda, + const double *X, const BLASINT incX, const double beta, + double *Y, const BLASINT incY); +void BLASNAME(cblas_dgbmv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const BLASINT KL, const BLASINT KU, const double alpha, + const double *A, const BLASINT lda, const double *X, + const BLASINT incX, const double beta, double *Y, const BLASINT incY); +void BLASNAME(cblas_dtrmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const double *A, const BLASINT lda, + double *X, const BLASINT incX); +void BLASNAME(cblas_dtbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const double *A, const BLASINT lda, + double *X, const BLASINT incX); +void BLASNAME(cblas_dtpmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const double *Ap, double *X, const BLASINT incX); +void BLASNAME(cblas_dtrsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const double *A, const BLASINT lda, double *X, + const BLASINT incX); +void BLASNAME(cblas_dtbsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const double *A, const BLASINT lda, + double *X, const BLASINT incX); +void BLASNAME(cblas_dtpsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const double *Ap, double *X, const BLASINT incX); + +void BLASNAME(cblas_cgemv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + const void *X, const BLASINT incX, const void *beta, + void *Y, const BLASINT incY); +void BLASNAME(cblas_cgbmv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const BLASINT KL, const BLASINT KU, const void *alpha, + const void *A, const BLASINT lda, const void *X, + const BLASINT incX, const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_ctrmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *A, const BLASINT lda, + void *X, const BLASINT incX); +void BLASNAME(cblas_ctbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const void *A, const BLASINT lda, + void *X, const BLASINT incX); +void BLASNAME(cblas_ctpmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *Ap, void *X, const BLASINT incX); +void BLASNAME(cblas_ctrsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *A, const BLASINT lda, void *X, + const BLASINT incX); +void BLASNAME(cblas_ctbsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const void *A, const BLASINT lda, + void *X, const BLASINT incX); +void BLASNAME(cblas_ctpsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *Ap, void *X, const BLASINT incX); + +void BLASNAME(cblas_zgemv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + const void *X, const BLASINT incX, const void *beta, + void *Y, const BLASINT incY); +void BLASNAME(cblas_zgbmv)(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const BLASINT M, const BLASINT N, + const BLASINT KL, const BLASINT KU, const void *alpha, + const void *A, const BLASINT lda, const void *X, + const BLASINT incX, const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_ztrmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *A, const BLASINT lda, + void *X, const BLASINT incX); +void BLASNAME(cblas_ztbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const void *A, const BLASINT lda, + void *X, const BLASINT incX); +void BLASNAME(cblas_ztpmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *Ap, void *X, const BLASINT incX); +void BLASNAME(cblas_ztrsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *A, const BLASINT lda, void *X, + const BLASINT incX); +void BLASNAME(cblas_ztbsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const BLASINT K, const void *A, const BLASINT lda, + void *X, const BLASINT incX); +void BLASNAME(cblas_ztpsv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const BLASINT N, const void *Ap, void *X, const BLASINT incX); + + +/* + * Routines with S and D prefixes only + */ +void BLASNAME(cblas_ssymv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const float *A, + const BLASINT lda, const float *X, const BLASINT incX, + const float beta, float *Y, const BLASINT incY); +void BLASNAME(cblas_ssbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const BLASINT K, const float alpha, const float *A, + const BLASINT lda, const float *X, const BLASINT incX, + const float beta, float *Y, const BLASINT incY); +void BLASNAME(cblas_sspmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const float *Ap, + const float *X, const BLASINT incX, + const float beta, float *Y, const BLASINT incY); +void BLASNAME(cblas_sger)(const enum CBLAS_ORDER order, const BLASINT M, const BLASINT N, + const float alpha, const float *X, const BLASINT incX, + const float *Y, const BLASINT incY, float *A, const BLASINT lda); +void BLASNAME(cblas_ssyr)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const float *X, + const BLASINT incX, float *A, const BLASINT lda); +void BLASNAME(cblas_sspr)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const float *X, + const BLASINT incX, float *Ap); +void BLASNAME(cblas_ssyr2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const float *X, + const BLASINT incX, const float *Y, const BLASINT incY, float *A, + const BLASINT lda); +void BLASNAME(cblas_sspr2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const float *X, + const BLASINT incX, const float *Y, const BLASINT incY, float *A); + +void BLASNAME(cblas_dsymv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const double *A, + const BLASINT lda, const double *X, const BLASINT incX, + const double beta, double *Y, const BLASINT incY); +void BLASNAME(cblas_dsbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const BLASINT K, const double alpha, const double *A, + const BLASINT lda, const double *X, const BLASINT incX, + const double beta, double *Y, const BLASINT incY); +void BLASNAME(cblas_dspmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const double *Ap, + const double *X, const BLASINT incX, + const double beta, double *Y, const BLASINT incY); +void BLASNAME(cblas_dger)(const enum CBLAS_ORDER order, const BLASINT M, const BLASINT N, + const double alpha, const double *X, const BLASINT incX, + const double *Y, const BLASINT incY, double *A, const BLASINT lda); +void BLASNAME(cblas_dsyr)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const double *X, + const BLASINT incX, double *A, const BLASINT lda); +void BLASNAME(cblas_dspr)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const double *X, + const BLASINT incX, double *Ap); +void BLASNAME(cblas_dsyr2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const double *X, + const BLASINT incX, const double *Y, const BLASINT incY, double *A, + const BLASINT lda); +void BLASNAME(cblas_dspr2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const double *X, + const BLASINT incX, const double *Y, const BLASINT incY, double *A); + + +/* + * Routines with C and Z prefixes only + */ +void BLASNAME(cblas_chemv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const void *alpha, const void *A, + const BLASINT lda, const void *X, const BLASINT incX, + const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_chbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const BLASINT K, const void *alpha, const void *A, + const BLASINT lda, const void *X, const BLASINT incX, + const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_chpmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const void *alpha, const void *Ap, + const void *X, const BLASINT incX, + const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_cgeru)(const enum CBLAS_ORDER order, const BLASINT M, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *A, const BLASINT lda); +void BLASNAME(cblas_cgerc)(const enum CBLAS_ORDER order, const BLASINT M, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *A, const BLASINT lda); +void BLASNAME(cblas_cher)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const void *X, const BLASINT incX, + void *A, const BLASINT lda); +void BLASNAME(cblas_chpr)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const float alpha, const void *X, + const BLASINT incX, void *A); +void BLASNAME(cblas_cher2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *A, const BLASINT lda); +void BLASNAME(cblas_chpr2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *Ap); + +void BLASNAME(cblas_zhemv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const void *alpha, const void *A, + const BLASINT lda, const void *X, const BLASINT incX, + const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_zhbmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const BLASINT K, const void *alpha, const void *A, + const BLASINT lda, const void *X, const BLASINT incX, + const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_zhpmv)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const void *alpha, const void *Ap, + const void *X, const BLASINT incX, + const void *beta, void *Y, const BLASINT incY); +void BLASNAME(cblas_zgeru)(const enum CBLAS_ORDER order, const BLASINT M, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *A, const BLASINT lda); +void BLASNAME(cblas_zgerc)(const enum CBLAS_ORDER order, const BLASINT M, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *A, const BLASINT lda); +void BLASNAME(cblas_zher)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const void *X, const BLASINT incX, + void *A, const BLASINT lda); +void BLASNAME(cblas_zhpr)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, + const BLASINT N, const double alpha, const void *X, + const BLASINT incX, void *A); +void BLASNAME(cblas_zher2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *A, const BLASINT lda); +void BLASNAME(cblas_zhpr2)(const enum CBLAS_ORDER order, const enum CBLAS_UPLO Uplo, const BLASINT N, + const void *alpha, const void *X, const BLASINT incX, + const void *Y, const BLASINT incY, void *Ap); + +/* + * =========================================================================== + * Prototypes for level 3 BLAS + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (S, D, C, Z) + */ +void BLASNAME(cblas_sgemm)(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const BLASINT M, const BLASINT N, + const BLASINT K, const float alpha, const float *A, + const BLASINT lda, const float *B, const BLASINT ldb, + const float beta, float *C, const BLASINT ldc); +void BLASNAME(cblas_ssymm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const BLASINT M, const BLASINT N, + const float alpha, const float *A, const BLASINT lda, + const float *B, const BLASINT ldb, const float beta, + float *C, const BLASINT ldc); +void BLASNAME(cblas_ssyrk)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const float alpha, const float *A, const BLASINT lda, + const float beta, float *C, const BLASINT ldc); +void BLASNAME(cblas_ssyr2k)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const float alpha, const float *A, const BLASINT lda, + const float *B, const BLASINT ldb, const float beta, + float *C, const BLASINT ldc); +void BLASNAME(cblas_strmm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const float alpha, const float *A, const BLASINT lda, + float *B, const BLASINT ldb); +void BLASNAME(cblas_strsm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const float alpha, const float *A, const BLASINT lda, + float *B, const BLASINT ldb); + +void BLASNAME(cblas_dgemm)(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const BLASINT M, const BLASINT N, + const BLASINT K, const double alpha, const double *A, + const BLASINT lda, const double *B, const BLASINT ldb, + const double beta, double *C, const BLASINT ldc); +void BLASNAME(cblas_dsymm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const BLASINT M, const BLASINT N, + const double alpha, const double *A, const BLASINT lda, + const double *B, const BLASINT ldb, const double beta, + double *C, const BLASINT ldc); +void BLASNAME(cblas_dsyrk)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const double alpha, const double *A, const BLASINT lda, + const double beta, double *C, const BLASINT ldc); +void BLASNAME(cblas_dsyr2k)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const double alpha, const double *A, const BLASINT lda, + const double *B, const BLASINT ldb, const double beta, + double *C, const BLASINT ldc); +void BLASNAME(cblas_dtrmm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const double alpha, const double *A, const BLASINT lda, + double *B, const BLASINT ldb); +void BLASNAME(cblas_dtrsm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const double alpha, const double *A, const BLASINT lda, + double *B, const BLASINT ldb); + +void BLASNAME(cblas_cgemm)(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const BLASINT M, const BLASINT N, + const BLASINT K, const void *alpha, const void *A, + const BLASINT lda, const void *B, const BLASINT ldb, + const void *beta, void *C, const BLASINT ldc); +void BLASNAME(cblas_csymm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const void *beta, + void *C, const BLASINT ldc); +void BLASNAME(cblas_csyrk)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const void *alpha, const void *A, const BLASINT lda, + const void *beta, void *C, const BLASINT ldc); +void BLASNAME(cblas_csyr2k)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const void *beta, + void *C, const BLASINT ldc); +void BLASNAME(cblas_ctrmm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + void *B, const BLASINT ldb); +void BLASNAME(cblas_ctrsm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + void *B, const BLASINT ldb); + +void BLASNAME(cblas_zgemm)(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const BLASINT M, const BLASINT N, + const BLASINT K, const void *alpha, const void *A, + const BLASINT lda, const void *B, const BLASINT ldb, + const void *beta, void *C, const BLASINT ldc); +void BLASNAME(cblas_zsymm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const void *beta, + void *C, const BLASINT ldc); +void BLASNAME(cblas_zsyrk)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const void *alpha, const void *A, const BLASINT lda, + const void *beta, void *C, const BLASINT ldc); +void BLASNAME(cblas_zsyr2k)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const void *beta, + void *C, const BLASINT ldc); +void BLASNAME(cblas_ztrmm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + void *B, const BLASINT ldb); +void BLASNAME(cblas_ztrsm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + void *B, const BLASINT ldb); + + +/* + * Routines with prefixes C and Z only + */ +void BLASNAME(cblas_chemm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const void *beta, + void *C, const BLASINT ldc); +void BLASNAME(cblas_cherk)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const float alpha, const void *A, const BLASINT lda, + const float beta, void *C, const BLASINT ldc); +void BLASNAME(cblas_cher2k)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const float beta, + void *C, const BLASINT ldc); + +void BLASNAME(cblas_zhemm)(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const BLASINT M, const BLASINT N, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const void *beta, + void *C, const BLASINT ldc); +void BLASNAME(cblas_zherk)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const double alpha, const void *A, const BLASINT lda, + const double beta, void *C, const BLASINT ldc); +void BLASNAME(cblas_zher2k)(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const BLASINT N, const BLASINT K, + const void *alpha, const void *A, const BLASINT lda, + const void *B, const BLASINT ldb, const double beta, + void *C, const BLASINT ldc); + +void BLASNAME(cblas_xerbla)(BLASINT p, const char *rout, const char *form, ...); + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_CBLAS_BASE_H_ */ diff --git a/mkl_umath/src/npyv/npy_config.h b/mkl_umath/src/npyv/npy_config.h new file mode 100644 index 00000000..e5903668 --- /dev/null +++ b/mkl_umath/src/npyv/npy_config.h @@ -0,0 +1,188 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CONFIG_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CONFIG_H_ + +#include "config.h" +#include "npy_cpu_dispatch.h" // brings NPY_HAVE_[CPU features] +#include "numpy/numpyconfig.h" +#include "numpy/utils.h" +#include "numpy/npy_os.h" + +/* blocklist */ + +/* Disable broken functions on z/OS */ +#if defined (__MVS__) + +#define NPY_BLOCK_POWF +#define NPY_BLOCK_EXPF +#undef HAVE___THREAD + +#endif + +/* Disable broken MS math functions */ +#if defined(__MINGW32_VERSION) + +#define NPY_BLOCK_ATAN2 +#define NPY_BLOCK_ATAN2F +#define NPY_BLOCK_ATAN2L + +#define NPY_BLOCK_HYPOT +#define NPY_BLOCK_HYPOTF +#define NPY_BLOCK_HYPOTL + +#endif + +#if defined(_MSC_VER) + +#undef HAVE_CASIN +#undef HAVE_CASINF +#undef HAVE_CASINL +#undef HAVE_CASINH +#undef HAVE_CASINHF +#undef HAVE_CASINHL +#undef HAVE_CATAN +#undef HAVE_CATANF +#undef HAVE_CATANL +#undef HAVE_CATANH +#undef HAVE_CATANHF +#undef HAVE_CATANHL +#undef HAVE_CSQRT +#undef HAVE_CSQRTF +#undef HAVE_CSQRTL +#undef HAVE_CLOG +#undef HAVE_CLOGF +#undef HAVE_CLOGL +#undef HAVE_CACOS +#undef HAVE_CACOSF +#undef HAVE_CACOSL +#undef HAVE_CACOSH +#undef HAVE_CACOSHF +#undef HAVE_CACOSHL + +#endif + +/* MSVC _hypot messes with fp precision mode on 32-bit, see gh-9567 */ +#if defined(_MSC_VER) && !defined(_WIN64) + +#undef HAVE_CABS +#undef HAVE_CABSF +#undef HAVE_CABSL + +#define NPY_BLOCK_HYPOT +#define NPY_BLOCK_HYPOTF +#define NPY_BLOCK_HYPOTL + +#endif + + +/* Intel C for Windows uses POW for 64 bits longdouble*/ +#if defined(_MSC_VER) && defined(__INTEL_COMPILER) +#if NPY_SIZEOF_LONGDOUBLE == 8 +#define NPY_BLOCK_POWL +#endif +#endif /* defined(_MSC_VER) && defined(__INTEL_COMPILER) */ + +/* powl gives zero division warning on OS X, see gh-8307 */ +#if defined(NPY_OS_DARWIN) +#define NPY_BLOCK_POWL +#endif + +#ifdef __CYGWIN__ +/* Loss of precision */ +#undef HAVE_CASINHL +#undef HAVE_CASINH +#undef HAVE_CASINHF + +/* Loss of precision */ +#undef HAVE_CATANHL +#undef HAVE_CATANH +#undef HAVE_CATANHF + +/* Loss of precision and branch cuts */ +#undef HAVE_CATANL +#undef HAVE_CATAN +#undef HAVE_CATANF + +/* Branch cuts */ +#undef HAVE_CACOSHF +#undef HAVE_CACOSH + +/* Branch cuts */ +#undef HAVE_CSQRTF +#undef HAVE_CSQRT + +/* Branch cuts and loss of precision */ +#undef HAVE_CASINF +#undef HAVE_CASIN +#undef HAVE_CASINL + +/* Branch cuts */ +#undef HAVE_CACOSF +#undef HAVE_CACOS + +/* log2(exp2(i)) off by a few eps */ +#define NPY_BLOCK_LOG2 + +/* np.power(..., dtype=np.complex256) doesn't report overflow */ +#undef HAVE_CPOWL +#undef HAVE_CEXPL + +#include +#if CYGWIN_VERSION_DLL_MAJOR < 3003 +// rather than blocklist cabsl, hypotl, modfl, sqrtl, error out +#error cygwin < 3.3 not supported, please update +#endif +#endif + +/* Disable broken gnu trig functions */ +#if defined(HAVE_FEATURES_H) +#include + +#if defined(__GLIBC__) +#if !__GLIBC_PREREQ(2, 18) + +#undef HAVE_CASIN +#undef HAVE_CASINF +#undef HAVE_CASINL +#undef HAVE_CASINH +#undef HAVE_CASINHF +#undef HAVE_CASINHL +#undef HAVE_CATAN +#undef HAVE_CATANF +#undef HAVE_CATANL +#undef HAVE_CATANH +#undef HAVE_CATANHF +#undef HAVE_CATANHL +#undef HAVE_CACOS +#undef HAVE_CACOSF +#undef HAVE_CACOSL +#undef HAVE_CACOSH +#undef HAVE_CACOSHF +#undef HAVE_CACOSHL + +#endif /* __GLIBC_PREREQ(2, 18) */ +#else /* defined(__GLIBC) */ +/* musl linux?, see issue #25092 */ + +#undef HAVE_CASIN +#undef HAVE_CASINF +#undef HAVE_CASINL +#undef HAVE_CASINH +#undef HAVE_CASINHF +#undef HAVE_CASINHL +#undef HAVE_CATAN +#undef HAVE_CATANF +#undef HAVE_CATANL +#undef HAVE_CATANH +#undef HAVE_CATANHF +#undef HAVE_CATANHL +#undef HAVE_CACOS +#undef HAVE_CACOSF +#undef HAVE_CACOSL +#undef HAVE_CACOSH +#undef HAVE_CACOSHF +#undef HAVE_CACOSHL + +#endif /* defined(__GLIBC) */ +#endif /* defined(HAVE_FEATURES_H) */ + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_CONFIG_H_ */ diff --git a/mkl_umath/src/npyv/npy_cpu_dispatch.h b/mkl_umath/src/npyv/npy_cpu_dispatch.h new file mode 100644 index 00000000..ddf6bd55 --- /dev/null +++ b/mkl_umath/src/npyv/npy_cpu_dispatch.h @@ -0,0 +1,132 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_H_ +/** + * This file is part of the NumPy CPU dispatcher. + * + * Please have a look at doc/reference/simd-optimizations.html + * To get a better understanding of the mechanism behind it. + */ +#include "npy_cpu_features.h" // NPY_CPU_HAVE +#if (defined(__s390x__) || defined(__powerpc64__)) && !defined(__cplusplus) && defined(bool) + /* + * "altivec.h" header contains the definitions(bool, vector, pixel), + * usually in c++ we undefine them after including the header. + * It's better anyway to take them off and use built-in types(__vector, __pixel, __bool) instead, + * since c99 supports bool variables which may lead to ambiguous errors. + */ + // backup 'bool' before including 'npy_cpu_dispatch_config.h', since it may not defined as a compiler token. + #define NPY__CPU_DISPATCH_GUARD_BOOL + typedef bool npy__cpu_dispatch_guard_bool; +#endif +/** + * Including the main configuration header 'npy_cpu_dispatch_config.h'. + * This header is generated by the 'ccompiler_opt' distutils module and the Meson build system. + * + * For the distutils-generated version, it contains: + * - Headers for platform-specific instruction sets. + * - Feature #definitions, e.g. NPY_HAVE_AVX2. + * - Helper macros that encapsulate enabled features through user-defined build options + * '--cpu-baseline' and '--cpu-dispatch'. These options are essential for implementing + * attributes like `__cpu_baseline__` and `__cpu_dispatch__` in the NumPy module. + * + * For the Meson-generated version, it contains: + * - Headers for platform-specific instruction sets. + * - Helper macros that encapsulate enabled features through user-defined build options + * '--cpu-baseline' and '--cpu-dispatch'. These options remain crucial for implementing + * attributes like `__cpu_baseline__` and `__cpu_dispatch__` in the NumPy module. + * - Additional helper macros necessary for runtime dispatching. + * + * Note: In the Meson build, features #definitions are conveyed via compiler arguments. + */ +#include "npy_cpu_dispatch_config.h" +#ifndef NPY__CPU_MESON_BUILD + // Define helper macros necessary for runtime dispatching for distutils. + #include "npy_cpu_dispatch_distutils.h" +#endif +#if defined(NPY_HAVE_VSX) || defined(NPY_HAVE_VX) + #undef bool + #undef vector + #undef pixel + #ifdef NPY__CPU_DISPATCH_GUARD_BOOL + #define bool npy__cpu_dispatch_guard_bool + #undef NPY__CPU_DISPATCH_GUARD_BOOL + #endif +#endif +/** + * Initialize the CPU dispatch tracer. + * + * This function simply adds an empty dictionary with the attribute + * '__cpu_targets_info__' to the provided module. + * + * It should be called only once during the loading of the NumPy module. + * Note: This function is not thread-safe. + * + * @param mod The module to which the '__cpu_targets_info__' dictionary will be added. + * @return 0 on success. + */ +NPY_VISIBILITY_HIDDEN int +npy_cpu_dispatch_tracer_init(PyObject *mod); +/** + * Insert data into the initialized '__cpu_targets_info__' dictionary. + * + * This function adds the function name as a key and another dictionary as a value. + * The inner dictionary holds the 'signature' as a key and splits 'dispatch_info' into another dictionary. + * The innermost dictionary contains the current enabled target as 'current' and available targets as 'available'. + * + * Note: This function should not be used directly; it should be used through the macro NPY_CPU_DISPATCH_TRACE(), + * which is responsible for filling in the enabled CPU targets. + * + * Example: + * + * const char *dispatch_info[] = {"AVX2", "AVX512_SKX AVX2 baseline"}; + * npy_cpu_dispatch_trace("add", "bbb", dispatch_info); + * + * const char *dispatch_info[] = {"AVX2", "AVX2 SSE41 baseline"}; + * npy_cpu_dispatch_trace("add", "BBB", dispatch_info); + * + * This will insert the following structure into the '__cpu_targets_info__' dictionary: + * + * numpy._core._multiarray_umath.__cpu_targets_info__ + * { + * "add": { + * "bbb": { + * "current": "AVX2", + * "available": "AVX512_SKX AVX2 baseline" + * }, + * "BBB": { + * "current": "AVX2", + * "available": "AVX2 SSE41 baseline" + * }, + * }, + * } + * + * @param func_name The name of the function. + * @param signature The signature of the function. + * @param dispatch_info The information about CPU dispatching. + */ +NPY_VISIBILITY_HIDDEN void +npy_cpu_dispatch_trace(const char *func_name, const char *signature, + const char **dispatch_info); +/** + * Extract the enabled CPU targets from the generated configuration file. + * + * This macro is used to extract the enabled CPU targets from the generated configuration file, + * which is derived from 'meson.multi_targets()' or from 'disutils.CCompilerOpt' in the case of using distutils. + * It then calls 'npy_cpu_dispatch_trace()' to insert a new item into the '__cpu_targets_info__' dictionary, + * based on the provided FUNC_NAME and SIGNATURE. + * + * For more clarification, please refer to the macro 'NPY_CPU_DISPATCH_INFO()' defined in 'meson_cpu/main_config.h.in' + * and check 'np.lib.utils.opt_func_info()' for the final usage of this trace. + * + * Example: + * #include "arithmetic.dispatch.h" + * NPY_CPU_DISPATCH_CALL(BYTE_add_ptr = BYTE_add); + * NPY_CPU_DISPATCH_TRACE("add", "bbb"); + */ +#define NPY_CPU_DISPATCH_TRACE(FNAME, SIGNATURE) \ +{ \ + const char *dinfo[] = NPY_CPU_DISPATCH_INFO(); \ + npy_cpu_dispatch_trace(FNAME, SIGNATURE, dinfo); \ +} while(0) + +#endif // NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_H_ diff --git a/mkl_umath/src/npyv/npy_cpu_dispatch_distutils.h b/mkl_umath/src/npyv/npy_cpu_dispatch_distutils.h new file mode 100644 index 00000000..8db99541 --- /dev/null +++ b/mkl_umath/src/npyv/npy_cpu_dispatch_distutils.h @@ -0,0 +1,116 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_DISTUTILS_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_DISTUTILS_H_ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_H_ + #error "Not standalone header please use 'npy_cpu_dispatch.h'" +#endif +/** + * This header should be removed after support for distutils is removed. + * It provides helper macros required for CPU runtime dispatching, + * which are already defined within `meson_cpu/main_config.h.in`. + * + * The following macros are explained within `meson_cpu/main_config.h.in`, + * although there are some differences in their usage: + * + * - Dispatched targets must be defined at the top of each dispatch-able + * source file within an inline or multi-line comment block. + * For example: //@targets baseline SSE2 AVX2 AVX512_SKX + * + * - The generated configuration derived from each dispatch-able source + * file must be guarded with `#ifndef NPY_DISABLE_OPTIMIZATION`. + * For example: + * #ifndef NPY_DISABLE_OPTIMIZATION + * #include "arithmetic.dispatch.h" + * #endif + */ +#include "npy_cpu_features.h" // NPY_CPU_HAVE +#include "numpy/utils.h" // NPY_EXPAND, NPY_CAT + +#ifdef NPY__CPU_TARGET_CURRENT + // 'NPY__CPU_TARGET_CURRENT': only defined by the dispatch-able sources + #define NPY_CPU_DISPATCH_CURFX(NAME) NPY_CAT(NPY_CAT(NAME, _), NPY__CPU_TARGET_CURRENT) +#else + #define NPY_CPU_DISPATCH_CURFX(NAME) NPY_EXPAND(NAME) +#endif +/** + * Defining the default behavior for the configurable macros of dispatch-able sources, + * 'NPY__CPU_DISPATCH_CALL(...)' and 'NPY__CPU_DISPATCH_BASELINE_CALL(...)' + * + * These macros are defined inside the generated config files that been derived from + * the configuration statements of the dispatch-able sources. + * + * The generated config file takes the same name of the dispatch-able source with replacing + * the extension to '.h' instead of '.c', and it should be treated as a header template. + */ +#ifndef NPY_DISABLE_OPTIMIZATION + #define NPY__CPU_DISPATCH_BASELINE_CALL(CB, ...) \ + &&"Expected config header of the dispatch-able source"; + #define NPY__CPU_DISPATCH_CALL(CHK, CB, ...) \ + &&"Expected config header of the dispatch-able source"; +#else + /** + * We assume by default that all configuration statements contains 'baseline' option however, + * if the dispatch-able source doesn't require it, then the dispatch-able source and following macros + * need to be guard it with '#ifndef NPY_DISABLE_OPTIMIZATION' + */ + #define NPY__CPU_DISPATCH_BASELINE_CALL(CB, ...) \ + NPY_EXPAND(CB(__VA_ARGS__)) + #define NPY__CPU_DISPATCH_CALL(CHK, CB, ...) +#endif // !NPY_DISABLE_OPTIMIZATION + +#define NPY_CPU_DISPATCH_DECLARE(...) \ + NPY__CPU_DISPATCH_CALL(NPY_CPU_DISPATCH_DECLARE_CHK_, NPY_CPU_DISPATCH_DECLARE_CB_, __VA_ARGS__) \ + NPY__CPU_DISPATCH_BASELINE_CALL(NPY_CPU_DISPATCH_DECLARE_BASE_CB_, __VA_ARGS__) +// Preprocessor callbacks +#define NPY_CPU_DISPATCH_DECLARE_CB_(DUMMY, TARGET_NAME, LEFT, ...) \ + NPY_CAT(NPY_CAT(LEFT, _), TARGET_NAME) __VA_ARGS__; +#define NPY_CPU_DISPATCH_DECLARE_BASE_CB_(LEFT, ...) \ + LEFT __VA_ARGS__; +// Dummy CPU runtime checking +#define NPY_CPU_DISPATCH_DECLARE_CHK_(FEATURE) + +#define NPY_CPU_DISPATCH_DECLARE_XB(...) \ + NPY__CPU_DISPATCH_CALL(NPY_CPU_DISPATCH_DECLARE_CHK_, NPY_CPU_DISPATCH_DECLARE_CB_, __VA_ARGS__) +#define NPY_CPU_DISPATCH_CALL(...) \ + NPY__CPU_DISPATCH_CALL(NPY_CPU_HAVE, NPY_CPU_DISPATCH_CALL_CB_, __VA_ARGS__) \ + NPY__CPU_DISPATCH_BASELINE_CALL(NPY_CPU_DISPATCH_CALL_BASE_CB_, __VA_ARGS__) +// Preprocessor callbacks +#define NPY_CPU_DISPATCH_CALL_CB_(TESTED_FEATURES, TARGET_NAME, LEFT, ...) \ + (TESTED_FEATURES) ? (NPY_CAT(NPY_CAT(LEFT, _), TARGET_NAME) __VA_ARGS__) : +#define NPY_CPU_DISPATCH_CALL_BASE_CB_(LEFT, ...) \ + (LEFT __VA_ARGS__) + +#define NPY_CPU_DISPATCH_CALL_XB(...) \ + NPY__CPU_DISPATCH_CALL(NPY_CPU_HAVE, NPY_CPU_DISPATCH_CALL_XB_CB_, __VA_ARGS__) \ + ((void) 0 /* discarded expression value */) +#define NPY_CPU_DISPATCH_CALL_XB_CB_(TESTED_FEATURES, TARGET_NAME, LEFT, ...) \ + (TESTED_FEATURES) ? (void) (NPY_CAT(NPY_CAT(LEFT, _), TARGET_NAME) __VA_ARGS__) : + +#define NPY_CPU_DISPATCH_CALL_ALL(...) \ + (NPY__CPU_DISPATCH_CALL(NPY_CPU_HAVE, NPY_CPU_DISPATCH_CALL_ALL_CB_, __VA_ARGS__) \ + NPY__CPU_DISPATCH_BASELINE_CALL(NPY_CPU_DISPATCH_CALL_ALL_BASE_CB_, __VA_ARGS__)) +// Preprocessor callbacks +#define NPY_CPU_DISPATCH_CALL_ALL_CB_(TESTED_FEATURES, TARGET_NAME, LEFT, ...) \ + ((TESTED_FEATURES) ? (NPY_CAT(NPY_CAT(LEFT, _), TARGET_NAME) __VA_ARGS__) : (void) 0), +#define NPY_CPU_DISPATCH_CALL_ALL_BASE_CB_(LEFT, ...) \ + ( LEFT __VA_ARGS__ ) + +#define NPY_CPU_DISPATCH_INFO() \ + { \ + NPY__CPU_DISPATCH_CALL(NPY_CPU_HAVE, NPY_CPU_DISPATCH_INFO_HIGH_CB_, DUMMY) \ + NPY__CPU_DISPATCH_BASELINE_CALL(NPY_CPU_DISPATCH_INFO_BASE_HIGH_CB_, DUMMY) \ + "", \ + NPY__CPU_DISPATCH_CALL(NPY_CPU_HAVE, NPY_CPU_DISPATCH_INFO_CB_, DUMMY) \ + NPY__CPU_DISPATCH_BASELINE_CALL(NPY_CPU_DISPATCH_INFO_BASE_CB_, DUMMY) \ + ""\ + } +#define NPY_CPU_DISPATCH_INFO_HIGH_CB_(TESTED_FEATURES, TARGET_NAME, ...) \ + (TESTED_FEATURES) ? NPY_TOSTRING(TARGET_NAME) : +#define NPY_CPU_DISPATCH_INFO_BASE_HIGH_CB_(...) \ + (1) ? "baseline(" NPY_WITH_CPU_BASELINE ")" : +// Preprocessor callbacks +#define NPY_CPU_DISPATCH_INFO_CB_(TESTED_FEATURES, TARGET_NAME, ...) \ + NPY_TOSTRING(TARGET_NAME) " " +#define NPY_CPU_DISPATCH_INFO_BASE_CB_(...) \ + "baseline(" NPY_WITH_CPU_BASELINE ")" + +#endif // NUMPY_CORE_SRC_COMMON_NPY_CPU_DISPATCH_DISTUTILS_H_ diff --git a/mkl_umath/src/npyv/npy_cpu_features.h b/mkl_umath/src/npyv/npy_cpu_features.h new file mode 100644 index 00000000..83522b93 --- /dev/null +++ b/mkl_umath/src/npyv/npy_cpu_features.h @@ -0,0 +1,201 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CPU_FEATURES_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CPU_FEATURES_H_ + +#include // for PyObject +#include "numpy/numpyconfig.h" // for NPY_VISIBILITY_HIDDEN + +#ifdef __cplusplus +extern "C" { +#endif + +enum npy_cpu_features +{ + NPY_CPU_FEATURE_NONE = 0, + // X86 + NPY_CPU_FEATURE_MMX = 1, + NPY_CPU_FEATURE_SSE = 2, + NPY_CPU_FEATURE_SSE2 = 3, + NPY_CPU_FEATURE_SSE3 = 4, + NPY_CPU_FEATURE_SSSE3 = 5, + NPY_CPU_FEATURE_SSE41 = 6, + NPY_CPU_FEATURE_POPCNT = 7, + NPY_CPU_FEATURE_SSE42 = 8, + NPY_CPU_FEATURE_AVX = 9, + NPY_CPU_FEATURE_F16C = 10, + NPY_CPU_FEATURE_XOP = 11, + NPY_CPU_FEATURE_FMA4 = 12, + NPY_CPU_FEATURE_FMA3 = 13, + NPY_CPU_FEATURE_AVX2 = 14, + NPY_CPU_FEATURE_FMA = 15, // AVX2 & FMA3, provides backward compatibility + + NPY_CPU_FEATURE_AVX512F = 30, + NPY_CPU_FEATURE_AVX512CD = 31, + NPY_CPU_FEATURE_AVX512ER = 32, + NPY_CPU_FEATURE_AVX512PF = 33, + NPY_CPU_FEATURE_AVX5124FMAPS = 34, + NPY_CPU_FEATURE_AVX5124VNNIW = 35, + NPY_CPU_FEATURE_AVX512VPOPCNTDQ = 36, + NPY_CPU_FEATURE_AVX512BW = 37, + NPY_CPU_FEATURE_AVX512DQ = 38, + NPY_CPU_FEATURE_AVX512VL = 39, + NPY_CPU_FEATURE_AVX512IFMA = 40, + NPY_CPU_FEATURE_AVX512VBMI = 41, + NPY_CPU_FEATURE_AVX512VNNI = 42, + NPY_CPU_FEATURE_AVX512VBMI2 = 43, + NPY_CPU_FEATURE_AVX512BITALG = 44, + NPY_CPU_FEATURE_AVX512FP16 = 45, + + // X86 CPU Groups + // Knights Landing (F,CD,ER,PF) + NPY_CPU_FEATURE_AVX512_KNL = 101, + // Knights Mill (F,CD,ER,PF,4FMAPS,4VNNIW,VPOPCNTDQ) + NPY_CPU_FEATURE_AVX512_KNM = 102, + // Skylake-X (F,CD,BW,DQ,VL) + NPY_CPU_FEATURE_AVX512_SKX = 103, + // Cascade Lake (F,CD,BW,DQ,VL,VNNI) + NPY_CPU_FEATURE_AVX512_CLX = 104, + // Cannon Lake (F,CD,BW,DQ,VL,IFMA,VBMI) + NPY_CPU_FEATURE_AVX512_CNL = 105, + // Ice Lake (F,CD,BW,DQ,VL,IFMA,VBMI,VNNI,VBMI2,BITALG,VPOPCNTDQ) + NPY_CPU_FEATURE_AVX512_ICL = 106, + // Sapphire Rapids (Ice Lake, AVX512FP16) + NPY_CPU_FEATURE_AVX512_SPR = 107, + + // IBM/POWER VSX + // POWER7 + NPY_CPU_FEATURE_VSX = 200, + // POWER8 + NPY_CPU_FEATURE_VSX2 = 201, + // POWER9 + NPY_CPU_FEATURE_VSX3 = 202, + // POWER10 + NPY_CPU_FEATURE_VSX4 = 203, + + // ARM + NPY_CPU_FEATURE_NEON = 300, + NPY_CPU_FEATURE_NEON_FP16 = 301, + // FMA + NPY_CPU_FEATURE_NEON_VFPV4 = 302, + // Advanced SIMD + NPY_CPU_FEATURE_ASIMD = 303, + // ARMv8.2 half-precision + NPY_CPU_FEATURE_FPHP = 304, + // ARMv8.2 half-precision vector arithm + NPY_CPU_FEATURE_ASIMDHP = 305, + // ARMv8.2 dot product + NPY_CPU_FEATURE_ASIMDDP = 306, + // ARMv8.2 single&half-precision multiply + NPY_CPU_FEATURE_ASIMDFHM = 307, + // Scalable Vector Extensions (SVE) + NPY_CPU_FEATURE_SVE = 308, + + // IBM/ZARCH + NPY_CPU_FEATURE_VX = 350, + + // Vector-Enhancements Facility 1 + NPY_CPU_FEATURE_VXE = 351, + + // Vector-Enhancements Facility 2 + NPY_CPU_FEATURE_VXE2 = 352, + + NPY_CPU_FEATURE_MAX +}; + +/* + * Initialize CPU features + * + * This function + * - detects runtime CPU features + * - check that baseline CPU features are present + * - uses 'NPY_DISABLE_CPU_FEATURES' to disable dispatchable features + * - uses 'NPY_ENABLE_CPU_FEATURES' to enable dispatchable features + * + * It will set a RuntimeError when + * - CPU baseline features from the build are not supported at runtime + * - 'NPY_DISABLE_CPU_FEATURES' tries to disable a baseline feature + * - 'NPY_DISABLE_CPU_FEATURES' and 'NPY_ENABLE_CPU_FEATURES' are + * simultaneously set + * - 'NPY_ENABLE_CPU_FEATURES' tries to enable a feature that is not supported + * by the machine or build + * - 'NPY_ENABLE_CPU_FEATURES' tries to enable a feature when the project was + * not built with any feature optimization support + * + * It will set an ImportWarning when: + * - 'NPY_DISABLE_CPU_FEATURES' tries to disable a feature that is not supported + * by the machine or build + * - 'NPY_DISABLE_CPU_FEATURES' or 'NPY_ENABLE_CPU_FEATURES' tries to + * disable/enable a feature when the project was not built with any feature + * optimization support + * + * return 0 on success otherwise return -1 + */ +NPY_VISIBILITY_HIDDEN int +npy_cpu_init(void); + +/* + * return 0 if CPU feature isn't available + * note: `npy_cpu_init` must be called first otherwise it will always return 0 +*/ +NPY_VISIBILITY_HIDDEN int +npy_cpu_have(int feature_id); + +#define NPY_CPU_HAVE(FEATURE_NAME) \ +npy_cpu_have(NPY_CPU_FEATURE_##FEATURE_NAME) + +/* + * return a new dictionary contains CPU feature names + * with runtime availability. + * same as npy_cpu_have, `npy_cpu_init` must be called first. + */ +NPY_VISIBILITY_HIDDEN PyObject * +npy_cpu_features_dict(void); +/* + * Return a new a Python list contains the minimal set of required optimizations + * that supported by the compiler and platform according to the specified + * values to command argument '--cpu-baseline'. + * + * This function is mainly used to implement umath's attribute '__cpu_baseline__', + * and the items are sorted from the lowest to highest interest. + * + * For example, according to the default build configuration and by assuming the compiler + * support all the involved optimizations then the returned list should equivalent to: + * + * On x86: ['SSE', 'SSE2'] + * On x64: ['SSE', 'SSE2', 'SSE3'] + * On armhf: [] + * On aarch64: ['NEON', 'NEON_FP16', 'NEON_VPFV4', 'ASIMD'] + * On ppc64: [] + * On ppc64le: ['VSX', 'VSX2'] + * On s390x: [] + * On any other arch or if the optimization is disabled: [] + */ +NPY_VISIBILITY_HIDDEN PyObject * +npy_cpu_baseline_list(void); +/* + * Return a new a Python list contains the dispatched set of additional optimizations + * that supported by the compiler and platform according to the specified + * values to command argument '--cpu-dispatch'. + * + * This function is mainly used to implement umath's attribute '__cpu_dispatch__', + * and the items are sorted from the lowest to highest interest. + * + * For example, according to the default build configuration and by assuming the compiler + * support all the involved optimizations then the returned list should equivalent to: + * + * On x86: ['SSE3', 'SSSE3', 'SSE41', 'POPCNT', 'SSE42', 'AVX', 'F16C', 'FMA3', 'AVX2', 'AVX512F', ...] + * On x64: ['SSSE3', 'SSE41', 'POPCNT', 'SSE42', 'AVX', 'F16C', 'FMA3', 'AVX2', 'AVX512F', ...] + * On armhf: ['NEON', 'NEON_FP16', 'NEON_VPFV4', 'ASIMD', 'ASIMDHP', 'ASIMDDP', 'ASIMDFHM'] + * On aarch64: ['ASIMDHP', 'ASIMDDP', 'ASIMDFHM'] + * On ppc64: ['VSX', 'VSX2', 'VSX3', 'VSX4'] + * On ppc64le: ['VSX3', 'VSX4'] + * On s390x: ['VX', 'VXE', VXE2] + * On any other arch or if the optimization is disabled: [] + */ +NPY_VISIBILITY_HIDDEN PyObject * +npy_cpu_dispatch_list(void); + +#ifdef __cplusplus +} +#endif + +#endif // NUMPY_CORE_SRC_COMMON_NPY_CPU_FEATURES_H_ diff --git a/mkl_umath/src/npyv/npy_cpuinfo_parser.h b/mkl_umath/src/npyv/npy_cpuinfo_parser.h new file mode 100644 index 00000000..154c4245 --- /dev/null +++ b/mkl_umath/src/npyv/npy_cpuinfo_parser.h @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CPUINFO_PARSER_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CPUINFO_PARSER_H_ +#include +#include +#include +#include +#include + +#define NPY__HWCAP 16 +#define NPY__HWCAP2 26 + +// arch/arm/include/uapi/asm/hwcap.h +#define NPY__HWCAP_HALF (1 << 1) +#define NPY__HWCAP_NEON (1 << 12) +#define NPY__HWCAP_VFPv3 (1 << 13) +#define NPY__HWCAP_VFPv4 (1 << 16) +#define NPY__HWCAP2_AES (1 << 0) +#define NPY__HWCAP2_PMULL (1 << 1) +#define NPY__HWCAP2_SHA1 (1 << 2) +#define NPY__HWCAP2_SHA2 (1 << 3) +#define NPY__HWCAP2_CRC32 (1 << 4) +// arch/arm64/include/uapi/asm/hwcap.h +#define NPY__HWCAP_FP (1 << 0) +#define NPY__HWCAP_ASIMD (1 << 1) +#define NPY__HWCAP_FPHP (1 << 9) +#define NPY__HWCAP_ASIMDHP (1 << 10) +#define NPY__HWCAP_ASIMDDP (1 << 20) +#define NPY__HWCAP_SVE (1 << 22) +#define NPY__HWCAP_ASIMDFHM (1 << 23) +/* + * Get the size of a file by reading it until the end. This is needed + * because files under /proc do not always return a valid size when + * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. + */ +static int +get_file_size(const char* pathname) +{ + int fd, result = 0; + char buffer[256]; + + fd = open(pathname, O_RDONLY); + if (fd < 0) { + return -1; + } + + for (;;) { + int ret = read(fd, buffer, sizeof buffer); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + break; + } + if (ret == 0) { + break; + } + result += ret; + } + close(fd); + return result; +} + +/* + * Read the content of /proc/cpuinfo into a user-provided buffer. + * Return the length of the data, or -1 on error. Does *not* + * zero-terminate the content. Will not read more + * than 'buffsize' bytes. + */ +static int +read_file(const char* pathname, char* buffer, size_t buffsize) +{ + int fd, count; + + fd = open(pathname, O_RDONLY); + if (fd < 0) { + return -1; + } + count = 0; + while (count < (int)buffsize) { + int ret = read(fd, buffer + count, buffsize - count); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + if (count == 0) { + count = -1; + } + break; + } + if (ret == 0) { + break; + } + count += ret; + } + close(fd); + return count; +} + +/* + * Extract the content of a the first occurrence of a given field in + * the content of /proc/cpuinfo and return it as a heap-allocated + * string that must be freed by the caller. + * + * Return NULL if not found + */ +static char* +extract_cpuinfo_field(const char* buffer, int buflen, const char* field) +{ + int fieldlen = strlen(field); + const char* bufend = buffer + buflen; + char* result = NULL; + int len; + const char *p, *q; + + /* Look for first field occurrence, and ensures it starts the line. */ + p = buffer; + for (;;) { + p = memmem(p, bufend-p, field, fieldlen); + if (p == NULL) { + goto EXIT; + } + + if (p == buffer || p[-1] == '\n') { + break; + } + + p += fieldlen; + } + + /* Skip to the first column followed by a space */ + p += fieldlen; + p = memchr(p, ':', bufend-p); + if (p == NULL || p[1] != ' ') { + goto EXIT; + } + + /* Find the end of the line */ + p += 2; + q = memchr(p, '\n', bufend-p); + if (q == NULL) { + q = bufend; + } + + /* Copy the line into a heap-allocated buffer */ + len = q - p; + result = malloc(len + 1); + if (result == NULL) { + goto EXIT; + } + + memcpy(result, p, len); + result[len] = '\0'; + +EXIT: + return result; +} + +/* + * Checks that a space-separated list of items contains one given 'item'. + * Returns 1 if found, 0 otherwise. + */ +static int +has_list_item(const char* list, const char* item) +{ + const char* p = list; + int itemlen = strlen(item); + + if (list == NULL) { + return 0; + } + + while (*p) { + const char* q; + + /* skip spaces */ + while (*p == ' ' || *p == '\t') { + p++; + } + + /* find end of current list item */ + q = p; + while (*q && *q != ' ' && *q != '\t') { + q++; + } + + if (itemlen == q-p && !memcmp(p, item, itemlen)) { + return 1; + } + + /* skip to next item */ + p = q; + } + return 0; +} + +static void setHwcap(char* cpuFeatures, unsigned long* hwcap) { + *hwcap |= has_list_item(cpuFeatures, "neon") ? NPY__HWCAP_NEON : 0; + *hwcap |= has_list_item(cpuFeatures, "half") ? NPY__HWCAP_HALF : 0; + *hwcap |= has_list_item(cpuFeatures, "vfpv3") ? NPY__HWCAP_VFPv3 : 0; + *hwcap |= has_list_item(cpuFeatures, "vfpv4") ? NPY__HWCAP_VFPv4 : 0; + + *hwcap |= has_list_item(cpuFeatures, "asimd") ? NPY__HWCAP_ASIMD : 0; + *hwcap |= has_list_item(cpuFeatures, "fp") ? NPY__HWCAP_FP : 0; + *hwcap |= has_list_item(cpuFeatures, "fphp") ? NPY__HWCAP_FPHP : 0; + *hwcap |= has_list_item(cpuFeatures, "asimdhp") ? NPY__HWCAP_ASIMDHP : 0; + *hwcap |= has_list_item(cpuFeatures, "asimddp") ? NPY__HWCAP_ASIMDDP : 0; + *hwcap |= has_list_item(cpuFeatures, "asimdfhm") ? NPY__HWCAP_ASIMDFHM : 0; +} + +static int +get_feature_from_proc_cpuinfo(unsigned long *hwcap, unsigned long *hwcap2) { + char* cpuinfo = NULL; + int cpuinfo_len; + cpuinfo_len = get_file_size("/proc/cpuinfo"); + if (cpuinfo_len < 0) { + return 0; + } + cpuinfo = malloc(cpuinfo_len); + if (cpuinfo == NULL) { + return 0; + } + cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len); + char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features"); + if(cpuFeatures == NULL) { + return 0; + } + setHwcap(cpuFeatures, hwcap); + *hwcap2 |= *hwcap; + *hwcap2 |= has_list_item(cpuFeatures, "aes") ? NPY__HWCAP2_AES : 0; + *hwcap2 |= has_list_item(cpuFeatures, "pmull") ? NPY__HWCAP2_PMULL : 0; + *hwcap2 |= has_list_item(cpuFeatures, "sha1") ? NPY__HWCAP2_SHA1 : 0; + *hwcap2 |= has_list_item(cpuFeatures, "sha2") ? NPY__HWCAP2_SHA2 : 0; + *hwcap2 |= has_list_item(cpuFeatures, "crc32") ? NPY__HWCAP2_CRC32 : 0; + return 1; +} +#endif /* NUMPY_CORE_SRC_COMMON_NPY_CPUINFO_PARSER_H_ */ diff --git a/mkl_umath/src/npyv/npy_ctypes.h b/mkl_umath/src/npyv/npy_ctypes.h new file mode 100644 index 00000000..578de063 --- /dev/null +++ b/mkl_umath/src/npyv/npy_ctypes.h @@ -0,0 +1,50 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_CTYPES_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_CTYPES_H_ + +#include + +#include "npy_import.h" + +/* + * Check if a python type is a ctypes class. + * + * Works like the Py_Check functions, returning true if the argument + * looks like a ctypes object. + * + * This entire function is just a wrapper around the Python function of the + * same name. + */ +static inline int +npy_ctypes_check(PyTypeObject *obj) +{ + static PyObject *py_func = NULL; + PyObject *ret_obj; + int ret; + + npy_cache_import("numpy._core._internal", "npy_ctypes_check", &py_func); + if (py_func == NULL) { + goto fail; + } + + ret_obj = PyObject_CallFunctionObjArgs(py_func, (PyObject *)obj, NULL); + if (ret_obj == NULL) { + goto fail; + } + + ret = PyObject_IsTrue(ret_obj); + Py_DECREF(ret_obj); + if (ret == -1) { + goto fail; + } + + return ret; + +fail: + /* If the above fails, then we should just assume that the type is not from + * ctypes + */ + PyErr_Clear(); + return 0; +} + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_CTYPES_H_ */ diff --git a/mkl_umath/src/npyv/npy_dlpack.h b/mkl_umath/src/npyv/npy_dlpack.h new file mode 100644 index 00000000..cb926a26 --- /dev/null +++ b/mkl_umath/src/npyv/npy_dlpack.h @@ -0,0 +1,28 @@ +#include "Python.h" +#include "dlpack/dlpack.h" + +#ifndef NPY_DLPACK_H +#define NPY_DLPACK_H + +// Part of the Array API specification. +#define NPY_DLPACK_CAPSULE_NAME "dltensor" +#define NPY_DLPACK_USED_CAPSULE_NAME "used_dltensor" + +// Used internally by NumPy to store a base object +// as it has to release a reference to the original +// capsule. +#define NPY_DLPACK_INTERNAL_CAPSULE_NAME "numpy_dltensor" + +PyObject * +array_dlpack(PyArrayObject *self, PyObject *const *args, Py_ssize_t len_args, + PyObject *kwnames); + + +PyObject * +array_dlpack_device(PyArrayObject *self, PyObject *NPY_UNUSED(args)); + + +NPY_NO_EXPORT PyObject * +from_dlpack(PyObject *NPY_UNUSED(self), PyObject *obj); + +#endif diff --git a/mkl_umath/src/npyv/npy_extint128.h b/mkl_umath/src/npyv/npy_extint128.h new file mode 100644 index 00000000..776d71c7 --- /dev/null +++ b/mkl_umath/src/npyv/npy_extint128.h @@ -0,0 +1,317 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_EXTINT128_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_EXTINT128_H_ + + +typedef struct { + signed char sign; + npy_uint64 lo, hi; +} npy_extint128_t; + + +/* Integer addition with overflow checking */ +static inline npy_int64 +safe_add(npy_int64 a, npy_int64 b, char *overflow_flag) +{ + if (a > 0 && b > NPY_MAX_INT64 - a) { + *overflow_flag = 1; + } + else if (a < 0 && b < NPY_MIN_INT64 - a) { + *overflow_flag = 1; + } + return a + b; +} + + +/* Integer subtraction with overflow checking */ +static inline npy_int64 +safe_sub(npy_int64 a, npy_int64 b, char *overflow_flag) +{ + if (a >= 0 && b < a - NPY_MAX_INT64) { + *overflow_flag = 1; + } + else if (a < 0 && b > a - NPY_MIN_INT64) { + *overflow_flag = 1; + } + return a - b; +} + + +/* Integer multiplication with overflow checking */ +static inline npy_int64 +safe_mul(npy_int64 a, npy_int64 b, char *overflow_flag) +{ + if (a > 0) { + if (b > NPY_MAX_INT64 / a || b < NPY_MIN_INT64 / a) { + *overflow_flag = 1; + } + } + else if (a < 0) { + if (b > 0 && a < NPY_MIN_INT64 / b) { + *overflow_flag = 1; + } + else if (b < 0 && a < NPY_MAX_INT64 / b) { + *overflow_flag = 1; + } + } + return a * b; +} + + +/* Long integer init */ +static inline npy_extint128_t +to_128(npy_int64 x) +{ + npy_extint128_t result; + result.sign = (x >= 0 ? 1 : -1); + if (x >= 0) { + result.lo = x; + } + else { + result.lo = (npy_uint64)(-(x + 1)) + 1; + } + result.hi = 0; + return result; +} + + +static inline npy_int64 +to_64(npy_extint128_t x, char *overflow) +{ + if (x.hi != 0 || + (x.sign > 0 && x.lo > NPY_MAX_INT64) || + (x.sign < 0 && x.lo != 0 && x.lo - 1 > -(NPY_MIN_INT64 + 1))) { + *overflow = 1; + } + return x.lo * x.sign; +} + + +/* Long integer multiply */ +static inline npy_extint128_t +mul_64_64(npy_int64 a, npy_int64 b) +{ + npy_extint128_t x, y, z; + npy_uint64 x1, x2, y1, y2, r1, r2, prev; + + x = to_128(a); + y = to_128(b); + + x1 = x.lo & 0xffffffff; + x2 = x.lo >> 32; + + y1 = y.lo & 0xffffffff; + y2 = y.lo >> 32; + + r1 = x1*y2; + r2 = x2*y1; + + z.sign = x.sign * y.sign; + z.hi = x2*y2 + (r1 >> 32) + (r2 >> 32); + z.lo = x1*y1; + + /* Add with carry */ + prev = z.lo; + z.lo += (r1 << 32); + if (z.lo < prev) { + ++z.hi; + } + + prev = z.lo; + z.lo += (r2 << 32); + if (z.lo < prev) { + ++z.hi; + } + + return z; +} + + +/* Long integer add */ +static inline npy_extint128_t +add_128(npy_extint128_t x, npy_extint128_t y, char *overflow) +{ + npy_extint128_t z; + + if (x.sign == y.sign) { + z.sign = x.sign; + z.hi = x.hi + y.hi; + if (z.hi < x.hi) { + *overflow = 1; + } + z.lo = x.lo + y.lo; + if (z.lo < x.lo) { + if (z.hi == NPY_MAX_UINT64) { + *overflow = 1; + } + ++z.hi; + } + } + else if (x.hi > y.hi || (x.hi == y.hi && x.lo >= y.lo)) { + z.sign = x.sign; + z.hi = x.hi - y.hi; + z.lo = x.lo; + z.lo -= y.lo; + if (z.lo > x.lo) { + --z.hi; + } + } + else { + z.sign = y.sign; + z.hi = y.hi - x.hi; + z.lo = y.lo; + z.lo -= x.lo; + if (z.lo > y.lo) { + --z.hi; + } + } + + return z; +} + + +/* Long integer negation */ +static inline npy_extint128_t +neg_128(npy_extint128_t x) +{ + npy_extint128_t z = x; + z.sign *= -1; + return z; +} + + +static inline npy_extint128_t +sub_128(npy_extint128_t x, npy_extint128_t y, char *overflow) +{ + return add_128(x, neg_128(y), overflow); +} + + +static inline npy_extint128_t +shl_128(npy_extint128_t v) +{ + npy_extint128_t z; + z = v; + z.hi <<= 1; + z.hi |= (z.lo & (((npy_uint64)1) << 63)) >> 63; + z.lo <<= 1; + return z; +} + + +static inline npy_extint128_t +shr_128(npy_extint128_t v) +{ + npy_extint128_t z; + z = v; + z.lo >>= 1; + z.lo |= (z.hi & 0x1) << 63; + z.hi >>= 1; + return z; +} + +static inline int +gt_128(npy_extint128_t a, npy_extint128_t b) +{ + if (a.sign > 0 && b.sign > 0) { + return (a.hi > b.hi) || (a.hi == b.hi && a.lo > b.lo); + } + else if (a.sign < 0 && b.sign < 0) { + return (a.hi < b.hi) || (a.hi == b.hi && a.lo < b.lo); + } + else if (a.sign > 0 && b.sign < 0) { + return a.hi != 0 || a.lo != 0 || b.hi != 0 || b.lo != 0; + } + else { + return 0; + } +} + + +/* Long integer divide */ +static inline npy_extint128_t +divmod_128_64(npy_extint128_t x, npy_int64 b, npy_int64 *mod) +{ + npy_extint128_t remainder, pointer, result, divisor; + char overflow = 0; + + assert(b > 0); + + if (b <= 1 || x.hi == 0) { + result.sign = x.sign; + result.lo = x.lo / b; + result.hi = x.hi / b; + *mod = x.sign * (x.lo % b); + return result; + } + + /* Long division, not the most efficient choice */ + remainder = x; + remainder.sign = 1; + + divisor.sign = 1; + divisor.hi = 0; + divisor.lo = b; + + result.sign = 1; + result.lo = 0; + result.hi = 0; + + pointer.sign = 1; + pointer.lo = 1; + pointer.hi = 0; + + while ((divisor.hi & (((npy_uint64)1) << 63)) == 0 && + gt_128(remainder, divisor)) { + divisor = shl_128(divisor); + pointer = shl_128(pointer); + } + + while (pointer.lo || pointer.hi) { + if (!gt_128(divisor, remainder)) { + remainder = sub_128(remainder, divisor, &overflow); + result = add_128(result, pointer, &overflow); + } + divisor = shr_128(divisor); + pointer = shr_128(pointer); + } + + /* Fix signs and return; cannot overflow */ + result.sign = x.sign; + *mod = x.sign * remainder.lo; + + return result; +} + + +/* Divide and round down (positive divisor; no overflows) */ +static inline npy_extint128_t +floordiv_128_64(npy_extint128_t a, npy_int64 b) +{ + npy_extint128_t result; + npy_int64 remainder; + char overflow = 0; + assert(b > 0); + result = divmod_128_64(a, b, &remainder); + if (a.sign < 0 && remainder != 0) { + result = sub_128(result, to_128(1), &overflow); + } + return result; +} + + +/* Divide and round up (positive divisor; no overflows) */ +static inline npy_extint128_t +ceildiv_128_64(npy_extint128_t a, npy_int64 b) +{ + npy_extint128_t result; + npy_int64 remainder; + char overflow = 0; + assert(b > 0); + result = divmod_128_64(a, b, &remainder); + if (a.sign > 0 && remainder != 0) { + result = add_128(result, to_128(1), &overflow); + } + return result; +} + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_EXTINT128_H_ */ diff --git a/mkl_umath/src/npyv/npy_fpmath.h b/mkl_umath/src/npyv/npy_fpmath.h new file mode 100644 index 00000000..27e9ea3f --- /dev/null +++ b/mkl_umath/src/npyv/npy_fpmath.h @@ -0,0 +1,30 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_NPY_FPMATH_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_NPY_FPMATH_H_ + +#include "npy_config.h" + +#include "numpy/npy_os.h" +#include "numpy/npy_cpu.h" +#include "numpy/npy_common.h" + +#if !(defined(HAVE_LDOUBLE_IEEE_QUAD_BE) || \ + defined(HAVE_LDOUBLE_IEEE_QUAD_LE) || \ + defined(HAVE_LDOUBLE_IEEE_DOUBLE_LE) || \ + defined(HAVE_LDOUBLE_IEEE_DOUBLE_BE) || \ + defined(HAVE_LDOUBLE_INTEL_EXTENDED_16_BYTES_LE) || \ + defined(HAVE_LDOUBLE_INTEL_EXTENDED_12_BYTES_LE) || \ + defined(HAVE_LDOUBLE_MOTOROLA_EXTENDED_12_BYTES_BE) || \ + defined(HAVE_LDOUBLE_IBM_DOUBLE_DOUBLE_BE) || \ + defined(HAVE_LDOUBLE_IBM_DOUBLE_DOUBLE_LE)) + #error No long double representation defined +#endif + +/* for back-compat, also keep old name for double-double */ +#ifdef HAVE_LDOUBLE_IBM_DOUBLE_DOUBLE_LE + #define HAVE_LDOUBLE_DOUBLE_DOUBLE_LE +#endif +#ifdef HAVE_LDOUBLE_IBM_DOUBLE_DOUBLE_BE + #define HAVE_LDOUBLE_DOUBLE_DOUBLE_BE +#endif + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_NPY_FPMATH_H_ */ diff --git a/mkl_umath/src/npyv/npy_hashtable.h b/mkl_umath/src/npyv/npy_hashtable.h new file mode 100644 index 00000000..a0bf8196 --- /dev/null +++ b/mkl_umath/src/npyv/npy_hashtable.h @@ -0,0 +1,32 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_NPY_HASHTABLE_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_NPY_HASHTABLE_H_ + +#include + +#define NPY_NO_DEPRECATED_API NPY_API_VERSION +#include "numpy/ndarraytypes.h" + + +typedef struct { + int key_len; /* number of identities used */ + /* Buckets stores: val1, key1[0], key1[1], ..., val2, key2[0], ... */ + PyObject **buckets; + npy_intp size; /* current size */ + npy_intp nelem; /* number of elements */ +} PyArrayIdentityHash; + + +NPY_NO_EXPORT int +PyArrayIdentityHash_SetItem(PyArrayIdentityHash *tb, + PyObject *const *key, PyObject *value, int replace); + +NPY_NO_EXPORT PyObject * +PyArrayIdentityHash_GetItem(PyArrayIdentityHash const *tb, PyObject *const *key); + +NPY_NO_EXPORT PyArrayIdentityHash * +PyArrayIdentityHash_New(int key_len); + +NPY_NO_EXPORT void +PyArrayIdentityHash_Dealloc(PyArrayIdentityHash *tb); + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_NPY_HASHTABLE_H_ */ diff --git a/mkl_umath/src/npyv/npy_import.h b/mkl_umath/src/npyv/npy_import.h new file mode 100644 index 00000000..58b4ba0b --- /dev/null +++ b/mkl_umath/src/npyv/npy_import.h @@ -0,0 +1,32 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_IMPORT_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_IMPORT_H_ + +#include + +/*! \brief Fetch and cache Python function. + * + * Import a Python function and cache it for use. The function checks if + * cache is NULL, and if not NULL imports the Python function specified by + * \a module and \a function, increments its reference count, and stores + * the result in \a cache. Usually \a cache will be a static variable and + * should be initialized to NULL. On error \a cache will contain NULL on + * exit, + * + * @param module Absolute module name. + * @param attr module attribute to cache. + * @param cache Storage location for imported function. + */ +static inline void +npy_cache_import(const char *module, const char *attr, PyObject **cache) +{ + if (NPY_UNLIKELY(*cache == NULL)) { + PyObject *mod = PyImport_ImportModule(module); + + if (mod != NULL) { + *cache = PyObject_GetAttrString(mod, attr); + Py_DECREF(mod); + } + } +} + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_IMPORT_H_ */ diff --git a/mkl_umath/src/npyv/npy_longdouble.h b/mkl_umath/src/npyv/npy_longdouble.h new file mode 100644 index 00000000..cf8b37bc --- /dev/null +++ b/mkl_umath/src/npyv/npy_longdouble.h @@ -0,0 +1,27 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_LONGDOUBLE_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_LONGDOUBLE_H_ + +#include "npy_config.h" +#include "numpy/ndarraytypes.h" + +/* Convert a npy_longdouble to a python `long` integer. + * + * Results are rounded towards zero. + * + * This performs the same task as PyLong_FromDouble, but for long doubles + * which have a greater range. + */ +NPY_VISIBILITY_HIDDEN PyObject * +npy_longdouble_to_PyLong(npy_longdouble ldval); + +/* Convert a python `long` integer to a npy_longdouble + * + * This performs the same task as PyLong_AsDouble, but for long doubles + * which have a greater range. + * + * Returns -1 if an error occurs. + */ +NPY_VISIBILITY_HIDDEN npy_longdouble +npy_longdouble_from_PyLong(PyObject *long_obj); + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_LONGDOUBLE_H_ */ diff --git a/mkl_umath/src/npyv/npy_partition.h b/mkl_umath/src/npyv/npy_partition.h new file mode 100644 index 00000000..57f834d9 --- /dev/null +++ b/mkl_umath/src/npyv/npy_partition.h @@ -0,0 +1,34 @@ +#ifndef NUMPY_CORE_SRC_COMMON_PARTITION_H_ +#define NUMPY_CORE_SRC_COMMON_PARTITION_H_ + +#include "npy_sort.h" + +/* Python include is for future object sorts */ +#include + +#include +#include + +#define NPY_MAX_PIVOT_STACK 50 + +typedef int (PyArray_PartitionFunc)(void *, npy_intp, npy_intp, + npy_intp *, npy_intp *, npy_intp, + void *); +typedef int (PyArray_ArgPartitionFunc)(void *, npy_intp *, npy_intp, npy_intp, + npy_intp *, npy_intp *, npy_intp, + void *); +#ifdef __cplusplus +extern "C" { +#endif + +NPY_NO_EXPORT PyArray_PartitionFunc * +get_partition_func(int type, NPY_SELECTKIND which); + +NPY_NO_EXPORT PyArray_ArgPartitionFunc * +get_argpartition_func(int type, NPY_SELECTKIND which); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mkl_umath/src/npyv/npy_pycompat.h b/mkl_umath/src/npyv/npy_pycompat.h new file mode 100644 index 00000000..ce6c34fa --- /dev/null +++ b/mkl_umath/src/npyv/npy_pycompat.h @@ -0,0 +1,22 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_PYCOMPAT_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_PYCOMPAT_H_ + +#include "numpy/npy_3kcompat.h" + + +/* + * In Python 3.10a7 (or b1), python started using the identity for the hash + * when a value is NaN. See https://bugs.python.org/issue43475 + */ +#if PY_VERSION_HEX > 0x030a00a6 +#define Npy_HashDouble _Py_HashDouble +#else +static inline Py_hash_t +Npy_HashDouble(PyObject *NPY_UNUSED(identity), double val) +{ + return _Py_HashDouble(val); +} +#endif + + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_PYCOMPAT_H_ */ diff --git a/mkl_umath/src/npyv/npy_svml.h b/mkl_umath/src/npyv/npy_svml.h new file mode 100644 index 00000000..64e9ee53 --- /dev/null +++ b/mkl_umath/src/npyv/npy_svml.h @@ -0,0 +1,71 @@ +#if NPY_SIMD && defined(NPY_HAVE_AVX512_SPR) && defined(NPY_CAN_LINK_SVML) +extern void __svml_exps32(const npy_half*, npy_half*, npy_intp); +extern void __svml_exp2s32(const npy_half*, npy_half*, npy_intp); +extern void __svml_logs32(const npy_half*, npy_half*, npy_intp); +extern void __svml_log2s32(const npy_half*, npy_half*, npy_intp); +extern void __svml_log10s32(const npy_half*, npy_half*, npy_intp); +extern void __svml_expm1s32(const npy_half*, npy_half*, npy_intp); +extern void __svml_log1ps32(const npy_half*, npy_half*, npy_intp); +extern void __svml_cbrts32(const npy_half*, npy_half*, npy_intp); +extern void __svml_sins32(const npy_half*, npy_half*, npy_intp); +extern void __svml_coss32(const npy_half*, npy_half*, npy_intp); +extern void __svml_tans32(const npy_half*, npy_half*, npy_intp); +extern void __svml_asins32(const npy_half*, npy_half*, npy_intp); +extern void __svml_acoss32(const npy_half*, npy_half*, npy_intp); +extern void __svml_atans32(const npy_half*, npy_half*, npy_intp); +extern void __svml_atan2s32(const npy_half*, npy_half*, npy_intp); +extern void __svml_sinhs32(const npy_half*, npy_half*, npy_intp); +extern void __svml_coshs32(const npy_half*, npy_half*, npy_intp); +extern void __svml_tanhs32(const npy_half*, npy_half*, npy_intp); +extern void __svml_asinhs32(const npy_half*, npy_half*, npy_intp); +extern void __svml_acoshs32(const npy_half*, npy_half*, npy_intp); +extern void __svml_atanhs32(const npy_half*, npy_half*, npy_intp); +#endif + +#if NPY_SIMD && defined(NPY_HAVE_AVX512_SKX) && defined(NPY_CAN_LINK_SVML) +extern __m512 __svml_expf16(__m512 x); +extern __m512 __svml_exp2f16(__m512 x); +extern __m512 __svml_logf16(__m512 x); +extern __m512 __svml_log2f16(__m512 x); +extern __m512 __svml_log10f16(__m512 x); +extern __m512 __svml_expm1f16(__m512 x); +extern __m512 __svml_log1pf16(__m512 x); +extern __m512 __svml_cbrtf16(__m512 x); +extern __m512 __svml_sinf16(__m512 x); +extern __m512 __svml_cosf16(__m512 x); +extern __m512 __svml_tanf16(__m512 x); +extern __m512 __svml_asinf16(__m512 x); +extern __m512 __svml_acosf16(__m512 x); +extern __m512 __svml_atanf16(__m512 x); +extern __m512 __svml_atan2f16(__m512 x, __m512 y); +extern __m512 __svml_sinhf16(__m512 x); +extern __m512 __svml_coshf16(__m512 x); +extern __m512 __svml_tanhf16(__m512 x); +extern __m512 __svml_asinhf16(__m512 x); +extern __m512 __svml_acoshf16(__m512 x); +extern __m512 __svml_atanhf16(__m512 x); +extern __m512 __svml_powf16(__m512 x, __m512 y); + +extern __m512d __svml_exp8_ha(__m512d x); +extern __m512d __svml_exp28_ha(__m512d x); +extern __m512d __svml_log8_ha(__m512d x); +extern __m512d __svml_log28_ha(__m512d x); +extern __m512d __svml_log108_ha(__m512d x); +extern __m512d __svml_expm18_ha(__m512d x); +extern __m512d __svml_log1p8_ha(__m512d x); +extern __m512d __svml_cbrt8_ha(__m512d x); +extern __m512d __svml_sin8_ha(__m512d x); +extern __m512d __svml_cos8_ha(__m512d x); +extern __m512d __svml_tan8_ha(__m512d x); +extern __m512d __svml_asin8_ha(__m512d x); +extern __m512d __svml_acos8_ha(__m512d x); +extern __m512d __svml_atan8_ha(__m512d x); +extern __m512d __svml_atan28_ha(__m512d x, __m512d y); +extern __m512d __svml_sinh8_ha(__m512d x); +extern __m512d __svml_cosh8_ha(__m512d x); +extern __m512d __svml_tanh8_ha(__m512d x); +extern __m512d __svml_asinh8_ha(__m512d x); +extern __m512d __svml_acosh8_ha(__m512d x); +extern __m512d __svml_atanh8_ha(__m512d x); +extern __m512d __svml_pow8_ha(__m512d x, __m512d y); +#endif diff --git a/mkl_umath/src/npyv/npyv.h b/mkl_umath/src/npyv/npyv.h new file mode 100644 index 00000000..545ca48c --- /dev/null +++ b/mkl_umath/src/npyv/npyv.h @@ -0,0 +1,112 @@ +#ifndef MKL_UMATH_NPYV_H +#define MKL_UMATH_NPYV_H + +/* + * Simplified SIMD vectorization wrapper for mkl_umath + * Using direct AVX2 intrinsics instead of NumPy's complex npyv layer + * + * This is a proof-of-concept focusing on FLOAT add operation only. + */ + +#include "numpy/npy_common.h" +#include // AVX2 intrinsics + +/* + * Check if AVX2 is available at compile time + */ +#ifdef __AVX2__ + #define NPYV_CAN_VECTORIZE_FLOAT 1 + #define NPYV_CAN_VECTORIZE_DOUBLE 1 + + // AVX2 vector lanes + #define npyv_nlanes_f32 8 // 256 bits / 32 bits + #define npyv_nlanes_f64 4 // 256 bits / 64 bits + #define npyv_nlanes_u8 32 // 256 bits / 8 bits + + // Type definitions + typedef __m256 npyv_f32; + typedef __m256d npyv_f64; + + // Load operations + #define npyv_load_f32(ptr) _mm256_loadu_ps((const float*)(ptr)) + #define npyv_load_f64(ptr) _mm256_loadu_pd((const double*)(ptr)) + + // Store operations + #define npyv_store_f32(ptr, vec) _mm256_storeu_ps((float*)(ptr), (vec)) + #define npyv_store_f64(ptr, vec) _mm256_storeu_pd((double*)(ptr), (vec)) + + // Arithmetic operations + #define npyv_add_f32(a, b) _mm256_add_ps((a), (b)) + #define npyv_add_f64(a, b) _mm256_add_pd((a), (b)) + + // Set all lanes to same value + #define npyv_setall_f32(val) _mm256_set1_ps(val) + #define npyv_setall_f64(val) _mm256_set1_pd(val) + + // Conditional load/store (simplified - just use regular ops for prototype) + static inline npyv_f32 npyv_load_tillz_f32(const float *ptr, npy_intp len) { + if (len >= 8) return npyv_load_f32(ptr); + // For partial loads, create mask and zero out unused elements + float temp[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + for (npy_intp i = 0; i < len && i < 8; i++) temp[i] = ptr[i]; + return _mm256_loadu_ps(temp); + } + + static inline npyv_f64 npyv_load_tillz_f64(const double *ptr, npy_intp len) { + if (len >= 4) return npyv_load_f64(ptr); + double temp[4] = {0, 0, 0, 0}; + for (npy_intp i = 0; i < len && i < 4; i++) temp[i] = ptr[i]; + return _mm256_loadu_pd(temp); + } + + static inline void npyv_store_till_f32(float *ptr, npy_intp len, npyv_f32 vec) { + if (len >= 8) { + npyv_store_f32(ptr, vec); + } else { + float temp[8]; + npyv_store_f32(temp, vec); + for (npy_intp i = 0; i < len && i < 8; i++) ptr[i] = temp[i]; + } + } + + static inline void npyv_store_till_f64(double *ptr, npy_intp len, npyv_f64 vec) { + if (len >= 4) { + npyv_store_f64(ptr, vec); + } else { + double temp[4]; + npyv_store_f64(temp, vec); + for (npy_intp i = 0; i < len && i < 4; i++) ptr[i] = temp[i]; + } + } + + // Cleanup (no-op for AVX2) + #define npyv_cleanup() do {} while(0) + +#else + // SIMD not available + #define NPYV_CAN_VECTORIZE_FLOAT 0 + #define NPYV_CAN_VECTORIZE_DOUBLE 0 +#endif + +/* + * Memory overlap detection (copied from NumPy) + */ +static inline int +is_mem_overlap(const void *src, npy_intp src_step, + const void *dst, npy_intp dst_step, npy_intp len) +{ + const char *src_ptr = (const char *)src; + const char *dst_ptr = (const char *)dst; + + if (src_ptr == dst_ptr) { + return 0; // Same pointer, always safe + } + + npy_intp src_size = len * src_step; + npy_intp dst_size = len * dst_step; + + // Check if ranges overlap + return !((src_ptr + src_size <= dst_ptr) || (dst_ptr + dst_size <= src_ptr)); +} + +#endif /* MKL_UMATH_NPYV_H */ diff --git a/mkl_umath/src/npyv/numpy_tag.h b/mkl_umath/src/npyv/numpy_tag.h new file mode 100644 index 00000000..ee0c36ca --- /dev/null +++ b/mkl_umath/src/npyv/numpy_tag.h @@ -0,0 +1,259 @@ +#ifndef _NPY_COMMON_TAG_H_ +#define _NPY_COMMON_TAG_H_ + +#include "../npysort/npysort_common.h" + +namespace npy { + +template +struct taglist { + static constexpr unsigned size = sizeof...(tags); +}; + +struct integral_tag { +}; +struct floating_point_tag { +}; +struct complex_tag { +}; +struct date_tag { +}; + +struct bool_tag : integral_tag { + using type = npy_bool; + static constexpr NPY_TYPES type_value = NPY_BOOL; + static int less(type const& a, type const& b) { + return BOOL_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct byte_tag : integral_tag { + using type = npy_byte; + static constexpr NPY_TYPES type_value = NPY_BYTE; + static int less(type const& a, type const& b) { + return BYTE_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct ubyte_tag : integral_tag { + using type = npy_ubyte; + static constexpr NPY_TYPES type_value = NPY_UBYTE; + static int less(type const& a, type const& b) { + return UBYTE_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct short_tag : integral_tag { + using type = npy_short; + static constexpr NPY_TYPES type_value = NPY_SHORT; + static int less(type const& a, type const& b) { + return SHORT_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct ushort_tag : integral_tag { + using type = npy_ushort; + static constexpr NPY_TYPES type_value = NPY_USHORT; + static int less(type const& a, type const& b) { + return USHORT_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct int_tag : integral_tag { + using type = npy_int; + static constexpr NPY_TYPES type_value = NPY_INT; + static int less(type const& a, type const& b) { + return INT_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct uint_tag : integral_tag { + using type = npy_uint; + static constexpr NPY_TYPES type_value = NPY_UINT; + static int less(type const& a, type const& b) { + return UINT_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct long_tag : integral_tag { + using type = npy_long; + static constexpr NPY_TYPES type_value = NPY_LONG; + static int less(type const& a, type const& b) { + return LONG_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct ulong_tag : integral_tag { + using type = npy_ulong; + static constexpr NPY_TYPES type_value = NPY_ULONG; + static int less(type const& a, type const& b) { + return ULONG_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct longlong_tag : integral_tag { + using type = npy_longlong; + static constexpr NPY_TYPES type_value = NPY_LONGLONG; + static int less(type const& a, type const& b) { + return LONGLONG_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct ulonglong_tag : integral_tag { + using type = npy_ulonglong; + static constexpr NPY_TYPES type_value = NPY_ULONGLONG; + static int less(type const& a, type const& b) { + return ULONGLONG_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct half_tag { + using type = npy_half; + static constexpr NPY_TYPES type_value = NPY_HALF; + static int less(type const& a, type const& b) { + return HALF_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct float_tag : floating_point_tag { + using type = npy_float; + static constexpr NPY_TYPES type_value = NPY_FLOAT; + static int less(type const& a, type const& b) { + return FLOAT_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct double_tag : floating_point_tag { + using type = npy_double; + static constexpr NPY_TYPES type_value = NPY_DOUBLE; + static int less(type const& a, type const& b) { + return DOUBLE_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct longdouble_tag : floating_point_tag { + using type = npy_longdouble; + static constexpr NPY_TYPES type_value = NPY_LONGDOUBLE; + static int less(type const& a, type const& b) { + return LONGDOUBLE_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct cfloat_tag : complex_tag { + using type = npy_cfloat; + static constexpr NPY_TYPES type_value = NPY_CFLOAT; + static int less(type const& a, type const& b) { + return CFLOAT_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct cdouble_tag : complex_tag { + using type = npy_cdouble; + static constexpr NPY_TYPES type_value = NPY_CDOUBLE; + static int less(type const& a, type const& b) { + return CDOUBLE_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct clongdouble_tag : complex_tag { + using type = npy_clongdouble; + static constexpr NPY_TYPES type_value = NPY_CLONGDOUBLE; + static int less(type const& a, type const& b) { + return CLONGDOUBLE_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct datetime_tag : date_tag { + using type = npy_datetime; + static constexpr NPY_TYPES type_value = NPY_DATETIME; + static int less(type const& a, type const& b) { + return DATETIME_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; +struct timedelta_tag : date_tag { + using type = npy_timedelta; + static constexpr NPY_TYPES type_value = NPY_TIMEDELTA; + static int less(type const& a, type const& b) { + return TIMEDELTA_LT(a, b); + } + static int less_equal(type const& a, type const& b) { + return !less(b, a); + } +}; + +struct string_tag { + using type = npy_char; + static constexpr NPY_TYPES type_value = NPY_STRING; + static int less(type const* a, type const* b, size_t len) { + return STRING_LT(a, b, len); + } + static int less_equal(type const* a, type const* b, size_t len) { + return !less(b, a, len); + } + static void swap(type* a, type* b, size_t len) { + STRING_SWAP(a, b, len); + } + static void copy(type * a, type const* b, size_t len) { + STRING_COPY(a, b, len); + } +}; + +struct unicode_tag { + using type = npy_ucs4; + static constexpr NPY_TYPES type_value = NPY_UNICODE; + static int less(type const* a, type const* b, size_t len) { + return UNICODE_LT(a, b, len); + } + static int less_equal(type const* a, type const* b, size_t len) { + return !less(b, a, len); + } + static void swap(type* a, type* b, size_t len) { + UNICODE_SWAP(a, b, len); + } + static void copy(type * a, type const* b, size_t len) { + UNICODE_COPY(a, b, len); + } +}; + +} // namespace npy + +#endif diff --git a/mkl_umath/src/npyv/numpyos.h b/mkl_umath/src/npyv/numpyos.h new file mode 100644 index 00000000..fac82f7d --- /dev/null +++ b/mkl_umath/src/npyv/numpyos.h @@ -0,0 +1,68 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_NUMPYOS_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_NUMPYOS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +NPY_NO_EXPORT char* +NumPyOS_ascii_formatd(char *buffer, size_t buf_size, + const char *format, + double val, int decimal); + +NPY_NO_EXPORT char* +NumPyOS_ascii_formatf(char *buffer, size_t buf_size, + const char *format, + float val, int decimal); + +NPY_NO_EXPORT char* +NumPyOS_ascii_formatl(char *buffer, size_t buf_size, + const char *format, + long double val, int decimal); + +NPY_NO_EXPORT double +NumPyOS_ascii_strtod(const char *s, char** endptr); + +NPY_NO_EXPORT long double +NumPyOS_ascii_strtold(const char *s, char** endptr); + +NPY_NO_EXPORT int +NumPyOS_ascii_ftolf(FILE *fp, double *value); + +NPY_NO_EXPORT int +NumPyOS_ascii_ftoLf(FILE *fp, long double *value); + +NPY_NO_EXPORT int +NumPyOS_ascii_isspace(int c); + +NPY_NO_EXPORT int +NumPyOS_ascii_isalpha(char c); + +NPY_NO_EXPORT int +NumPyOS_ascii_isdigit(char c); + +NPY_NO_EXPORT int +NumPyOS_ascii_isalnum(char c); + +NPY_NO_EXPORT int +NumPyOS_ascii_islower(char c); + +NPY_NO_EXPORT int +NumPyOS_ascii_isupper(char c); + +NPY_NO_EXPORT int +NumPyOS_ascii_tolower(char c); + +/* Convert a string to an int in an arbitrary base */ +NPY_NO_EXPORT npy_longlong +NumPyOS_strtoll(const char *str, char **endptr, int base); + +/* Convert a string to an int in an arbitrary base */ +NPY_NO_EXPORT npy_ulonglong +NumPyOS_strtoull(const char *str, char **endptr, int base); + +#ifdef __cplusplus +} +#endif + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_NUMPYOS_H_ */ diff --git a/mkl_umath/src/npyv/simd.h b/mkl_umath/src/npyv/simd.h new file mode 100644 index 00000000..2d9d48cf --- /dev/null +++ b/mkl_umath/src/npyv/simd.h @@ -0,0 +1,171 @@ +#ifndef _NPY_SIMD_H_ +#define _NPY_SIMD_H_ +/** + * the NumPy C SIMD vectorization interface "NPYV" are types and functions intended + * to simplify vectorization of code on different platforms, currently supports + * the following SIMD extensions SSE, AVX2, AVX512, VSX and NEON. + * + * TODO: Add an independent sphinx doc. +*/ +#include "numpy/npy_common.h" +#ifndef __cplusplus + #include +#endif + +#include "npy_cpu_dispatch.h" +#include "simd_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* + * clang commit an aggressive optimization behaviour when flag `-ftrapping-math` + * isn't fully supported that's present at -O1 or greater. When partially loading a + * vector register for a operations that requires to fill up the remaining lanes + * with certain value for example divide operation needs to fill the remaining value + * with non-zero integer to avoid fp exception divide-by-zero. + * clang optimizer notices that the entire register is not needed for the store + * and optimizes out the fill of non-zero integer to the remaining + * elements. As workaround we mark the returned register with `volatile` + * followed by symmetric operand operation e.g. `or` + * to convince the compiler that the entire vector is needed. + */ +#if defined(__clang__) && !defined(NPY_HAVE_CLANG_FPSTRICT) + #define NPY_SIMD_GUARD_PARTIAL_LOAD 1 +#else + #define NPY_SIMD_GUARD_PARTIAL_LOAD 0 +#endif + +#if defined(_MSC_VER) && defined(_M_IX86) +/* + * Avoid using any of the following intrinsics with MSVC 32-bit, + * even if they are apparently work on newer versions. + * They had bad impact on the generated instructions, + * sometimes the compiler deal with them without the respect + * of 32-bit mode which lead to crush due to execute 64-bit + * instructions and other times generate bad emulated instructions. + */ + #undef _mm512_set1_epi64 + #undef _mm256_set1_epi64x + #undef _mm_set1_epi64x + #undef _mm512_setr_epi64x + #undef _mm256_setr_epi64x + #undef _mm_setr_epi64x + #undef _mm512_set_epi64x + #undef _mm256_set_epi64x + #undef _mm_set_epi64x +#endif + +// lane type by intrin suffix +typedef npy_uint8 npyv_lanetype_u8; +typedef npy_int8 npyv_lanetype_s8; +typedef npy_uint16 npyv_lanetype_u16; +typedef npy_int16 npyv_lanetype_s16; +typedef npy_uint32 npyv_lanetype_u32; +typedef npy_int32 npyv_lanetype_s32; +typedef npy_uint64 npyv_lanetype_u64; +typedef npy_int64 npyv_lanetype_s64; +typedef float npyv_lanetype_f32; +typedef double npyv_lanetype_f64; + +#if defined(NPY_HAVE_AVX512F) && !defined(NPY_SIMD_FORCE_256) && !defined(NPY_SIMD_FORCE_128) + #include "avx512/avx512.h" +#elif defined(NPY_HAVE_AVX2) && !defined(NPY_SIMD_FORCE_128) + #include "avx2/avx2.h" +#elif defined(NPY_HAVE_SSE2) + #include "sse/sse.h" +#endif + +// TODO: Add support for VSX(2.06) and BE Mode for VSX +#if defined(NPY_HAVE_VX) || (defined(NPY_HAVE_VSX2) && defined(__LITTLE_ENDIAN__)) + #include "vec/vec.h" +#endif + +#ifdef NPY_HAVE_NEON + #include "neon/neon.h" +#endif + +#ifndef NPY_SIMD + /// SIMD width in bits or 0 if there's no SIMD extension available. + #define NPY_SIMD 0 + /// SIMD width in bytes or 0 if there's no SIMD extension available. + #define NPY_SIMD_WIDTH 0 + /// 1 if the enabled SIMD extension supports single-precision otherwise 0. + #define NPY_SIMD_F32 0 + /// 1 if the enabled SIMD extension supports double-precision otherwise 0. + #define NPY_SIMD_F64 0 + /// 1 if the enabled SIMD extension supports native FMA otherwise 0. + /// note: we still emulate(fast) FMA intrinsics even if they + /// aren't supported but they shouldn't be used if the precision is matters. + #define NPY_SIMD_FMA3 0 + /// 1 if the enabled SIMD extension is running on big-endian mode otherwise 0. + #define NPY_SIMD_BIGENDIAN 0 + /// 1 if the supported comparison intrinsics(lt, le, gt, ge) + /// raises FP invalid exception for quite NaNs. + #define NPY_SIMD_CMPSIGNAL 0 +#endif + +// enable emulated mask operations for all SIMD extension except for AVX512 +#if !defined(NPY_HAVE_AVX512F) && NPY_SIMD && NPY_SIMD < 512 + #include "emulate_maskop.h" +#endif + +// enable integer divisor generator for all SIMD extensions +#if NPY_SIMD + #include "intdiv.h" +#endif + +/** + * Some SIMD extensions currently(AVX2, AVX512F) require (de facto) + * a maximum number of strides sizes when dealing with non-contiguous memory access. + * + * Therefore the following functions must be used to check the maximum + * acceptable limit of strides before using any of non-contiguous load/store intrinsics. + * + * For instance: + * npy_intp ld_stride = step[0] / sizeof(float); + * npy_intp st_stride = step[1] / sizeof(float); + * + * if (npyv_loadable_stride_f32(ld_stride) && npyv_storable_stride_f32(st_stride)) { + * for (;;) + * npyv_f32 a = npyv_loadn_f32(ld_pointer, ld_stride); + * // ... + * npyv_storen_f32(st_pointer, st_stride, a); + * } + * else { + * for (;;) + * // C scalars + * } + */ +#ifndef NPY_SIMD_MAXLOAD_STRIDE32 + #define NPY_SIMD_MAXLOAD_STRIDE32 0 +#endif +#ifndef NPY_SIMD_MAXSTORE_STRIDE32 + #define NPY_SIMD_MAXSTORE_STRIDE32 0 +#endif +#ifndef NPY_SIMD_MAXLOAD_STRIDE64 + #define NPY_SIMD_MAXLOAD_STRIDE64 0 +#endif +#ifndef NPY_SIMD_MAXSTORE_STRIDE64 + #define NPY_SIMD_MAXSTORE_STRIDE64 0 +#endif +#define NPYV_IMPL_MAXSTRIDE(SFX, MAXLOAD, MAXSTORE) \ + NPY_FINLINE int npyv_loadable_stride_##SFX(npy_intp stride) \ + { return MAXLOAD > 0 ? llabs(stride) <= MAXLOAD : 1; } \ + NPY_FINLINE int npyv_storable_stride_##SFX(npy_intp stride) \ + { return MAXSTORE > 0 ? llabs(stride) <= MAXSTORE : 1; } +#if NPY_SIMD + NPYV_IMPL_MAXSTRIDE(u32, NPY_SIMD_MAXLOAD_STRIDE32, NPY_SIMD_MAXSTORE_STRIDE32) + NPYV_IMPL_MAXSTRIDE(s32, NPY_SIMD_MAXLOAD_STRIDE32, NPY_SIMD_MAXSTORE_STRIDE32) + NPYV_IMPL_MAXSTRIDE(f32, NPY_SIMD_MAXLOAD_STRIDE32, NPY_SIMD_MAXSTORE_STRIDE32) + NPYV_IMPL_MAXSTRIDE(u64, NPY_SIMD_MAXLOAD_STRIDE64, NPY_SIMD_MAXSTORE_STRIDE64) + NPYV_IMPL_MAXSTRIDE(s64, NPY_SIMD_MAXLOAD_STRIDE64, NPY_SIMD_MAXSTORE_STRIDE64) +#endif +#if NPY_SIMD_F64 + NPYV_IMPL_MAXSTRIDE(f64, NPY_SIMD_MAXLOAD_STRIDE64, NPY_SIMD_MAXSTORE_STRIDE64) +#endif + +#ifdef __cplusplus +} +#endif +#endif // _NPY_SIMD_H_ diff --git a/mkl_umath/src/npyv/simd_utils.h b/mkl_umath/src/npyv/simd_utils.h new file mode 100644 index 00000000..06c2f16f --- /dev/null +++ b/mkl_umath/src/npyv/simd_utils.h @@ -0,0 +1,48 @@ +#ifndef _NPY_SIMD_UTILS_H +#define _NPY_SIMD_UTILS_H + +#define NPYV__SET_2(CAST, I0, I1, ...) (CAST)(I0), (CAST)(I1) + +#define NPYV__SET_4(CAST, I0, I1, I2, I3, ...) \ + (CAST)(I0), (CAST)(I1), (CAST)(I2), (CAST)(I3) + +#define NPYV__SET_8(CAST, I0, I1, I2, I3, I4, I5, I6, I7, ...) \ + (CAST)(I0), (CAST)(I1), (CAST)(I2), (CAST)(I3), (CAST)(I4), (CAST)(I5), (CAST)(I6), (CAST)(I7) + +#define NPYV__SET_16(CAST, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, ...) \ + NPYV__SET_8(CAST, I0, I1, I2, I3, I4, I5, I6, I7), \ + NPYV__SET_8(CAST, I8, I9, I10, I11, I12, I13, I14, I15) + +#define NPYV__SET_32(CAST, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, \ +I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, ...) \ + \ + NPYV__SET_16(CAST, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15), \ + NPYV__SET_16(CAST, I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31) + +#define NPYV__SET_64(CAST, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, \ +I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, \ +I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47, \ +I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63, ...) \ + \ + NPYV__SET_32(CAST, I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, \ +I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31), \ + NPYV__SET_32(CAST, I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47, \ +I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63) + +#define NPYV__SET_FILL_2(CAST, F, ...) NPY_EXPAND(NPYV__SET_2(CAST, __VA_ARGS__, F, F)) + +#define NPYV__SET_FILL_4(CAST, F, ...) NPY_EXPAND(NPYV__SET_4(CAST, __VA_ARGS__, F, F, F, F)) + +#define NPYV__SET_FILL_8(CAST, F, ...) NPY_EXPAND(NPYV__SET_8(CAST, __VA_ARGS__, F, F, F, F, F, F, F, F)) + +#define NPYV__SET_FILL_16(CAST, F, ...) NPY_EXPAND(NPYV__SET_16(CAST, __VA_ARGS__, \ + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F)) + +#define NPYV__SET_FILL_32(CAST, F, ...) NPY_EXPAND(NPYV__SET_32(CAST, __VA_ARGS__, \ + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F)) + +#define NPYV__SET_FILL_64(CAST, F, ...) NPY_EXPAND(NPYV__SET_64(CAST, __VA_ARGS__, \ + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, \ + F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F)) + +#endif // _NPY_SIMD_UTILS_H diff --git a/mkl_umath/src/npyv/sse/arithmetic.h b/mkl_umath/src/npyv/sse/arithmetic.h new file mode 100644 index 00000000..357b136d --- /dev/null +++ b/mkl_umath/src/npyv/sse/arithmetic.h @@ -0,0 +1,415 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_ARITHMETIC_H +#define _NPY_SIMD_SSE_ARITHMETIC_H + +/*************************** + * Addition + ***************************/ +// non-saturated +#define npyv_add_u8 _mm_add_epi8 +#define npyv_add_s8 _mm_add_epi8 +#define npyv_add_u16 _mm_add_epi16 +#define npyv_add_s16 _mm_add_epi16 +#define npyv_add_u32 _mm_add_epi32 +#define npyv_add_s32 _mm_add_epi32 +#define npyv_add_u64 _mm_add_epi64 +#define npyv_add_s64 _mm_add_epi64 +#define npyv_add_f32 _mm_add_ps +#define npyv_add_f64 _mm_add_pd + +// saturated +#define npyv_adds_u8 _mm_adds_epu8 +#define npyv_adds_s8 _mm_adds_epi8 +#define npyv_adds_u16 _mm_adds_epu16 +#define npyv_adds_s16 _mm_adds_epi16 +// TODO: rest, after implement Packs intrins + +/*************************** + * Subtraction + ***************************/ +// non-saturated +#define npyv_sub_u8 _mm_sub_epi8 +#define npyv_sub_s8 _mm_sub_epi8 +#define npyv_sub_u16 _mm_sub_epi16 +#define npyv_sub_s16 _mm_sub_epi16 +#define npyv_sub_u32 _mm_sub_epi32 +#define npyv_sub_s32 _mm_sub_epi32 +#define npyv_sub_u64 _mm_sub_epi64 +#define npyv_sub_s64 _mm_sub_epi64 +#define npyv_sub_f32 _mm_sub_ps +#define npyv_sub_f64 _mm_sub_pd + +// saturated +#define npyv_subs_u8 _mm_subs_epu8 +#define npyv_subs_s8 _mm_subs_epi8 +#define npyv_subs_u16 _mm_subs_epu16 +#define npyv_subs_s16 _mm_subs_epi16 +// TODO: rest, after implement Packs intrins + +/*************************** + * Multiplication + ***************************/ +// non-saturated +NPY_FINLINE __m128i npyv_mul_u8(__m128i a, __m128i b) +{ + const __m128i mask = _mm_set1_epi32(0xFF00FF00); + __m128i even = _mm_mullo_epi16(a, b); + __m128i odd = _mm_mullo_epi16(_mm_srai_epi16(a, 8), _mm_srai_epi16(b, 8)); + odd = _mm_slli_epi16(odd, 8); + return npyv_select_u8(mask, odd, even); +} +#define npyv_mul_s8 npyv_mul_u8 +#define npyv_mul_u16 _mm_mullo_epi16 +#define npyv_mul_s16 _mm_mullo_epi16 + +#ifdef NPY_HAVE_SSE41 + #define npyv_mul_u32 _mm_mullo_epi32 +#else + NPY_FINLINE __m128i npyv_mul_u32(__m128i a, __m128i b) + { + __m128i even = _mm_mul_epu32(a, b); + __m128i odd = _mm_mul_epu32(_mm_srli_epi64(a, 32), _mm_srli_epi64(b, 32)); + __m128i low = _mm_unpacklo_epi32(even, odd); + __m128i high = _mm_unpackhi_epi32(even, odd); + return _mm_unpacklo_epi64(low, high); + } +#endif // NPY_HAVE_SSE41 +#define npyv_mul_s32 npyv_mul_u32 +// TODO: emulate 64-bit*/ +#define npyv_mul_f32 _mm_mul_ps +#define npyv_mul_f64 _mm_mul_pd + +// saturated +// TODO: after implement Packs intrins + +/*************************** + * Integer Division + ***************************/ +// See simd/intdiv.h for more clarification +// divide each unsigned 8-bit element by a precomputed divisor +NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor) +{ + const __m128i bmask = _mm_set1_epi32(0x00FF00FF); + const __m128i shf1b = _mm_set1_epi8(0xFFU >> _mm_cvtsi128_si32(divisor.val[1])); + const __m128i shf2b = _mm_set1_epi8(0xFFU >> _mm_cvtsi128_si32(divisor.val[2])); + // high part of unsigned multiplication + __m128i mulhi_even = _mm_mullo_epi16(_mm_and_si128(a, bmask), divisor.val[0]); + __m128i mulhi_odd = _mm_mullo_epi16(_mm_srli_epi16(a, 8), divisor.val[0]); + mulhi_even = _mm_srli_epi16(mulhi_even, 8); + __m128i mulhi = npyv_select_u8(bmask, mulhi_even, mulhi_odd); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m128i q = _mm_sub_epi8(a, mulhi); + q = _mm_and_si128(_mm_srl_epi16(q, divisor.val[1]), shf1b); + q = _mm_add_epi8(mulhi, q); + q = _mm_and_si128(_mm_srl_epi16(q, divisor.val[2]), shf2b); + return q; +} +// divide each signed 8-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor); +NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor) +{ + const __m128i bmask = _mm_set1_epi32(0x00FF00FF); + // instead of _mm_cvtepi8_epi16/_mm_packs_epi16 to wrap around overflow + __m128i divc_even = npyv_divc_s16(_mm_srai_epi16(_mm_slli_epi16(a, 8), 8), divisor); + __m128i divc_odd = npyv_divc_s16(_mm_srai_epi16(a, 8), divisor); + divc_odd = _mm_slli_epi16(divc_odd, 8); + return npyv_select_u8(bmask, divc_even, divc_odd); +} +// divide each unsigned 16-bit element by a precomputed divisor +NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor) +{ + // high part of unsigned multiplication + __m128i mulhi = _mm_mulhi_epu16(a, divisor.val[0]); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m128i q = _mm_sub_epi16(a, mulhi); + q = _mm_srl_epi16(q, divisor.val[1]); + q = _mm_add_epi16(mulhi, q); + q = _mm_srl_epi16(q, divisor.val[2]); + return q; +} +// divide each signed 16-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor) +{ + // high part of signed multiplication + __m128i mulhi = _mm_mulhi_epi16(a, divisor.val[0]); + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + __m128i q = _mm_sra_epi16(_mm_add_epi16(a, mulhi), divisor.val[1]); + q = _mm_sub_epi16(q, _mm_srai_epi16(a, 15)); + q = _mm_sub_epi16(_mm_xor_si128(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 32-bit element by a precomputed divisor +NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor) +{ + // high part of unsigned multiplication + __m128i mulhi_even = _mm_srli_epi64(_mm_mul_epu32(a, divisor.val[0]), 32); + __m128i mulhi_odd = _mm_mul_epu32(_mm_srli_epi64(a, 32), divisor.val[0]); +#ifdef NPY_HAVE_SSE41 + __m128i mulhi = _mm_blend_epi16(mulhi_even, mulhi_odd, 0xCC); +#else + __m128i mask_13 = _mm_setr_epi32(0, -1, 0, -1); + mulhi_odd = _mm_and_si128(mulhi_odd, mask_13); + __m128i mulhi = _mm_or_si128(mulhi_even, mulhi_odd); +#endif + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m128i q = _mm_sub_epi32(a, mulhi); + q = _mm_srl_epi32(q, divisor.val[1]); + q = _mm_add_epi32(mulhi, q); + q = _mm_srl_epi32(q, divisor.val[2]); + return q; +} +// divide each signed 32-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor) +{ + __m128i asign = _mm_srai_epi32(a, 31); +#ifdef NPY_HAVE_SSE41 + // high part of signed multiplication + __m128i mulhi_even = _mm_srli_epi64(_mm_mul_epi32(a, divisor.val[0]), 32); + __m128i mulhi_odd = _mm_mul_epi32(_mm_srli_epi64(a, 32), divisor.val[0]); + __m128i mulhi = _mm_blend_epi16(mulhi_even, mulhi_odd, 0xCC); +#else // not SSE4.1 + // high part of "unsigned" multiplication + __m128i mulhi_even = _mm_srli_epi64(_mm_mul_epu32(a, divisor.val[0]), 32); + __m128i mulhi_odd = _mm_mul_epu32(_mm_srli_epi64(a, 32), divisor.val[0]); + __m128i mask_13 = _mm_setr_epi32(0, -1, 0, -1); + mulhi_odd = _mm_and_si128(mulhi_odd, mask_13); + __m128i mulhi = _mm_or_si128(mulhi_even, mulhi_odd); + // convert unsigned to signed high multiplication + // mulhi - ((a < 0) ? m : 0) - ((m < 0) ? a : 0); + const __m128i msign= _mm_srai_epi32(divisor.val[0], 31); + __m128i m_asign = _mm_and_si128(divisor.val[0], asign); + __m128i a_msign = _mm_and_si128(a, msign); + mulhi = _mm_sub_epi32(mulhi, m_asign); + mulhi = _mm_sub_epi32(mulhi, a_msign); +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + __m128i q = _mm_sra_epi32(_mm_add_epi32(a, mulhi), divisor.val[1]); + q = _mm_sub_epi32(q, asign); + q = _mm_sub_epi32(_mm_xor_si128(q, divisor.val[2]), divisor.val[2]); + return q; +} +// returns the high 64 bits of unsigned 64-bit multiplication +// xref https://stackoverflow.com/a/28827013 +NPY_FINLINE npyv_u64 npyv__mullhi_u64(npyv_u64 a, npyv_u64 b) +{ + __m128i lomask = npyv_setall_s64(0xffffffff); + __m128i a_hi = _mm_srli_epi64(a, 32); // a0l, a0h, a1l, a1h + __m128i b_hi = _mm_srli_epi64(b, 32); // b0l, b0h, b1l, b1h + // compute partial products + __m128i w0 = _mm_mul_epu32(a, b); // a0l*b0l, a1l*b1l + __m128i w1 = _mm_mul_epu32(a, b_hi); // a0l*b0h, a1l*b1h + __m128i w2 = _mm_mul_epu32(a_hi, b); // a0h*b0l, a1h*b0l + __m128i w3 = _mm_mul_epu32(a_hi, b_hi); // a0h*b0h, a1h*b1h + // sum partial products + __m128i w0h = _mm_srli_epi64(w0, 32); + __m128i s1 = _mm_add_epi64(w1, w0h); + __m128i s1l = _mm_and_si128(s1, lomask); + __m128i s1h = _mm_srli_epi64(s1, 32); + + __m128i s2 = _mm_add_epi64(w2, s1l); + __m128i s2h = _mm_srli_epi64(s2, 32); + + __m128i hi = _mm_add_epi64(w3, s1h); + hi = _mm_add_epi64(hi, s2h); + return hi; +} +// divide each unsigned 64-bit element by a precomputed divisor +NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor) +{ + // high part of unsigned multiplication + __m128i mulhi = npyv__mullhi_u64(a, divisor.val[0]); + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + __m128i q = _mm_sub_epi64(a, mulhi); + q = _mm_srl_epi64(q, divisor.val[1]); + q = _mm_add_epi64(mulhi, q); + q = _mm_srl_epi64(q, divisor.val[2]); + return q; +} +// divide each signed 64-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor) +{ + // high part of unsigned multiplication + __m128i mulhi = npyv__mullhi_u64(a, divisor.val[0]); + // convert unsigned to signed high multiplication + // mulhi - ((a < 0) ? m : 0) - ((m < 0) ? a : 0); +#ifdef NPY_HAVE_SSE42 + const __m128i msign= _mm_cmpgt_epi64(_mm_setzero_si128(), divisor.val[0]); + __m128i asign = _mm_cmpgt_epi64(_mm_setzero_si128(), a); +#else + const __m128i msign= _mm_srai_epi32(_mm_shuffle_epi32(divisor.val[0], _MM_SHUFFLE(3, 3, 1, 1)), 31); + __m128i asign = _mm_srai_epi32(_mm_shuffle_epi32(a, _MM_SHUFFLE(3, 3, 1, 1)), 31); +#endif + __m128i m_asign = _mm_and_si128(divisor.val[0], asign); + __m128i a_msign = _mm_and_si128(a, msign); + mulhi = _mm_sub_epi64(mulhi, m_asign); + mulhi = _mm_sub_epi64(mulhi, a_msign); + // q = (a + mulhi) >> sh + __m128i q = _mm_add_epi64(a, mulhi); + // emulate arithmetic right shift + const __m128i sigb = npyv_setall_s64(1LL << 63); + q = _mm_srl_epi64(_mm_add_epi64(q, sigb), divisor.val[1]); + q = _mm_sub_epi64(q, _mm_srl_epi64(sigb, divisor.val[1])); + // q = q - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + q = _mm_sub_epi64(q, asign); + q = _mm_sub_epi64(_mm_xor_si128(q, divisor.val[2]), divisor.val[2]); + return q; +} +/*************************** + * Division + ***************************/ +// TODO: emulate integer division +#define npyv_div_f32 _mm_div_ps +#define npyv_div_f64 _mm_div_pd +/*************************** + * FUSED + ***************************/ +#ifdef NPY_HAVE_FMA3 + // multiply and add, a*b + c + #define npyv_muladd_f32 _mm_fmadd_ps + #define npyv_muladd_f64 _mm_fmadd_pd + // multiply and subtract, a*b - c + #define npyv_mulsub_f32 _mm_fmsub_ps + #define npyv_mulsub_f64 _mm_fmsub_pd + // negate multiply and add, -(a*b) + c + #define npyv_nmuladd_f32 _mm_fnmadd_ps + #define npyv_nmuladd_f64 _mm_fnmadd_pd + // negate multiply and subtract, -(a*b) - c + #define npyv_nmulsub_f32 _mm_fnmsub_ps + #define npyv_nmulsub_f64 _mm_fnmsub_pd + // multiply, add for odd elements and subtract even elements. + // (a * b) -+ c + #define npyv_muladdsub_f32 _mm_fmaddsub_ps + #define npyv_muladdsub_f64 _mm_fmaddsub_pd +#elif defined(NPY_HAVE_FMA4) + // multiply and add, a*b + c + #define npyv_muladd_f32 _mm_macc_ps + #define npyv_muladd_f64 _mm_macc_pd + // multiply and subtract, a*b - c + #define npyv_mulsub_f32 _mm_msub_ps + #define npyv_mulsub_f64 _mm_msub_pd + // negate multiply and add, -(a*b) + c + #define npyv_nmuladd_f32 _mm_nmacc_ps + #define npyv_nmuladd_f64 _mm_nmacc_pd + // multiply, add for odd elements and subtract even elements. + // (a * b) -+ c + #define npyv_muladdsub_f32 _mm_maddsub_ps + #define npyv_muladdsub_f64 _mm_maddsub_pd +#else + // multiply and add, a*b + c + NPY_FINLINE npyv_f32 npyv_muladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return npyv_add_f32(npyv_mul_f32(a, b), c); } + NPY_FINLINE npyv_f64 npyv_muladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return npyv_add_f64(npyv_mul_f64(a, b), c); } + // multiply and subtract, a*b - c + NPY_FINLINE npyv_f32 npyv_mulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return npyv_sub_f32(npyv_mul_f32(a, b), c); } + NPY_FINLINE npyv_f64 npyv_mulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return npyv_sub_f64(npyv_mul_f64(a, b), c); } + // negate multiply and add, -(a*b) + c + NPY_FINLINE npyv_f32 npyv_nmuladd_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { return npyv_sub_f32(c, npyv_mul_f32(a, b)); } + NPY_FINLINE npyv_f64 npyv_nmuladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return npyv_sub_f64(c, npyv_mul_f64(a, b)); } + // multiply, add for odd elements and subtract even elements. + // (a * b) -+ c + NPY_FINLINE npyv_f32 npyv_muladdsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { + npyv_f32 m = npyv_mul_f32(a, b); + #ifdef NPY_HAVE_SSE3 + return _mm_addsub_ps(m, c); + #else + const npyv_f32 msign = npyv_set_f32(-0.0f, 0.0f, -0.0f, 0.0f); + return npyv_add_f32(m, npyv_xor_f32(msign, c)); + #endif + } + NPY_FINLINE npyv_f64 npyv_muladdsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { + npyv_f64 m = npyv_mul_f64(a, b); + #ifdef NPY_HAVE_SSE3 + return _mm_addsub_pd(m, c); + #else + const npyv_f64 msign = npyv_set_f64(-0.0, 0.0); + return npyv_add_f64(m, npyv_xor_f64(msign, c)); + #endif + } +#endif // NPY_HAVE_FMA3 +#ifndef NPY_HAVE_FMA3 // for FMA4 and NON-FMA3 + // negate multiply and subtract, -(a*b) - c + NPY_FINLINE npyv_f32 npyv_nmulsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) + { + npyv_f32 neg_a = npyv_xor_f32(a, npyv_setall_f32(-0.0f)); + return npyv_sub_f32(npyv_mul_f32(neg_a, b), c); + } + NPY_FINLINE npyv_f64 npyv_nmulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { + npyv_f64 neg_a = npyv_xor_f64(a, npyv_setall_f64(-0.0)); + return npyv_sub_f64(npyv_mul_f64(neg_a, b), c); + } +#endif // !NPY_HAVE_FMA3 + +/*************************** + * Summation + ***************************/ +// reduce sum across vector +NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) +{ + __m128i t = _mm_add_epi32(a, _mm_srli_si128(a, 8)); + t = _mm_add_epi32(t, _mm_srli_si128(t, 4)); + return (unsigned)_mm_cvtsi128_si32(t); +} + +NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) +{ + __m128i one = _mm_add_epi64(a, _mm_unpackhi_epi64(a, a)); + return (npy_uint64)npyv128_cvtsi128_si64(one); +} + +NPY_FINLINE float npyv_sum_f32(npyv_f32 a) +{ +#ifdef NPY_HAVE_SSE3 + __m128 sum_halves = _mm_hadd_ps(a, a); + return _mm_cvtss_f32(_mm_hadd_ps(sum_halves, sum_halves)); +#else + __m128 t1 = _mm_movehl_ps(a, a); + __m128 t2 = _mm_add_ps(a, t1); + __m128 t3 = _mm_shuffle_ps(t2, t2, 1); + __m128 t4 = _mm_add_ss(t2, t3); + return _mm_cvtss_f32(t4); +#endif +} + +NPY_FINLINE double npyv_sum_f64(npyv_f64 a) +{ +#ifdef NPY_HAVE_SSE3 + return _mm_cvtsd_f64(_mm_hadd_pd(a, a)); +#else + return _mm_cvtsd_f64(_mm_add_pd(a, _mm_unpackhi_pd(a, a))); +#endif +} + +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ + __m128i two = _mm_sad_epu8(a, _mm_setzero_si128()); + __m128i one = _mm_add_epi16(two, _mm_unpackhi_epi64(two, two)); + return (npy_uint16)_mm_cvtsi128_si32(one); +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ + const __m128i even_mask = _mm_set1_epi32(0x0000FFFF); + __m128i even = _mm_and_si128(a, even_mask); + __m128i odd = _mm_srli_epi32(a, 16); + __m128i four = _mm_add_epi32(even, odd); + return npyv_sum_u32(four); +} + +#endif // _NPY_SIMD_SSE_ARITHMETIC_H + + diff --git a/mkl_umath/src/npyv/sse/conversion.h b/mkl_umath/src/npyv/sse/conversion.h new file mode 100644 index 00000000..0811bf06 --- /dev/null +++ b/mkl_umath/src/npyv/sse/conversion.h @@ -0,0 +1,94 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_CVT_H +#define _NPY_SIMD_SSE_CVT_H + +// convert mask types to integer types +#define npyv_cvt_u8_b8(BL) BL +#define npyv_cvt_s8_b8(BL) BL +#define npyv_cvt_u16_b16(BL) BL +#define npyv_cvt_s16_b16(BL) BL +#define npyv_cvt_u32_b32(BL) BL +#define npyv_cvt_s32_b32(BL) BL +#define npyv_cvt_u64_b64(BL) BL +#define npyv_cvt_s64_b64(BL) BL +#define npyv_cvt_f32_b32 _mm_castsi128_ps +#define npyv_cvt_f64_b64 _mm_castsi128_pd + +// convert integer types to mask types +#define npyv_cvt_b8_u8(A) A +#define npyv_cvt_b8_s8(A) A +#define npyv_cvt_b16_u16(A) A +#define npyv_cvt_b16_s16(A) A +#define npyv_cvt_b32_u32(A) A +#define npyv_cvt_b32_s32(A) A +#define npyv_cvt_b64_u64(A) A +#define npyv_cvt_b64_s64(A) A +#define npyv_cvt_b32_f32 _mm_castps_si128 +#define npyv_cvt_b64_f64 _mm_castpd_si128 + +// convert boolean vector to integer bitfield +NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) +{ return (npy_uint16)_mm_movemask_epi8(a); } +NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a) +{ + __m128i pack = _mm_packs_epi16(a, a); + return (npy_uint8)_mm_movemask_epi8(pack); +} +NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a) +{ return (npy_uint8)_mm_movemask_ps(_mm_castsi128_ps(a)); } +NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a) +{ return (npy_uint8)_mm_movemask_pd(_mm_castsi128_pd(a)); } + +// expand +NPY_FINLINE npyv_u16x2 npyv_expand_u16_u8(npyv_u8 data) { + npyv_u16x2 r; + const __m128i z = _mm_setzero_si128(); + r.val[0] = _mm_unpacklo_epi8(data, z); + r.val[1] = _mm_unpackhi_epi8(data, z); + return r; +} + +NPY_FINLINE npyv_u32x2 npyv_expand_u32_u16(npyv_u16 data) { + npyv_u32x2 r; + const __m128i z = _mm_setzero_si128(); + r.val[0] = _mm_unpacklo_epi16(data, z); + r.val[1] = _mm_unpackhi_epi16(data, z); + return r; +} + +// pack two 16-bit boolean into one 8-bit boolean vector +NPY_FINLINE npyv_b8 npyv_pack_b8_b16(npyv_b16 a, npyv_b16 b) { + return _mm_packs_epi16(a, b); +} + +// pack four 32-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b32(npyv_b32 a, npyv_b32 b, npyv_b32 c, npyv_b32 d) { + npyv_b16 ab = _mm_packs_epi32(a, b); + npyv_b16 cd = _mm_packs_epi32(c, d); + return npyv_pack_b8_b16(ab, cd); +} + +// pack eight 64-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b64(npyv_b64 a, npyv_b64 b, npyv_b64 c, npyv_b64 d, + npyv_b64 e, npyv_b64 f, npyv_b64 g, npyv_b64 h) { + npyv_b32 ab = _mm_packs_epi32(a, b); + npyv_b32 cd = _mm_packs_epi32(c, d); + npyv_b32 ef = _mm_packs_epi32(e, f); + npyv_b32 gh = _mm_packs_epi32(g, h); + return npyv_pack_b8_b32(ab, cd, ef, gh); +} + +// round to nearest integer (assuming even) +#define npyv_round_s32_f32 _mm_cvtps_epi32 +NPY_FINLINE npyv_s32 npyv_round_s32_f64(npyv_f64 a, npyv_f64 b) +{ + __m128i lo = _mm_cvtpd_epi32(a), hi = _mm_cvtpd_epi32(b); + return _mm_unpacklo_epi64(lo, hi); +} + +#endif // _NPY_SIMD_SSE_CVT_H diff --git a/mkl_umath/src/npyv/sse/math.h b/mkl_umath/src/npyv/sse/math.h new file mode 100644 index 00000000..b51c935a --- /dev/null +++ b/mkl_umath/src/npyv/sse/math.h @@ -0,0 +1,463 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_MATH_H +#define _NPY_SIMD_SSE_MATH_H +/*************************** + * Elementary + ***************************/ +// Square root +#define npyv_sqrt_f32 _mm_sqrt_ps +#define npyv_sqrt_f64 _mm_sqrt_pd + +// Reciprocal +NPY_FINLINE npyv_f32 npyv_recip_f32(npyv_f32 a) +{ return _mm_div_ps(_mm_set1_ps(1.0f), a); } +NPY_FINLINE npyv_f64 npyv_recip_f64(npyv_f64 a) +{ return _mm_div_pd(_mm_set1_pd(1.0), a); } + +// Absolute +NPY_FINLINE npyv_f32 npyv_abs_f32(npyv_f32 a) +{ + return _mm_and_ps( + a, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)) + ); +} +NPY_FINLINE npyv_f64 npyv_abs_f64(npyv_f64 a) +{ + return _mm_and_pd( + a, _mm_castsi128_pd(npyv_setall_s64(0x7fffffffffffffffLL)) + ); +} + +// Square +NPY_FINLINE npyv_f32 npyv_square_f32(npyv_f32 a) +{ return _mm_mul_ps(a, a); } +NPY_FINLINE npyv_f64 npyv_square_f64(npyv_f64 a) +{ return _mm_mul_pd(a, a); } + +// Maximum, natively mapping with no guarantees to handle NaN. +#define npyv_max_f32 _mm_max_ps +#define npyv_max_f64 _mm_max_pd +// Maximum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_maxp_f32(npyv_f32 a, npyv_f32 b) +{ + __m128i nn = npyv_notnan_f32(b); + __m128 max = _mm_max_ps(a, b); + return npyv_select_f32(nn, max, a); +} +NPY_FINLINE npyv_f64 npyv_maxp_f64(npyv_f64 a, npyv_f64 b) +{ + __m128i nn = npyv_notnan_f64(b); + __m128d max = _mm_max_pd(a, b); + return npyv_select_f64(nn, max, a); +} +NPY_FINLINE npyv_f32 npyv_maxn_f32(npyv_f32 a, npyv_f32 b) +{ + __m128i nn = npyv_notnan_f32(a); + __m128 max = _mm_max_ps(a, b); + return npyv_select_f32(nn, max, a); +} +NPY_FINLINE npyv_f64 npyv_maxn_f64(npyv_f64 a, npyv_f64 b) +{ + __m128i nn = npyv_notnan_f64(a); + __m128d max = _mm_max_pd(a, b); + return npyv_select_f64(nn, max, a); +} +// Maximum, integer operations +#ifdef NPY_HAVE_SSE41 + #define npyv_max_s8 _mm_max_epi8 + #define npyv_max_u16 _mm_max_epu16 + #define npyv_max_u32 _mm_max_epu32 + #define npyv_max_s32 _mm_max_epi32 +#else + NPY_FINLINE npyv_s8 npyv_max_s8(npyv_s8 a, npyv_s8 b) + { + return npyv_select_s8(npyv_cmpgt_s8(a, b), a, b); + } + NPY_FINLINE npyv_u16 npyv_max_u16(npyv_u16 a, npyv_u16 b) + { + return npyv_select_u16(npyv_cmpgt_u16(a, b), a, b); + } + NPY_FINLINE npyv_u32 npyv_max_u32(npyv_u32 a, npyv_u32 b) + { + return npyv_select_u32(npyv_cmpgt_u32(a, b), a, b); + } + NPY_FINLINE npyv_s32 npyv_max_s32(npyv_s32 a, npyv_s32 b) + { + return npyv_select_s32(npyv_cmpgt_s32(a, b), a, b); + } +#endif +#define npyv_max_u8 _mm_max_epu8 +#define npyv_max_s16 _mm_max_epi16 +NPY_FINLINE npyv_u64 npyv_max_u64(npyv_u64 a, npyv_u64 b) +{ + return npyv_select_u64(npyv_cmpgt_u64(a, b), a, b); +} +NPY_FINLINE npyv_s64 npyv_max_s64(npyv_s64 a, npyv_s64 b) +{ + return npyv_select_s64(npyv_cmpgt_s64(a, b), a, b); +} + +// Minimum, natively mapping with no guarantees to handle NaN. +#define npyv_min_f32 _mm_min_ps +#define npyv_min_f64 _mm_min_pd +// Minimum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +NPY_FINLINE npyv_f32 npyv_minp_f32(npyv_f32 a, npyv_f32 b) +{ + __m128i nn = npyv_notnan_f32(b); + __m128 min = _mm_min_ps(a, b); + return npyv_select_f32(nn, min, a); +} +NPY_FINLINE npyv_f64 npyv_minp_f64(npyv_f64 a, npyv_f64 b) +{ + __m128i nn = npyv_notnan_f64(b); + __m128d min = _mm_min_pd(a, b); + return npyv_select_f64(nn, min, a); +} +NPY_FINLINE npyv_f32 npyv_minn_f32(npyv_f32 a, npyv_f32 b) +{ + __m128i nn = npyv_notnan_f32(a); + __m128 min = _mm_min_ps(a, b); + return npyv_select_f32(nn, min, a); +} +NPY_FINLINE npyv_f64 npyv_minn_f64(npyv_f64 a, npyv_f64 b) +{ + __m128i nn = npyv_notnan_f64(a); + __m128d min = _mm_min_pd(a, b); + return npyv_select_f64(nn, min, a); +} +// Minimum, integer operations +#ifdef NPY_HAVE_SSE41 + #define npyv_min_s8 _mm_min_epi8 + #define npyv_min_u16 _mm_min_epu16 + #define npyv_min_u32 _mm_min_epu32 + #define npyv_min_s32 _mm_min_epi32 +#else + NPY_FINLINE npyv_s8 npyv_min_s8(npyv_s8 a, npyv_s8 b) + { + return npyv_select_s8(npyv_cmplt_s8(a, b), a, b); + } + NPY_FINLINE npyv_u16 npyv_min_u16(npyv_u16 a, npyv_u16 b) + { + return npyv_select_u16(npyv_cmplt_u16(a, b), a, b); + } + NPY_FINLINE npyv_u32 npyv_min_u32(npyv_u32 a, npyv_u32 b) + { + return npyv_select_u32(npyv_cmplt_u32(a, b), a, b); + } + NPY_FINLINE npyv_s32 npyv_min_s32(npyv_s32 a, npyv_s32 b) + { + return npyv_select_s32(npyv_cmplt_s32(a, b), a, b); + } +#endif +#define npyv_min_u8 _mm_min_epu8 +#define npyv_min_s16 _mm_min_epi16 +NPY_FINLINE npyv_u64 npyv_min_u64(npyv_u64 a, npyv_u64 b) +{ + return npyv_select_u64(npyv_cmplt_u64(a, b), a, b); +} +NPY_FINLINE npyv_s64 npyv_min_s64(npyv_s64 a, npyv_s64 b) +{ + return npyv_select_s64(npyv_cmplt_s64(a, b), a, b); +} + +// reduce min&max for 32&64-bits +#define NPY_IMPL_SSE_REDUCE_MINMAX(STYPE, INTRIN, VINTRIN) \ + NPY_FINLINE STYPE##32 npyv_reduce_##INTRIN##32(__m128i a) \ + { \ + __m128i v64 = npyv_##INTRIN##32(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = npyv_##INTRIN##32(v64, _mm_shuffle_epi32(v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + return (STYPE##32)_mm_cvtsi128_si32(v32); \ + } \ + NPY_FINLINE STYPE##64 npyv_reduce_##INTRIN##64(__m128i a) \ + { \ + __m128i v64 = npyv_##INTRIN##64(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 3, 2))); \ + return (STYPE##64)npyv_extract0_u64(v64); \ + } + +NPY_IMPL_SSE_REDUCE_MINMAX(npy_uint, min_u, min_epu) +NPY_IMPL_SSE_REDUCE_MINMAX(npy_int, min_s, min_epi) +NPY_IMPL_SSE_REDUCE_MINMAX(npy_uint, max_u, max_epu) +NPY_IMPL_SSE_REDUCE_MINMAX(npy_int, max_s, max_epi) +#undef NPY_IMPL_SSE_REDUCE_MINMAX +// reduce min&max for ps & pd +#define NPY_IMPL_SSE_REDUCE_MINMAX(INTRIN, INF, INF64) \ + NPY_FINLINE float npyv_reduce_##INTRIN##_f32(npyv_f32 a) \ + { \ + __m128 v64 = _mm_##INTRIN##_ps(a, _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128 v32 = _mm_##INTRIN##_ps(v64, _mm_shuffle_ps(v64, v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + return _mm_cvtss_f32(v32); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##_f64(npyv_f64 a) \ + { \ + __m128d v64 = _mm_##INTRIN##_pd(a, _mm_shuffle_pd(a, a, _MM_SHUFFLE(0, 0, 0, 1))); \ + return _mm_cvtsd_f64(v64); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##p_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_any_b32(notnan))) { \ + return _mm_cvtss_f32(a); \ + } \ + a = npyv_select_f32(notnan, a, npyv_reinterpret_f32_u32(npyv_setall_u32(INF))); \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##p_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_any_b64(notnan))) { \ + return _mm_cvtsd_f64(a); \ + } \ + a = npyv_select_f64(notnan, a, npyv_reinterpret_f64_u64(npyv_setall_u64(INF64))); \ + return npyv_reduce_##INTRIN##_f64(a); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##n_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_all_b32(notnan))) { \ + const union { npy_uint32 i; float f;} pnan = {0x7fc00000UL}; \ + return pnan.f; \ + } \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##n_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_all_b64(notnan))) { \ + const union { npy_uint64 i; double d;} pnan = {0x7ff8000000000000ull}; \ + return pnan.d; \ + } \ + return npyv_reduce_##INTRIN##_f64(a); \ + } + +NPY_IMPL_SSE_REDUCE_MINMAX(min, 0x7f800000, 0x7ff0000000000000) +NPY_IMPL_SSE_REDUCE_MINMAX(max, 0xff800000, 0xfff0000000000000) +#undef NPY_IMPL_SSE_REDUCE_MINMAX + +// reduce min&max for 8&16-bits +#define NPY_IMPL_SSE_REDUCE_MINMAX(STYPE, INTRIN) \ + NPY_FINLINE STYPE##16 npyv_reduce_##INTRIN##16(__m128i a) \ + { \ + __m128i v64 = npyv_##INTRIN##16(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = npyv_##INTRIN##16(v64, _mm_shuffle_epi32(v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v16 = npyv_##INTRIN##16(v32, _mm_shufflelo_epi16(v32, _MM_SHUFFLE(0, 0, 0, 1))); \ + return (STYPE##16)_mm_cvtsi128_si32(v16); \ + } \ + NPY_FINLINE STYPE##8 npyv_reduce_##INTRIN##8(__m128i a) \ + { \ + __m128i v64 = npyv_##INTRIN##8(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 3, 2))); \ + __m128i v32 = npyv_##INTRIN##8(v64, _mm_shuffle_epi32(v64, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v16 = npyv_##INTRIN##8(v32, _mm_shufflelo_epi16(v32, _MM_SHUFFLE(0, 0, 0, 1))); \ + __m128i v8 = npyv_##INTRIN##8(v16, _mm_srli_epi16(v16, 8)); \ + return (STYPE##16)_mm_cvtsi128_si32(v8); \ + } +NPY_IMPL_SSE_REDUCE_MINMAX(npy_uint, min_u) +NPY_IMPL_SSE_REDUCE_MINMAX(npy_int, min_s) +NPY_IMPL_SSE_REDUCE_MINMAX(npy_uint, max_u) +NPY_IMPL_SSE_REDUCE_MINMAX(npy_int, max_s) +#undef NPY_IMPL_SSE_REDUCE_MINMAX + +// round to nearest integer even +NPY_FINLINE npyv_f32 npyv_rint_f32(npyv_f32 a) +{ +#ifdef NPY_HAVE_SSE41 + return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); +#else + const __m128 szero = _mm_set1_ps(-0.0f); + const __m128i exp_mask = _mm_set1_epi32(0xff000000); + + __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); + nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); + nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); + + // eliminate nans/inf to avoid invalid fp errors + __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); + __m128i roundi = _mm_cvtps_epi32(x); + __m128 round = _mm_cvtepi32_ps(roundi); + // respect signed zero + round = _mm_or_ps(round, _mm_and_ps(a, szero)); + // if overflow return a + __m128i overflow_mask = _mm_cmpeq_epi32(roundi, _mm_castps_si128(szero)); + // a if a overflow or nonfinite + return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, round); +#endif +} + +// round to nearest integer even +NPY_FINLINE npyv_f64 npyv_rint_f64(npyv_f64 a) +{ +#ifdef NPY_HAVE_SSE41 + return _mm_round_pd(a, _MM_FROUND_TO_NEAREST_INT); +#else + const __m128d szero = _mm_set1_pd(-0.0); + const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); + __m128d nan_mask = _mm_cmpunord_pd(a, a); + // eliminate nans to avoid invalid fp errors within cmpge + __m128d abs_x = npyv_abs_f64(_mm_xor_pd(nan_mask, a)); + // round by add magic number 2^52 + // assuming that MXCSR register is set to rounding + __m128d round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); + // copysign + round = _mm_or_pd(round, _mm_and_pd(a, szero)); + // a if |a| >= 2^52 or a == NaN + __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); + mask = _mm_or_pd(mask, nan_mask); + return npyv_select_f64(_mm_castpd_si128(mask), a, round); +#endif +} +// ceil +#ifdef NPY_HAVE_SSE41 + #define npyv_ceil_f32 _mm_ceil_ps + #define npyv_ceil_f64 _mm_ceil_pd +#else + NPY_FINLINE npyv_f32 npyv_ceil_f32(npyv_f32 a) + { + const __m128 one = _mm_set1_ps(1.0f); + const __m128 szero = _mm_set1_ps(-0.0f); + const __m128i exp_mask = _mm_set1_epi32(0xff000000); + + __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); + nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); + nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); + + // eliminate nans/inf to avoid invalid fp errors + __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); + __m128i roundi = _mm_cvtps_epi32(x); + __m128 round = _mm_cvtepi32_ps(roundi); + __m128 ceil = _mm_add_ps(round, _mm_and_ps(_mm_cmplt_ps(round, x), one)); + // respect signed zero + ceil = _mm_or_ps(ceil, _mm_and_ps(a, szero)); + // if overflow return a + __m128i overflow_mask = _mm_cmpeq_epi32(roundi, _mm_castps_si128(szero)); + // a if a overflow or nonfinite + return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, ceil); + } + NPY_FINLINE npyv_f64 npyv_ceil_f64(npyv_f64 a) + { + const __m128d one = _mm_set1_pd(1.0); + const __m128d szero = _mm_set1_pd(-0.0); + const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); + __m128d nan_mask = _mm_cmpunord_pd(a, a); + // eliminate nans to avoid invalid fp errors within cmpge + __m128d x = _mm_xor_pd(nan_mask, a); + __m128d abs_x = npyv_abs_f64(x); + __m128d sign_x = _mm_and_pd(x, szero); + // round by add magic number 2^52 + // assuming that MXCSR register is set to rounding + __m128d round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); + // copysign + round = _mm_or_pd(round, sign_x); + __m128d ceil = _mm_add_pd(round, _mm_and_pd(_mm_cmplt_pd(round, x), one)); + // respects sign of 0.0 + ceil = _mm_or_pd(ceil, sign_x); + // a if |a| >= 2^52 or a == NaN + __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); + mask = _mm_or_pd(mask, nan_mask); + return npyv_select_f64(_mm_castpd_si128(mask), a, ceil); + } +#endif + +// trunc +#ifdef NPY_HAVE_SSE41 + #define npyv_trunc_f32(A) _mm_round_ps(A, _MM_FROUND_TO_ZERO) + #define npyv_trunc_f64(A) _mm_round_pd(A, _MM_FROUND_TO_ZERO) +#else + NPY_FINLINE npyv_f32 npyv_trunc_f32(npyv_f32 a) + { + const __m128 szero = _mm_set1_ps(-0.0f); + const __m128i exp_mask = _mm_set1_epi32(0xff000000); + + __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); + nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); + nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); + + // eliminate nans/inf to avoid invalid fp errors + __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); + __m128i trunci = _mm_cvttps_epi32(x); + __m128 trunc = _mm_cvtepi32_ps(trunci); + // respect signed zero, e.g. -0.5 -> -0.0 + trunc = _mm_or_ps(trunc, _mm_and_ps(a, szero)); + // if overflow return a + __m128i overflow_mask = _mm_cmpeq_epi32(trunci, _mm_castps_si128(szero)); + // a if a overflow or nonfinite + return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, trunc); + } + NPY_FINLINE npyv_f64 npyv_trunc_f64(npyv_f64 a) + { + const __m128d one = _mm_set1_pd(1.0); + const __m128d szero = _mm_set1_pd(-0.0); + const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); + __m128d nan_mask = _mm_cmpunord_pd(a, a); + // eliminate nans to avoid invalid fp errors within cmpge + __m128d abs_x = npyv_abs_f64(_mm_xor_pd(nan_mask, a)); + // round by add magic number 2^52 + // assuming that MXCSR register is set to rounding + __m128d abs_round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); + __m128d subtrahend = _mm_and_pd(_mm_cmpgt_pd(abs_round, abs_x), one); + __m128d trunc = _mm_sub_pd(abs_round, subtrahend); + // copysign + trunc = _mm_or_pd(trunc, _mm_and_pd(a, szero)); + // a if |a| >= 2^52 or a == NaN + __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); + mask = _mm_or_pd(mask, nan_mask); + return npyv_select_f64(_mm_castpd_si128(mask), a, trunc); + } +#endif + +// floor +#ifdef NPY_HAVE_SSE41 + #define npyv_floor_f32 _mm_floor_ps + #define npyv_floor_f64 _mm_floor_pd +#else + NPY_FINLINE npyv_f32 npyv_floor_f32(npyv_f32 a) + { + const __m128 one = _mm_set1_ps(1.0f); + const __m128 szero = _mm_set1_ps(-0.0f); + const __m128i exp_mask = _mm_set1_epi32(0xff000000); + + __m128i nfinite_mask = _mm_slli_epi32(_mm_castps_si128(a), 1); + nfinite_mask = _mm_and_si128(nfinite_mask, exp_mask); + nfinite_mask = _mm_cmpeq_epi32(nfinite_mask, exp_mask); + + // eliminate nans/inf to avoid invalid fp errors + __m128 x = _mm_xor_ps(a, _mm_castsi128_ps(nfinite_mask)); + __m128i roundi = _mm_cvtps_epi32(x); + __m128 round = _mm_cvtepi32_ps(roundi); + __m128 floor = _mm_sub_ps(round, _mm_and_ps(_mm_cmpgt_ps(round, x), one)); + // respect signed zero + floor = _mm_or_ps(floor, _mm_and_ps(a, szero)); + // if overflow return a + __m128i overflow_mask = _mm_cmpeq_epi32(roundi, _mm_castps_si128(szero)); + // a if a overflow or nonfinite + return npyv_select_f32(_mm_or_si128(nfinite_mask, overflow_mask), a, floor); + } + NPY_FINLINE npyv_f64 npyv_floor_f64(npyv_f64 a) + { + const __m128d one = _mm_set1_pd(1.0f); + const __m128d szero = _mm_set1_pd(-0.0f); + const __m128d two_power_52 = _mm_set1_pd(0x10000000000000); + __m128d nan_mask = _mm_cmpunord_pd(a, a); + // eliminate nans to avoid invalid fp errors within cmpge + __m128d x = _mm_xor_pd(nan_mask, a); + __m128d abs_x = npyv_abs_f64(x); + __m128d sign_x = _mm_and_pd(x, szero); + // round by add magic number 2^52 + // assuming that MXCSR register is set to rounding + __m128d round = _mm_sub_pd(_mm_add_pd(two_power_52, abs_x), two_power_52); + // copysign + round = _mm_or_pd(round, sign_x); + __m128d floor = _mm_sub_pd(round, _mm_and_pd(_mm_cmpgt_pd(round, x), one)); + // a if |a| >= 2^52 or a == NaN + __m128d mask = _mm_cmpge_pd(abs_x, two_power_52); + mask = _mm_or_pd(mask, nan_mask); + return npyv_select_f64(_mm_castpd_si128(mask), a, floor); + } +#endif // NPY_HAVE_SSE41 + +#endif // _NPY_SIMD_SSE_MATH_H diff --git a/mkl_umath/src/npyv/sse/memory.h b/mkl_umath/src/npyv/sse/memory.h new file mode 100644 index 00000000..90c01ffe --- /dev/null +++ b/mkl_umath/src/npyv/sse/memory.h @@ -0,0 +1,759 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_MEMORY_H +#define _NPY_SIMD_SSE_MEMORY_H + +#include "misc.h" + +/*************************** + * load/store + ***************************/ +// stream load +#ifdef NPY_HAVE_SSE41 + #define npyv__loads(PTR) _mm_stream_load_si128((__m128i *)(PTR)) +#else + #define npyv__loads(PTR) _mm_load_si128((const __m128i *)(PTR)) +#endif +#define NPYV_IMPL_SSE_MEM_INT(CTYPE, SFX) \ + NPY_FINLINE npyv_##SFX npyv_load_##SFX(const CTYPE *ptr) \ + { return _mm_loadu_si128((const __m128i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loada_##SFX(const CTYPE *ptr) \ + { return _mm_load_si128((const __m128i*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loads_##SFX(const CTYPE *ptr) \ + { return npyv__loads(ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loadl_##SFX(const CTYPE *ptr) \ + { return _mm_loadl_epi64((const __m128i*)ptr); } \ + NPY_FINLINE void npyv_store_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_storeu_si128((__m128i*)ptr, vec); } \ + NPY_FINLINE void npyv_storea_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_store_si128((__m128i*)ptr, vec); } \ + NPY_FINLINE void npyv_stores_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_stream_si128((__m128i*)ptr, vec); } \ + NPY_FINLINE void npyv_storel_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_storel_epi64((__m128i *)ptr, vec); } \ + NPY_FINLINE void npyv_storeh_##SFX(CTYPE *ptr, npyv_##SFX vec) \ + { _mm_storel_epi64((__m128i *)ptr, _mm_unpackhi_epi64(vec, vec)); } + +NPYV_IMPL_SSE_MEM_INT(npy_uint8, u8) +NPYV_IMPL_SSE_MEM_INT(npy_int8, s8) +NPYV_IMPL_SSE_MEM_INT(npy_uint16, u16) +NPYV_IMPL_SSE_MEM_INT(npy_int16, s16) +NPYV_IMPL_SSE_MEM_INT(npy_uint32, u32) +NPYV_IMPL_SSE_MEM_INT(npy_int32, s32) +NPYV_IMPL_SSE_MEM_INT(npy_uint64, u64) +NPYV_IMPL_SSE_MEM_INT(npy_int64, s64) + +// unaligned load +#define npyv_load_f32 _mm_loadu_ps +#define npyv_load_f64 _mm_loadu_pd +// aligned load +#define npyv_loada_f32 _mm_load_ps +#define npyv_loada_f64 _mm_load_pd +// load lower part +#define npyv_loadl_f32(PTR) _mm_castsi128_ps(npyv_loadl_u32((const npy_uint32*)(PTR))) +#define npyv_loadl_f64(PTR) _mm_castsi128_pd(npyv_loadl_u32((const npy_uint32*)(PTR))) +// stream load +#define npyv_loads_f32(PTR) _mm_castsi128_ps(npyv__loads(PTR)) +#define npyv_loads_f64(PTR) _mm_castsi128_pd(npyv__loads(PTR)) +// unaligned store +#define npyv_store_f32 _mm_storeu_ps +#define npyv_store_f64 _mm_storeu_pd +// aligned store +#define npyv_storea_f32 _mm_store_ps +#define npyv_storea_f64 _mm_store_pd +// stream store +#define npyv_stores_f32 _mm_stream_ps +#define npyv_stores_f64 _mm_stream_pd +// store lower part +#define npyv_storel_f32(PTR, VEC) _mm_storel_epi64((__m128i*)(PTR), _mm_castps_si128(VEC)); +#define npyv_storel_f64(PTR, VEC) _mm_storel_epi64((__m128i*)(PTR), _mm_castpd_si128(VEC)); +// store higher part +#define npyv_storeh_f32(PTR, VEC) npyv_storeh_u32((npy_uint32*)(PTR), _mm_castps_si128(VEC)) +#define npyv_storeh_f64(PTR, VEC) npyv_storeh_u32((npy_uint32*)(PTR), _mm_castpd_si128(VEC)) +/*************************** + * Non-contiguous Load + ***************************/ +//// 32 +NPY_FINLINE npyv_s32 npyv_loadn_s32(const npy_int32 *ptr, npy_intp stride) +{ + __m128i a = _mm_cvtsi32_si128(*ptr); +#ifdef NPY_HAVE_SSE41 + a = _mm_insert_epi32(a, ptr[stride], 1); + a = _mm_insert_epi32(a, ptr[stride*2], 2); + a = _mm_insert_epi32(a, ptr[stride*3], 3); +#else + __m128i a1 = _mm_cvtsi32_si128(ptr[stride]); + __m128i a2 = _mm_cvtsi32_si128(ptr[stride*2]); + __m128i a3 = _mm_cvtsi32_si128(ptr[stride*3]); + a = _mm_unpacklo_epi32(a, a1); + a = _mm_unpacklo_epi64(a, _mm_unpacklo_epi32(a2, a3)); +#endif + return a; +} +NPY_FINLINE npyv_u32 npyv_loadn_u32(const npy_uint32 *ptr, npy_intp stride) +{ return npyv_loadn_s32((const npy_int32*)ptr, stride); } +NPY_FINLINE npyv_f32 npyv_loadn_f32(const float *ptr, npy_intp stride) +{ return _mm_castsi128_ps(npyv_loadn_s32((const npy_int32*)ptr, stride)); } +//// 64 +NPY_FINLINE npyv_f64 npyv_loadn_f64(const double *ptr, npy_intp stride) +{ return _mm_loadh_pd(npyv_loadl_f64(ptr), ptr + stride); } +NPY_FINLINE npyv_u64 npyv_loadn_u64(const npy_uint64 *ptr, npy_intp stride) +{ return _mm_castpd_si128(npyv_loadn_f64((const double*)ptr, stride)); } +NPY_FINLINE npyv_s64 npyv_loadn_s64(const npy_int64 *ptr, npy_intp stride) +{ return _mm_castpd_si128(npyv_loadn_f64((const double*)ptr, stride)); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_f32 npyv_loadn2_f32(const float *ptr, npy_intp stride) +{ + __m128d r = _mm_loadh_pd( + npyv_loadl_f64((const double*)ptr), (const double*)(ptr + stride) + ); + return _mm_castpd_ps(r); +} +NPY_FINLINE npyv_u32 npyv_loadn2_u32(const npy_uint32 *ptr, npy_intp stride) +{ return _mm_castps_si128(npyv_loadn2_f32((const float*)ptr, stride)); } +NPY_FINLINE npyv_s32 npyv_loadn2_s32(const npy_int32 *ptr, npy_intp stride) +{ return _mm_castps_si128(npyv_loadn2_f32((const float*)ptr, stride)); } + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_f64 npyv_loadn2_f64(const double *ptr, npy_intp stride) +{ (void)stride; return npyv_load_f64(ptr); } +NPY_FINLINE npyv_u64 npyv_loadn2_u64(const npy_uint64 *ptr, npy_intp stride) +{ (void)stride; return npyv_load_u64(ptr); } +NPY_FINLINE npyv_s64 npyv_loadn2_s64(const npy_int64 *ptr, npy_intp stride) +{ (void)stride; return npyv_load_s64(ptr); } + +/*************************** + * Non-contiguous Store + ***************************/ +//// 32 +NPY_FINLINE void npyv_storen_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ + ptr[stride * 0] = _mm_cvtsi128_si32(a); +#ifdef NPY_HAVE_SSE41 + ptr[stride * 1] = _mm_extract_epi32(a, 1); + ptr[stride * 2] = _mm_extract_epi32(a, 2); + ptr[stride * 3] = _mm_extract_epi32(a, 3); +#else + ptr[stride * 1] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 1))); + ptr[stride * 2] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 2))); + ptr[stride * 3] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 3))); +#endif +} +NPY_FINLINE void npyv_storen_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ npyv_storen_s32((npy_int32*)ptr, stride, a); } +NPY_FINLINE void npyv_storen_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen_s32((npy_int32*)ptr, stride, _mm_castps_si128(a)); } +//// 64 +NPY_FINLINE void npyv_storen_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ + _mm_storel_pd(ptr, a); + _mm_storeh_pd(ptr + stride, a); +} +NPY_FINLINE void npyv_storen_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ npyv_storen_f64((double*)ptr, stride, _mm_castsi128_pd(a)); } +NPY_FINLINE void npyv_storen_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ npyv_storen_f64((double*)ptr, stride, _mm_castsi128_pd(a)); } + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ + _mm_storel_pd((double*)ptr, _mm_castsi128_pd(a)); + _mm_storeh_pd((double*)(ptr + stride), _mm_castsi128_pd(a)); +} +NPY_FINLINE void npyv_storen2_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, a); } +NPY_FINLINE void npyv_storen2_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, _mm_castps_si128(a)); } + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ (void)stride; npyv_store_u64(ptr, a); } +NPY_FINLINE void npyv_storen2_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ (void)stride; npyv_store_s64(ptr, a); } +NPY_FINLINE void npyv_storen2_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ (void)stride; npyv_store_f64(ptr, a); } +/********************************* + * Partial Load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 npyv_load_till_s32(const npy_int32 *ptr, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + #ifndef NPY_HAVE_SSE41 + const short *wptr = (const short*)ptr; + #endif + const __m128i vfill = npyv_setall_s32(fill); + __m128i a; + switch(nlane) { + case 2: + a = _mm_castpd_si128( + _mm_loadl_pd(_mm_castsi128_pd(vfill), (double*)ptr) + ); + break; + #ifdef NPY_HAVE_SSE41 + case 1: + a = _mm_insert_epi32(vfill, ptr[0], 0); + break; + case 3: + a = _mm_loadl_epi64((const __m128i*)ptr); + a = _mm_insert_epi32(a, ptr[2], 2); + a = _mm_insert_epi32(a, fill, 3); + break; + #else + case 1: + a = _mm_insert_epi16(vfill, wptr[0], 0); + a = _mm_insert_epi16(a, wptr[1], 1); + break; + case 3: + a = _mm_loadl_epi64((const __m128i*)ptr); + a = _mm_unpacklo_epi64(a, vfill); + a = _mm_insert_epi16(a, wptr[4], 4); + a = _mm_insert_epi16(a, wptr[5], 5); + break; + #endif // NPY_HAVE_SSE41 + default: + return npyv_load_s32(ptr); + } + #if NPY_SIMD_GUARD_PARTIAL_LOAD + // We use a variable marked 'volatile' to convince the compiler that + // the entire vector is needed. + volatile __m128i workaround = a; + // avoid optimizing it out + a = _mm_or_si128(workaround, a); + #endif + return a; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + switch(nlane) { + case 1: + return _mm_cvtsi32_si128(*ptr); + case 2: + return _mm_loadl_epi64((const __m128i*)ptr); + case 3: { + npyv_s32 a = _mm_loadl_epi64((const __m128i*)ptr); + #ifdef NPY_HAVE_SSE41 + return _mm_insert_epi32(a, ptr[2], 2); + #else + return _mm_unpacklo_epi64(a, _mm_cvtsi32_si128(ptr[2])); + #endif + } + default: + return npyv_load_s32(ptr); + } +} +//// 64 +NPY_FINLINE npyv_s64 npyv_load_till_s64(const npy_int64 *ptr, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + if (nlane == 1) { + const __m128i vfill = npyv_setall_s64(fill); + npyv_s64 a = _mm_castpd_si128( + _mm_loadl_pd(_mm_castsi128_pd(vfill), (double*)ptr) + ); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m128i workaround = a; + a = _mm_or_si128(workaround, a); + #endif + return a; + } + return npyv_load_s64(ptr); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_load_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ + assert(nlane > 0); + if (nlane == 1) { + return _mm_loadl_epi64((const __m128i*)ptr); + } + return npyv_load_s64(ptr); +} + +//// 64-bit nlane +NPY_FINLINE npyv_s32 npyv_load2_till_s32(const npy_int32 *ptr, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + if (nlane == 1) { + const __m128i vfill = npyv_set_s32(fill_lo, fill_hi, fill_lo, fill_hi); + __m128i a = _mm_castpd_si128( + _mm_loadl_pd(_mm_castsi128_pd(vfill), (double*)ptr) + ); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m128i workaround = a; + a = _mm_or_si128(workaround, a); + #endif + return a; + } + return npyv_load_s32(ptr); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load2_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ return npyv_load_tillz_s64((const npy_int64*)ptr, nlane); } + +//// 128-bit nlane +NPY_FINLINE npyv_s64 npyv_load2_till_s64(const npy_int64 *ptr, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ (void)nlane; (void)fill_lo; (void)fill_hi; return npyv_load_s64(ptr); } + +NPY_FINLINE npyv_s64 npyv_load2_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ (void)nlane; return npyv_load_s64(ptr); } + +/********************************* + * Non-contiguous partial load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 +npyv_loadn_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + __m128i vfill = npyv_setall_s32(fill); + #ifndef NPY_HAVE_SSE41 + const short *wptr = (const short*)ptr; + #endif + switch(nlane) { + #ifdef NPY_HAVE_SSE41 + case 3: + vfill = _mm_insert_epi32(vfill, ptr[stride*2], 2); + case 2: + vfill = _mm_insert_epi32(vfill, ptr[stride], 1); + case 1: + vfill = _mm_insert_epi32(vfill, ptr[0], 0); + break; + #else + case 3: + vfill = _mm_unpacklo_epi32(_mm_cvtsi32_si128(ptr[stride*2]), vfill); + case 2: + vfill = _mm_unpacklo_epi64(_mm_unpacklo_epi32( + _mm_cvtsi32_si128(*ptr), _mm_cvtsi32_si128(ptr[stride]) + ), vfill); + break; + case 1: + vfill = _mm_insert_epi16(vfill, wptr[0], 0); + vfill = _mm_insert_epi16(vfill, wptr[1], 1); + break; + #endif // NPY_HAVE_SSE41 + default: + return npyv_loadn_s32(ptr, stride); + } // switch +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m128i workaround = vfill; + vfill = _mm_or_si128(workaround, vfill); +#endif + return vfill; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 +npyv_loadn_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ + assert(nlane > 0); + switch(nlane) { + case 1: + return _mm_cvtsi32_si128(ptr[0]); + case 2:; + { + npyv_s32 a = _mm_cvtsi32_si128(ptr[0]); + #ifdef NPY_HAVE_SSE41 + return _mm_insert_epi32(a, ptr[stride], 1); + #else + return _mm_unpacklo_epi32(a, _mm_cvtsi32_si128(ptr[stride])); + #endif // NPY_HAVE_SSE41 + } + case 3: + { + npyv_s32 a = _mm_cvtsi32_si128(ptr[0]); + #ifdef NPY_HAVE_SSE41 + a = _mm_insert_epi32(a, ptr[stride], 1); + a = _mm_insert_epi32(a, ptr[stride*2], 2); + return a; + #else + a = _mm_unpacklo_epi32(a, _mm_cvtsi32_si128(ptr[stride])); + a = _mm_unpacklo_epi64(a, _mm_cvtsi32_si128(ptr[stride*2])); + return a; + #endif // NPY_HAVE_SSE41 + } + default: + return npyv_loadn_s32(ptr, stride); + } +} +//// 64 +NPY_FINLINE npyv_s64 +npyv_loadn_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + if (nlane == 1) { + return npyv_load_till_s64(ptr, 1, fill); + } + return npyv_loadn_s64(ptr, stride); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_loadn_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ + assert(nlane > 0); + if (nlane == 1) { + return _mm_loadl_epi64((const __m128i*)ptr); + } + return npyv_loadn_s64(ptr, stride); +} + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_s32 npyv_loadn2_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + if (nlane == 1) { + const __m128i vfill = npyv_set_s32(0, 0, fill_lo, fill_hi); + __m128i a = _mm_castpd_si128( + _mm_loadl_pd(_mm_castsi128_pd(vfill), (double*)ptr) + ); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile __m128i workaround = a; + a = _mm_or_si128(workaround, a); + #endif + return a; + } + return npyv_loadn2_s32(ptr, stride); +} +NPY_FINLINE npyv_s32 npyv_loadn2_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ + assert(nlane > 0); + if (nlane == 1) { + return _mm_loadl_epi64((const __m128i*)ptr); + } + return npyv_loadn2_s32(ptr, stride); +} + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ assert(nlane > 0); (void)stride; (void)nlane; (void)fill_lo; (void)fill_hi; return npyv_load_s64(ptr); } + +NPY_FINLINE npyv_s64 npyv_loadn2_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ assert(nlane > 0); (void)stride; (void)nlane; return npyv_load_s64(ptr); } + +/********************************* + * Partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_store_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + switch(nlane) { + case 1: + *ptr = _mm_cvtsi128_si32(a); + break; + case 2: + _mm_storel_epi64((__m128i *)ptr, a); + break; + case 3: + _mm_storel_epi64((__m128i *)ptr, a); + #ifdef NPY_HAVE_SSE41 + ptr[2] = _mm_extract_epi32(a, 2); + #else + ptr[2] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 2))); + #endif + break; + default: + npyv_store_s32(ptr, a); + } +} +//// 64 +NPY_FINLINE void npyv_store_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + if (nlane == 1) { + _mm_storel_epi64((__m128i *)ptr, a); + return; + } + npyv_store_s64(ptr, a); +} +//// 64-bit nlane +NPY_FINLINE void npyv_store2_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ npyv_store_till_s64((npy_int64*)ptr, nlane, a); } + +//// 128-bit nlane +NPY_FINLINE void npyv_store2_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); (void)nlane; + npyv_store_s64(ptr, a); +} + +/********************************* + * Non-contiguous partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_storen_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + ptr[stride*0] = _mm_cvtsi128_si32(a); + switch(nlane) { + case 1: + return; +#ifdef NPY_HAVE_SSE41 + case 2: + ptr[stride*1] = _mm_extract_epi32(a, 1); + return; + case 3: + ptr[stride*1] = _mm_extract_epi32(a, 1); + ptr[stride*2] = _mm_extract_epi32(a, 2); + return; + default: + ptr[stride*1] = _mm_extract_epi32(a, 1); + ptr[stride*2] = _mm_extract_epi32(a, 2); + ptr[stride*3] = _mm_extract_epi32(a, 3); +#else + case 2: + ptr[stride*1] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 1))); + return; + case 3: + ptr[stride*1] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 1))); + ptr[stride*2] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 2))); + return; + default: + ptr[stride*1] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 1))); + ptr[stride*2] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 2))); + ptr[stride*3] = _mm_cvtsi128_si32(_mm_shuffle_epi32(a, _MM_SHUFFLE(0, 0, 0, 3))); +#endif + } +} +//// 64 +NPY_FINLINE void npyv_storen_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + if (nlane == 1) { + _mm_storel_epi64((__m128i *)ptr, a); + return; + } + npyv_storen_s64(ptr, stride, a); +} + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + npyv_storel_s32(ptr, a); + if (nlane > 1) { + npyv_storeh_s32(ptr + stride, a); + } +} + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ assert(nlane > 0); (void)stride; (void)nlane; npyv_store_s64(ptr, a); } + +/***************************************************************** + * Implement partial load/store for u32/f32/u64/f64... via casting + *****************************************************************/ +#define NPYV_IMPL_SSE_REST_PARTIAL_TYPES(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_SSE_REST_PARTIAL_TYPES(u32, s32) +NPYV_IMPL_SSE_REST_PARTIAL_TYPES(f32, s32) +NPYV_IMPL_SSE_REST_PARTIAL_TYPES(u64, s64) +NPYV_IMPL_SSE_REST_PARTIAL_TYPES(f64, s64) + +// 128-bit/64-bit stride +#define NPYV_IMPL_SSE_REST_PARTIAL_TYPES_PAIR(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun_lo.to_##T_SFX, pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun_lo.to_##T_SFX, \ + pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_SSE_REST_PARTIAL_TYPES_PAIR(u32, s32) +NPYV_IMPL_SSE_REST_PARTIAL_TYPES_PAIR(f32, s32) +NPYV_IMPL_SSE_REST_PARTIAL_TYPES_PAIR(u64, s64) +NPYV_IMPL_SSE_REST_PARTIAL_TYPES_PAIR(f64, s64) + +/************************************************************ + * de-interlave load / interleave contiguous store + ************************************************************/ +// two channels +#define NPYV_IMPL_SSE_MEM_INTERLEAVE(SFX, ZSFX) \ + NPY_FINLINE npyv_##ZSFX##x2 npyv_zip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX); \ + NPY_FINLINE npyv_##ZSFX##x2 npyv_unzip_##ZSFX(npyv_##ZSFX, npyv_##ZSFX); \ + NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2( \ + const npyv_lanetype_##SFX *ptr \ + ) { \ + return npyv_unzip_##ZSFX( \ + npyv_load_##SFX(ptr), npyv_load_##SFX(ptr+npyv_nlanes_##SFX) \ + ); \ + } \ + NPY_FINLINE void npyv_store_##SFX##x2( \ + npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v \ + ) { \ + npyv_##SFX##x2 zip = npyv_zip_##ZSFX(v.val[0], v.val[1]); \ + npyv_store_##SFX(ptr, zip.val[0]); \ + npyv_store_##SFX(ptr + npyv_nlanes_##SFX, zip.val[1]); \ + } + +NPYV_IMPL_SSE_MEM_INTERLEAVE(u8, u8) +NPYV_IMPL_SSE_MEM_INTERLEAVE(s8, u8) +NPYV_IMPL_SSE_MEM_INTERLEAVE(u16, u16) +NPYV_IMPL_SSE_MEM_INTERLEAVE(s16, u16) +NPYV_IMPL_SSE_MEM_INTERLEAVE(u32, u32) +NPYV_IMPL_SSE_MEM_INTERLEAVE(s32, u32) +NPYV_IMPL_SSE_MEM_INTERLEAVE(u64, u64) +NPYV_IMPL_SSE_MEM_INTERLEAVE(s64, u64) +NPYV_IMPL_SSE_MEM_INTERLEAVE(f32, f32) +NPYV_IMPL_SSE_MEM_INTERLEAVE(f64, f64) + +/********************************* + * Lookup table + *********************************/ +// uses vector as indexes into a table +// that contains 32 elements of float32. +NPY_FINLINE npyv_f32 npyv_lut32_f32(const float *table, npyv_u32 idx) +{ + const int i0 = _mm_cvtsi128_si32(idx); +#ifdef NPY_HAVE_SSE41 + const int i1 = _mm_extract_epi32(idx, 1); + const int i2 = _mm_extract_epi32(idx, 2); + const int i3 = _mm_extract_epi32(idx, 3); +#else + const int i1 = _mm_extract_epi16(idx, 2); + const int i2 = _mm_extract_epi16(idx, 4); + const int i3 = _mm_extract_epi16(idx, 6); +#endif + return npyv_set_f32(table[i0], table[i1], table[i2], table[i3]); +} +NPY_FINLINE npyv_u32 npyv_lut32_u32(const npy_uint32 *table, npyv_u32 idx) +{ return npyv_reinterpret_u32_f32(npyv_lut32_f32((const float*)table, idx)); } +NPY_FINLINE npyv_s32 npyv_lut32_s32(const npy_int32 *table, npyv_u32 idx) +{ return npyv_reinterpret_s32_f32(npyv_lut32_f32((const float*)table, idx)); } + +// uses vector as indexes into a table +// that contains 16 elements of float64. +NPY_FINLINE npyv_f64 npyv_lut16_f64(const double *table, npyv_u64 idx) +{ + const int i0 = _mm_cvtsi128_si32(idx); +#ifdef NPY_HAVE_SSE41 + const int i1 = _mm_extract_epi32(idx, 2); +#else + const int i1 = _mm_extract_epi16(idx, 4); +#endif + return npyv_set_f64(table[i0], table[i1]); +} +NPY_FINLINE npyv_u64 npyv_lut16_u64(const npy_uint64 *table, npyv_u64 idx) +{ return npyv_reinterpret_u64_f64(npyv_lut16_f64((const double*)table, idx)); } +NPY_FINLINE npyv_s64 npyv_lut16_s64(const npy_int64 *table, npyv_u64 idx) +{ return npyv_reinterpret_s64_f64(npyv_lut16_f64((const double*)table, idx)); } + +#endif // _NPY_SIMD_SSE_MEMORY_H diff --git a/mkl_umath/src/npyv/sse/misc.h b/mkl_umath/src/npyv/sse/misc.h new file mode 100644 index 00000000..b01ff172 --- /dev/null +++ b/mkl_umath/src/npyv/sse/misc.h @@ -0,0 +1,258 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_MISC_H +#define _NPY_SIMD_SSE_MISC_H + +// vector with zero lanes +#define npyv_zero_u8 _mm_setzero_si128 +#define npyv_zero_s8 _mm_setzero_si128 +#define npyv_zero_u16 _mm_setzero_si128 +#define npyv_zero_s16 _mm_setzero_si128 +#define npyv_zero_u32 _mm_setzero_si128 +#define npyv_zero_s32 _mm_setzero_si128 +#define npyv_zero_u64 _mm_setzero_si128 +#define npyv_zero_s64 _mm_setzero_si128 +#define npyv_zero_f32 _mm_setzero_ps +#define npyv_zero_f64 _mm_setzero_pd + +// vector with a specific value set to all lanes +#define npyv_setall_u8(VAL) _mm_set1_epi8((char)(VAL)) +#define npyv_setall_s8(VAL) _mm_set1_epi8((char)(VAL)) +#define npyv_setall_u16(VAL) _mm_set1_epi16((short)(VAL)) +#define npyv_setall_s16(VAL) _mm_set1_epi16((short)(VAL)) +#define npyv_setall_u32(VAL) _mm_set1_epi32((int)(VAL)) +#define npyv_setall_s32(VAL) _mm_set1_epi32((int)(VAL)) +#define npyv_setall_f32 _mm_set1_ps +#define npyv_setall_f64 _mm_set1_pd + +NPY_FINLINE __m128i npyv__setr_epi64(npy_int64 i0, npy_int64 i1); + +NPY_FINLINE npyv_u64 npyv_setall_u64(npy_uint64 a) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return npyv__setr_epi64((npy_int64)a, (npy_int64)a); +#else + return _mm_set1_epi64x((npy_int64)a); +#endif +} +NPY_FINLINE npyv_s64 npyv_setall_s64(npy_int64 a) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return npyv__setr_epi64(a, a); +#else + return _mm_set1_epi64x((npy_int64)a); +#endif +} + +/** + * vector with specific values set to each lane and + * set a specific value to all remained lanes + * + * Args that generated by NPYV__SET_FILL_* not going to expand if + * _mm_setr_* are defined as macros. + */ +NPY_FINLINE __m128i npyv__setr_epi8( + char i0, char i1, char i2, char i3, char i4, char i5, char i6, char i7, + char i8, char i9, char i10, char i11, char i12, char i13, char i14, char i15) +{ + return _mm_setr_epi8(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15); +} +NPY_FINLINE __m128i npyv__setr_epi16(short i0, short i1, short i2, short i3, short i4, short i5, + short i6, short i7) +{ + return _mm_setr_epi16(i0, i1, i2, i3, i4, i5, i6, i7); +} +NPY_FINLINE __m128i npyv__setr_epi32(int i0, int i1, int i2, int i3) +{ + return _mm_setr_epi32(i0, i1, i2, i3); +} +NPY_FINLINE __m128i npyv__setr_epi64(npy_int64 i0, npy_int64 i1) +{ +#if defined(_MSC_VER) && defined(_M_IX86) + return _mm_setr_epi32((int)i0, (int)(i0 >> 32), (int)i1, (int)(i1 >> 32)); +#else + return _mm_set_epi64x(i1, i0); +#endif +} +NPY_FINLINE __m128 npyv__setr_ps(float i0, float i1, float i2, float i3) +{ + return _mm_setr_ps(i0, i1, i2, i3); +} +NPY_FINLINE __m128d npyv__setr_pd(double i0, double i1) +{ + return _mm_setr_pd(i0, i1); +} +#define npyv_setf_u8(FILL, ...) npyv__setr_epi8(NPYV__SET_FILL_16(char, FILL, __VA_ARGS__)) +#define npyv_setf_s8(FILL, ...) npyv__setr_epi8(NPYV__SET_FILL_16(char, FILL, __VA_ARGS__)) +#define npyv_setf_u16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_8(short, FILL, __VA_ARGS__)) +#define npyv_setf_s16(FILL, ...) npyv__setr_epi16(NPYV__SET_FILL_8(short, FILL, __VA_ARGS__)) +#define npyv_setf_u32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_4(int, FILL, __VA_ARGS__)) +#define npyv_setf_s32(FILL, ...) npyv__setr_epi32(NPYV__SET_FILL_4(int, FILL, __VA_ARGS__)) +#define npyv_setf_u64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_2(npy_int64, FILL, __VA_ARGS__)) +#define npyv_setf_s64(FILL, ...) npyv__setr_epi64(NPYV__SET_FILL_2(npy_int64, FILL, __VA_ARGS__)) +#define npyv_setf_f32(FILL, ...) npyv__setr_ps(NPYV__SET_FILL_4(float, FILL, __VA_ARGS__)) +#define npyv_setf_f64(FILL, ...) npyv__setr_pd(NPYV__SET_FILL_2(double, FILL, __VA_ARGS__)) + +// vector with specific values set to each lane and +// set zero to all remained lanes +#define npyv_set_u8(...) npyv_setf_u8(0, __VA_ARGS__) +#define npyv_set_s8(...) npyv_setf_s8(0, __VA_ARGS__) +#define npyv_set_u16(...) npyv_setf_u16(0, __VA_ARGS__) +#define npyv_set_s16(...) npyv_setf_s16(0, __VA_ARGS__) +#define npyv_set_u32(...) npyv_setf_u32(0, __VA_ARGS__) +#define npyv_set_s32(...) npyv_setf_s32(0, __VA_ARGS__) +#define npyv_set_u64(...) npyv_setf_u64(0, __VA_ARGS__) +#define npyv_set_s64(...) npyv_setf_s64(0, __VA_ARGS__) +#define npyv_set_f32(...) npyv_setf_f32(0, __VA_ARGS__) +#define npyv_set_f64(...) npyv_setf_f64(0, __VA_ARGS__) + +// Per lane select +#ifdef NPY_HAVE_SSE41 + #define npyv_select_u8(MASK, A, B) _mm_blendv_epi8(B, A, MASK) + #define npyv_select_f32(MASK, A, B) _mm_blendv_ps(B, A, _mm_castsi128_ps(MASK)) + #define npyv_select_f64(MASK, A, B) _mm_blendv_pd(B, A, _mm_castsi128_pd(MASK)) +#else + NPY_FINLINE __m128i npyv_select_u8(__m128i mask, __m128i a, __m128i b) + { return _mm_xor_si128(b, _mm_and_si128(_mm_xor_si128(b, a), mask)); } + NPY_FINLINE __m128 npyv_select_f32(__m128i mask, __m128 a, __m128 b) + { return _mm_xor_ps(b, _mm_and_ps(_mm_xor_ps(b, a), _mm_castsi128_ps(mask))); } + NPY_FINLINE __m128d npyv_select_f64(__m128i mask, __m128d a, __m128d b) + { return _mm_xor_pd(b, _mm_and_pd(_mm_xor_pd(b, a), _mm_castsi128_pd(mask))); } +#endif +#define npyv_select_s8 npyv_select_u8 +#define npyv_select_u16 npyv_select_u8 +#define npyv_select_s16 npyv_select_u8 +#define npyv_select_u32 npyv_select_u8 +#define npyv_select_s32 npyv_select_u8 +#define npyv_select_u64 npyv_select_u8 +#define npyv_select_s64 npyv_select_u8 + +// extract the first vector's lane +#define npyv_extract0_u8(A) ((npy_uint8)_mm_cvtsi128_si32(A)) +#define npyv_extract0_s8(A) ((npy_int8)_mm_cvtsi128_si32(A)) +#define npyv_extract0_u16(A) ((npy_uint16)_mm_cvtsi128_si32(A)) +#define npyv_extract0_s16(A) ((npy_int16)_mm_cvtsi128_si32(A)) +#define npyv_extract0_u32(A) ((npy_uint32)_mm_cvtsi128_si32(A)) +#define npyv_extract0_s32(A) ((npy_int32)_mm_cvtsi128_si32(A)) +#define npyv_extract0_u64(A) ((npy_uint64)npyv128_cvtsi128_si64(A)) +#define npyv_extract0_s64(A) ((npy_int64)npyv128_cvtsi128_si64(A)) +#define npyv_extract0_f32 _mm_cvtss_f32 +#define npyv_extract0_f64 _mm_cvtsd_f64 + +// Reinterpret +#define npyv_reinterpret_u8_u8(X) X +#define npyv_reinterpret_u8_s8(X) X +#define npyv_reinterpret_u8_u16(X) X +#define npyv_reinterpret_u8_s16(X) X +#define npyv_reinterpret_u8_u32(X) X +#define npyv_reinterpret_u8_s32(X) X +#define npyv_reinterpret_u8_u64(X) X +#define npyv_reinterpret_u8_s64(X) X +#define npyv_reinterpret_u8_f32 _mm_castps_si128 +#define npyv_reinterpret_u8_f64 _mm_castpd_si128 + +#define npyv_reinterpret_s8_s8(X) X +#define npyv_reinterpret_s8_u8(X) X +#define npyv_reinterpret_s8_u16(X) X +#define npyv_reinterpret_s8_s16(X) X +#define npyv_reinterpret_s8_u32(X) X +#define npyv_reinterpret_s8_s32(X) X +#define npyv_reinterpret_s8_u64(X) X +#define npyv_reinterpret_s8_s64(X) X +#define npyv_reinterpret_s8_f32 _mm_castps_si128 +#define npyv_reinterpret_s8_f64 _mm_castpd_si128 + +#define npyv_reinterpret_u16_u16(X) X +#define npyv_reinterpret_u16_u8(X) X +#define npyv_reinterpret_u16_s8(X) X +#define npyv_reinterpret_u16_s16(X) X +#define npyv_reinterpret_u16_u32(X) X +#define npyv_reinterpret_u16_s32(X) X +#define npyv_reinterpret_u16_u64(X) X +#define npyv_reinterpret_u16_s64(X) X +#define npyv_reinterpret_u16_f32 _mm_castps_si128 +#define npyv_reinterpret_u16_f64 _mm_castpd_si128 + +#define npyv_reinterpret_s16_s16(X) X +#define npyv_reinterpret_s16_u8(X) X +#define npyv_reinterpret_s16_s8(X) X +#define npyv_reinterpret_s16_u16(X) X +#define npyv_reinterpret_s16_u32(X) X +#define npyv_reinterpret_s16_s32(X) X +#define npyv_reinterpret_s16_u64(X) X +#define npyv_reinterpret_s16_s64(X) X +#define npyv_reinterpret_s16_f32 _mm_castps_si128 +#define npyv_reinterpret_s16_f64 _mm_castpd_si128 + +#define npyv_reinterpret_u32_u32(X) X +#define npyv_reinterpret_u32_u8(X) X +#define npyv_reinterpret_u32_s8(X) X +#define npyv_reinterpret_u32_u16(X) X +#define npyv_reinterpret_u32_s16(X) X +#define npyv_reinterpret_u32_s32(X) X +#define npyv_reinterpret_u32_u64(X) X +#define npyv_reinterpret_u32_s64(X) X +#define npyv_reinterpret_u32_f32 _mm_castps_si128 +#define npyv_reinterpret_u32_f64 _mm_castpd_si128 + +#define npyv_reinterpret_s32_s32(X) X +#define npyv_reinterpret_s32_u8(X) X +#define npyv_reinterpret_s32_s8(X) X +#define npyv_reinterpret_s32_u16(X) X +#define npyv_reinterpret_s32_s16(X) X +#define npyv_reinterpret_s32_u32(X) X +#define npyv_reinterpret_s32_u64(X) X +#define npyv_reinterpret_s32_s64(X) X +#define npyv_reinterpret_s32_f32 _mm_castps_si128 +#define npyv_reinterpret_s32_f64 _mm_castpd_si128 + +#define npyv_reinterpret_u64_u64(X) X +#define npyv_reinterpret_u64_u8(X) X +#define npyv_reinterpret_u64_s8(X) X +#define npyv_reinterpret_u64_u16(X) X +#define npyv_reinterpret_u64_s16(X) X +#define npyv_reinterpret_u64_u32(X) X +#define npyv_reinterpret_u64_s32(X) X +#define npyv_reinterpret_u64_s64(X) X +#define npyv_reinterpret_u64_f32 _mm_castps_si128 +#define npyv_reinterpret_u64_f64 _mm_castpd_si128 + +#define npyv_reinterpret_s64_s64(X) X +#define npyv_reinterpret_s64_u8(X) X +#define npyv_reinterpret_s64_s8(X) X +#define npyv_reinterpret_s64_u16(X) X +#define npyv_reinterpret_s64_s16(X) X +#define npyv_reinterpret_s64_u32(X) X +#define npyv_reinterpret_s64_s32(X) X +#define npyv_reinterpret_s64_u64(X) X +#define npyv_reinterpret_s64_f32 _mm_castps_si128 +#define npyv_reinterpret_s64_f64 _mm_castpd_si128 + +#define npyv_reinterpret_f32_f32(X) X +#define npyv_reinterpret_f32_u8 _mm_castsi128_ps +#define npyv_reinterpret_f32_s8 _mm_castsi128_ps +#define npyv_reinterpret_f32_u16 _mm_castsi128_ps +#define npyv_reinterpret_f32_s16 _mm_castsi128_ps +#define npyv_reinterpret_f32_u32 _mm_castsi128_ps +#define npyv_reinterpret_f32_s32 _mm_castsi128_ps +#define npyv_reinterpret_f32_u64 _mm_castsi128_ps +#define npyv_reinterpret_f32_s64 _mm_castsi128_ps +#define npyv_reinterpret_f32_f64 _mm_castpd_ps + +#define npyv_reinterpret_f64_f64(X) X +#define npyv_reinterpret_f64_u8 _mm_castsi128_pd +#define npyv_reinterpret_f64_s8 _mm_castsi128_pd +#define npyv_reinterpret_f64_u16 _mm_castsi128_pd +#define npyv_reinterpret_f64_s16 _mm_castsi128_pd +#define npyv_reinterpret_f64_u32 _mm_castsi128_pd +#define npyv_reinterpret_f64_s32 _mm_castsi128_pd +#define npyv_reinterpret_f64_u64 _mm_castsi128_pd +#define npyv_reinterpret_f64_s64 _mm_castsi128_pd +#define npyv_reinterpret_f64_f32 _mm_castps_pd + +// Only required by AVX2/AVX512 +#define npyv_cleanup() ((void)0) + +#endif // _NPY_SIMD_SSE_MISC_H diff --git a/mkl_umath/src/npyv/sse/operators.h b/mkl_umath/src/npyv/sse/operators.h new file mode 100644 index 00000000..59182679 --- /dev/null +++ b/mkl_umath/src/npyv/sse/operators.h @@ -0,0 +1,342 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_OPERATORS_H +#define _NPY_SIMD_SSE_OPERATORS_H + +/*************************** + * Shifting + ***************************/ + +// left +#define npyv_shl_u16(A, C) _mm_sll_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s16(A, C) _mm_sll_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_u32(A, C) _mm_sll_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s32(A, C) _mm_sll_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_u64(A, C) _mm_sll_epi64(A, _mm_cvtsi32_si128(C)) +#define npyv_shl_s64(A, C) _mm_sll_epi64(A, _mm_cvtsi32_si128(C)) + +// left by an immediate constant +#define npyv_shli_u16 _mm_slli_epi16 +#define npyv_shli_s16 _mm_slli_epi16 +#define npyv_shli_u32 _mm_slli_epi32 +#define npyv_shli_s32 _mm_slli_epi32 +#define npyv_shli_u64 _mm_slli_epi64 +#define npyv_shli_s64 _mm_slli_epi64 + +// right +#define npyv_shr_u16(A, C) _mm_srl_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_s16(A, C) _mm_sra_epi16(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_u32(A, C) _mm_srl_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_s32(A, C) _mm_sra_epi32(A, _mm_cvtsi32_si128(C)) +#define npyv_shr_u64(A, C) _mm_srl_epi64(A, _mm_cvtsi32_si128(C)) +NPY_FINLINE __m128i npyv_shr_s64(__m128i a, int c) +{ + const __m128i sbit = npyv_setall_s64(0x8000000000000000); + const __m128i cv = _mm_cvtsi32_si128(c); + __m128i r = _mm_srl_epi64(_mm_add_epi64(a, sbit), cv); + return _mm_sub_epi64(r, _mm_srl_epi64(sbit, cv)); +} + +// Right by an immediate constant +#define npyv_shri_u16 _mm_srli_epi16 +#define npyv_shri_s16 _mm_srai_epi16 +#define npyv_shri_u32 _mm_srli_epi32 +#define npyv_shri_s32 _mm_srai_epi32 +#define npyv_shri_u64 _mm_srli_epi64 +#define npyv_shri_s64 npyv_shr_s64 + +/*************************** + * Logical + ***************************/ + +// AND +#define npyv_and_u8 _mm_and_si128 +#define npyv_and_s8 _mm_and_si128 +#define npyv_and_u16 _mm_and_si128 +#define npyv_and_s16 _mm_and_si128 +#define npyv_and_u32 _mm_and_si128 +#define npyv_and_s32 _mm_and_si128 +#define npyv_and_u64 _mm_and_si128 +#define npyv_and_s64 _mm_and_si128 +#define npyv_and_f32 _mm_and_ps +#define npyv_and_f64 _mm_and_pd +#define npyv_and_b8 _mm_and_si128 +#define npyv_and_b16 _mm_and_si128 +#define npyv_and_b32 _mm_and_si128 +#define npyv_and_b64 _mm_and_si128 + +// OR +#define npyv_or_u8 _mm_or_si128 +#define npyv_or_s8 _mm_or_si128 +#define npyv_or_u16 _mm_or_si128 +#define npyv_or_s16 _mm_or_si128 +#define npyv_or_u32 _mm_or_si128 +#define npyv_or_s32 _mm_or_si128 +#define npyv_or_u64 _mm_or_si128 +#define npyv_or_s64 _mm_or_si128 +#define npyv_or_f32 _mm_or_ps +#define npyv_or_f64 _mm_or_pd +#define npyv_or_b8 _mm_or_si128 +#define npyv_or_b16 _mm_or_si128 +#define npyv_or_b32 _mm_or_si128 +#define npyv_or_b64 _mm_or_si128 + +// XOR +#define npyv_xor_u8 _mm_xor_si128 +#define npyv_xor_s8 _mm_xor_si128 +#define npyv_xor_u16 _mm_xor_si128 +#define npyv_xor_s16 _mm_xor_si128 +#define npyv_xor_u32 _mm_xor_si128 +#define npyv_xor_s32 _mm_xor_si128 +#define npyv_xor_u64 _mm_xor_si128 +#define npyv_xor_s64 _mm_xor_si128 +#define npyv_xor_f32 _mm_xor_ps +#define npyv_xor_f64 _mm_xor_pd +#define npyv_xor_b8 _mm_xor_si128 +#define npyv_xor_b16 _mm_xor_si128 +#define npyv_xor_b32 _mm_xor_si128 +#define npyv_xor_b64 _mm_xor_si128 + +// NOT +#define npyv_not_u8(A) _mm_xor_si128(A, _mm_set1_epi32(-1)) +#define npyv_not_s8 npyv_not_u8 +#define npyv_not_u16 npyv_not_u8 +#define npyv_not_s16 npyv_not_u8 +#define npyv_not_u32 npyv_not_u8 +#define npyv_not_s32 npyv_not_u8 +#define npyv_not_u64 npyv_not_u8 +#define npyv_not_s64 npyv_not_u8 +#define npyv_not_f32(A) _mm_xor_ps(A, _mm_castsi128_ps(_mm_set1_epi32(-1))) +#define npyv_not_f64(A) _mm_xor_pd(A, _mm_castsi128_pd(_mm_set1_epi32(-1))) +#define npyv_not_b8 npyv_not_u8 +#define npyv_not_b16 npyv_not_u8 +#define npyv_not_b32 npyv_not_u8 +#define npyv_not_b64 npyv_not_u8 + +// ANDC, ORC and XNOR +#define npyv_andc_u8(A, B) _mm_andnot_si128(B, A) +#define npyv_andc_b8(A, B) _mm_andnot_si128(B, A) +#define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A) +#define npyv_xnor_b8 _mm_cmpeq_epi8 + +/*************************** + * Comparison + ***************************/ + +// Int Equal +#define npyv_cmpeq_u8 _mm_cmpeq_epi8 +#define npyv_cmpeq_s8 _mm_cmpeq_epi8 +#define npyv_cmpeq_u16 _mm_cmpeq_epi16 +#define npyv_cmpeq_s16 _mm_cmpeq_epi16 +#define npyv_cmpeq_u32 _mm_cmpeq_epi32 +#define npyv_cmpeq_s32 _mm_cmpeq_epi32 +#define npyv_cmpeq_s64 npyv_cmpeq_u64 + +#ifdef NPY_HAVE_SSE41 + #define npyv_cmpeq_u64 _mm_cmpeq_epi64 +#else + NPY_FINLINE __m128i npyv_cmpeq_u64(__m128i a, __m128i b) + { + __m128i cmpeq = _mm_cmpeq_epi32(a, b); + __m128i cmpeq_h = _mm_srli_epi64(cmpeq, 32); + __m128i test = _mm_and_si128(cmpeq, cmpeq_h); + return _mm_shuffle_epi32(test, _MM_SHUFFLE(2, 2, 0, 0)); + } +#endif + +// Int Not Equal +#ifdef NPY_HAVE_XOP + #define npyv_cmpneq_u8 _mm_comneq_epi8 + #define npyv_cmpneq_u16 _mm_comneq_epi16 + #define npyv_cmpneq_u32 _mm_comneq_epi32 + #define npyv_cmpneq_u64 _mm_comneq_epi64 +#else + #define npyv_cmpneq_u8(A, B) npyv_not_u8(npyv_cmpeq_u8(A, B)) + #define npyv_cmpneq_u16(A, B) npyv_not_u16(npyv_cmpeq_u16(A, B)) + #define npyv_cmpneq_u32(A, B) npyv_not_u32(npyv_cmpeq_u32(A, B)) + #define npyv_cmpneq_u64(A, B) npyv_not_u64(npyv_cmpeq_u64(A, B)) +#endif +#define npyv_cmpneq_s8 npyv_cmpneq_u8 +#define npyv_cmpneq_s16 npyv_cmpneq_u16 +#define npyv_cmpneq_s32 npyv_cmpneq_u32 +#define npyv_cmpneq_s64 npyv_cmpneq_u64 + +// signed greater than +#define npyv_cmpgt_s8 _mm_cmpgt_epi8 +#define npyv_cmpgt_s16 _mm_cmpgt_epi16 +#define npyv_cmpgt_s32 _mm_cmpgt_epi32 + +#ifdef NPY_HAVE_SSE42 + #define npyv_cmpgt_s64 _mm_cmpgt_epi64 +#else + NPY_FINLINE __m128i npyv_cmpgt_s64(__m128i a, __m128i b) + { + __m128i sub = _mm_sub_epi64(b, a); + __m128i nsame_sbit = _mm_xor_si128(a, b); + // nsame_sbit ? b : sub + __m128i test = _mm_xor_si128(sub, _mm_and_si128(_mm_xor_si128(sub, b), nsame_sbit)); + __m128i extend_sbit = _mm_shuffle_epi32(_mm_srai_epi32(test, 31), _MM_SHUFFLE(3, 3, 1, 1)); + return extend_sbit; + } +#endif + +// signed greater than or equal +#ifdef NPY_HAVE_XOP + #define npyv_cmpge_s8 _mm_comge_epi8 + #define npyv_cmpge_s16 _mm_comge_epi16 + #define npyv_cmpge_s32 _mm_comge_epi32 + #define npyv_cmpge_s64 _mm_comge_epi64 +#else + #define npyv_cmpge_s8(A, B) npyv_not_s8(_mm_cmpgt_epi8(B, A)) + #define npyv_cmpge_s16(A, B) npyv_not_s16(_mm_cmpgt_epi16(B, A)) + #define npyv_cmpge_s32(A, B) npyv_not_s32(_mm_cmpgt_epi32(B, A)) + #define npyv_cmpge_s64(A, B) npyv_not_s64(npyv_cmpgt_s64(B, A)) +#endif + +// unsigned greater than +#ifdef NPY_HAVE_XOP + #define npyv_cmpgt_u8 _mm_comgt_epu8 + #define npyv_cmpgt_u16 _mm_comgt_epu16 + #define npyv_cmpgt_u32 _mm_comgt_epu32 + #define npyv_cmpgt_u64 _mm_comgt_epu64 +#else + #define NPYV_IMPL_SSE_UNSIGNED_GT(LEN, SIGN) \ + NPY_FINLINE __m128i npyv_cmpgt_u##LEN(__m128i a, __m128i b) \ + { \ + const __m128i sbit = _mm_set1_epi32(SIGN); \ + return _mm_cmpgt_epi##LEN( \ + _mm_xor_si128(a, sbit), _mm_xor_si128(b, sbit) \ + ); \ + } + + NPYV_IMPL_SSE_UNSIGNED_GT(8, 0x80808080) + NPYV_IMPL_SSE_UNSIGNED_GT(16, 0x80008000) + NPYV_IMPL_SSE_UNSIGNED_GT(32, 0x80000000) + + NPY_FINLINE __m128i npyv_cmpgt_u64(__m128i a, __m128i b) + { + const __m128i sbit = npyv_setall_s64(0x8000000000000000); + return npyv_cmpgt_s64(_mm_xor_si128(a, sbit), _mm_xor_si128(b, sbit)); + } +#endif + +// unsigned greater than or equal +#ifdef NPY_HAVE_XOP + #define npyv_cmpge_u8 _mm_comge_epu8 + #define npyv_cmpge_u16 _mm_comge_epu16 + #define npyv_cmpge_u32 _mm_comge_epu32 + #define npyv_cmpge_u64 _mm_comge_epu64 +#else + NPY_FINLINE __m128i npyv_cmpge_u8(__m128i a, __m128i b) + { return _mm_cmpeq_epi8(a, _mm_max_epu8(a, b)); } + #ifdef NPY_HAVE_SSE41 + NPY_FINLINE __m128i npyv_cmpge_u16(__m128i a, __m128i b) + { return _mm_cmpeq_epi16(a, _mm_max_epu16(a, b)); } + NPY_FINLINE __m128i npyv_cmpge_u32(__m128i a, __m128i b) + { return _mm_cmpeq_epi32(a, _mm_max_epu32(a, b)); } + #else + #define npyv_cmpge_u16(A, B) _mm_cmpeq_epi16(_mm_subs_epu16(B, A), _mm_setzero_si128()) + #define npyv_cmpge_u32(A, B) npyv_not_u32(npyv_cmpgt_u32(B, A)) + #endif + #define npyv_cmpge_u64(A, B) npyv_not_u64(npyv_cmpgt_u64(B, A)) +#endif + +// less than +#define npyv_cmplt_u8(A, B) npyv_cmpgt_u8(B, A) +#define npyv_cmplt_s8(A, B) npyv_cmpgt_s8(B, A) +#define npyv_cmplt_u16(A, B) npyv_cmpgt_u16(B, A) +#define npyv_cmplt_s16(A, B) npyv_cmpgt_s16(B, A) +#define npyv_cmplt_u32(A, B) npyv_cmpgt_u32(B, A) +#define npyv_cmplt_s32(A, B) npyv_cmpgt_s32(B, A) +#define npyv_cmplt_u64(A, B) npyv_cmpgt_u64(B, A) +#define npyv_cmplt_s64(A, B) npyv_cmpgt_s64(B, A) + +// less than or equal +#define npyv_cmple_u8(A, B) npyv_cmpge_u8(B, A) +#define npyv_cmple_s8(A, B) npyv_cmpge_s8(B, A) +#define npyv_cmple_u16(A, B) npyv_cmpge_u16(B, A) +#define npyv_cmple_s16(A, B) npyv_cmpge_s16(B, A) +#define npyv_cmple_u32(A, B) npyv_cmpge_u32(B, A) +#define npyv_cmple_s32(A, B) npyv_cmpge_s32(B, A) +#define npyv_cmple_u64(A, B) npyv_cmpge_u64(B, A) +#define npyv_cmple_s64(A, B) npyv_cmpge_s64(B, A) + +// precision comparison +#define npyv_cmpeq_f32(a, b) _mm_castps_si128(_mm_cmpeq_ps(a, b)) +#define npyv_cmpeq_f64(a, b) _mm_castpd_si128(_mm_cmpeq_pd(a, b)) +#define npyv_cmpneq_f32(a, b) _mm_castps_si128(_mm_cmpneq_ps(a, b)) +#define npyv_cmpneq_f64(a, b) _mm_castpd_si128(_mm_cmpneq_pd(a, b)) +#define npyv_cmplt_f32(a, b) _mm_castps_si128(_mm_cmplt_ps(a, b)) +#define npyv_cmplt_f64(a, b) _mm_castpd_si128(_mm_cmplt_pd(a, b)) +#define npyv_cmple_f32(a, b) _mm_castps_si128(_mm_cmple_ps(a, b)) +#define npyv_cmple_f64(a, b) _mm_castpd_si128(_mm_cmple_pd(a, b)) +#define npyv_cmpgt_f32(a, b) _mm_castps_si128(_mm_cmpgt_ps(a, b)) +#define npyv_cmpgt_f64(a, b) _mm_castpd_si128(_mm_cmpgt_pd(a, b)) +#define npyv_cmpge_f32(a, b) _mm_castps_si128(_mm_cmpge_ps(a, b)) +#define npyv_cmpge_f64(a, b) _mm_castpd_si128(_mm_cmpge_pd(a, b)) + +// check special cases +NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a) +{ return _mm_castps_si128(_mm_cmpord_ps(a, a)); } +NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a) +{ return _mm_castpd_si128(_mm_cmpord_pd(a, a)); } + +// Test cross all vector lanes +// any: returns true if any of the elements is not equal to zero +// all: returns true if all elements are not equal to zero +#define NPYV_IMPL_SSE_ANYALL(SFX) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { return _mm_movemask_epi8(a) != 0; } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { return _mm_movemask_epi8(a) == 0xffff; } +NPYV_IMPL_SSE_ANYALL(b8) +NPYV_IMPL_SSE_ANYALL(b16) +NPYV_IMPL_SSE_ANYALL(b32) +NPYV_IMPL_SSE_ANYALL(b64) +#undef NPYV_IMPL_SSE_ANYALL + +#define NPYV_IMPL_SSE_ANYALL(SFX, MSFX, TSFX, MASK) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { \ + return _mm_movemask_##MSFX( \ + _mm_cmpeq_##TSFX(a, npyv_zero_##SFX()) \ + ) != MASK; \ + } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { \ + return _mm_movemask_##MSFX( \ + _mm_cmpeq_##TSFX(a, npyv_zero_##SFX()) \ + ) == 0; \ + } +NPYV_IMPL_SSE_ANYALL(u8, epi8, epi8, 0xffff) +NPYV_IMPL_SSE_ANYALL(s8, epi8, epi8, 0xffff) +NPYV_IMPL_SSE_ANYALL(u16, epi8, epi16, 0xffff) +NPYV_IMPL_SSE_ANYALL(s16, epi8, epi16, 0xffff) +NPYV_IMPL_SSE_ANYALL(u32, epi8, epi32, 0xffff) +NPYV_IMPL_SSE_ANYALL(s32, epi8, epi32, 0xffff) +#ifdef NPY_HAVE_SSE41 + NPYV_IMPL_SSE_ANYALL(u64, epi8, epi64, 0xffff) + NPYV_IMPL_SSE_ANYALL(s64, epi8, epi64, 0xffff) +#else + NPY_FINLINE bool npyv_any_u64(npyv_u64 a) + { + return _mm_movemask_epi8( + _mm_cmpeq_epi32(a, npyv_zero_u64()) + ) != 0xffff; + } + NPY_FINLINE bool npyv_all_u64(npyv_u64 a) + { + a = _mm_cmpeq_epi32(a, npyv_zero_u64()); + a = _mm_and_si128(a, _mm_shuffle_epi32(a, _MM_SHUFFLE(2, 3, 0, 1))); + return _mm_movemask_epi8(a) == 0; + } + #define npyv_any_s64 npyv_any_u64 + #define npyv_all_s64 npyv_all_u64 +#endif +NPYV_IMPL_SSE_ANYALL(f32, ps, ps, 0xf) +NPYV_IMPL_SSE_ANYALL(f64, pd, pd, 0x3) +#undef NPYV_IMPL_SSE_ANYALL + +#endif // _NPY_SIMD_SSE_OPERATORS_H diff --git a/mkl_umath/src/npyv/sse/reorder.h b/mkl_umath/src/npyv/sse/reorder.h new file mode 100644 index 00000000..9a57f648 --- /dev/null +++ b/mkl_umath/src/npyv/sse/reorder.h @@ -0,0 +1,212 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_REORDER_H +#define _NPY_SIMD_SSE_REORDER_H + +// combine lower part of two vectors +#define npyv_combinel_u8 _mm_unpacklo_epi64 +#define npyv_combinel_s8 _mm_unpacklo_epi64 +#define npyv_combinel_u16 _mm_unpacklo_epi64 +#define npyv_combinel_s16 _mm_unpacklo_epi64 +#define npyv_combinel_u32 _mm_unpacklo_epi64 +#define npyv_combinel_s32 _mm_unpacklo_epi64 +#define npyv_combinel_u64 _mm_unpacklo_epi64 +#define npyv_combinel_s64 _mm_unpacklo_epi64 +#define npyv_combinel_f32(A, B) _mm_castsi128_ps(_mm_unpacklo_epi64(_mm_castps_si128(A), _mm_castps_si128(B))) +#define npyv_combinel_f64 _mm_unpacklo_pd + +// combine higher part of two vectors +#define npyv_combineh_u8 _mm_unpackhi_epi64 +#define npyv_combineh_s8 _mm_unpackhi_epi64 +#define npyv_combineh_u16 _mm_unpackhi_epi64 +#define npyv_combineh_s16 _mm_unpackhi_epi64 +#define npyv_combineh_u32 _mm_unpackhi_epi64 +#define npyv_combineh_s32 _mm_unpackhi_epi64 +#define npyv_combineh_u64 _mm_unpackhi_epi64 +#define npyv_combineh_s64 _mm_unpackhi_epi64 +#define npyv_combineh_f32(A, B) _mm_castsi128_ps(_mm_unpackhi_epi64(_mm_castps_si128(A), _mm_castps_si128(B))) +#define npyv_combineh_f64 _mm_unpackhi_pd + +// combine two vectors from lower and higher parts of two other vectors +NPY_FINLINE npyv_m128ix2 npyv__combine(__m128i a, __m128i b) +{ + npyv_m128ix2 r; + r.val[0] = npyv_combinel_u8(a, b); + r.val[1] = npyv_combineh_u8(a, b); + return r; +} +NPY_FINLINE npyv_f32x2 npyv_combine_f32(__m128 a, __m128 b) +{ + npyv_f32x2 r; + r.val[0] = npyv_combinel_f32(a, b); + r.val[1] = npyv_combineh_f32(a, b); + return r; +} +NPY_FINLINE npyv_f64x2 npyv_combine_f64(__m128d a, __m128d b) +{ + npyv_f64x2 r; + r.val[0] = npyv_combinel_f64(a, b); + r.val[1] = npyv_combineh_f64(a, b); + return r; +} +#define npyv_combine_u8 npyv__combine +#define npyv_combine_s8 npyv__combine +#define npyv_combine_u16 npyv__combine +#define npyv_combine_s16 npyv__combine +#define npyv_combine_u32 npyv__combine +#define npyv_combine_s32 npyv__combine +#define npyv_combine_u64 npyv__combine +#define npyv_combine_s64 npyv__combine + +// interleave two vectors +#define NPYV_IMPL_SSE_ZIP(T_VEC, SFX, INTR_SFX) \ + NPY_FINLINE T_VEC##x2 npyv_zip_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC##x2 r; \ + r.val[0] = _mm_unpacklo_##INTR_SFX(a, b); \ + r.val[1] = _mm_unpackhi_##INTR_SFX(a, b); \ + return r; \ + } + +NPYV_IMPL_SSE_ZIP(npyv_u8, u8, epi8) +NPYV_IMPL_SSE_ZIP(npyv_s8, s8, epi8) +NPYV_IMPL_SSE_ZIP(npyv_u16, u16, epi16) +NPYV_IMPL_SSE_ZIP(npyv_s16, s16, epi16) +NPYV_IMPL_SSE_ZIP(npyv_u32, u32, epi32) +NPYV_IMPL_SSE_ZIP(npyv_s32, s32, epi32) +NPYV_IMPL_SSE_ZIP(npyv_u64, u64, epi64) +NPYV_IMPL_SSE_ZIP(npyv_s64, s64, epi64) +NPYV_IMPL_SSE_ZIP(npyv_f32, f32, ps) +NPYV_IMPL_SSE_ZIP(npyv_f64, f64, pd) + +// deinterleave two vectors +NPY_FINLINE npyv_u8x2 npyv_unzip_u8(npyv_u8 ab0, npyv_u8 ab1) +{ +#ifdef NPY_HAVE_SSSE3 + const __m128i idx = _mm_setr_epi8( + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 + ); + __m128i abl = _mm_shuffle_epi8(ab0, idx); + __m128i abh = _mm_shuffle_epi8(ab1, idx); + return npyv_combine_u8(abl, abh); +#else + __m128i ab_083b = _mm_unpacklo_epi8(ab0, ab1); + __m128i ab_4c6e = _mm_unpackhi_epi8(ab0, ab1); + __m128i ab_048c = _mm_unpacklo_epi8(ab_083b, ab_4c6e); + __m128i ab_36be = _mm_unpackhi_epi8(ab_083b, ab_4c6e); + __m128i ab_0346 = _mm_unpacklo_epi8(ab_048c, ab_36be); + __m128i ab_8bc8 = _mm_unpackhi_epi8(ab_048c, ab_36be); + npyv_u8x2 r; + r.val[0] = _mm_unpacklo_epi8(ab_0346, ab_8bc8); + r.val[1] = _mm_unpackhi_epi8(ab_0346, ab_8bc8); + return r; +#endif +} +#define npyv_unzip_s8 npyv_unzip_u8 + +NPY_FINLINE npyv_u16x2 npyv_unzip_u16(npyv_u16 ab0, npyv_u16 ab1) +{ +#ifdef NPY_HAVE_SSSE3 + const __m128i idx = _mm_setr_epi8( + 0,1, 4,5, 8,9, 12,13, 2,3, 6,7, 10,11, 14,15 + ); + __m128i abl = _mm_shuffle_epi8(ab0, idx); + __m128i abh = _mm_shuffle_epi8(ab1, idx); + return npyv_combine_u16(abl, abh); +#else + __m128i ab_0415 = _mm_unpacklo_epi16(ab0, ab1); + __m128i ab_263f = _mm_unpackhi_epi16(ab0, ab1); + __m128i ab_0246 = _mm_unpacklo_epi16(ab_0415, ab_263f); + __m128i ab_135f = _mm_unpackhi_epi16(ab_0415, ab_263f); + npyv_u16x2 r; + r.val[0] = _mm_unpacklo_epi16(ab_0246, ab_135f); + r.val[1] = _mm_unpackhi_epi16(ab_0246, ab_135f); + return r; +#endif +} +#define npyv_unzip_s16 npyv_unzip_u16 + +NPY_FINLINE npyv_u32x2 npyv_unzip_u32(npyv_u32 ab0, npyv_u32 ab1) +{ + __m128i abl = _mm_shuffle_epi32(ab0, _MM_SHUFFLE(3, 1, 2, 0)); + __m128i abh = _mm_shuffle_epi32(ab1, _MM_SHUFFLE(3, 1, 2, 0)); + return npyv_combine_u32(abl, abh); +} +#define npyv_unzip_s32 npyv_unzip_u32 + +NPY_FINLINE npyv_u64x2 npyv_unzip_u64(npyv_u64 ab0, npyv_u64 ab1) +{ return npyv_combine_u64(ab0, ab1); } +#define npyv_unzip_s64 npyv_unzip_u64 + +NPY_FINLINE npyv_f32x2 npyv_unzip_f32(npyv_f32 ab0, npyv_f32 ab1) +{ + npyv_f32x2 r; + r.val[0] = _mm_shuffle_ps(ab0, ab1, _MM_SHUFFLE(2, 0, 2, 0)); + r.val[1] = _mm_shuffle_ps(ab0, ab1, _MM_SHUFFLE(3, 1, 3, 1)); + return r; +} +NPY_FINLINE npyv_f64x2 npyv_unzip_f64(npyv_f64 ab0, npyv_f64 ab1) +{ return npyv_combine_f64(ab0, ab1); } + +// Reverse elements of each 64-bit lane +NPY_FINLINE npyv_u16 npyv_rev64_u16(npyv_u16 a) +{ +#ifdef NPY_HAVE_SSSE3 + const __m128i idx = _mm_setr_epi8( + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9 + ); + return _mm_shuffle_epi8(a, idx); +#else + __m128i lo = _mm_shufflelo_epi16(a, _MM_SHUFFLE(0, 1, 2, 3)); + return _mm_shufflehi_epi16(lo, _MM_SHUFFLE(0, 1, 2, 3)); +#endif +} +#define npyv_rev64_s16 npyv_rev64_u16 + +NPY_FINLINE npyv_u8 npyv_rev64_u8(npyv_u8 a) +{ +#ifdef NPY_HAVE_SSSE3 + const __m128i idx = _mm_setr_epi8( + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8 + ); + return _mm_shuffle_epi8(a, idx); +#else + __m128i rev16 = npyv_rev64_u16(a); + // swap 8bit pairs + return _mm_or_si128(_mm_slli_epi16(rev16, 8), _mm_srli_epi16(rev16, 8)); +#endif +} +#define npyv_rev64_s8 npyv_rev64_u8 + +NPY_FINLINE npyv_u32 npyv_rev64_u32(npyv_u32 a) +{ + return _mm_shuffle_epi32(a, _MM_SHUFFLE(2, 3, 0, 1)); +} +#define npyv_rev64_s32 npyv_rev64_u32 + +NPY_FINLINE npyv_f32 npyv_rev64_f32(npyv_f32 a) +{ + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 0, 1)); +} + +// Permuting the elements of each 128-bit lane by immediate index for +// each element. +#define npyv_permi128_u32(A, E0, E1, E2, E3) \ + _mm_shuffle_epi32(A, _MM_SHUFFLE(E3, E2, E1, E0)) + +#define npyv_permi128_s32 npyv_permi128_u32 + +#define npyv_permi128_u64(A, E0, E1) \ + _mm_shuffle_epi32(A, _MM_SHUFFLE(((E1)<<1)+1, ((E1)<<1), ((E0)<<1)+1, ((E0)<<1))) + +#define npyv_permi128_s64 npyv_permi128_u64 + +#define npyv_permi128_f32(A, E0, E1, E2, E3) \ + _mm_shuffle_ps(A, A, _MM_SHUFFLE(E3, E2, E1, E0)) + +#define npyv_permi128_f64(A, E0, E1) \ + _mm_shuffle_pd(A, A, _MM_SHUFFLE2(E1, E0)) + +#endif // _NPY_SIMD_SSE_REORDER_H diff --git a/mkl_umath/src/npyv/sse/sse.h b/mkl_umath/src/npyv/sse/sse.h new file mode 100644 index 00000000..0c6b8cdb --- /dev/null +++ b/mkl_umath/src/npyv/sse/sse.h @@ -0,0 +1,76 @@ +#ifndef _NPY_SIMD_H_ + #error "Not a standalone header" +#endif + +#define NPY_SIMD 128 +#define NPY_SIMD_WIDTH 16 +#define NPY_SIMD_F32 1 +#define NPY_SIMD_F64 1 +#if defined(NPY_HAVE_FMA3) || defined(NPY_HAVE_FMA4) + #define NPY_SIMD_FMA3 1 // native support +#else + #define NPY_SIMD_FMA3 0 // fast emulated +#endif +#define NPY_SIMD_BIGENDIAN 0 +#define NPY_SIMD_CMPSIGNAL 1 + +typedef __m128i npyv_u8; +typedef __m128i npyv_s8; +typedef __m128i npyv_u16; +typedef __m128i npyv_s16; +typedef __m128i npyv_u32; +typedef __m128i npyv_s32; +typedef __m128i npyv_u64; +typedef __m128i npyv_s64; +typedef __m128 npyv_f32; +typedef __m128d npyv_f64; + +typedef __m128i npyv_b8; +typedef __m128i npyv_b16; +typedef __m128i npyv_b32; +typedef __m128i npyv_b64; + +typedef struct { __m128i val[2]; } npyv_m128ix2; +typedef npyv_m128ix2 npyv_u8x2; +typedef npyv_m128ix2 npyv_s8x2; +typedef npyv_m128ix2 npyv_u16x2; +typedef npyv_m128ix2 npyv_s16x2; +typedef npyv_m128ix2 npyv_u32x2; +typedef npyv_m128ix2 npyv_s32x2; +typedef npyv_m128ix2 npyv_u64x2; +typedef npyv_m128ix2 npyv_s64x2; + +typedef struct { __m128i val[3]; } npyv_m128ix3; +typedef npyv_m128ix3 npyv_u8x3; +typedef npyv_m128ix3 npyv_s8x3; +typedef npyv_m128ix3 npyv_u16x3; +typedef npyv_m128ix3 npyv_s16x3; +typedef npyv_m128ix3 npyv_u32x3; +typedef npyv_m128ix3 npyv_s32x3; +typedef npyv_m128ix3 npyv_u64x3; +typedef npyv_m128ix3 npyv_s64x3; + +typedef struct { __m128 val[2]; } npyv_f32x2; +typedef struct { __m128d val[2]; } npyv_f64x2; +typedef struct { __m128 val[3]; } npyv_f32x3; +typedef struct { __m128d val[3]; } npyv_f64x3; + +#define npyv_nlanes_u8 16 +#define npyv_nlanes_s8 16 +#define npyv_nlanes_u16 8 +#define npyv_nlanes_s16 8 +#define npyv_nlanes_u32 4 +#define npyv_nlanes_s32 4 +#define npyv_nlanes_u64 2 +#define npyv_nlanes_s64 2 +#define npyv_nlanes_f32 4 +#define npyv_nlanes_f64 2 + +#include "utils.h" +#include "memory.h" +#include "misc.h" +#include "reorder.h" +#include "operators.h" +#include "conversion.h" +#include "arithmetic.h" +#include "math.h" diff --git a/mkl_umath/src/npyv/sse/utils.h b/mkl_umath/src/npyv/sse/utils.h new file mode 100644 index 00000000..c23def11 --- /dev/null +++ b/mkl_umath/src/npyv/sse/utils.h @@ -0,0 +1,19 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_SSE_UTILS_H +#define _NPY_SIMD_SSE_UTILS_H + +#if !defined(__x86_64__) && !defined(_M_X64) +NPY_FINLINE npy_int64 npyv128_cvtsi128_si64(__m128i a) +{ + npy_int64 NPY_DECL_ALIGNED(16) idx[2]; + _mm_store_si128((__m128i *)idx, a); + return idx[0]; +} +#else + #define npyv128_cvtsi128_si64 _mm_cvtsi128_si64 +#endif + +#endif // _NPY_SIMD_SSE_UTILS_H diff --git a/mkl_umath/src/npyv/ucsnarrow.h b/mkl_umath/src/npyv/ucsnarrow.h new file mode 100644 index 00000000..4b17a280 --- /dev/null +++ b/mkl_umath/src/npyv/ucsnarrow.h @@ -0,0 +1,7 @@ +#ifndef NUMPY_CORE_SRC_COMMON_NPY_UCSNARROW_H_ +#define NUMPY_CORE_SRC_COMMON_NPY_UCSNARROW_H_ + +NPY_NO_EXPORT PyUnicodeObject * +PyUnicode_FromUCS4(char const *src, Py_ssize_t size, int swap, int align); + +#endif /* NUMPY_CORE_SRC_COMMON_NPY_UCSNARROW_H_ */ diff --git a/mkl_umath/src/npyv/ufunc_override.h b/mkl_umath/src/npyv/ufunc_override.h new file mode 100644 index 00000000..5da95fb2 --- /dev/null +++ b/mkl_umath/src/npyv/ufunc_override.h @@ -0,0 +1,38 @@ +#ifndef NUMPY_CORE_SRC_COMMON_UFUNC_OVERRIDE_H_ +#define NUMPY_CORE_SRC_COMMON_UFUNC_OVERRIDE_H_ + +#include "npy_config.h" + +/* + * Check whether an object has __array_ufunc__ defined on its class and it + * is not the default, i.e., the object is not an ndarray, and its + * __array_ufunc__ is not the same as that of ndarray. + * + * Returns a new reference, the value of type(obj).__array_ufunc__ if it + * exists and is different from that of ndarray, and NULL otherwise. + */ +NPY_NO_EXPORT PyObject * +PyUFuncOverride_GetNonDefaultArrayUfunc(PyObject *obj); + +/* + * Check whether an object has __array_ufunc__ defined on its class and it + * is not the default, i.e., the object is not an ndarray, and its + * __array_ufunc__ is not the same as that of ndarray. + * + * Returns 1 if this is the case, 0 if not. + */ +NPY_NO_EXPORT int +PyUFunc_HasOverride(PyObject *obj); + +/* + * Get possible out argument from kwds, and returns the number of outputs + * contained within it: if a tuple, the number of elements in it, 1 otherwise. + * The out argument itself is returned in out_kwd_obj, and the outputs + * in the out_obj array (as borrowed references). + * + * Returns 0 if no outputs found, -1 if kwds is not a dict (with an error set). + */ +NPY_NO_EXPORT int +PyUFuncOverride_GetOutObjects(PyObject *kwds, PyObject **out_kwd_obj, PyObject ***out_objs); + +#endif /* NUMPY_CORE_SRC_COMMON_UFUNC_OVERRIDE_H_ */ diff --git a/mkl_umath/src/npyv/umathmodule.h b/mkl_umath/src/npyv/umathmodule.h new file mode 100644 index 00000000..73d85334 --- /dev/null +++ b/mkl_umath/src/npyv/umathmodule.h @@ -0,0 +1,18 @@ +#ifndef NUMPY_CORE_SRC_COMMON_UMATHMODULE_H_ +#define NUMPY_CORE_SRC_COMMON_UMATHMODULE_H_ + +#include "ufunc_object.h" +#include "ufunc_type_resolution.h" +#include "extobj.h" /* for the python side extobj set/get */ + + +NPY_NO_EXPORT PyObject * +get_sfloat_dtype(PyObject *NPY_UNUSED(mod), PyObject *NPY_UNUSED(args)); + +PyObject * add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args); +PyObject * ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUSED(kwds)); + + +int initumath(PyObject *m); + +#endif /* NUMPY_CORE_SRC_COMMON_UMATHMODULE_H_ */ diff --git a/mkl_umath/src/npyv/vec/arithmetic.h b/mkl_umath/src/npyv/vec/arithmetic.h new file mode 100644 index 00000000..85f4d6b2 --- /dev/null +++ b/mkl_umath/src/npyv/vec/arithmetic.h @@ -0,0 +1,409 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_ARITHMETIC_H +#define _NPY_SIMD_VEC_ARITHMETIC_H + +/*************************** + * Addition + ***************************/ +// non-saturated +#define npyv_add_u8 vec_add +#define npyv_add_s8 vec_add +#define npyv_add_u16 vec_add +#define npyv_add_s16 vec_add +#define npyv_add_u32 vec_add +#define npyv_add_s32 vec_add +#define npyv_add_u64 vec_add +#define npyv_add_s64 vec_add +#if NPY_SIMD_F32 +#define npyv_add_f32 vec_add +#endif +#define npyv_add_f64 vec_add + +// saturated +#ifdef NPY_HAVE_VX + #define NPYV_IMPL_VX_ADDS(SFX, PSFX) \ + NPY_FINLINE npyv_##SFX npyv_adds_##SFX(npyv_##SFX a, npyv_##SFX b)\ + { \ + return vec_pack##PSFX( \ + vec_add(vec_unpackh(a), vec_unpackh(b)), \ + vec_add(vec_unpackl(a), vec_unpackl(b)) \ + ); \ + } + + NPYV_IMPL_VX_ADDS(u8, su) + NPYV_IMPL_VX_ADDS(s8, s) + NPYV_IMPL_VX_ADDS(u16, su) + NPYV_IMPL_VX_ADDS(s16, s) +#else // VSX + #define npyv_adds_u8 vec_adds + #define npyv_adds_s8 vec_adds + #define npyv_adds_u16 vec_adds + #define npyv_adds_s16 vec_adds +#endif +/*************************** + * Subtraction + ***************************/ +// non-saturated +#define npyv_sub_u8 vec_sub +#define npyv_sub_s8 vec_sub +#define npyv_sub_u16 vec_sub +#define npyv_sub_s16 vec_sub +#define npyv_sub_u32 vec_sub +#define npyv_sub_s32 vec_sub +#define npyv_sub_u64 vec_sub +#define npyv_sub_s64 vec_sub +#if NPY_SIMD_F32 +#define npyv_sub_f32 vec_sub +#endif +#define npyv_sub_f64 vec_sub + +// saturated +#ifdef NPY_HAVE_VX + #define NPYV_IMPL_VX_SUBS(SFX, PSFX) \ + NPY_FINLINE npyv_##SFX npyv_subs_##SFX(npyv_##SFX a, npyv_##SFX b)\ + { \ + return vec_pack##PSFX( \ + vec_sub(vec_unpackh(a), vec_unpackh(b)), \ + vec_sub(vec_unpackl(a), vec_unpackl(b)) \ + ); \ + } + + NPYV_IMPL_VX_SUBS(u8, su) + NPYV_IMPL_VX_SUBS(s8, s) + NPYV_IMPL_VX_SUBS(u16, su) + NPYV_IMPL_VX_SUBS(s16, s) +#else // VSX + #define npyv_subs_u8 vec_subs + #define npyv_subs_s8 vec_subs + #define npyv_subs_u16 vec_subs + #define npyv_subs_s16 vec_subs +#endif + +/*************************** + * Multiplication + ***************************/ +// non-saturated +// up to GCC 6 vec_mul only supports precisions and llong +#if defined(NPY_HAVE_VSX) && defined(__GNUC__) && __GNUC__ < 7 + #define NPYV_IMPL_VSX_MUL(T_VEC, SFX, ...) \ + NPY_FINLINE T_VEC npyv_mul_##SFX(T_VEC a, T_VEC b) \ + { \ + const npyv_u8 ev_od = {__VA_ARGS__}; \ + return vec_perm( \ + (T_VEC)vec_mule(a, b), \ + (T_VEC)vec_mulo(a, b), ev_od \ + ); \ + } + + NPYV_IMPL_VSX_MUL(npyv_u8, u8, 0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30) + NPYV_IMPL_VSX_MUL(npyv_s8, s8, 0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30) + NPYV_IMPL_VSX_MUL(npyv_u16, u16, 0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29) + NPYV_IMPL_VSX_MUL(npyv_s16, s16, 0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29) + + // vmuluwm can be used for unsigned or signed 32-bit integers + #define NPYV_IMPL_VSX_MUL_32(T_VEC, SFX) \ + NPY_FINLINE T_VEC npyv_mul_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC ret; \ + __asm__ __volatile__( \ + "vmuluwm %0,%1,%2" : \ + "=v" (ret) : "v" (a), "v" (b) \ + ); \ + return ret; \ + } + + NPYV_IMPL_VSX_MUL_32(npyv_u32, u32) + NPYV_IMPL_VSX_MUL_32(npyv_s32, s32) + +#else + #define npyv_mul_u8 vec_mul + #define npyv_mul_s8 vec_mul + #define npyv_mul_u16 vec_mul + #define npyv_mul_s16 vec_mul + #define npyv_mul_u32 vec_mul + #define npyv_mul_s32 vec_mul +#endif +#if NPY_SIMD_F32 +#define npyv_mul_f32 vec_mul +#endif +#define npyv_mul_f64 vec_mul + +/*************************** + * Integer Division + ***************************/ +// See simd/intdiv.h for more clarification +// divide each unsigned 8-bit element by a precomputed divisor +NPY_FINLINE npyv_u8 npyv_divc_u8(npyv_u8 a, const npyv_u8x3 divisor) +{ +#ifdef NPY_HAVE_VX + npyv_u8 mulhi = vec_mulh(a, divisor.val[0]); +#else // VSX + const npyv_u8 mergeo_perm = { + 1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31 + }; + // high part of unsigned multiplication + npyv_u16 mul_even = vec_mule(a, divisor.val[0]); + npyv_u16 mul_odd = vec_mulo(a, divisor.val[0]); + npyv_u8 mulhi = (npyv_u8)vec_perm(mul_even, mul_odd, mergeo_perm); +#endif + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + npyv_u8 q = vec_sub(a, mulhi); + q = vec_sr(q, divisor.val[1]); + q = vec_add(mulhi, q); + q = vec_sr(q, divisor.val[2]); + return q; +} +// divide each signed 8-bit element by a precomputed divisor +NPY_FINLINE npyv_s8 npyv_divc_s8(npyv_s8 a, const npyv_s8x3 divisor) +{ +#ifdef NPY_HAVE_VX + npyv_s8 mulhi = vec_mulh(a, divisor.val[0]); +#else + const npyv_u8 mergeo_perm = { + 1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31 + }; + // high part of signed multiplication + npyv_s16 mul_even = vec_mule(a, divisor.val[0]); + npyv_s16 mul_odd = vec_mulo(a, divisor.val[0]); + npyv_s8 mulhi = (npyv_s8)vec_perm(mul_even, mul_odd, mergeo_perm); +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + npyv_s8 q = vec_sra_s8(vec_add(a, mulhi), (npyv_u8)divisor.val[1]); + q = vec_sub(q, vec_sra_s8(a, npyv_setall_u8(7))); + q = vec_sub(vec_xor(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 16-bit element by a precomputed divisor +NPY_FINLINE npyv_u16 npyv_divc_u16(npyv_u16 a, const npyv_u16x3 divisor) +{ +#ifdef NPY_HAVE_VX + npyv_u16 mulhi = vec_mulh(a, divisor.val[0]); +#else // VSX + const npyv_u8 mergeo_perm = { + 2, 3, 18, 19, 6, 7, 22, 23, 10, 11, 26, 27, 14, 15, 30, 31 + }; + // high part of unsigned multiplication + npyv_u32 mul_even = vec_mule(a, divisor.val[0]); + npyv_u32 mul_odd = vec_mulo(a, divisor.val[0]); + npyv_u16 mulhi = (npyv_u16)vec_perm(mul_even, mul_odd, mergeo_perm); +#endif + // floor(a/d) = (mulhi + ((a-mulhi) >> sh1)) >> sh2 + npyv_u16 q = vec_sub(a, mulhi); + q = vec_sr(q, divisor.val[1]); + q = vec_add(mulhi, q); + q = vec_sr(q, divisor.val[2]); + return q; +} +// divide each signed 16-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s16 npyv_divc_s16(npyv_s16 a, const npyv_s16x3 divisor) +{ +#ifdef NPY_HAVE_VX + npyv_s16 mulhi = vec_mulh(a, divisor.val[0]); +#else // VSX + const npyv_u8 mergeo_perm = { + 2, 3, 18, 19, 6, 7, 22, 23, 10, 11, 26, 27, 14, 15, 30, 31 + }; + // high part of signed multiplication + npyv_s32 mul_even = vec_mule(a, divisor.val[0]); + npyv_s32 mul_odd = vec_mulo(a, divisor.val[0]); + npyv_s16 mulhi = (npyv_s16)vec_perm(mul_even, mul_odd, mergeo_perm); +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + npyv_s16 q = vec_sra_s16(vec_add(a, mulhi), (npyv_u16)divisor.val[1]); + q = vec_sub(q, vec_sra_s16(a, npyv_setall_u16(15))); + q = vec_sub(vec_xor(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 32-bit element by a precomputed divisor +NPY_FINLINE npyv_u32 npyv_divc_u32(npyv_u32 a, const npyv_u32x3 divisor) +{ +#if defined(NPY_HAVE_VSX4) || defined(NPY_HAVE_VX) + // high part of unsigned multiplication + npyv_u32 mulhi = vec_mulh(a, divisor.val[0]); +#else // VSX + #if defined(__GNUC__) && __GNUC__ < 8 + // Doubleword integer wide multiplication supported by GCC 8+ + npyv_u64 mul_even, mul_odd; + __asm__ ("vmulouw %0,%1,%2" : "=v" (mul_even) : "v" (a), "v" (divisor.val[0])); + __asm__ ("vmuleuw %0,%1,%2" : "=v" (mul_odd) : "v" (a), "v" (divisor.val[0])); + #else + // Doubleword integer wide multiplication supported by GCC 8+ + npyv_u64 mul_even = vec_mule(a, divisor.val[0]); + npyv_u64 mul_odd = vec_mulo(a, divisor.val[0]); + #endif + // high part of unsigned multiplication + npyv_u32 mulhi = vec_mergeo((npyv_u32)mul_even, (npyv_u32)mul_odd); +#endif + // floor(x/d) = (((a-mulhi) >> sh1) + mulhi) >> sh2 + npyv_u32 q = vec_sub(a, mulhi); + q = vec_sr(q, divisor.val[1]); + q = vec_add(mulhi, q); + q = vec_sr(q, divisor.val[2]); + return q; +} +// divide each signed 32-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s32 npyv_divc_s32(npyv_s32 a, const npyv_s32x3 divisor) +{ +#if defined(NPY_HAVE_VSX4) || defined(NPY_HAVE_VX) + // high part of signed multiplication + npyv_s32 mulhi = vec_mulh(a, divisor.val[0]); +#else + #if defined(__GNUC__) && __GNUC__ < 8 + // Doubleword integer wide multiplication supported by GCC8+ + npyv_s64 mul_even, mul_odd; + __asm__ ("vmulosw %0,%1,%2" : "=v" (mul_even) : "v" (a), "v" (divisor.val[0])); + __asm__ ("vmulesw %0,%1,%2" : "=v" (mul_odd) : "v" (a), "v" (divisor.val[0])); + #else + // Doubleword integer wide multiplication supported by GCC8+ + npyv_s64 mul_even = vec_mule(a, divisor.val[0]); + npyv_s64 mul_odd = vec_mulo(a, divisor.val[0]); + #endif + // high part of signed multiplication + npyv_s32 mulhi = vec_mergeo((npyv_s32)mul_even, (npyv_s32)mul_odd); +#endif + // q = ((a + mulhi) >> sh1) - XSIGN(a) + // trunc(a/d) = (q ^ dsign) - dsign + npyv_s32 q = vec_sra_s32(vec_add(a, mulhi), (npyv_u32)divisor.val[1]); + q = vec_sub(q, vec_sra_s32(a, npyv_setall_u32(31))); + q = vec_sub(vec_xor(q, divisor.val[2]), divisor.val[2]); + return q; +} +// divide each unsigned 64-bit element by a precomputed divisor +NPY_FINLINE npyv_u64 npyv_divc_u64(npyv_u64 a, const npyv_u64x3 divisor) +{ +#if defined(NPY_HAVE_VSX4) + return vec_div(a, divisor.val[0]); +#else + const npy_uint64 d = vec_extract(divisor.val[0], 0); + return npyv_set_u64(vec_extract(a, 0) / d, vec_extract(a, 1) / d); +#endif +} +// divide each signed 64-bit element by a precomputed divisor (round towards zero) +NPY_FINLINE npyv_s64 npyv_divc_s64(npyv_s64 a, const npyv_s64x3 divisor) +{ + npyv_b64 overflow = npyv_and_b64(vec_cmpeq(a, npyv_setall_s64(-1LL << 63)), (npyv_b64)divisor.val[1]); + npyv_s64 d = vec_sel(divisor.val[0], npyv_setall_s64(1), overflow); + return vec_div(a, d); +} +/*************************** + * Division + ***************************/ +#if NPY_SIMD_F32 + #define npyv_div_f32 vec_div +#endif +#define npyv_div_f64 vec_div + +/*************************** + * FUSED + ***************************/ +// multiply and add, a*b + c +#define npyv_muladd_f64 vec_madd +// multiply and subtract, a*b - c +#define npyv_mulsub_f64 vec_msub +#if NPY_SIMD_F32 + #define npyv_muladd_f32 vec_madd + #define npyv_mulsub_f32 vec_msub +#endif +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX) + // negate multiply and add, -(a*b) + c + #define npyv_nmuladd_f32 vec_nmsub // equivalent to -(a*b - c) + #define npyv_nmuladd_f64 vec_nmsub + // negate multiply and subtract, -(a*b) - c + #define npyv_nmulsub_f64 vec_nmadd + #define npyv_nmulsub_f32 vec_nmadd // equivalent to -(a*b + c) +#else + NPY_FINLINE npyv_f64 npyv_nmuladd_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return vec_neg(vec_msub(a, b, c)); } + NPY_FINLINE npyv_f64 npyv_nmulsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) + { return vec_neg(vec_madd(a, b, c)); } +#endif +// multiply, add for odd elements and subtract even elements. +// (a * b) -+ c +#if NPY_SIMD_F32 +NPY_FINLINE npyv_f32 npyv_muladdsub_f32(npyv_f32 a, npyv_f32 b, npyv_f32 c) +{ + const npyv_f32 msign = npyv_set_f32(-0.0f, 0.0f, -0.0f, 0.0f); + return npyv_muladd_f32(a, b, npyv_xor_f32(msign, c)); +} +#endif +NPY_FINLINE npyv_f64 npyv_muladdsub_f64(npyv_f64 a, npyv_f64 b, npyv_f64 c) +{ + const npyv_f64 msign = npyv_set_f64(-0.0, 0.0); + return npyv_muladd_f64(a, b, npyv_xor_f64(msign, c)); +} +/*************************** + * Summation + ***************************/ +// reduce sum across vector +NPY_FINLINE npy_uint64 npyv_sum_u64(npyv_u64 a) +{ +#ifdef NPY_HAVE_VX + const npyv_u64 zero = npyv_zero_u64(); + return vec_extract((npyv_u64)vec_sum_u128(a, zero), 1); +#else + return vec_extract(vec_add(a, vec_mergel(a, a)), 0); +#endif +} + +NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) +{ +#ifdef NPY_HAVE_VX + const npyv_u32 zero = npyv_zero_u32(); + return vec_extract((npyv_u32)vec_sum_u128(a, zero), 3); +#else + const npyv_u32 rs = vec_add(a, vec_sld(a, a, 8)); + return vec_extract(vec_add(rs, vec_sld(rs, rs, 4)), 0); +#endif +} + +#if NPY_SIMD_F32 +NPY_FINLINE float npyv_sum_f32(npyv_f32 a) +{ + npyv_f32 sum = vec_add(a, npyv_combineh_f32(a, a)); + return vec_extract(sum, 0) + vec_extract(sum, 1); + (void)sum; +} +#endif + +NPY_FINLINE double npyv_sum_f64(npyv_f64 a) +{ + return vec_extract(a, 0) + vec_extract(a, 1); +} + +// expand the source vector and performs sum reduce +NPY_FINLINE npy_uint16 npyv_sumup_u8(npyv_u8 a) +{ +#ifdef NPY_HAVE_VX + const npyv_u8 zero = npyv_zero_u8(); + npyv_u32 sum4 = vec_sum4(a, zero); + return (npy_uint16)npyv_sum_u32(sum4); +#else + const npyv_u32 zero = npyv_zero_u32(); + npyv_u32 four = vec_sum4s(a, zero); + npyv_s32 one = vec_sums((npyv_s32)four, (npyv_s32)zero); + return (npy_uint16)vec_extract(one, 3); + (void)one; +#endif +} + +NPY_FINLINE npy_uint32 npyv_sumup_u16(npyv_u16 a) +{ +#ifdef NPY_HAVE_VX + npyv_u64 sum = vec_sum2(a, npyv_zero_u16()); + return (npy_uint32)npyv_sum_u64(sum); +#else // VSX + const npyv_s32 zero = npyv_zero_s32(); + npyv_u32x2 eight = npyv_expand_u32_u16(a); + npyv_u32 four = vec_add(eight.val[0], eight.val[1]); + npyv_s32 one = vec_sums((npyv_s32)four, zero); + return (npy_uint32)vec_extract(one, 3); + (void)one; +#endif +} + +#endif // _NPY_SIMD_VEC_ARITHMETIC_H diff --git a/mkl_umath/src/npyv/vec/conversion.h b/mkl_umath/src/npyv/vec/conversion.h new file mode 100644 index 00000000..922109f7 --- /dev/null +++ b/mkl_umath/src/npyv/vec/conversion.h @@ -0,0 +1,237 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_CVT_H +#define _NPY_SIMD_VEC_CVT_H + +// convert boolean vectors to integer vectors +#define npyv_cvt_u8_b8(BL) ((npyv_u8) BL) +#define npyv_cvt_s8_b8(BL) ((npyv_s8) BL) +#define npyv_cvt_u16_b16(BL) ((npyv_u16) BL) +#define npyv_cvt_s16_b16(BL) ((npyv_s16) BL) +#define npyv_cvt_u32_b32(BL) ((npyv_u32) BL) +#define npyv_cvt_s32_b32(BL) ((npyv_s32) BL) +#define npyv_cvt_u64_b64(BL) ((npyv_u64) BL) +#define npyv_cvt_s64_b64(BL) ((npyv_s64) BL) +#if NPY_SIMD_F32 + #define npyv_cvt_f32_b32(BL) ((npyv_f32) BL) +#endif +#define npyv_cvt_f64_b64(BL) ((npyv_f64) BL) + +// convert integer vectors to boolean vectors +#define npyv_cvt_b8_u8(A) ((npyv_b8) A) +#define npyv_cvt_b8_s8(A) ((npyv_b8) A) +#define npyv_cvt_b16_u16(A) ((npyv_b16) A) +#define npyv_cvt_b16_s16(A) ((npyv_b16) A) +#define npyv_cvt_b32_u32(A) ((npyv_b32) A) +#define npyv_cvt_b32_s32(A) ((npyv_b32) A) +#define npyv_cvt_b64_u64(A) ((npyv_b64) A) +#define npyv_cvt_b64_s64(A) ((npyv_b64) A) +#if NPY_SIMD_F32 + #define npyv_cvt_b32_f32(A) ((npyv_b32) A) +#endif +#define npyv_cvt_b64_f64(A) ((npyv_b64) A) + +//expand +NPY_FINLINE npyv_u16x2 npyv_expand_u16_u8(npyv_u8 data) +{ + npyv_u16x2 r; +#ifdef NPY_HAVE_VX + r.val[0] = vec_unpackh(data); + r.val[1] = vec_unpackl(data); +#else + npyv_u8 zero = npyv_zero_u8(); + r.val[0] = (npyv_u16)vec_mergeh(data, zero); + r.val[1] = (npyv_u16)vec_mergel(data, zero); +#endif + return r; +} + +NPY_FINLINE npyv_u32x2 npyv_expand_u32_u16(npyv_u16 data) +{ + npyv_u32x2 r; +#ifdef NPY_HAVE_VX + r.val[0] = vec_unpackh(data); + r.val[1] = vec_unpackl(data); +#else + npyv_u16 zero = npyv_zero_u16(); + r.val[0] = (npyv_u32)vec_mergeh(data, zero); + r.val[1] = (npyv_u32)vec_mergel(data, zero); +#endif + return r; +} + +// pack two 16-bit boolean into one 8-bit boolean vector +NPY_FINLINE npyv_b8 npyv_pack_b8_b16(npyv_b16 a, npyv_b16 b) { + return vec_pack(a, b); +} + +// pack four 32-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 npyv_pack_b8_b32(npyv_b32 a, npyv_b32 b, npyv_b32 c, npyv_b32 d) { + npyv_b16 ab = vec_pack(a, b); + npyv_b16 cd = vec_pack(c, d); + return npyv_pack_b8_b16(ab, cd); +} + +// pack eight 64-bit boolean vectors into one 8-bit boolean vector +NPY_FINLINE npyv_b8 +npyv_pack_b8_b64(npyv_b64 a, npyv_b64 b, npyv_b64 c, npyv_b64 d, + npyv_b64 e, npyv_b64 f, npyv_b64 g, npyv_b64 h) { + npyv_b32 ab = vec_pack(a, b); + npyv_b32 cd = vec_pack(c, d); + npyv_b32 ef = vec_pack(e, f); + npyv_b32 gh = vec_pack(g, h); + return npyv_pack_b8_b32(ab, cd, ef, gh); +} + +// convert boolean vector to integer bitfield +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX2) + NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) + { + const npyv_u8 qperm = npyv_set_u8(120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0); + npyv_u16 r = (npyv_u16)vec_vbpermq((npyv_u8)a, qperm); + #ifdef NPY_HAVE_VXE + return vec_extract(r, 3); + #else + return vec_extract(r, 4); + #endif + // to suppress ambiguous warning: variable `r` but not used [-Wunused-but-set-variable] + (void)r; + } + NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a) + { + const npyv_u8 qperm = npyv_setf_u8(128, 112, 96, 80, 64, 48, 32, 16, 0); + npyv_u8 r = (npyv_u8)vec_vbpermq((npyv_u8)a, qperm); + #ifdef NPY_HAVE_VXE + return vec_extract(r, 6); + #else + return vec_extract(r, 8); + #endif + // to suppress ambiguous warning: variable `r` but not used [-Wunused-but-set-variable] + (void)r; + } + NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a) + { + #ifdef NPY_HAVE_VXE + const npyv_u8 qperm = npyv_setf_u8(128, 128, 128, 128, 128, 96, 64, 32, 0); + #else + const npyv_u8 qperm = npyv_setf_u8(128, 96, 64, 32, 0); + #endif + npyv_u8 r = (npyv_u8)vec_vbpermq((npyv_u8)a, qperm); + #ifdef NPY_HAVE_VXE + return vec_extract(r, 6); + #else + return vec_extract(r, 8); + #endif + // to suppress ambiguous warning: variable `r` but not used [-Wunused-but-set-variable] + (void)r; + } + NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a) + { + #ifdef NPY_HAVE_VXE + const npyv_u8 qperm = npyv_setf_u8(128, 128, 128, 128, 128, 128, 128, 64, 0); + #else + const npyv_u8 qperm = npyv_setf_u8(128, 64, 0); + #endif + npyv_u8 r = (npyv_u8)vec_vbpermq((npyv_u8)a, qperm); + #ifdef NPY_HAVE_VXE + return vec_extract(r, 6); + #else + return vec_extract(r, 8); + #endif + // to suppress ambiguous warning: variable `r` but not used [-Wunused-but-set-variable] + (void)r; + } +#else + NPY_FINLINE npy_uint64 npyv_tobits_b8(npyv_b8 a) + { + const npyv_u8 scale = npyv_set_u8(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128); + npyv_u8 seq_scale = vec_and((npyv_u8)a, scale); + npyv_u64 sum = vec_sum2(vec_sum4(seq_scale, npyv_zero_u8()), npyv_zero_u32()); + return vec_extract(sum, 0) + ((int)vec_extract(sum, 1) << 8); + } + NPY_FINLINE npy_uint64 npyv_tobits_b16(npyv_b16 a) + { + const npyv_u16 scale = npyv_set_u16(1, 2, 4, 8, 16, 32, 64, 128); + npyv_u16 seq_scale = vec_and((npyv_u16)a, scale); + npyv_u64 sum = vec_sum2(seq_scale, npyv_zero_u16()); + return vec_extract(vec_sum_u128(sum, npyv_zero_u64()), 15); + } + NPY_FINLINE npy_uint64 npyv_tobits_b32(npyv_b32 a) + { + const npyv_u32 scale = npyv_set_u32(1, 2, 4, 8); + npyv_u32 seq_scale = vec_and((npyv_u32)a, scale); + return vec_extract(vec_sum_u128(seq_scale, npyv_zero_u32()), 15); + } + NPY_FINLINE npy_uint64 npyv_tobits_b64(npyv_b64 a) + { + const npyv_u64 scale = npyv_set_u64(1, 2); + npyv_u64 seq_scale = vec_and((npyv_u64)a, scale); + return vec_extract(vec_sum_u128(seq_scale, npyv_zero_u64()), 15); + } +#endif +// truncate compatible with all compilers(internal use for now) +#if NPY_SIMD_F32 + NPY_FINLINE npyv_s32 npyv__trunc_s32_f32(npyv_f32 a) + { + #ifdef NPY_HAVE_VXE2 + return vec_signed(a); + #elif defined(NPY_HAVE_VXE) + return vec_packs(vec_signed(npyv_doublee(vec_mergeh(a,a))), + vec_signed(npyv_doublee(vec_mergel(a, a)))); + // VSX + #elif defined(__IBMC__) + return vec_cts(a, 0); + #elif defined(__clang__) + /** + * old versions of CLANG doesn't support %x in the inline asm template + * which fixes register number when using any of the register constraints wa, wd, wf. + * therefore, we count on built-in functions. + */ + return __builtin_convertvector(a, npyv_s32); + #else // gcc + npyv_s32 ret; + __asm__ ("xvcvspsxws %x0,%x1" : "=wa" (ret) : "wa" (a)); + return ret; + #endif + } +#endif + +NPY_FINLINE npyv_s32 npyv__trunc_s32_f64(npyv_f64 a, npyv_f64 b) +{ +#ifdef NPY_HAVE_VX + return vec_packs(vec_signed(a), vec_signed(b)); +// VSX +#elif defined(__IBMC__) + const npyv_u8 seq_even = npyv_set_u8(0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27); + // unfortunately, XLC missing asm register vsx fixer + // hopefully, xlc can optimize around big-endian compatibility + npyv_s32 lo_even = vec_cts(a, 0); + npyv_s32 hi_even = vec_cts(b, 0); + return vec_perm(lo_even, hi_even, seq_even); +#else + const npyv_u8 seq_odd = npyv_set_u8(4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31); + #ifdef __clang__ + // __builtin_convertvector doesn't support this conversion on wide range of versions + // fortunately, almost all versions have direct builtin of 'xvcvdpsxws' + npyv_s32 lo_odd = __builtin_vsx_xvcvdpsxws(a); + npyv_s32 hi_odd = __builtin_vsx_xvcvdpsxws(b); + #else // gcc + npyv_s32 lo_odd, hi_odd; + __asm__ ("xvcvdpsxws %x0,%x1" : "=wa" (lo_odd) : "wa" (a)); + __asm__ ("xvcvdpsxws %x0,%x1" : "=wa" (hi_odd) : "wa" (b)); + #endif + return vec_perm(lo_odd, hi_odd, seq_odd); +#endif +} + +// round to nearest integer (assuming even) +#if NPY_SIMD_F32 + NPY_FINLINE npyv_s32 npyv_round_s32_f32(npyv_f32 a) + { return npyv__trunc_s32_f32(vec_rint(a)); } +#endif +NPY_FINLINE npyv_s32 npyv_round_s32_f64(npyv_f64 a, npyv_f64 b) +{ return npyv__trunc_s32_f64(vec_rint(a), vec_rint(b)); } + +#endif // _NPY_SIMD_VEC_CVT_H diff --git a/mkl_umath/src/npyv/vec/math.h b/mkl_umath/src/npyv/vec/math.h new file mode 100644 index 00000000..85690f76 --- /dev/null +++ b/mkl_umath/src/npyv/vec/math.h @@ -0,0 +1,285 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_MATH_H +#define _NPY_SIMD_VEC_MATH_H +/*************************** + * Elementary + ***************************/ +// Square root +#if NPY_SIMD_F32 + #define npyv_sqrt_f32 vec_sqrt +#endif +#define npyv_sqrt_f64 vec_sqrt + +// Reciprocal +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_recip_f32(npyv_f32 a) + { + const npyv_f32 one = npyv_setall_f32(1.0f); + return vec_div(one, a); + } +#endif +NPY_FINLINE npyv_f64 npyv_recip_f64(npyv_f64 a) +{ + const npyv_f64 one = npyv_setall_f64(1.0); + return vec_div(one, a); +} + +// Absolute +#if NPY_SIMD_F32 + #define npyv_abs_f32 vec_abs +#endif +#define npyv_abs_f64 vec_abs + +// Square +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_square_f32(npyv_f32 a) + { return vec_mul(a, a); } +#endif +NPY_FINLINE npyv_f64 npyv_square_f64(npyv_f64 a) +{ return vec_mul(a, a); } + +// Maximum, natively mapping with no guarantees to handle NaN. +#if NPY_SIMD_F32 + #define npyv_max_f32 vec_max +#endif +#define npyv_max_f64 vec_max +// Maximum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +#if NPY_SIMD_F32 + #define npyv_maxp_f32 vec_max +#endif +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX) + #define npyv_maxp_f64 vec_max +#else + // vfmindb & vfmaxdb appears in zarch12 + NPY_FINLINE npyv_f64 npyv_maxp_f64(npyv_f64 a, npyv_f64 b) + { + npyv_b64 nn_a = npyv_notnan_f64(a); + npyv_b64 nn_b = npyv_notnan_f64(b); + return vec_max(vec_sel(b, a, nn_a), vec_sel(a, b, nn_b)); + } +#endif +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_maxn_f32(npyv_f32 a, npyv_f32 b) + { + npyv_b32 nn_a = npyv_notnan_f32(a); + npyv_b32 nn_b = npyv_notnan_f32(b); + npyv_f32 max = vec_max(a, b); + return vec_sel(b, vec_sel(a, max, nn_a), nn_b); + } +#endif +NPY_FINLINE npyv_f64 npyv_maxn_f64(npyv_f64 a, npyv_f64 b) +{ + npyv_b64 nn_a = npyv_notnan_f64(a); + npyv_b64 nn_b = npyv_notnan_f64(b); + npyv_f64 max = vec_max(a, b); + return vec_sel(b, vec_sel(a, max, nn_a), nn_b); +} + +// Maximum, integer operations +#define npyv_max_u8 vec_max +#define npyv_max_s8 vec_max +#define npyv_max_u16 vec_max +#define npyv_max_s16 vec_max +#define npyv_max_u32 vec_max +#define npyv_max_s32 vec_max +#define npyv_max_u64 vec_max +#define npyv_max_s64 vec_max + +// Minimum, natively mapping with no guarantees to handle NaN. +#if NPY_SIMD_F32 + #define npyv_min_f32 vec_min +#endif +#define npyv_min_f64 vec_min +// Minimum, supports IEEE floating-point arithmetic (IEC 60559), +// - If one of the two vectors contains NaN, the equivalent element of the other vector is set +// - Only if both corresponded elements are NaN, NaN is set. +#if NPY_SIMD_F32 + #define npyv_minp_f32 vec_min +#endif +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX) + #define npyv_minp_f64 vec_min +#else + // vfmindb & vfmaxdb appears in zarch12 + NPY_FINLINE npyv_f64 npyv_minp_f64(npyv_f64 a, npyv_f64 b) + { + npyv_b64 nn_a = npyv_notnan_f64(a); + npyv_b64 nn_b = npyv_notnan_f64(b); + return vec_min(vec_sel(b, a, nn_a), vec_sel(a, b, nn_b)); + } +#endif +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_minn_f32(npyv_f32 a, npyv_f32 b) + { + npyv_b32 nn_a = npyv_notnan_f32(a); + npyv_b32 nn_b = npyv_notnan_f32(b); + npyv_f32 min = vec_min(a, b); + return vec_sel(b, vec_sel(a, min, nn_a), nn_b); + } +#endif +NPY_FINLINE npyv_f64 npyv_minn_f64(npyv_f64 a, npyv_f64 b) +{ + npyv_b64 nn_a = npyv_notnan_f64(a); + npyv_b64 nn_b = npyv_notnan_f64(b); + npyv_f64 min = vec_min(a, b); + return vec_sel(b, vec_sel(a, min, nn_a), nn_b); +} + +// Minimum, integer operations +#define npyv_min_u8 vec_min +#define npyv_min_s8 vec_min +#define npyv_min_u16 vec_min +#define npyv_min_s16 vec_min +#define npyv_min_u32 vec_min +#define npyv_min_s32 vec_min +#define npyv_min_u64 vec_min +#define npyv_min_s64 vec_min + +#define NPY_IMPL_VEC_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + npyv_##SFX r = vec_##INTRIN(a, vec_sld(a, a, 8)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 4)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 2)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 1)); \ + return (npy_##STYPE)vec_extract(r, 0); \ + } +NPY_IMPL_VEC_REDUCE_MINMAX(min, uint8, u8) +NPY_IMPL_VEC_REDUCE_MINMAX(max, uint8, u8) +NPY_IMPL_VEC_REDUCE_MINMAX(min, int8, s8) +NPY_IMPL_VEC_REDUCE_MINMAX(max, int8, s8) +#undef NPY_IMPL_VEC_REDUCE_MINMAX + +#define NPY_IMPL_VEC_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + npyv_##SFX r = vec_##INTRIN(a, vec_sld(a, a, 8)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 4)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 2)); \ + return (npy_##STYPE)vec_extract(r, 0); \ + } +NPY_IMPL_VEC_REDUCE_MINMAX(min, uint16, u16) +NPY_IMPL_VEC_REDUCE_MINMAX(max, uint16, u16) +NPY_IMPL_VEC_REDUCE_MINMAX(min, int16, s16) +NPY_IMPL_VEC_REDUCE_MINMAX(max, int16, s16) +#undef NPY_IMPL_VEC_REDUCE_MINMAX + +#define NPY_IMPL_VEC_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + npyv_##SFX r = vec_##INTRIN(a, vec_sld(a, a, 8)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 4)); \ + return (npy_##STYPE)vec_extract(r, 0); \ + } +NPY_IMPL_VEC_REDUCE_MINMAX(min, uint32, u32) +NPY_IMPL_VEC_REDUCE_MINMAX(max, uint32, u32) +NPY_IMPL_VEC_REDUCE_MINMAX(min, int32, s32) +NPY_IMPL_VEC_REDUCE_MINMAX(max, int32, s32) +#undef NPY_IMPL_VEC_REDUCE_MINMAX + +#define NPY_IMPL_VEC_REDUCE_MINMAX(INTRIN, STYPE, SFX) \ + NPY_FINLINE npy_##STYPE npyv_reduce_##INTRIN##_##SFX(npyv_##SFX a) \ + { \ + npyv_##SFX r = vec_##INTRIN(a, vec_sld(a, a, 8)); \ + return (npy_##STYPE)vec_extract(r, 0); \ + (void)r; \ + } +NPY_IMPL_VEC_REDUCE_MINMAX(min, uint64, u64) +NPY_IMPL_VEC_REDUCE_MINMAX(max, uint64, u64) +NPY_IMPL_VEC_REDUCE_MINMAX(min, int64, s64) +NPY_IMPL_VEC_REDUCE_MINMAX(max, int64, s64) +#undef NPY_IMPL_VEC_REDUCE_MINMAX + +#if NPY_SIMD_F32 + #define NPY_IMPL_VEC_REDUCE_MINMAX(INTRIN, INF) \ + NPY_FINLINE float npyv_reduce_##INTRIN##_f32(npyv_f32 a) \ + { \ + npyv_f32 r = vec_##INTRIN(a, vec_sld(a, a, 8)); \ + r = vec_##INTRIN(r, vec_sld(r, r, 4)); \ + return vec_extract(r, 0); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##p_f32(npyv_f32 a) \ + { \ + return npyv_reduce_##INTRIN##_f32(a); \ + } \ + NPY_FINLINE float npyv_reduce_##INTRIN##n_f32(npyv_f32 a) \ + { \ + npyv_b32 notnan = npyv_notnan_f32(a); \ + if (NPY_UNLIKELY(!npyv_all_b32(notnan))) { \ + const union { npy_uint32 i; float f;} \ + pnan = {0x7fc00000UL}; \ + return pnan.f; \ + } \ + return npyv_reduce_##INTRIN##_f32(a); \ + } + NPY_IMPL_VEC_REDUCE_MINMAX(min, 0x7f800000) + NPY_IMPL_VEC_REDUCE_MINMAX(max, 0xff800000) + #undef NPY_IMPL_VEC_REDUCE_MINMAX +#endif // NPY_SIMD_F32 + +#define NPY_IMPL_VEC_REDUCE_MINMAX(INTRIN, INF) \ + NPY_FINLINE double npyv_reduce_##INTRIN##_f64(npyv_f64 a) \ + { \ + npyv_f64 r = vec_##INTRIN(a, vec_sld(a, a, 8)); \ + return vec_extract(r, 0); \ + (void)r; \ + } \ + NPY_FINLINE double npyv_reduce_##INTRIN##n_f64(npyv_f64 a) \ + { \ + npyv_b64 notnan = npyv_notnan_f64(a); \ + if (NPY_UNLIKELY(!npyv_all_b64(notnan))) { \ + const union { npy_uint64 i; double f;} \ + pnan = {0x7ff8000000000000ull}; \ + return pnan.f; \ + } \ + return npyv_reduce_##INTRIN##_f64(a); \ + } +NPY_IMPL_VEC_REDUCE_MINMAX(min, 0x7ff0000000000000) +NPY_IMPL_VEC_REDUCE_MINMAX(max, 0xfff0000000000000) +#undef NPY_IMPL_VEC_REDUCE_MINMAX + +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX) + #define npyv_reduce_minp_f64 npyv_reduce_min_f64 + #define npyv_reduce_maxp_f64 npyv_reduce_max_f64 +#else + NPY_FINLINE double npyv_reduce_minp_f64(npyv_f64 a) + { + npyv_b64 notnan = npyv_notnan_f64(a); + if (NPY_UNLIKELY(!npyv_any_b64(notnan))) { + return vec_extract(a, 0); + } + a = npyv_select_f64(notnan, a, npyv_reinterpret_f64_u64( + npyv_setall_u64(0x7ff0000000000000))); + return npyv_reduce_min_f64(a); + } + NPY_FINLINE double npyv_reduce_maxp_f64(npyv_f64 a) + { + npyv_b64 notnan = npyv_notnan_f64(a); + if (NPY_UNLIKELY(!npyv_any_b64(notnan))) { + return vec_extract(a, 0); + } + a = npyv_select_f64(notnan, a, npyv_reinterpret_f64_u64( + npyv_setall_u64(0xfff0000000000000))); + return npyv_reduce_max_f64(a); + } +#endif +// round to nearest int even +#define npyv_rint_f64 vec_rint +// ceil +#define npyv_ceil_f64 vec_ceil +// trunc +#define npyv_trunc_f64 vec_trunc +// floor +#define npyv_floor_f64 vec_floor +#if NPY_SIMD_F32 + #define npyv_rint_f32 vec_rint + #define npyv_ceil_f32 vec_ceil + #define npyv_trunc_f32 vec_trunc + #define npyv_floor_f32 vec_floor +#endif + +#endif // _NPY_SIMD_VEC_MATH_H diff --git a/mkl_umath/src/npyv/vec/memory.h b/mkl_umath/src/npyv/vec/memory.h new file mode 100644 index 00000000..dbcdc16d --- /dev/null +++ b/mkl_umath/src/npyv/vec/memory.h @@ -0,0 +1,703 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_MEMORY_H +#define _NPY_SIMD_VEC_MEMORY_H + +#include "misc.h" + +/**************************** + * Private utilities + ****************************/ +// TODO: test load by cast +#define VSX__CAST_lOAD 0 +#if VSX__CAST_lOAD + #define npyv__load(T_VEC, PTR) (*((T_VEC*)(PTR))) +#else + /** + * CLANG fails to load unaligned addresses via vec_xl, vec_xst + * so we failback to vec_vsx_ld, vec_vsx_st + */ + #if defined (NPY_HAVE_VSX2) && ( \ + (defined(__GNUC__) && !defined(vec_xl)) || (defined(__clang__) && !defined(__IBMC__)) \ + ) + #define npyv__load(T_VEC, PTR) vec_vsx_ld(0, PTR) + #else // VX + #define npyv__load(T_VEC, PTR) vec_xl(0, PTR) + #endif +#endif +// unaligned store +#if defined (NPY_HAVE_VSX2) && ( \ + (defined(__GNUC__) && !defined(vec_xl)) || (defined(__clang__) && !defined(__IBMC__)) \ +) + #define npyv__store(PTR, VEC) vec_vsx_st(VEC, 0, PTR) +#else // VX + #define npyv__store(PTR, VEC) vec_xst(VEC, 0, PTR) +#endif + +// aligned load/store +#if defined (NPY_HAVE_VSX) + #define npyv__loada(PTR) vec_ld(0, PTR) + #define npyv__storea(PTR, VEC) vec_st(VEC, 0, PTR) +#else // VX + #define npyv__loada(PTR) vec_xl(0, PTR) + #define npyv__storea(PTR, VEC) vec_xst(VEC, 0, PTR) +#endif + +// avoid aliasing rules +NPY_FINLINE npy_uint64 *npyv__ptr2u64(const void *ptr) +{ npy_uint64 *ptr64 = (npy_uint64*)ptr; return ptr64; } + +// load lower part +NPY_FINLINE npyv_u64 npyv__loadl(const void *ptr) +{ +#ifdef NPY_HAVE_VSX + #if defined(__clang__) && !defined(__IBMC__) + // vec_promote doesn't support doubleword on clang + return npyv_setall_u64(*npyv__ptr2u64(ptr)); + #else + return vec_promote(*npyv__ptr2u64(ptr), 0); + #endif +#else // VX + return vec_load_len((const unsigned long long*)ptr, 7); +#endif +} +// store lower part +#define npyv__storel(PTR, VEC) \ + *npyv__ptr2u64(PTR) = vec_extract(((npyv_u64)VEC), 0) + +#define npyv__storeh(PTR, VEC) \ + *npyv__ptr2u64(PTR) = vec_extract(((npyv_u64)VEC), 1) + +/**************************** + * load/store + ****************************/ +#define NPYV_IMPL_VEC_MEM(SFX, DW_CAST) \ + NPY_FINLINE npyv_##SFX npyv_load_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return (npyv_##SFX)npyv__load(npyv_##SFX, (const npyv_lanetype_##DW_CAST*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loada_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return (npyv_##SFX)npyv__loada((const npyv_lanetype_u32*)ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loads_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return npyv_loada_##SFX(ptr); } \ + NPY_FINLINE npyv_##SFX npyv_loadl_##SFX(const npyv_lanetype_##SFX *ptr) \ + { return (npyv_##SFX)npyv__loadl(ptr); } \ + NPY_FINLINE void npyv_store_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { npyv__store((npyv_lanetype_##DW_CAST*)ptr, (npyv_##DW_CAST)vec); } \ + NPY_FINLINE void npyv_storea_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { npyv__storea((npyv_lanetype_u32*)ptr, (npyv_u32)vec); } \ + NPY_FINLINE void npyv_stores_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { npyv_storea_##SFX(ptr, vec); } \ + NPY_FINLINE void npyv_storel_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { npyv__storel(ptr, vec); } \ + NPY_FINLINE void npyv_storeh_##SFX(npyv_lanetype_##SFX *ptr, npyv_##SFX vec) \ + { npyv__storeh(ptr, vec); } + +NPYV_IMPL_VEC_MEM(u8, u8) +NPYV_IMPL_VEC_MEM(s8, s8) +NPYV_IMPL_VEC_MEM(u16, u16) +NPYV_IMPL_VEC_MEM(s16, s16) +NPYV_IMPL_VEC_MEM(u32, u32) +NPYV_IMPL_VEC_MEM(s32, s32) +NPYV_IMPL_VEC_MEM(u64, f64) +NPYV_IMPL_VEC_MEM(s64, f64) +#if NPY_SIMD_F32 +NPYV_IMPL_VEC_MEM(f32, f32) +#endif +NPYV_IMPL_VEC_MEM(f64, f64) + +/*************************** + * Non-contiguous Load + ***************************/ +//// 32 +NPY_FINLINE npyv_u32 npyv_loadn_u32(const npy_uint32 *ptr, npy_intp stride) +{ + return npyv_set_u32( + ptr[stride * 0], ptr[stride * 1], + ptr[stride * 2], ptr[stride * 3] + ); +} +NPY_FINLINE npyv_s32 npyv_loadn_s32(const npy_int32 *ptr, npy_intp stride) +{ return (npyv_s32)npyv_loadn_u32((const npy_uint32*)ptr, stride); } +#if NPY_SIMD_F32 +NPY_FINLINE npyv_f32 npyv_loadn_f32(const float *ptr, npy_intp stride) +{ return (npyv_f32)npyv_loadn_u32((const npy_uint32*)ptr, stride); } +#endif +//// 64 +NPY_FINLINE npyv_u64 npyv_loadn_u64(const npy_uint64 *ptr, npy_intp stride) +{ return npyv_set_u64(ptr[0], ptr[stride]); } +NPY_FINLINE npyv_s64 npyv_loadn_s64(const npy_int64 *ptr, npy_intp stride) +{ return npyv_set_s64(ptr[0], ptr[stride]); } +NPY_FINLINE npyv_f64 npyv_loadn_f64(const double *ptr, npy_intp stride) +{ return npyv_set_f64(ptr[0], ptr[stride]); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_u32 npyv_loadn2_u32(const npy_uint32 *ptr, npy_intp stride) +{ return (npyv_u32)npyv_set_u64(*(npy_uint64*)ptr, *(npy_uint64*)(ptr + stride)); } +NPY_FINLINE npyv_s32 npyv_loadn2_s32(const npy_int32 *ptr, npy_intp stride) +{ return (npyv_s32)npyv_set_u64(*(npy_uint64*)ptr, *(npy_uint64*)(ptr + stride)); } +#if NPY_SIMD_F32 +NPY_FINLINE npyv_f32 npyv_loadn2_f32(const float *ptr, npy_intp stride) +{ return (npyv_f32)npyv_set_u64(*(npy_uint64*)ptr, *(npy_uint64*)(ptr + stride)); } +#endif +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_u64 npyv_loadn2_u64(const npy_uint64 *ptr, npy_intp stride) +{ (void)stride; return npyv_load_u64(ptr); } +NPY_FINLINE npyv_s64 npyv_loadn2_s64(const npy_int64 *ptr, npy_intp stride) +{ (void)stride; return npyv_load_s64(ptr); } +NPY_FINLINE npyv_f64 npyv_loadn2_f64(const double *ptr, npy_intp stride) +{ (void)stride; return npyv_load_f64(ptr); } + +/*************************** + * Non-contiguous Store + ***************************/ +//// 32 +NPY_FINLINE void npyv_storen_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ + ptr[stride * 0] = vec_extract(a, 0); + ptr[stride * 1] = vec_extract(a, 1); + ptr[stride * 2] = vec_extract(a, 2); + ptr[stride * 3] = vec_extract(a, 3); +} +NPY_FINLINE void npyv_storen_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen_u32((npy_uint32*)ptr, stride, (npyv_u32)a); } +#if NPY_SIMD_F32 +NPY_FINLINE void npyv_storen_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen_u32((npy_uint32*)ptr, stride, (npyv_u32)a); } +#endif +//// 64 +NPY_FINLINE void npyv_storen_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ + ptr[stride * 0] = vec_extract(a, 0); + ptr[stride * 1] = vec_extract(a, 1); +} +NPY_FINLINE void npyv_storen_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ npyv_storen_u64((npy_uint64*)ptr, stride, (npyv_u64)a); } +NPY_FINLINE void npyv_storen_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ npyv_storen_u64((npy_uint64*)ptr, stride, (npyv_u64)a); } + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_u32(npy_uint32 *ptr, npy_intp stride, npyv_u32 a) +{ + *(npy_uint64*)ptr = vec_extract((npyv_u64)a, 0); + *(npy_uint64*)(ptr + stride) = vec_extract((npyv_u64)a, 1); +} +NPY_FINLINE void npyv_storen2_s32(npy_int32 *ptr, npy_intp stride, npyv_s32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, (npyv_u32)a); } +#if NPY_SIMD_F32 +NPY_FINLINE void npyv_storen2_f32(float *ptr, npy_intp stride, npyv_f32 a) +{ npyv_storen2_u32((npy_uint32*)ptr, stride, (npyv_u32)a); } +#endif +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_u64(npy_uint64 *ptr, npy_intp stride, npyv_u64 a) +{ (void)stride; npyv_store_u64(ptr, a); } +NPY_FINLINE void npyv_storen2_s64(npy_int64 *ptr, npy_intp stride, npyv_s64 a) +{ (void)stride; npyv_store_s64(ptr, a); } +NPY_FINLINE void npyv_storen2_f64(double *ptr, npy_intp stride, npyv_f64 a) +{ (void)stride; npyv_store_f64(ptr, a); } + +/********************************* + * Partial Load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 npyv_load_till_s32(const npy_int32 *ptr, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + npyv_s32 vfill = npyv_setall_s32(fill); +#ifdef NPY_HAVE_VX + const unsigned blane = (nlane > 4) ? 4 : nlane; + const npyv_u32 steps = npyv_set_u32(0, 1, 2, 3); + const npyv_u32 vlane = npyv_setall_u32(blane); + const npyv_b32 mask = vec_cmpgt(vlane, steps); + npyv_s32 a = vec_load_len(ptr, blane*4-1); + a = vec_sel(vfill, a, mask); +#else + npyv_s32 a; + switch(nlane) { + case 1: + a = vec_insert(ptr[0], vfill, 0); + break; + case 2: + a = (npyv_s32)vec_insert( + *npyv__ptr2u64(ptr), (npyv_u64)vfill, 0 + ); + break; + case 3: + vfill = vec_insert(ptr[2], vfill, 2); + a = (npyv_s32)vec_insert( + *npyv__ptr2u64(ptr), (npyv_u64)vfill, 0 + ); + break; + default: + return npyv_load_s32(ptr); + } +#endif +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = a; + a = vec_or(workaround, a); +#endif + return a; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ +#ifdef NPY_HAVE_VX + unsigned blane = (nlane > 4) ? 4 : nlane; + return vec_load_len(ptr, blane*4-1); +#else + return npyv_load_till_s32(ptr, nlane, 0); +#endif +} +//// 64 +NPY_FINLINE npyv_s64 npyv_load_till_s64(const npy_int64 *ptr, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_s64 r = npyv_set_s64(ptr[0], fill); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s64 workaround = r; + r = vec_or(workaround, r); + #endif + return r; + } + return npyv_load_s64(ptr); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_load_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ +#ifdef NPY_HAVE_VX + unsigned blane = (nlane > 2) ? 2 : nlane; + return vec_load_len((const signed long long*)ptr, blane*8-1); +#else + return npyv_load_till_s64(ptr, nlane, 0); +#endif +} +//// 64-bit nlane +NPY_FINLINE npyv_s32 npyv_load2_till_s32(const npy_int32 *ptr, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_s32 r = npyv_set_s32(ptr[0], ptr[1], fill_lo, fill_hi); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = r; + r = vec_or(workaround, r); + #endif + return r; + } + return npyv_load_s32(ptr); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 npyv_load2_tillz_s32(const npy_int32 *ptr, npy_uintp nlane) +{ return (npyv_s32)npyv_load_tillz_s64((const npy_int64*)ptr, nlane); } + +//// 128-bit nlane +NPY_FINLINE npyv_s64 npyv_load2_till_s64(const npy_int64 *ptr, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ (void)nlane; (void)fill_lo; (void)fill_hi; return npyv_load_s64(ptr); } + +NPY_FINLINE npyv_s64 npyv_load2_tillz_s64(const npy_int64 *ptr, npy_uintp nlane) +{ (void)nlane; return npyv_load_s64(ptr); } +/********************************* + * Non-contiguous partial load + *********************************/ +//// 32 +NPY_FINLINE npyv_s32 +npyv_loadn_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npy_int32 fill) +{ + assert(nlane > 0); + npyv_s32 vfill = npyv_setall_s32(fill); + switch(nlane) { + case 3: + vfill = vec_insert(ptr[stride*2], vfill, 2); + case 2: + vfill = vec_insert(ptr[stride], vfill, 1); + case 1: + vfill = vec_insert(*ptr, vfill, 0); + break; + default: + return npyv_loadn_s32(ptr, stride); + } // switch +#if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = vfill; + vfill = vec_or(workaround, vfill); +#endif + return vfill; +} +// fill zero to rest lanes +NPY_FINLINE npyv_s32 +npyv_loadn_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s32(ptr, stride, nlane, 0); } +//// 64 +NPY_FINLINE npyv_s64 +npyv_loadn_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npy_int64 fill) +{ + assert(nlane > 0); + if (nlane == 1) { + return npyv_load_till_s64(ptr, nlane, fill); + } + return npyv_loadn_s64(ptr, stride); +} +// fill zero to rest lanes +NPY_FINLINE npyv_s64 npyv_loadn_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ return npyv_loadn_till_s64(ptr, stride, nlane, 0); } + +//// 64-bit load over 32-bit stride +NPY_FINLINE npyv_s32 npyv_loadn2_till_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane, + npy_int32 fill_lo, npy_int32 fill_hi) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_s32 r = npyv_set_s32(ptr[0], ptr[1], fill_lo, fill_hi); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = r; + r = vec_or(workaround, r); + #endif + return r; + } + return npyv_loadn2_s32(ptr, stride); +} +NPY_FINLINE npyv_s32 npyv_loadn2_tillz_s32(const npy_int32 *ptr, npy_intp stride, npy_uintp nlane) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_s32 r = (npyv_s32)npyv_set_s64(*(npy_int64*)ptr, 0); + #if NPY_SIMD_GUARD_PARTIAL_LOAD + volatile npyv_s32 workaround = r; + r = vec_or(workaround, r); + #endif + return r; + } + return npyv_loadn2_s32(ptr, stride); +} + +//// 128-bit load over 64-bit stride +NPY_FINLINE npyv_s64 npyv_loadn2_till_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane, + npy_int64 fill_lo, npy_int64 fill_hi) +{ assert(nlane > 0); (void)stride; (void)nlane; (void)fill_lo; (void)fill_hi; return npyv_load_s64(ptr); } + +NPY_FINLINE npyv_s64 npyv_loadn2_tillz_s64(const npy_int64 *ptr, npy_intp stride, npy_uintp nlane) +{ assert(nlane > 0); (void)stride; (void)nlane; return npyv_load_s64(ptr); } + +/********************************* + * Partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_store_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); +#ifdef NPY_HAVE_VX + unsigned blane = (nlane > 4) ? 4 : nlane; + vec_store_len(a, ptr, blane*4-1); +#else + switch(nlane) { + case 1: + *ptr = vec_extract(a, 0); + break; + case 2: + npyv_storel_s32(ptr, a); + break; + case 3: + npyv_storel_s32(ptr, a); + ptr[2] = vec_extract(a, 2); + break; + default: + npyv_store_s32(ptr, a); + } +#endif +} +//// 64 +NPY_FINLINE void npyv_store_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); +#ifdef NPY_HAVE_VX + unsigned blane = (nlane > 2) ? 2 : nlane; + vec_store_len(a, (signed long long*)ptr, blane*8-1); +#else + if (nlane == 1) { + npyv_storel_s64(ptr, a); + return; + } + npyv_store_s64(ptr, a); +#endif +} + +//// 64-bit nlane +NPY_FINLINE void npyv_store2_till_s32(npy_int32 *ptr, npy_uintp nlane, npyv_s32 a) +{ npyv_store_till_s64((npy_int64*)ptr, nlane, (npyv_s64)a); } + +//// 128-bit nlane +NPY_FINLINE void npyv_store2_till_s64(npy_int64 *ptr, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); (void)nlane; + npyv_store_s64(ptr, a); +} + +/********************************* + * Non-contiguous partial store + *********************************/ +//// 32 +NPY_FINLINE void npyv_storen_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + ptr[stride*0] = vec_extract(a, 0); + switch(nlane) { + case 1: + return; + case 2: + ptr[stride*1] = vec_extract(a, 1); + return; + case 3: + ptr[stride*1] = vec_extract(a, 1); + ptr[stride*2] = vec_extract(a, 2); + return; + default: + ptr[stride*1] = vec_extract(a, 1); + ptr[stride*2] = vec_extract(a, 2); + ptr[stride*3] = vec_extract(a, 3); + } +} +//// 64 +NPY_FINLINE void npyv_storen_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ + assert(nlane > 0); + if (nlane == 1) { + npyv_storel_s64(ptr, a); + return; + } + npyv_storen_s64(ptr, stride, a); +} + +//// 64-bit store over 32-bit stride +NPY_FINLINE void npyv_storen2_till_s32(npy_int32 *ptr, npy_intp stride, npy_uintp nlane, npyv_s32 a) +{ + assert(nlane > 0); + npyv_storel_s32(ptr, a); + if (nlane > 1) { + npyv_storeh_s32(ptr + stride, a); + } +} + +//// 128-bit store over 64-bit stride +NPY_FINLINE void npyv_storen2_till_s64(npy_int64 *ptr, npy_intp stride, npy_uintp nlane, npyv_s64 a) +{ assert(nlane > 0); (void)stride; (void)nlane; npyv_store_s64(ptr, a); } + +/***************************************************************** + * Implement partial load/store for u32/f32/u64/f64... via casting + *****************************************************************/ +#define NPYV_IMPL_VEC_REST_PARTIAL_TYPES(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill) \ + { \ + union { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + } pun; \ + pun.from_##F_SFX = fill; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_VEC_REST_PARTIAL_TYPES(u32, s32) +#if NPY_SIMD_F32 +NPYV_IMPL_VEC_REST_PARTIAL_TYPES(f32, s32) +#endif +NPYV_IMPL_VEC_REST_PARTIAL_TYPES(u64, s64) +NPYV_IMPL_VEC_REST_PARTIAL_TYPES(f64, s64) + +// 128-bit/64-bit stride +#define NPYV_IMPL_VEC_REST_PARTIAL_TYPES_PAIR(F_SFX, T_SFX) \ + NPY_FINLINE npyv_##F_SFX npyv_load2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane, pun_lo.to_##T_SFX, pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_till_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, \ + npyv_lanetype_##F_SFX fill_lo, npyv_lanetype_##F_SFX fill_hi) \ + { \ + union pun { \ + npyv_lanetype_##F_SFX from_##F_SFX; \ + npyv_lanetype_##T_SFX to_##T_SFX; \ + }; \ + union pun pun_lo; \ + union pun pun_hi; \ + pun_lo.from_##F_SFX = fill_lo; \ + pun_hi.from_##F_SFX = fill_hi; \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_till_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane, pun_lo.to_##T_SFX, \ + pun_hi.to_##T_SFX \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_load2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_load2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, nlane \ + )); \ + } \ + NPY_FINLINE npyv_##F_SFX npyv_loadn2_tillz_##F_SFX \ + (const npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane) \ + { \ + return npyv_reinterpret_##F_SFX##_##T_SFX(npyv_loadn2_tillz_##T_SFX( \ + (const npyv_lanetype_##T_SFX *)ptr, stride, nlane \ + )); \ + } \ + NPY_FINLINE void npyv_store2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_store2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } \ + NPY_FINLINE void npyv_storen2_till_##F_SFX \ + (npyv_lanetype_##F_SFX *ptr, npy_intp stride, npy_uintp nlane, npyv_##F_SFX a) \ + { \ + npyv_storen2_till_##T_SFX( \ + (npyv_lanetype_##T_SFX *)ptr, stride, nlane, \ + npyv_reinterpret_##T_SFX##_##F_SFX(a) \ + ); \ + } + +NPYV_IMPL_VEC_REST_PARTIAL_TYPES_PAIR(u32, s32) +#if NPY_SIMD_F32 +NPYV_IMPL_VEC_REST_PARTIAL_TYPES_PAIR(f32, s32) +#endif +NPYV_IMPL_VEC_REST_PARTIAL_TYPES_PAIR(u64, s64) +NPYV_IMPL_VEC_REST_PARTIAL_TYPES_PAIR(f64, s64) + +/************************************************************ + * de-interlave load / interleave contiguous store + ************************************************************/ +// two channels +#define NPYV_IMPL_VEC_MEM_INTERLEAVE(SFX) \ + NPY_FINLINE npyv_##SFX##x2 npyv_zip_##SFX(npyv_##SFX, npyv_##SFX); \ + NPY_FINLINE npyv_##SFX##x2 npyv_unzip_##SFX(npyv_##SFX, npyv_##SFX); \ + NPY_FINLINE npyv_##SFX##x2 npyv_load_##SFX##x2( \ + const npyv_lanetype_##SFX *ptr \ + ) { \ + return npyv_unzip_##SFX( \ + npyv_load_##SFX(ptr), npyv_load_##SFX(ptr+npyv_nlanes_##SFX) \ + ); \ + } \ + NPY_FINLINE void npyv_store_##SFX##x2( \ + npyv_lanetype_##SFX *ptr, npyv_##SFX##x2 v \ + ) { \ + npyv_##SFX##x2 zip = npyv_zip_##SFX(v.val[0], v.val[1]); \ + npyv_store_##SFX(ptr, zip.val[0]); \ + npyv_store_##SFX(ptr + npyv_nlanes_##SFX, zip.val[1]); \ + } + +NPYV_IMPL_VEC_MEM_INTERLEAVE(u8) +NPYV_IMPL_VEC_MEM_INTERLEAVE(s8) +NPYV_IMPL_VEC_MEM_INTERLEAVE(u16) +NPYV_IMPL_VEC_MEM_INTERLEAVE(s16) +NPYV_IMPL_VEC_MEM_INTERLEAVE(u32) +NPYV_IMPL_VEC_MEM_INTERLEAVE(s32) +NPYV_IMPL_VEC_MEM_INTERLEAVE(u64) +NPYV_IMPL_VEC_MEM_INTERLEAVE(s64) +#if NPY_SIMD_F32 +NPYV_IMPL_VEC_MEM_INTERLEAVE(f32) +#endif +NPYV_IMPL_VEC_MEM_INTERLEAVE(f64) + +/********************************* + * Lookup table + *********************************/ +// uses vector as indexes into a table +// that contains 32 elements of float32. +NPY_FINLINE npyv_u32 npyv_lut32_u32(const npy_uint32 *table, npyv_u32 idx) +{ + const unsigned i0 = vec_extract(idx, 0); + const unsigned i1 = vec_extract(idx, 1); + const unsigned i2 = vec_extract(idx, 2); + const unsigned i3 = vec_extract(idx, 3); + npyv_u32 r = vec_promote(table[i0], 0); + r = vec_insert(table[i1], r, 1); + r = vec_insert(table[i2], r, 2); + r = vec_insert(table[i3], r, 3); + return r; +} +NPY_FINLINE npyv_s32 npyv_lut32_s32(const npy_int32 *table, npyv_u32 idx) +{ return (npyv_s32)npyv_lut32_u32((const npy_uint32*)table, idx); } +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_lut32_f32(const float *table, npyv_u32 idx) + { return (npyv_f32)npyv_lut32_u32((const npy_uint32*)table, idx); } +#endif +// uses vector as indexes into a table +// that contains 16 elements of float64. +NPY_FINLINE npyv_f64 npyv_lut16_f64(const double *table, npyv_u64 idx) +{ +#ifdef NPY_HAVE_VX + const unsigned i0 = vec_extract((npyv_u32)idx, 1); + const unsigned i1 = vec_extract((npyv_u32)idx, 3); +#else + const unsigned i0 = vec_extract((npyv_u32)idx, 0); + const unsigned i1 = vec_extract((npyv_u32)idx, 2); +#endif + npyv_f64 r = vec_promote(table[i0], 0); + r = vec_insert(table[i1], r, 1); + return r; +} +NPY_FINLINE npyv_u64 npyv_lut16_u64(const npy_uint64 *table, npyv_u64 idx) +{ return npyv_reinterpret_u64_f64(npyv_lut16_f64((const double*)table, idx)); } +NPY_FINLINE npyv_s64 npyv_lut16_s64(const npy_int64 *table, npyv_u64 idx) +{ return npyv_reinterpret_s64_f64(npyv_lut16_f64((const double*)table, idx)); } + +#endif // _NPY_SIMD_VEC_MEMORY_H diff --git a/mkl_umath/src/npyv/vec/misc.h b/mkl_umath/src/npyv/vec/misc.h new file mode 100644 index 00000000..79c194d9 --- /dev/null +++ b/mkl_umath/src/npyv/vec/misc.h @@ -0,0 +1,233 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_MISC_H +#define _NPY_SIMD_VEC_MISC_H + +// vector with zero lanes +#define npyv_zero_u8() ((npyv_u8) npyv_setall_s32(0)) +#define npyv_zero_s8() ((npyv_s8) npyv_setall_s32(0)) +#define npyv_zero_u16() ((npyv_u16) npyv_setall_s32(0)) +#define npyv_zero_s16() ((npyv_s16) npyv_setall_s32(0)) +#define npyv_zero_u32() npyv_setall_u32(0) +#define npyv_zero_s32() npyv_setall_s32(0) +#define npyv_zero_u64() ((npyv_u64) npyv_setall_s32(0)) +#define npyv_zero_s64() ((npyv_s64) npyv_setall_s32(0)) +#if NPY_SIMD_F32 + #define npyv_zero_f32() npyv_setall_f32(0.0f) +#endif +#define npyv_zero_f64() npyv_setall_f64(0.0) + +// vector with a specific value set to all lanes +// the safest way to generate vsplti* and vsplt* instructions +#define NPYV_IMPL_VEC_SPLTB(T_VEC, V) ((T_VEC){V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V}) +#define NPYV_IMPL_VEC_SPLTH(T_VEC, V) ((T_VEC){V, V, V, V, V, V, V, V}) +#define NPYV_IMPL_VEC_SPLTW(T_VEC, V) ((T_VEC){V, V, V, V}) +#define NPYV_IMPL_VEC_SPLTD(T_VEC, V) ((T_VEC){V, V}) + +#define npyv_setall_u8(VAL) NPYV_IMPL_VEC_SPLTB(npyv_u8, (unsigned char)(VAL)) +#define npyv_setall_s8(VAL) NPYV_IMPL_VEC_SPLTB(npyv_s8, (signed char)(VAL)) +#define npyv_setall_u16(VAL) NPYV_IMPL_VEC_SPLTH(npyv_u16, (unsigned short)(VAL)) +#define npyv_setall_s16(VAL) NPYV_IMPL_VEC_SPLTH(npyv_s16, (short)(VAL)) +#define npyv_setall_u32(VAL) NPYV_IMPL_VEC_SPLTW(npyv_u32, (unsigned int)(VAL)) +#define npyv_setall_s32(VAL) NPYV_IMPL_VEC_SPLTW(npyv_s32, (int)(VAL)) +#if NPY_SIMD_F32 + #define npyv_setall_f32(VAL) NPYV_IMPL_VEC_SPLTW(npyv_f32, (VAL)) +#endif +#define npyv_setall_u64(VAL) NPYV_IMPL_VEC_SPLTD(npyv_u64, (npy_uint64)(VAL)) +#define npyv_setall_s64(VAL) NPYV_IMPL_VEC_SPLTD(npyv_s64, (npy_int64)(VAL)) +#define npyv_setall_f64(VAL) NPYV_IMPL_VEC_SPLTD(npyv_f64, VAL) + +// vector with specific values set to each lane and +// set a specific value to all remained lanes +#define npyv_setf_u8(FILL, ...) ((npyv_u8){NPYV__SET_FILL_16(unsigned char, FILL, __VA_ARGS__)}) +#define npyv_setf_s8(FILL, ...) ((npyv_s8){NPYV__SET_FILL_16(signed char, FILL, __VA_ARGS__)}) +#define npyv_setf_u16(FILL, ...) ((npyv_u16){NPYV__SET_FILL_8(unsigned short, FILL, __VA_ARGS__)}) +#define npyv_setf_s16(FILL, ...) ((npyv_s16){NPYV__SET_FILL_8(short, FILL, __VA_ARGS__)}) +#define npyv_setf_u32(FILL, ...) ((npyv_u32){NPYV__SET_FILL_4(unsigned int, FILL, __VA_ARGS__)}) +#define npyv_setf_s32(FILL, ...) ((npyv_s32){NPYV__SET_FILL_4(int, FILL, __VA_ARGS__)}) +#define npyv_setf_u64(FILL, ...) ((npyv_u64){NPYV__SET_FILL_2(npy_uint64, FILL, __VA_ARGS__)}) +#define npyv_setf_s64(FILL, ...) ((npyv_s64){NPYV__SET_FILL_2(npy_int64, FILL, __VA_ARGS__)}) +#if NPY_SIMD_F32 + #define npyv_setf_f32(FILL, ...) ((npyv_f32){NPYV__SET_FILL_4(float, FILL, __VA_ARGS__)}) +#endif +#define npyv_setf_f64(FILL, ...) ((npyv_f64){NPYV__SET_FILL_2(double, FILL, __VA_ARGS__)}) + +// vector with specific values set to each lane and +// set zero to all remained lanes +#define npyv_set_u8(...) npyv_setf_u8(0, __VA_ARGS__) +#define npyv_set_s8(...) npyv_setf_s8(0, __VA_ARGS__) +#define npyv_set_u16(...) npyv_setf_u16(0, __VA_ARGS__) +#define npyv_set_s16(...) npyv_setf_s16(0, __VA_ARGS__) +#define npyv_set_u32(...) npyv_setf_u32(0, __VA_ARGS__) +#define npyv_set_s32(...) npyv_setf_s32(0, __VA_ARGS__) +#define npyv_set_u64(...) npyv_setf_u64(0, __VA_ARGS__) +#define npyv_set_s64(...) npyv_setf_s64(0, __VA_ARGS__) +#if NPY_SIMD_F32 + #define npyv_set_f32(...) npyv_setf_f32(0, __VA_ARGS__) +#endif +#define npyv_set_f64(...) npyv_setf_f64(0, __VA_ARGS__) + +// Per lane select +#define npyv_select_u8(MASK, A, B) vec_sel(B, A, MASK) +#define npyv_select_s8 npyv_select_u8 +#define npyv_select_u16 npyv_select_u8 +#define npyv_select_s16 npyv_select_u8 +#define npyv_select_u32 npyv_select_u8 +#define npyv_select_s32 npyv_select_u8 +#define npyv_select_u64 npyv_select_u8 +#define npyv_select_s64 npyv_select_u8 +#if NPY_SIMD_F32 + #define npyv_select_f32 npyv_select_u8 +#endif +#define npyv_select_f64 npyv_select_u8 + +// extract the first vector's lane +#define npyv_extract0_u8(A) ((npy_uint8)vec_extract(A, 0)) +#define npyv_extract0_s8(A) ((npy_int8)vec_extract(A, 0)) +#define npyv_extract0_u16(A) ((npy_uint16)vec_extract(A, 0)) +#define npyv_extract0_s16(A) ((npy_int16)vec_extract(A, 0)) +#define npyv_extract0_u32(A) ((npy_uint32)vec_extract(A, 0)) +#define npyv_extract0_s32(A) ((npy_int32)vec_extract(A, 0)) +#define npyv_extract0_u64(A) ((npy_uint64)vec_extract(A, 0)) +#define npyv_extract0_s64(A) ((npy_int64)vec_extract(A, 0)) +#if NPY_SIMD_F32 + #define npyv_extract0_f32(A) vec_extract(A, 0) +#endif +#define npyv_extract0_f64(A) vec_extract(A, 0) + +// Reinterpret +#define npyv_reinterpret_u8_u8(X) X +#define npyv_reinterpret_u8_s8(X) ((npyv_u8)X) +#define npyv_reinterpret_u8_u16 npyv_reinterpret_u8_s8 +#define npyv_reinterpret_u8_s16 npyv_reinterpret_u8_s8 +#define npyv_reinterpret_u8_u32 npyv_reinterpret_u8_s8 +#define npyv_reinterpret_u8_s32 npyv_reinterpret_u8_s8 +#define npyv_reinterpret_u8_u64 npyv_reinterpret_u8_s8 +#define npyv_reinterpret_u8_s64 npyv_reinterpret_u8_s8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_u8_f32 npyv_reinterpret_u8_s8 +#endif +#define npyv_reinterpret_u8_f64 npyv_reinterpret_u8_s8 + +#define npyv_reinterpret_s8_s8(X) X +#define npyv_reinterpret_s8_u8(X) ((npyv_s8)X) +#define npyv_reinterpret_s8_u16 npyv_reinterpret_s8_u8 +#define npyv_reinterpret_s8_s16 npyv_reinterpret_s8_u8 +#define npyv_reinterpret_s8_u32 npyv_reinterpret_s8_u8 +#define npyv_reinterpret_s8_s32 npyv_reinterpret_s8_u8 +#define npyv_reinterpret_s8_u64 npyv_reinterpret_s8_u8 +#define npyv_reinterpret_s8_s64 npyv_reinterpret_s8_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_s8_f32 npyv_reinterpret_s8_u8 +#endif +#define npyv_reinterpret_s8_f64 npyv_reinterpret_s8_u8 + +#define npyv_reinterpret_u16_u16(X) X +#define npyv_reinterpret_u16_u8(X) ((npyv_u16)X) +#define npyv_reinterpret_u16_s8 npyv_reinterpret_u16_u8 +#define npyv_reinterpret_u16_s16 npyv_reinterpret_u16_u8 +#define npyv_reinterpret_u16_u32 npyv_reinterpret_u16_u8 +#define npyv_reinterpret_u16_s32 npyv_reinterpret_u16_u8 +#define npyv_reinterpret_u16_u64 npyv_reinterpret_u16_u8 +#define npyv_reinterpret_u16_s64 npyv_reinterpret_u16_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_u16_f32 npyv_reinterpret_u16_u8 +#endif +#define npyv_reinterpret_u16_f64 npyv_reinterpret_u16_u8 + +#define npyv_reinterpret_s16_s16(X) X +#define npyv_reinterpret_s16_u8(X) ((npyv_s16)X) +#define npyv_reinterpret_s16_s8 npyv_reinterpret_s16_u8 +#define npyv_reinterpret_s16_u16 npyv_reinterpret_s16_u8 +#define npyv_reinterpret_s16_u32 npyv_reinterpret_s16_u8 +#define npyv_reinterpret_s16_s32 npyv_reinterpret_s16_u8 +#define npyv_reinterpret_s16_u64 npyv_reinterpret_s16_u8 +#define npyv_reinterpret_s16_s64 npyv_reinterpret_s16_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_s16_f32 npyv_reinterpret_s16_u8 +#endif +#define npyv_reinterpret_s16_f64 npyv_reinterpret_s16_u8 + +#define npyv_reinterpret_u32_u32(X) X +#define npyv_reinterpret_u32_u8(X) ((npyv_u32)X) +#define npyv_reinterpret_u32_s8 npyv_reinterpret_u32_u8 +#define npyv_reinterpret_u32_u16 npyv_reinterpret_u32_u8 +#define npyv_reinterpret_u32_s16 npyv_reinterpret_u32_u8 +#define npyv_reinterpret_u32_s32 npyv_reinterpret_u32_u8 +#define npyv_reinterpret_u32_u64 npyv_reinterpret_u32_u8 +#define npyv_reinterpret_u32_s64 npyv_reinterpret_u32_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_u32_f32 npyv_reinterpret_u32_u8 +#endif +#define npyv_reinterpret_u32_f64 npyv_reinterpret_u32_u8 + +#define npyv_reinterpret_s32_s32(X) X +#define npyv_reinterpret_s32_u8(X) ((npyv_s32)X) +#define npyv_reinterpret_s32_s8 npyv_reinterpret_s32_u8 +#define npyv_reinterpret_s32_u16 npyv_reinterpret_s32_u8 +#define npyv_reinterpret_s32_s16 npyv_reinterpret_s32_u8 +#define npyv_reinterpret_s32_u32 npyv_reinterpret_s32_u8 +#define npyv_reinterpret_s32_u64 npyv_reinterpret_s32_u8 +#define npyv_reinterpret_s32_s64 npyv_reinterpret_s32_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_s32_f32 npyv_reinterpret_s32_u8 +#endif +#define npyv_reinterpret_s32_f64 npyv_reinterpret_s32_u8 + +#define npyv_reinterpret_u64_u64(X) X +#define npyv_reinterpret_u64_u8(X) ((npyv_u64)X) +#define npyv_reinterpret_u64_s8 npyv_reinterpret_u64_u8 +#define npyv_reinterpret_u64_u16 npyv_reinterpret_u64_u8 +#define npyv_reinterpret_u64_s16 npyv_reinterpret_u64_u8 +#define npyv_reinterpret_u64_u32 npyv_reinterpret_u64_u8 +#define npyv_reinterpret_u64_s32 npyv_reinterpret_u64_u8 +#define npyv_reinterpret_u64_s64 npyv_reinterpret_u64_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_u64_f32 npyv_reinterpret_u64_u8 +#endif +#define npyv_reinterpret_u64_f64 npyv_reinterpret_u64_u8 + +#define npyv_reinterpret_s64_s64(X) X +#define npyv_reinterpret_s64_u8(X) ((npyv_s64)X) +#define npyv_reinterpret_s64_s8 npyv_reinterpret_s64_u8 +#define npyv_reinterpret_s64_u16 npyv_reinterpret_s64_u8 +#define npyv_reinterpret_s64_s16 npyv_reinterpret_s64_u8 +#define npyv_reinterpret_s64_u32 npyv_reinterpret_s64_u8 +#define npyv_reinterpret_s64_s32 npyv_reinterpret_s64_u8 +#define npyv_reinterpret_s64_u64 npyv_reinterpret_s64_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_s64_f32 npyv_reinterpret_s64_u8 +#endif +#define npyv_reinterpret_s64_f64 npyv_reinterpret_s64_u8 + +#if NPY_SIMD_F32 + #define npyv_reinterpret_f32_f32(X) X + #define npyv_reinterpret_f32_u8(X) ((npyv_f32)X) + #define npyv_reinterpret_f32_s8 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_u16 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_s16 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_u32 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_s32 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_u64 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_s64 npyv_reinterpret_f32_u8 + #define npyv_reinterpret_f32_f64 npyv_reinterpret_f32_u8 +#endif + +#define npyv_reinterpret_f64_f64(X) X +#define npyv_reinterpret_f64_u8(X) ((npyv_f64)X) +#define npyv_reinterpret_f64_s8 npyv_reinterpret_f64_u8 +#define npyv_reinterpret_f64_u16 npyv_reinterpret_f64_u8 +#define npyv_reinterpret_f64_s16 npyv_reinterpret_f64_u8 +#define npyv_reinterpret_f64_u32 npyv_reinterpret_f64_u8 +#define npyv_reinterpret_f64_s32 npyv_reinterpret_f64_u8 +#define npyv_reinterpret_f64_u64 npyv_reinterpret_f64_u8 +#define npyv_reinterpret_f64_s64 npyv_reinterpret_f64_u8 +#if NPY_SIMD_F32 + #define npyv_reinterpret_f64_f32 npyv_reinterpret_f64_u8 +#endif +// Only required by AVX2/AVX512 +#define npyv_cleanup() ((void)0) + +#endif // _NPY_SIMD_VEC_MISC_H diff --git a/mkl_umath/src/npyv/vec/operators.h b/mkl_umath/src/npyv/vec/operators.h new file mode 100644 index 00000000..50dac20f --- /dev/null +++ b/mkl_umath/src/npyv/vec/operators.h @@ -0,0 +1,303 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_OPERATORS_H +#define _NPY_SIMD_VEC_OPERATORS_H + +/*************************** + * Shifting + ***************************/ + +// Left +#define npyv_shl_u16(A, C) vec_sl(A, npyv_setall_u16(C)) +#define npyv_shl_s16(A, C) vec_sl_s16(A, npyv_setall_u16(C)) +#define npyv_shl_u32(A, C) vec_sl(A, npyv_setall_u32(C)) +#define npyv_shl_s32(A, C) vec_sl_s32(A, npyv_setall_u32(C)) +#define npyv_shl_u64(A, C) vec_sl(A, npyv_setall_u64(C)) +#define npyv_shl_s64(A, C) vec_sl_s64(A, npyv_setall_u64(C)) + +// Left by an immediate constant +#define npyv_shli_u16 npyv_shl_u16 +#define npyv_shli_s16 npyv_shl_s16 +#define npyv_shli_u32 npyv_shl_u32 +#define npyv_shli_s32 npyv_shl_s32 +#define npyv_shli_u64 npyv_shl_u64 +#define npyv_shli_s64 npyv_shl_s64 + +// Right +#define npyv_shr_u16(A, C) vec_sr(A, npyv_setall_u16(C)) +#define npyv_shr_s16(A, C) vec_sra_s16(A, npyv_setall_u16(C)) +#define npyv_shr_u32(A, C) vec_sr(A, npyv_setall_u32(C)) +#define npyv_shr_s32(A, C) vec_sra_s32(A, npyv_setall_u32(C)) +#define npyv_shr_u64(A, C) vec_sr(A, npyv_setall_u64(C)) +#define npyv_shr_s64(A, C) vec_sra_s64(A, npyv_setall_u64(C)) + +// Right by an immediate constant +#define npyv_shri_u16 npyv_shr_u16 +#define npyv_shri_s16 npyv_shr_s16 +#define npyv_shri_u32 npyv_shr_u32 +#define npyv_shri_s32 npyv_shr_s32 +#define npyv_shri_u64 npyv_shr_u64 +#define npyv_shri_s64 npyv_shr_s64 + +/*************************** + * Logical + ***************************/ +#define NPYV_IMPL_VEC_BIN_CAST(INTRIN, SFX, CAST) \ + NPY_FINLINE npyv_##SFX npyv_##INTRIN##_##SFX(npyv_##SFX a, npyv_##SFX b) \ + { return (npyv_##SFX)vec_##INTRIN((CAST)a, (CAST)b); } + +// Up to GCC 6 logical intrinsics don't support bool long long +#if defined(__GNUC__) && __GNUC__ <= 6 + #define NPYV_IMPL_VEC_BIN_B64(INTRIN) NPYV_IMPL_VEC_BIN_CAST(INTRIN, b64, npyv_u64) +#else + #define NPYV_IMPL_VEC_BIN_B64(INTRIN) NPYV_IMPL_VEC_BIN_CAST(INTRIN, b64, npyv_b64) +#endif +// AND +#define npyv_and_u8 vec_and +#define npyv_and_s8 vec_and +#define npyv_and_u16 vec_and +#define npyv_and_s16 vec_and +#define npyv_and_u32 vec_and +#define npyv_and_s32 vec_and +#define npyv_and_u64 vec_and +#define npyv_and_s64 vec_and +#if NPY_SIMD_F32 + #define npyv_and_f32 vec_and +#endif +#define npyv_and_f64 vec_and +#define npyv_and_b8 vec_and +#define npyv_and_b16 vec_and +#define npyv_and_b32 vec_and +NPYV_IMPL_VEC_BIN_B64(and) + +// OR +#define npyv_or_u8 vec_or +#define npyv_or_s8 vec_or +#define npyv_or_u16 vec_or +#define npyv_or_s16 vec_or +#define npyv_or_u32 vec_or +#define npyv_or_s32 vec_or +#define npyv_or_u64 vec_or +#define npyv_or_s64 vec_or +#if NPY_SIMD_F32 + #define npyv_or_f32 vec_or +#endif +#define npyv_or_f64 vec_or +#define npyv_or_b8 vec_or +#define npyv_or_b16 vec_or +#define npyv_or_b32 vec_or +NPYV_IMPL_VEC_BIN_B64(or) + +// XOR +#define npyv_xor_u8 vec_xor +#define npyv_xor_s8 vec_xor +#define npyv_xor_u16 vec_xor +#define npyv_xor_s16 vec_xor +#define npyv_xor_u32 vec_xor +#define npyv_xor_s32 vec_xor +#define npyv_xor_u64 vec_xor +#define npyv_xor_s64 vec_xor +#if NPY_SIMD_F32 + #define npyv_xor_f32 vec_xor +#endif +#define npyv_xor_f64 vec_xor +#define npyv_xor_b8 vec_xor +#define npyv_xor_b16 vec_xor +#define npyv_xor_b32 vec_xor +NPYV_IMPL_VEC_BIN_B64(xor) + +// NOT +// note: we implement npyv_not_b*(boolean types) for internal use*/ +#define NPYV_IMPL_VEC_NOT_INT(VEC_LEN) \ + NPY_FINLINE npyv_u##VEC_LEN npyv_not_u##VEC_LEN(npyv_u##VEC_LEN a) \ + { return vec_nor(a, a); } \ + NPY_FINLINE npyv_s##VEC_LEN npyv_not_s##VEC_LEN(npyv_s##VEC_LEN a) \ + { return vec_nor(a, a); } \ + NPY_FINLINE npyv_b##VEC_LEN npyv_not_b##VEC_LEN(npyv_b##VEC_LEN a) \ + { return vec_nor(a, a); } + +NPYV_IMPL_VEC_NOT_INT(8) +NPYV_IMPL_VEC_NOT_INT(16) +NPYV_IMPL_VEC_NOT_INT(32) + +// on ppc64, up to gcc5 vec_nor doesn't support bool long long +#if defined(NPY_HAVE_VSX) && defined(__GNUC__) && __GNUC__ > 5 + NPYV_IMPL_VEC_NOT_INT(64) +#else + NPY_FINLINE npyv_u64 npyv_not_u64(npyv_u64 a) + { return vec_nor(a, a); } + NPY_FINLINE npyv_s64 npyv_not_s64(npyv_s64 a) + { return vec_nor(a, a); } + NPY_FINLINE npyv_b64 npyv_not_b64(npyv_b64 a) + { return (npyv_b64)vec_nor((npyv_u64)a, (npyv_u64)a); } +#endif + +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_not_f32(npyv_f32 a) + { return vec_nor(a, a); } +#endif +NPY_FINLINE npyv_f64 npyv_not_f64(npyv_f64 a) +{ return vec_nor(a, a); } + +// ANDC, ORC and XNOR +#define npyv_andc_u8 vec_andc +#define npyv_andc_b8 vec_andc +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX) + #define npyv_orc_b8 vec_orc + #define npyv_xnor_b8 vec_eqv +#else + #define npyv_orc_b8(A, B) npyv_or_b8(npyv_not_b8(B), A) + #define npyv_xnor_b8(A, B) npyv_not_b8(npyv_xor_b8(B, A)) +#endif + +/*************************** + * Comparison + ***************************/ + +// Int Equal +#define npyv_cmpeq_u8 vec_cmpeq +#define npyv_cmpeq_s8 vec_cmpeq +#define npyv_cmpeq_u16 vec_cmpeq +#define npyv_cmpeq_s16 vec_cmpeq +#define npyv_cmpeq_u32 vec_cmpeq +#define npyv_cmpeq_s32 vec_cmpeq +#define npyv_cmpeq_u64 vec_cmpeq +#define npyv_cmpeq_s64 vec_cmpeq +#if NPY_SIMD_F32 + #define npyv_cmpeq_f32 vec_cmpeq +#endif +#define npyv_cmpeq_f64 vec_cmpeq + +// Int Not Equal +#if defined(NPY_HAVE_VSX3) && (!defined(__GNUC__) || defined(vec_cmpne)) + // vec_cmpne supported by gcc since version 7 + #define npyv_cmpneq_u8 vec_cmpne + #define npyv_cmpneq_s8 vec_cmpne + #define npyv_cmpneq_u16 vec_cmpne + #define npyv_cmpneq_s16 vec_cmpne + #define npyv_cmpneq_u32 vec_cmpne + #define npyv_cmpneq_s32 vec_cmpne + #define npyv_cmpneq_u64 vec_cmpne + #define npyv_cmpneq_s64 vec_cmpne + #define npyv_cmpneq_f32 vec_cmpne + #define npyv_cmpneq_f64 vec_cmpne +#else + #define npyv_cmpneq_u8(A, B) npyv_not_b8(vec_cmpeq(A, B)) + #define npyv_cmpneq_s8(A, B) npyv_not_b8(vec_cmpeq(A, B)) + #define npyv_cmpneq_u16(A, B) npyv_not_b16(vec_cmpeq(A, B)) + #define npyv_cmpneq_s16(A, B) npyv_not_b16(vec_cmpeq(A, B)) + #define npyv_cmpneq_u32(A, B) npyv_not_b32(vec_cmpeq(A, B)) + #define npyv_cmpneq_s32(A, B) npyv_not_b32(vec_cmpeq(A, B)) + #define npyv_cmpneq_u64(A, B) npyv_not_b64(vec_cmpeq(A, B)) + #define npyv_cmpneq_s64(A, B) npyv_not_b64(vec_cmpeq(A, B)) + #if NPY_SIMD_F32 + #define npyv_cmpneq_f32(A, B) npyv_not_b32(vec_cmpeq(A, B)) + #endif + #define npyv_cmpneq_f64(A, B) npyv_not_b64(vec_cmpeq(A, B)) +#endif + +// Greater than +#define npyv_cmpgt_u8 vec_cmpgt +#define npyv_cmpgt_s8 vec_cmpgt +#define npyv_cmpgt_u16 vec_cmpgt +#define npyv_cmpgt_s16 vec_cmpgt +#define npyv_cmpgt_u32 vec_cmpgt +#define npyv_cmpgt_s32 vec_cmpgt +#define npyv_cmpgt_u64 vec_cmpgt +#define npyv_cmpgt_s64 vec_cmpgt +#if NPY_SIMD_F32 + #define npyv_cmpgt_f32 vec_cmpgt +#endif +#define npyv_cmpgt_f64 vec_cmpgt + +// Greater than or equal +// On ppc64le, up to gcc5 vec_cmpge only supports single and double precision +#if defined(NPY_HAVE_VX) || (defined(__GNUC__) && __GNUC__ > 5) + #define npyv_cmpge_u8 vec_cmpge + #define npyv_cmpge_s8 vec_cmpge + #define npyv_cmpge_u16 vec_cmpge + #define npyv_cmpge_s16 vec_cmpge + #define npyv_cmpge_u32 vec_cmpge + #define npyv_cmpge_s32 vec_cmpge + #define npyv_cmpge_u64 vec_cmpge + #define npyv_cmpge_s64 vec_cmpge +#else + #define npyv_cmpge_u8(A, B) npyv_not_b8(vec_cmpgt(B, A)) + #define npyv_cmpge_s8(A, B) npyv_not_b8(vec_cmpgt(B, A)) + #define npyv_cmpge_u16(A, B) npyv_not_b16(vec_cmpgt(B, A)) + #define npyv_cmpge_s16(A, B) npyv_not_b16(vec_cmpgt(B, A)) + #define npyv_cmpge_u32(A, B) npyv_not_b32(vec_cmpgt(B, A)) + #define npyv_cmpge_s32(A, B) npyv_not_b32(vec_cmpgt(B, A)) + #define npyv_cmpge_u64(A, B) npyv_not_b64(vec_cmpgt(B, A)) + #define npyv_cmpge_s64(A, B) npyv_not_b64(vec_cmpgt(B, A)) +#endif +#if NPY_SIMD_F32 + #define npyv_cmpge_f32 vec_cmpge +#endif +#define npyv_cmpge_f64 vec_cmpge + +// Less than +#define npyv_cmplt_u8(A, B) npyv_cmpgt_u8(B, A) +#define npyv_cmplt_s8(A, B) npyv_cmpgt_s8(B, A) +#define npyv_cmplt_u16(A, B) npyv_cmpgt_u16(B, A) +#define npyv_cmplt_s16(A, B) npyv_cmpgt_s16(B, A) +#define npyv_cmplt_u32(A, B) npyv_cmpgt_u32(B, A) +#define npyv_cmplt_s32(A, B) npyv_cmpgt_s32(B, A) +#define npyv_cmplt_u64(A, B) npyv_cmpgt_u64(B, A) +#define npyv_cmplt_s64(A, B) npyv_cmpgt_s64(B, A) +#if NPY_SIMD_F32 + #define npyv_cmplt_f32(A, B) npyv_cmpgt_f32(B, A) +#endif +#define npyv_cmplt_f64(A, B) npyv_cmpgt_f64(B, A) + +// Less than or equal +#define npyv_cmple_u8(A, B) npyv_cmpge_u8(B, A) +#define npyv_cmple_s8(A, B) npyv_cmpge_s8(B, A) +#define npyv_cmple_u16(A, B) npyv_cmpge_u16(B, A) +#define npyv_cmple_s16(A, B) npyv_cmpge_s16(B, A) +#define npyv_cmple_u32(A, B) npyv_cmpge_u32(B, A) +#define npyv_cmple_s32(A, B) npyv_cmpge_s32(B, A) +#define npyv_cmple_u64(A, B) npyv_cmpge_u64(B, A) +#define npyv_cmple_s64(A, B) npyv_cmpge_s64(B, A) +#if NPY_SIMD_F32 + #define npyv_cmple_f32(A, B) npyv_cmpge_f32(B, A) +#endif +#define npyv_cmple_f64(A, B) npyv_cmpge_f64(B, A) + +// check special cases +#if NPY_SIMD_F32 + NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a) + { return vec_cmpeq(a, a); } +#endif +NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a) +{ return vec_cmpeq(a, a); } + +// Test cross all vector lanes +// any: returns true if any of the elements is not equal to zero +// all: returns true if all elements are not equal to zero +#define NPYV_IMPL_VEC_ANYALL(SFX, SFX2) \ + NPY_FINLINE bool npyv_any_##SFX(npyv_##SFX a) \ + { return vec_any_ne(a, (npyv_##SFX)npyv_zero_##SFX2()); } \ + NPY_FINLINE bool npyv_all_##SFX(npyv_##SFX a) \ + { return vec_all_ne(a, (npyv_##SFX)npyv_zero_##SFX2()); } +NPYV_IMPL_VEC_ANYALL(b8, u8) +NPYV_IMPL_VEC_ANYALL(b16, u16) +NPYV_IMPL_VEC_ANYALL(b32, u32) +NPYV_IMPL_VEC_ANYALL(b64, u64) +NPYV_IMPL_VEC_ANYALL(u8, u8) +NPYV_IMPL_VEC_ANYALL(s8, s8) +NPYV_IMPL_VEC_ANYALL(u16, u16) +NPYV_IMPL_VEC_ANYALL(s16, s16) +NPYV_IMPL_VEC_ANYALL(u32, u32) +NPYV_IMPL_VEC_ANYALL(s32, s32) +NPYV_IMPL_VEC_ANYALL(u64, u64) +NPYV_IMPL_VEC_ANYALL(s64, s64) +#if NPY_SIMD_F32 + NPYV_IMPL_VEC_ANYALL(f32, f32) +#endif +NPYV_IMPL_VEC_ANYALL(f64, f64) +#undef NPYV_IMPL_VEC_ANYALL + +#endif // _NPY_SIMD_VEC_OPERATORS_H diff --git a/mkl_umath/src/npyv/vec/reorder.h b/mkl_umath/src/npyv/vec/reorder.h new file mode 100644 index 00000000..3910980a --- /dev/null +++ b/mkl_umath/src/npyv/vec/reorder.h @@ -0,0 +1,213 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_REORDER_H +#define _NPY_SIMD_VEC_REORDER_H + +// combine lower part of two vectors +#define npyv__combinel(A, B) vec_mergeh((npyv_u64)(A), (npyv_u64)(B)) +#define npyv_combinel_u8(A, B) ((npyv_u8) npyv__combinel(A, B)) +#define npyv_combinel_s8(A, B) ((npyv_s8) npyv__combinel(A, B)) +#define npyv_combinel_u16(A, B) ((npyv_u16)npyv__combinel(A, B)) +#define npyv_combinel_s16(A, B) ((npyv_s16)npyv__combinel(A, B)) +#define npyv_combinel_u32(A, B) ((npyv_u32)npyv__combinel(A, B)) +#define npyv_combinel_s32(A, B) ((npyv_s32)npyv__combinel(A, B)) +#define npyv_combinel_u64 vec_mergeh +#define npyv_combinel_s64 vec_mergeh +#if NPY_SIMD_F32 + #define npyv_combinel_f32(A, B) ((npyv_f32)npyv__combinel(A, B)) +#endif +#define npyv_combinel_f64 vec_mergeh + +// combine higher part of two vectors +#define npyv__combineh(A, B) vec_mergel((npyv_u64)(A), (npyv_u64)(B)) +#define npyv_combineh_u8(A, B) ((npyv_u8) npyv__combineh(A, B)) +#define npyv_combineh_s8(A, B) ((npyv_s8) npyv__combineh(A, B)) +#define npyv_combineh_u16(A, B) ((npyv_u16)npyv__combineh(A, B)) +#define npyv_combineh_s16(A, B) ((npyv_s16)npyv__combineh(A, B)) +#define npyv_combineh_u32(A, B) ((npyv_u32)npyv__combineh(A, B)) +#define npyv_combineh_s32(A, B) ((npyv_s32)npyv__combineh(A, B)) +#define npyv_combineh_u64 vec_mergel +#define npyv_combineh_s64 vec_mergel +#if NPY_SIMD_F32 + #define npyv_combineh_f32(A, B) ((npyv_f32)npyv__combineh(A, B)) +#endif +#define npyv_combineh_f64 vec_mergel + +/* + * combine: combine two vectors from lower and higher parts of two other vectors + * zip: interleave two vectors +*/ +#define NPYV_IMPL_VEC_COMBINE_ZIP(T_VEC, SFX) \ + NPY_FINLINE T_VEC##x2 npyv_combine_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC##x2 r; \ + r.val[0] = NPY_CAT(npyv_combinel_, SFX)(a, b); \ + r.val[1] = NPY_CAT(npyv_combineh_, SFX)(a, b); \ + return r; \ + } \ + NPY_FINLINE T_VEC##x2 npyv_zip_##SFX(T_VEC a, T_VEC b) \ + { \ + T_VEC##x2 r; \ + r.val[0] = vec_mergeh(a, b); \ + r.val[1] = vec_mergel(a, b); \ + return r; \ + } + +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_u8, u8) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_s8, s8) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_u16, u16) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_s16, s16) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_u32, u32) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_s32, s32) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_u64, u64) +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_s64, s64) +#if NPY_SIMD_F32 + NPYV_IMPL_VEC_COMBINE_ZIP(npyv_f32, f32) +#endif +NPYV_IMPL_VEC_COMBINE_ZIP(npyv_f64, f64) + +// deinterleave two vectors +NPY_FINLINE npyv_u8x2 npyv_unzip_u8(npyv_u8 ab0, npyv_u8 ab1) +{ + const npyv_u8 idx_even = npyv_set_u8( + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 + ); + const npyv_u8 idx_odd = npyv_set_u8( + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 + ); + npyv_u8x2 r; + r.val[0] = vec_perm(ab0, ab1, idx_even); + r.val[1] = vec_perm(ab0, ab1, idx_odd); + return r; +} +NPY_FINLINE npyv_s8x2 npyv_unzip_s8(npyv_s8 ab0, npyv_s8 ab1) +{ + npyv_u8x2 ru = npyv_unzip_u8((npyv_u8)ab0, (npyv_u8)ab1); + npyv_s8x2 r; + r.val[0] = (npyv_s8)ru.val[0]; + r.val[1] = (npyv_s8)ru.val[1]; + return r; +} +NPY_FINLINE npyv_u16x2 npyv_unzip_u16(npyv_u16 ab0, npyv_u16 ab1) +{ + const npyv_u8 idx_even = npyv_set_u8( + 0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25, 28, 29 + ); + const npyv_u8 idx_odd = npyv_set_u8( + 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 + ); + npyv_u16x2 r; + r.val[0] = vec_perm(ab0, ab1, idx_even); + r.val[1] = vec_perm(ab0, ab1, idx_odd); + return r; +} +NPY_FINLINE npyv_s16x2 npyv_unzip_s16(npyv_s16 ab0, npyv_s16 ab1) +{ + npyv_u16x2 ru = npyv_unzip_u16((npyv_u16)ab0, (npyv_u16)ab1); + npyv_s16x2 r; + r.val[0] = (npyv_s16)ru.val[0]; + r.val[1] = (npyv_s16)ru.val[1]; + return r; +} +NPY_FINLINE npyv_u32x2 npyv_unzip_u32(npyv_u32 ab0, npyv_u32 ab1) +{ + npyv_u32 m0 = vec_mergeh(ab0, ab1); + npyv_u32 m1 = vec_mergel(ab0, ab1); + npyv_u32 r0 = vec_mergeh(m0, m1); + npyv_u32 r1 = vec_mergel(m0, m1); + npyv_u32x2 r; + r.val[0] = r0; + r.val[1] = r1; + return r; +} +NPY_FINLINE npyv_s32x2 npyv_unzip_s32(npyv_s32 ab0, npyv_s32 ab1) +{ + npyv_u32x2 ru = npyv_unzip_u32((npyv_u32)ab0, (npyv_u32)ab1); + npyv_s32x2 r; + r.val[0] = (npyv_s32)ru.val[0]; + r.val[1] = (npyv_s32)ru.val[1]; + return r; +} +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32x2 npyv_unzip_f32(npyv_f32 ab0, npyv_f32 ab1) + { + npyv_u32x2 ru = npyv_unzip_u32((npyv_u32)ab0, (npyv_u32)ab1); + npyv_f32x2 r; + r.val[0] = (npyv_f32)ru.val[0]; + r.val[1] = (npyv_f32)ru.val[1]; + return r; + } +#endif +NPY_FINLINE npyv_u64x2 npyv_unzip_u64(npyv_u64 ab0, npyv_u64 ab1) +{ return npyv_combine_u64(ab0, ab1); } +NPY_FINLINE npyv_s64x2 npyv_unzip_s64(npyv_s64 ab0, npyv_s64 ab1) +{ return npyv_combine_s64(ab0, ab1); } +NPY_FINLINE npyv_f64x2 npyv_unzip_f64(npyv_f64 ab0, npyv_f64 ab1) +{ return npyv_combine_f64(ab0, ab1); } + +// Reverse elements of each 64-bit lane +NPY_FINLINE npyv_u8 npyv_rev64_u8(npyv_u8 a) +{ +#if defined(NPY_HAVE_VSX3) && ((defined(__GNUC__) && __GNUC__ > 7) || defined(__IBMC__)) + return (npyv_u8)vec_revb((npyv_u64)a); +#elif defined(NPY_HAVE_VSX3) && defined(NPY_HAVE_VSX_ASM) + npyv_u8 ret; + __asm__ ("xxbrd %x0,%x1" : "=wa" (ret) : "wa" (a)); + return ret; +#else + const npyv_u8 idx = npyv_set_u8( + 7, 6, 5, 4, 3, 2, 1, 0,/*64*/15, 14, 13, 12, 11, 10, 9, 8 + ); + return vec_perm(a, a, idx); +#endif +} +NPY_FINLINE npyv_s8 npyv_rev64_s8(npyv_s8 a) +{ return (npyv_s8)npyv_rev64_u8((npyv_u8)a); } + +NPY_FINLINE npyv_u16 npyv_rev64_u16(npyv_u16 a) +{ + const npyv_u8 idx = npyv_set_u8( + 6, 7, 4, 5, 2, 3, 0, 1,/*64*/14, 15, 12, 13, 10, 11, 8, 9 + ); + return vec_perm(a, a, idx); +} +NPY_FINLINE npyv_s16 npyv_rev64_s16(npyv_s16 a) +{ return (npyv_s16)npyv_rev64_u16((npyv_u16)a); } + +NPY_FINLINE npyv_u32 npyv_rev64_u32(npyv_u32 a) +{ + const npyv_u8 idx = npyv_set_u8( + 4, 5, 6, 7, 0, 1, 2, 3,/*64*/12, 13, 14, 15, 8, 9, 10, 11 + ); + return vec_perm(a, a, idx); +} +NPY_FINLINE npyv_s32 npyv_rev64_s32(npyv_s32 a) +{ return (npyv_s32)npyv_rev64_u32((npyv_u32)a); } +#if NPY_SIMD_F32 + NPY_FINLINE npyv_f32 npyv_rev64_f32(npyv_f32 a) + { return (npyv_f32)npyv_rev64_u32((npyv_u32)a); } +#endif + +// Permuting the elements of each 128-bit lane by immediate index for +// each element. +#define npyv_permi128_u32(A, E0, E1, E2, E3) \ + vec_perm(A, A, npyv_set_u8( \ + (E0<<2), (E0<<2)+1, (E0<<2)+2, (E0<<2)+3, \ + (E1<<2), (E1<<2)+1, (E1<<2)+2, (E1<<2)+3, \ + (E2<<2), (E2<<2)+1, (E2<<2)+2, (E2<<2)+3, \ + (E3<<2), (E3<<2)+1, (E3<<2)+2, (E3<<2)+3 \ + )) +#define npyv_permi128_s32 npyv_permi128_u32 +#define npyv_permi128_f32 npyv_permi128_u32 + +#if defined(__IBMC__) || defined(vec_permi) + #define npyv_permi128_u64(A, E0, E1) vec_permi(A, A, ((E0)<<1) | (E1)) +#else + #define npyv_permi128_u64(A, E0, E1) vec_xxpermdi(A, A, ((E0)<<1) | (E1)) +#endif +#define npyv_permi128_s64 npyv_permi128_u64 +#define npyv_permi128_f64 npyv_permi128_u64 + +#endif // _NPY_SIMD_VEC_REORDER_H diff --git a/mkl_umath/src/npyv/vec/utils.h b/mkl_umath/src/npyv/vec/utils.h new file mode 100644 index 00000000..f8b28cfe --- /dev/null +++ b/mkl_umath/src/npyv/vec/utils.h @@ -0,0 +1,84 @@ +#ifndef NPY_SIMD + #error "Not a standalone header" +#endif + +#ifndef _NPY_SIMD_VEC_UTILS_H +#define _NPY_SIMD_VEC_UTILS_H + +// the following intrinsics may not some|all by zvector API on gcc/clang +#ifdef NPY_HAVE_VX + #ifndef vec_neg + #define vec_neg(a) (-(a)) // Vector Negate + #endif + #ifndef vec_add + #define vec_add(a, b) ((a) + (b)) // Vector Add + #endif + #ifndef vec_sub + #define vec_sub(a, b) ((a) - (b)) // Vector Subtract + #endif + #ifndef vec_mul + #define vec_mul(a, b) ((a) * (b)) // Vector Multiply + #endif + #ifndef vec_div + #define vec_div(a, b) ((a) / (b)) // Vector Divide + #endif + #ifndef vec_neg + #define vec_neg(a) (-(a)) + #endif + #ifndef vec_and + #define vec_and(a, b) ((a) & (b)) // Vector AND + #endif + #ifndef vec_or + #define vec_or(a, b) ((a) | (b)) // Vector OR + #endif + #ifndef vec_xor + #define vec_xor(a, b) ((a) ^ (b)) // Vector XOR + #endif + #ifndef vec_sl + #define vec_sl(a, b) ((a) << (b)) // Vector Shift Left + #endif + #ifndef vec_sra + #define vec_sra(a, b) ((a) >> (b)) // Vector Shift Right + #endif + #ifndef vec_sr + #define vec_sr(a, b) ((a) >> (b)) // Vector Shift Right Algebraic + #endif + #ifndef vec_slo + #define vec_slo(a, b) vec_slb(a, (b) << 64) // Vector Shift Left by Octet + #endif + #ifndef vec_sro + #define vec_sro(a, b) vec_srb(a, (b) << 64) // Vector Shift Right by Octet + #endif + // vec_doublee maps to wrong intrin "vfll". + // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100871 + #if defined(__GNUC__) && !defined(__clang__) + #define npyv_doublee __builtin_s390_vflls + #else + #define npyv_doublee vec_doublee + #endif + // compatibility with vsx + #ifndef vec_vbpermq + #define vec_vbpermq vec_bperm_u128 + #endif + // zvector requires second operand to signed while vsx api expected to be + // unsigned, the following macros are set to remove this conflict + #define vec_sl_s8(a, b) vec_sl(a, (npyv_s8)(b)) + #define vec_sl_s16(a, b) vec_sl(a, (npyv_s16)(b)) + #define vec_sl_s32(a, b) vec_sl(a, (npyv_s32)(b)) + #define vec_sl_s64(a, b) vec_sl(a, (npyv_s64)(b)) + #define vec_sra_s8(a, b) vec_sra(a, (npyv_s8)(b)) + #define vec_sra_s16(a, b) vec_sra(a, (npyv_s16)(b)) + #define vec_sra_s32(a, b) vec_sra(a, (npyv_s32)(b)) + #define vec_sra_s64(a, b) vec_sra(a, (npyv_s64)(b)) +#else + #define vec_sl_s8 vec_sl + #define vec_sl_s16 vec_sl + #define vec_sl_s32 vec_sl + #define vec_sl_s64 vec_sl + #define vec_sra_s8 vec_sra + #define vec_sra_s16 vec_sra + #define vec_sra_s32 vec_sra + #define vec_sra_s64 vec_sra +#endif + +#endif // _NPY_SIMD_VEC_UTILS_H diff --git a/mkl_umath/src/npyv/vec/vec.h b/mkl_umath/src/npyv/vec/vec.h new file mode 100644 index 00000000..1d450866 --- /dev/null +++ b/mkl_umath/src/npyv/vec/vec.h @@ -0,0 +1,111 @@ +/** + * branch /vec(altivec-like) provides the SIMD operations for + * both IBM VSX(Power) and VX(ZArch). +*/ +#ifndef _NPY_SIMD_H_ + #error "Not a standalone header" +#endif + +#if !defined(NPY_HAVE_VX) && !defined(NPY_HAVE_VSX2) + #error "require minimum support VX(zarch11) or VSX2(Power8/ISA2.07)" +#endif + +#if defined(NPY_HAVE_VSX) && !defined(__LITTLE_ENDIAN__) + #error "VSX support doesn't cover big-endian mode yet, only zarch." +#endif +#if defined(NPY_HAVE_VX) && defined(__LITTLE_ENDIAN__) + #error "VX(zarch) support doesn't cover little-endian mode." +#endif + +#if defined(__GNUC__) && __GNUC__ <= 7 + /** + * GCC <= 7 produces ambiguous warning caused by -Werror=maybe-uninitialized, + * when certain intrinsics involved. `vec_ld` is one of them but it seemed to work fine, + * and suppressing the warning wouldn't affect its functionality. + */ + #pragma GCC diagnostic ignored "-Wuninitialized" + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + +#define NPY_SIMD 128 +#define NPY_SIMD_WIDTH 16 +#define NPY_SIMD_F64 1 +#if defined(NPY_HAVE_VXE) || defined(NPY_HAVE_VSX) + #define NPY_SIMD_F32 1 +#else + #define NPY_SIMD_F32 0 +#endif +#define NPY_SIMD_FMA3 1 // native support + +#ifdef NPY_HAVE_VX + #define NPY_SIMD_BIGENDIAN 1 + #define NPY_SIMD_CMPSIGNAL 0 +#else + #define NPY_SIMD_BIGENDIAN 0 + #define NPY_SIMD_CMPSIGNAL 1 +#endif + +typedef __vector unsigned char npyv_u8; +typedef __vector signed char npyv_s8; +typedef __vector unsigned short npyv_u16; +typedef __vector signed short npyv_s16; +typedef __vector unsigned int npyv_u32; +typedef __vector signed int npyv_s32; +typedef __vector unsigned long long npyv_u64; +typedef __vector signed long long npyv_s64; +#if NPY_SIMD_F32 +typedef __vector float npyv_f32; +#endif +typedef __vector double npyv_f64; + +typedef struct { npyv_u8 val[2]; } npyv_u8x2; +typedef struct { npyv_s8 val[2]; } npyv_s8x2; +typedef struct { npyv_u16 val[2]; } npyv_u16x2; +typedef struct { npyv_s16 val[2]; } npyv_s16x2; +typedef struct { npyv_u32 val[2]; } npyv_u32x2; +typedef struct { npyv_s32 val[2]; } npyv_s32x2; +typedef struct { npyv_u64 val[2]; } npyv_u64x2; +typedef struct { npyv_s64 val[2]; } npyv_s64x2; +#if NPY_SIMD_F32 +typedef struct { npyv_f32 val[2]; } npyv_f32x2; +#endif +typedef struct { npyv_f64 val[2]; } npyv_f64x2; + +typedef struct { npyv_u8 val[3]; } npyv_u8x3; +typedef struct { npyv_s8 val[3]; } npyv_s8x3; +typedef struct { npyv_u16 val[3]; } npyv_u16x3; +typedef struct { npyv_s16 val[3]; } npyv_s16x3; +typedef struct { npyv_u32 val[3]; } npyv_u32x3; +typedef struct { npyv_s32 val[3]; } npyv_s32x3; +typedef struct { npyv_u64 val[3]; } npyv_u64x3; +typedef struct { npyv_s64 val[3]; } npyv_s64x3; +#if NPY_SIMD_F32 +typedef struct { npyv_f32 val[3]; } npyv_f32x3; +#endif +typedef struct { npyv_f64 val[3]; } npyv_f64x3; + +#define npyv_nlanes_u8 16 +#define npyv_nlanes_s8 16 +#define npyv_nlanes_u16 8 +#define npyv_nlanes_s16 8 +#define npyv_nlanes_u32 4 +#define npyv_nlanes_s32 4 +#define npyv_nlanes_u64 2 +#define npyv_nlanes_s64 2 +#define npyv_nlanes_f32 4 +#define npyv_nlanes_f64 2 + +// using __bool with typedef cause ambiguous errors +#define npyv_b8 __vector __bool char +#define npyv_b16 __vector __bool short +#define npyv_b32 __vector __bool int +#define npyv_b64 __vector __bool long long + +#include "utils.h" +#include "memory.h" +#include "misc.h" +#include "reorder.h" +#include "operators.h" +#include "conversion.h" +#include "arithmetic.h" +#include "math.h" From a725d7ad40b483dd488b8387a8f1f943563e15c7 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Thu, 26 Mar 2026 15:21:28 +0100 Subject: [PATCH 2/7] Use MKL VML LinearFrac to fix regression observing in go_fast benchmark --- conda-recipe/meta.yaml | 2 +- mkl_umath/src/mkl_umath_loops.c.src | 34 ++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 1d44af71..6880255c 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -9,7 +9,7 @@ source: path: ../ build: - number: 4 + number: 5 script_env: - WHEELS_OUTPUT_FOLDER ignore_run_exports: diff --git a/mkl_umath/src/mkl_umath_loops.c.src b/mkl_umath/src/mkl_umath_loops.c.src index 9f889b27..dfa1076f 100644 --- a/mkl_umath/src/mkl_umath_loops.c.src +++ b/mkl_umath/src/mkl_umath_loops.c.src @@ -343,6 +343,37 @@ mkl_umath_@TYPE@_add(char **args, const npy_intp *dimensions, const npy_intp *st return; } + /* + * Calculate memory overlap checks once - reused by multiple tiers + */ + const int disjoint_or_same1 = DISJOINT_OR_SAME(src0, dst, len, sizeof(@type@)); + const int disjoint_or_same2 = DISJOINT_OR_SAME(src1, dst, len, sizeof(@type@)); + + /* + * TIER 3a: Large arrays with scalar broadcast - use MKL VML LinearFrac + * For operations like array + scalar or scalar + array + * LinearFrac computes: out = scaleA * in + shiftA + * For add: out = 1.0 * array + scalar + */ + // Pattern: scalar + array[i] (scalar is first argument with stride=0) + if (ssrc0 == 0 && ssrc1 == sizeof(@type@) && sdst == sizeof(@type@)) { + if (len >= VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same2) { + // scalar + array[i] → 1.0 * array[i] + scalar + CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, len, @type@, + src1, dst, 1.0, *(@type@*)src0, 0.0, 1.0); + return; + } + } + // Pattern: array[i] + scalar (scalar is second argument with stride=0) + else if (ssrc1 == 0 && ssrc0 == sizeof(@type@) && sdst == sizeof(@type@)) { + if (len >= VML_SIMPLE_OPS_THRESHOLD && disjoint_or_same1) { + // array[i] + scalar → 1.0 * array[i] + scalar + CHUNKED_VML_LINEARFRAC_CALL(v@s@LinearFrac, len, @type@, + src0, dst, 1.0, *(@type@*)src1, 0.0, 1.0); + return; + } + } + /* * TIER 3: Large arrays - use MKL VML * MKL's overhead is amortized, can use multi-threading @@ -352,9 +383,6 @@ mkl_umath_@TYPE@_add(char **args, const npy_intp *dimensions, const npy_intp *st sdst == sizeof(@type@)); if (len >= VML_SIMPLE_OPS_THRESHOLD && is_contiguous) { - const int disjoint_or_same1 = DISJOINT_OR_SAME(src0, dst, len, sizeof(@type@)); - const int disjoint_or_same2 = DISJOINT_OR_SAME(src1, dst, len, sizeof(@type@)); - if (disjoint_or_same1 && disjoint_or_same2) { CHUNKED_VML_CALL3(v@s@Add, len, @type@, @type@, src0, src1, dst); return; From 5c4d3772f96c76cd201d3fe25728d7c063912c47 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Thu, 26 Mar 2026 17:52:44 +0100 Subject: [PATCH 3/7] Add reduction branch back to add function --- conda-recipe/meta.yaml | 2 +- mkl_umath/src/mkl_umath_loops.c.src | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 6880255c..d472a7dd 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -9,7 +9,7 @@ source: path: ../ build: - number: 5 + number: 6 script_env: - WHEELS_OUTPUT_FOLDER ignore_run_exports: diff --git a/mkl_umath/src/mkl_umath_loops.c.src b/mkl_umath/src/mkl_umath_loops.c.src index dfa1076f..4e9e5302 100644 --- a/mkl_umath/src/mkl_umath_loops.c.src +++ b/mkl_umath/src/mkl_umath_loops.c.src @@ -253,7 +253,7 @@ divmod@c@(@type@ a, @type@ b, @type@ *modulus) #pragma intel optimization_level 2 #endif #endif -static @type@ +static inline @type@ pairwise_sum_@TYPE@(char *a, npy_intp n, npy_intp stride) { if (n < 8) { @@ -330,6 +330,16 @@ mkl_umath_@TYPE@_add(char **args, const npy_intp *dimensions, const npy_intp *st char *src0 = args[0], *src1 = args[1], *dst = args[2]; npy_intp ssrc0 = steps[0], ssrc1 = steps[1], sdst = steps[2]; + /* + * REDUCTION: For np.sum() operations + * Check FIRST, before any size-based optimizations + * Uses pairwise summation for numerical accuracy (O(log n) error vs O(n)) + */ + if (IS_BINARY_REDUCE) { + *((@type@*)src0) += pairwise_sum_@TYPE@(src1, len, ssrc1); + return; + } + /* * TIER 1: Tiny arrays - simple scalar loop * Overhead of SIMD setup not worth it From 81f6c4b516e33314eaa5dd20f69614bfb46f61d5 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 14 Apr 2026 15:16:30 +0200 Subject: [PATCH 4/7] Undo the temporary changes in conda-recipe/meta.yaml --- conda-recipe/meta.yaml | 4 +- intel_numpy_20260326_100014.txt | 812 ++++++++++++++++++++++++++++++ mkl_backend_20260326_100014.txt | 812 ++++++++++++++++++++++++++++++ mkl_umath_add_20260326_100014.txt | 812 ++++++++++++++++++++++++++++++ npbench_full_comparison.png | Bin 0 -> 433054 bytes stock_numpy_20260326_100014.txt | 812 ++++++++++++++++++++++++++++++ tmp/npbench_full_comparison.png | Bin 0 -> 433009 bytes 7 files changed, 3250 insertions(+), 2 deletions(-) create mode 100644 intel_numpy_20260326_100014.txt create mode 100644 mkl_backend_20260326_100014.txt create mode 100644 mkl_umath_add_20260326_100014.txt create mode 100644 npbench_full_comparison.png create mode 100644 stock_numpy_20260326_100014.txt create mode 100644 tmp/npbench_full_comparison.png diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index d472a7dd..5ec1f81a 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -9,7 +9,7 @@ source: path: ../ build: - number: 6 + number: {{ GIT_DESCRIBE_NUMBER }} script_env: - WHEELS_OUTPUT_FOLDER ignore_run_exports: @@ -20,7 +20,7 @@ requirements: - {{ compiler('c') }} - {{ compiler('cxx') }} - {{ stdlib('c') }} - - {{ compiler('dpcpp') }} 2025.3.0 # [not osx] + - {{ compiler('dpcpp') }} >=2024.2 # [not osx] host: - setuptools >=77 - cmake diff --git a/intel_numpy_20260326_100014.txt b/intel_numpy_20260326_100014.txt new file mode 100644 index 00000000..756b13cd --- /dev/null +++ b/intel_numpy_20260326_100014.txt @@ -0,0 +1,812 @@ +===================================== +Environment: intel_numpy (npbench_intel_numpy) +Timestamp: 20260326_100014 +Total benchmarks: 53 +===================================== + + +====================================== +Benchmark: adi (1/53) +Started at: Thu Mar 26 10:23:35 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with adi on the L dataset ***** +NumPy - default - first/validation: 727ms +NumPy - default - median: 728ms +SUCCESS: adi completed +Completed at: Thu Mar 26 10:23:45 AM PDT 2026 +====================================== + + +====================================== +Benchmark: arc_distance (2/53) +Started at: Thu Mar 26 10:23:45 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with arc_distance on the L dataset ***** +NumPy - default - first/validation: 165ms +NumPy - default - median: 97ms +SUCCESS: arc_distance completed +Completed at: Thu Mar 26 10:23:48 AM PDT 2026 +====================================== + + +====================================== +Benchmark: atax (3/53) +Started at: Thu Mar 26 10:23:48 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with atax on the L dataset ***** +NumPy - default - first/validation: 95ms +NumPy - default - median: 100ms +SUCCESS: atax completed +Completed at: Thu Mar 26 10:24:12 AM PDT 2026 +====================================== + + +====================================== +Benchmark: azimint_hist (4/53) +Started at: Thu Mar 26 10:24:12 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with azimint_hist on the L dataset ***** +NumPy - default - first/validation: 768ms +NumPy - default - median: 768ms +SUCCESS: azimint_hist completed +Completed at: Thu Mar 26 10:24:25 AM PDT 2026 +====================================== + + +====================================== +Benchmark: bicg (5/53) +Started at: Thu Mar 26 10:24:25 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with bicg on the L dataset ***** +NumPy - default - first/validation: 98ms +NumPy - default - median: 105ms +SUCCESS: bicg completed +Completed at: Thu Mar 26 10:24:49 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cavity_flow (6/53) +Started at: Thu Mar 26 10:24:49 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cavity_flow on the L dataset ***** +NumPy - default - first/validation: 688ms +NumPy - default - median: 628ms +SUCCESS: cavity_flow completed +Completed at: Thu Mar 26 10:24:57 AM PDT 2026 +====================================== + + +====================================== +Benchmark: channel_flow (7/53) +Started at: Thu Mar 26 10:24:57 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with channel_flow on the L dataset ***** +NumPy - default - first/validation: 6748ms +NumPy - default - median: 6883ms +SUCCESS: channel_flow completed +Completed at: Thu Mar 26 10:26:27 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cholesky (8/53) +Started at: Thu Mar 26 10:26:27 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cholesky on the L dataset ***** +NumPy - default - first/validation: 502ms +NumPy - default - median: 458ms +SUCCESS: cholesky completed +Completed at: Thu Mar 26 10:26:34 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cholesky2 (9/53) +Started at: Thu Mar 26 10:26:34 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cholesky2 on the L dataset ***** +NumPy - default - first/validation: 603ms +NumPy - default - median: 642ms +SUCCESS: cholesky2 completed +Completed at: Thu Mar 26 10:26:45 AM PDT 2026 +====================================== + + +====================================== +Benchmark: compute (10/53) +Started at: Thu Mar 26 10:26:45 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with compute on the L dataset ***** +NumPy - default - first/validation: 1767ms +NumPy - default - median: 1745ms +SUCCESS: compute completed +Completed at: Thu Mar 26 10:27:26 AM PDT 2026 +====================================== + + +====================================== +Benchmark: contour_integral (11/53) +Started at: Thu Mar 26 10:27:26 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with contour_integral on the L dataset ***** +NumPy - default - first/validation: 712ms +NumPy - default - median: 703ms +SUCCESS: contour_integral completed +Completed at: Thu Mar 26 10:27:36 AM PDT 2026 +====================================== + + +====================================== +Benchmark: conv2d_bias (12/53) +Started at: Thu Mar 26 10:27:36 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with conv2d_bias on the L dataset ***** +NumPy - default - first/validation: 833ms +NumPy - default - median: 758ms +SUCCESS: conv2d_bias completed +Completed at: Thu Mar 26 10:27:46 AM PDT 2026 +====================================== + + +====================================== +Benchmark: correlation (13/53) +Started at: Thu Mar 26 10:27:46 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with correlation on the L dataset ***** +NumPy - default - first/validation: 551ms +NumPy - default - median: 512ms +SUCCESS: correlation completed +Completed at: Thu Mar 26 10:27:54 AM PDT 2026 +====================================== + + +====================================== +Benchmark: covariance (14/53) +Started at: Thu Mar 26 10:27:54 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with covariance on the L dataset ***** +NumPy - default - first/validation: 422ms +NumPy - default - median: 492ms +SUCCESS: covariance completed +Completed at: Thu Mar 26 10:28:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: covariance2 (15/53) +Started at: Thu Mar 26 10:28:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with covariance2 on the L dataset ***** +NumPy - default - first/validation: 139ms +NumPy - default - median: 131ms +SUCCESS: covariance2 completed +Completed at: Thu Mar 26 10:28:04 AM PDT 2026 +====================================== + + +====================================== +Benchmark: crc16 (16/53) +Started at: Thu Mar 26 10:28:04 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with crc16 on the L dataset ***** +NumPy - default - first/validation: 188ms +NumPy - default - median: 198ms +SUCCESS: crc16 completed +Completed at: Thu Mar 26 10:28:07 AM PDT 2026 +====================================== + + +====================================== +Benchmark: deriche (17/53) +Started at: Thu Mar 26 10:28:07 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with deriche on the L dataset ***** +NumPy - default - first/validation: 531ms +NumPy - default - median: 543ms +SUCCESS: deriche completed +Completed at: Thu Mar 26 10:28:15 AM PDT 2026 +====================================== + + +====================================== +Benchmark: doitgen (18/53) +Started at: Thu Mar 26 10:28:15 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with doitgen on the L dataset ***** +NumPy - default - first/validation: 415ms +NumPy - default - median: 419ms +SUCCESS: doitgen completed +Completed at: Thu Mar 26 10:28:23 AM PDT 2026 +====================================== + + +====================================== +Benchmark: durbin (19/53) +Started at: Thu Mar 26 10:28:23 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with durbin on the L dataset ***** +NumPy - default - first/validation: 767ms +NumPy - default - median: 1025ms +SUCCESS: durbin completed +Completed at: Thu Mar 26 10:28:36 AM PDT 2026 +====================================== + + +====================================== +Benchmark: fdtd_2d (20/53) +Started at: Thu Mar 26 10:28:36 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with fdtd_2d on the L dataset ***** +NumPy - default - first/validation: 943ms +NumPy - default - median: 948ms +SUCCESS: fdtd_2d completed +Completed at: Thu Mar 26 10:28:49 AM PDT 2026 +====================================== + + +====================================== +Benchmark: floyd_warshall (21/53) +Started at: Thu Mar 26 10:28:49 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with floyd_warshall on the L dataset ***** +NumPy - default - first/validation: 910ms +NumPy - default - median: 924ms +SUCCESS: floyd_warshall completed +Completed at: Thu Mar 26 10:29:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gemm (22/53) +Started at: Thu Mar 26 10:29:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gemm on the L dataset ***** +NumPy - default - first/validation: 247ms +NumPy - default - median: 240ms +SUCCESS: gemm completed +Completed at: Thu Mar 26 10:29:13 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gemver (23/53) +Started at: Thu Mar 26 10:29:13 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gemver on the L dataset ***** +NumPy - default - first/validation: 432ms +NumPy - default - median: 444ms +SUCCESS: gemver completed +Completed at: Thu Mar 26 10:29:24 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gesummv (24/53) +Started at: Thu Mar 26 10:29:24 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gesummv on the L dataset ***** +NumPy - default - first/validation: 119ms +NumPy - default - median: 117ms +SUCCESS: gesummv completed +Completed at: Thu Mar 26 10:29:43 AM PDT 2026 +====================================== + + +====================================== +Benchmark: go_fast (25/53) +Started at: Thu Mar 26 10:29:43 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with go_fast on the L dataset ***** +NumPy - default - first/validation: 169ms +NumPy - default - median: 96ms +SUCCESS: go_fast completed +Completed at: Thu Mar 26 10:29:58 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gramschmidt (26/53) +Started at: Thu Mar 26 10:29:58 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gramschmidt on the L dataset ***** +NumPy - default - first/validation: 505ms +NumPy - default - median: 467ms +SUCCESS: gramschmidt completed +Completed at: Thu Mar 26 10:30:04 AM PDT 2026 +====================================== + + +====================================== +Benchmark: hdiff (27/53) +Started at: Thu Mar 26 10:30:04 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with hdiff on the L dataset ***** +NumPy - default - first/validation: 836ms +NumPy - default - median: 724ms +SUCCESS: hdiff completed +Completed at: Thu Mar 26 10:30:17 AM PDT 2026 +====================================== + + +====================================== +Benchmark: heat_3d (28/53) +Started at: Thu Mar 26 10:30:17 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with heat_3d on the L dataset ***** +NumPy - default - first/validation: 796ms +NumPy - default - median: 794ms +SUCCESS: heat_3d completed +Completed at: Thu Mar 26 10:30:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: jacobi_1d (29/53) +Started at: Thu Mar 26 10:30:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with jacobi_1d on the L dataset ***** +NumPy - default - first/validation: 754ms +NumPy - default - median: 710ms +SUCCESS: jacobi_1d completed +Completed at: Thu Mar 26 10:30:38 AM PDT 2026 +====================================== + + +====================================== +Benchmark: jacobi_2d (30/53) +Started at: Thu Mar 26 10:30:38 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with jacobi_2d on the L dataset ***** +NumPy - default - first/validation: 966ms +NumPy - default - median: 960ms +SUCCESS: jacobi_2d completed +Completed at: Thu Mar 26 10:30:51 AM PDT 2026 +====================================== + + +====================================== +Benchmark: k2mm (31/53) +Started at: Thu Mar 26 10:30:51 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with k2mm on the L dataset ***** +NumPy - default - first/validation: 379ms +NumPy - default - median: 332ms +SUCCESS: k2mm completed +Completed at: Thu Mar 26 10:31:05 AM PDT 2026 +====================================== + + +====================================== +Benchmark: k3mm (32/53) +Started at: Thu Mar 26 10:31:05 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with k3mm on the L dataset ***** +NumPy - default - first/validation: 321ms +NumPy - default - median: 319ms +SUCCESS: k3mm completed +Completed at: Thu Mar 26 10:31:20 AM PDT 2026 +====================================== + + +====================================== +Benchmark: lenet (33/53) +Started at: Thu Mar 26 10:31:20 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with lenet on the L dataset ***** +NumPy - default - first/validation: 599ms +NumPy - default - median: 569ms +SUCCESS: lenet completed +Completed at: Thu Mar 26 10:31:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: lu (34/53) +Started at: Thu Mar 26 10:31:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with lu on the L dataset ***** +NumPy - default - first/validation: 658ms +NumPy - default - median: 613ms +SUCCESS: lu completed +Completed at: Thu Mar 26 10:31:37 AM PDT 2026 +====================================== + + +====================================== +Benchmark: ludcmp (35/53) +Started at: Thu Mar 26 10:31:37 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with ludcmp on the L dataset ***** +NumPy - default - first/validation: 562ms +NumPy - default - median: 519ms +SUCCESS: ludcmp completed +Completed at: Thu Mar 26 10:31:44 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mandelbrot1 (36/53) +Started at: Thu Mar 26 10:31:44 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mandelbrot1 on the L dataset ***** +NumPy - default - first/validation: 910ms +NumPy - default - median: 830ms +SUCCESS: mandelbrot1 completed +Completed at: Thu Mar 26 10:31:56 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mandelbrot2 (37/53) +Started at: Thu Mar 26 10:31:56 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mandelbrot2 on the L dataset ***** +NumPy - default - first/validation: 428ms +NumPy - default - median: 331ms +SUCCESS: mandelbrot2 completed +Completed at: Thu Mar 26 10:32:00 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mlp (38/53) +Started at: Thu Mar 26 10:32:00 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mlp on the L dataset ***** +NumPy - default - first/validation: 199ms +NumPy - default - median: 131ms +SUCCESS: mlp completed +Completed at: Thu Mar 26 10:32:34 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mvt (39/53) +Started at: Thu Mar 26 10:32:34 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mvt on the L dataset ***** +NumPy - default - first/validation: 91ms +NumPy - default - median: 96ms +SUCCESS: mvt completed +Completed at: Thu Mar 26 10:32:57 AM PDT 2026 +====================================== + + +====================================== +Benchmark: nbody (40/53) +Started at: Thu Mar 26 10:32:57 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with nbody on the L dataset ***** +NumPy - default - first/validation: 246ms +NumPy - default - median: 188ms +SUCCESS: nbody completed +Completed at: Thu Mar 26 10:33:00 AM PDT 2026 +====================================== + + +====================================== +Benchmark: nussinov (41/53) +Started at: Thu Mar 26 10:33:00 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with nussinov on the L dataset ***** +NumPy - default - first/validation: 381ms +NumPy - default - median: 381ms +SUCCESS: nussinov completed +Completed at: Thu Mar 26 10:33:06 AM PDT 2026 +====================================== + + +====================================== +Benchmark: resnet (42/53) +Started at: Thu Mar 26 10:33:06 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with resnet on the L dataset ***** +NumPy - default - first/validation: 701ms +NumPy - default - median: 625ms +SUCCESS: resnet completed +Completed at: Thu Mar 26 10:33:14 AM PDT 2026 +====================================== + + +====================================== +Benchmark: scattering_self_energies (43/53) +Started at: Thu Mar 26 10:33:14 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with scattering_self_energies on the L dataset ***** +NumPy - default - first/validation: 464ms +NumPy - default - median: 406ms +SUCCESS: scattering_self_energies completed +Completed at: Thu Mar 26 10:33:20 AM PDT 2026 +====================================== + + +====================================== +Benchmark: seidel_2d (44/53) +Started at: Thu Mar 26 10:33:20 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with seidel_2d on the L dataset ***** +NumPy - default - first/validation: 553ms +NumPy - default - median: 555ms +SUCCESS: seidel_2d completed +Completed at: Thu Mar 26 10:33:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: softmax (45/53) +Started at: Thu Mar 26 10:33:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with softmax on the L dataset ***** +NumPy - default - first/validation: 644ms +NumPy - default - median: 589ms +SUCCESS: softmax completed +Completed at: Thu Mar 26 10:33:39 AM PDT 2026 +====================================== + + +====================================== +Benchmark: spmv (46/53) +Started at: Thu Mar 26 10:33:39 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with spmv on the L dataset ***** +Traceback (most recent call last): + File "/localdisk/work/antonvol/code/npbench/run_benchmark.py", line 57, in + test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) + ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run + bdata = self.bench.get_data(preset) + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data + exec(init_str, data) + ~~~~^^^^^^^^^^^^^^^^ + File "", line 1, in + File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize + from scipy.sparse import random +ModuleNotFoundError: No module named 'scipy' +ERROR: spmv failed with exit code 1 +Completed at: Thu Mar 26 10:33:40 AM PDT 2026 +====================================== + + +====================================== +Benchmark: stockham_fft (47/53) +Started at: Thu Mar 26 10:33:40 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with stockham_fft on the L dataset ***** +NumPy - default - first/validation: 787ms +NumPy - default - median: 778ms +SUCCESS: stockham_fft completed +Completed at: Thu Mar 26 10:33:51 AM PDT 2026 +====================================== + + +====================================== +Benchmark: symm (48/53) +Started at: Thu Mar 26 10:33:51 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with symm on the L dataset ***** +NumPy - default - first/validation: 480ms +NumPy - default - median: 473ms +SUCCESS: symm completed +Completed at: Thu Mar 26 10:33:57 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syr2k (49/53) +Started at: Thu Mar 26 10:33:57 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syr2k on the L dataset ***** +NumPy - default - first/validation: 511ms +NumPy - default - median: 515ms +SUCCESS: syr2k completed +Completed at: Thu Mar 26 10:34:05 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syrk (50/53) +Started at: Thu Mar 26 10:34:05 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syrk on the L dataset ***** +NumPy - default - first/validation: 480ms +NumPy - default - median: 471ms +SUCCESS: syrk completed +Completed at: Thu Mar 26 10:34:11 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trisolv (51/53) +Started at: Thu Mar 26 10:34:11 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trisolv on the L dataset ***** +NumPy - default - first/validation: 51ms +NumPy - default - median: 50ms +SUCCESS: trisolv completed +Completed at: Thu Mar 26 10:34:19 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trmm (52/53) +Started at: Thu Mar 26 10:34:19 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trmm on the L dataset ***** +NumPy - default - first/validation: 496ms +NumPy - default - median: 497ms +SUCCESS: trmm completed +Completed at: Thu Mar 26 10:34:26 AM PDT 2026 +====================================== + + +====================================== +Benchmark: vadv (53/53) +Started at: Thu Mar 26 10:34:26 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with vadv on the L dataset ***** +NumPy - default - first/validation: 836ms +NumPy - default - median: 824ms +SUCCESS: vadv completed +Completed at: Thu Mar 26 10:34:38 AM PDT 2026 +====================================== + diff --git a/mkl_backend_20260326_100014.txt b/mkl_backend_20260326_100014.txt new file mode 100644 index 00000000..f28e033c --- /dev/null +++ b/mkl_backend_20260326_100014.txt @@ -0,0 +1,812 @@ +===================================== +Environment: mkl_backend (npbench_mkl_numpy) +Timestamp: 20260326_100014 +Total benchmarks: 53 +===================================== + + +====================================== +Benchmark: adi (1/53) +Started at: Thu Mar 26 10:12:31 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with adi on the L dataset ***** +NumPy - default - first/validation: 694ms +NumPy - default - median: 689ms +SUCCESS: adi completed +Completed at: Thu Mar 26 10:12:40 AM PDT 2026 +====================================== + + +====================================== +Benchmark: arc_distance (2/53) +Started at: Thu Mar 26 10:12:40 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with arc_distance on the L dataset ***** +NumPy - default - first/validation: 482ms +NumPy - default - median: 484ms +SUCCESS: arc_distance completed +Completed at: Thu Mar 26 10:12:48 AM PDT 2026 +====================================== + + +====================================== +Benchmark: atax (3/53) +Started at: Thu Mar 26 10:12:48 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with atax on the L dataset ***** +NumPy - default - first/validation: 127ms +NumPy - default - median: 58ms +SUCCESS: atax completed +Completed at: Thu Mar 26 10:13:13 AM PDT 2026 +====================================== + + +====================================== +Benchmark: azimint_hist (4/53) +Started at: Thu Mar 26 10:13:13 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with azimint_hist on the L dataset ***** +NumPy - default - first/validation: 648ms +NumPy - default - median: 649ms +SUCCESS: azimint_hist completed +Completed at: Thu Mar 26 10:13:24 AM PDT 2026 +====================================== + + +====================================== +Benchmark: bicg (5/53) +Started at: Thu Mar 26 10:13:24 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with bicg on the L dataset ***** +NumPy - default - first/validation: 154ms +NumPy - default - median: 59ms +SUCCESS: bicg completed +Completed at: Thu Mar 26 10:13:49 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cavity_flow (6/53) +Started at: Thu Mar 26 10:13:49 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cavity_flow on the L dataset ***** +NumPy - default - first/validation: 468ms +NumPy - default - median: 468ms +SUCCESS: cavity_flow completed +Completed at: Thu Mar 26 10:13:55 AM PDT 2026 +====================================== + + +====================================== +Benchmark: channel_flow (7/53) +Started at: Thu Mar 26 10:13:55 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with channel_flow on the L dataset ***** +NumPy - default - first/validation: 4995ms +NumPy - default - median: 5031ms +SUCCESS: channel_flow completed +Completed at: Thu Mar 26 10:15:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cholesky (8/53) +Started at: Thu Mar 26 10:15:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cholesky on the L dataset ***** +NumPy - default - first/validation: 439ms +NumPy - default - median: 441ms +SUCCESS: cholesky completed +Completed at: Thu Mar 26 10:15:07 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cholesky2 (9/53) +Started at: Thu Mar 26 10:15:07 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cholesky2 on the L dataset ***** +NumPy - default - first/validation: 701ms +NumPy - default - median: 697ms +SUCCESS: cholesky2 completed +Completed at: Thu Mar 26 10:15:20 AM PDT 2026 +====================================== + + +====================================== +Benchmark: compute (10/53) +Started at: Thu Mar 26 10:15:20 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with compute on the L dataset ***** +NumPy - default - first/validation: 1715ms +NumPy - default - median: 1711ms +SUCCESS: compute completed +Completed at: Thu Mar 26 10:15:59 AM PDT 2026 +====================================== + + +====================================== +Benchmark: contour_integral (11/53) +Started at: Thu Mar 26 10:15:59 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with contour_integral on the L dataset ***** +NumPy - default - first/validation: 1011ms +NumPy - default - median: 648ms +SUCCESS: contour_integral completed +Completed at: Thu Mar 26 10:16:09 AM PDT 2026 +====================================== + + +====================================== +Benchmark: conv2d_bias (12/53) +Started at: Thu Mar 26 10:16:09 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with conv2d_bias on the L dataset ***** +NumPy - default - first/validation: 769ms +NumPy - default - median: 747ms +SUCCESS: conv2d_bias completed +Completed at: Thu Mar 26 10:16:19 AM PDT 2026 +====================================== + + +====================================== +Benchmark: correlation (13/53) +Started at: Thu Mar 26 10:16:19 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with correlation on the L dataset ***** +NumPy - default - first/validation: 1173ms +NumPy - default - median: 551ms +SUCCESS: correlation completed +Completed at: Thu Mar 26 10:16:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: covariance (14/53) +Started at: Thu Mar 26 10:16:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with covariance on the L dataset ***** +NumPy - default - first/validation: 995ms +NumPy - default - median: 431ms +SUCCESS: covariance completed +Completed at: Thu Mar 26 10:16:36 AM PDT 2026 +====================================== + + +====================================== +Benchmark: covariance2 (15/53) +Started at: Thu Mar 26 10:16:36 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with covariance2 on the L dataset ***** +NumPy - default - first/validation: 202ms +NumPy - default - median: 135ms +SUCCESS: covariance2 completed +Completed at: Thu Mar 26 10:16:38 AM PDT 2026 +====================================== + + +====================================== +Benchmark: crc16 (16/53) +Started at: Thu Mar 26 10:16:38 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with crc16 on the L dataset ***** +NumPy - default - first/validation: 186ms +NumPy - default - median: 189ms +SUCCESS: crc16 completed +Completed at: Thu Mar 26 10:16:41 AM PDT 2026 +====================================== + + +====================================== +Benchmark: deriche (17/53) +Started at: Thu Mar 26 10:16:41 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with deriche on the L dataset ***** +NumPy - default - first/validation: 598ms +NumPy - default - median: 626ms +SUCCESS: deriche completed +Completed at: Thu Mar 26 10:16:51 AM PDT 2026 +====================================== + + +====================================== +Benchmark: doitgen (18/53) +Started at: Thu Mar 26 10:16:51 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with doitgen on the L dataset ***** +NumPy - default - first/validation: 1412ms +NumPy - default - median: 418ms +SUCCESS: doitgen completed +Completed at: Thu Mar 26 10:16:59 AM PDT 2026 +====================================== + + +====================================== +Benchmark: durbin (19/53) +Started at: Thu Mar 26 10:16:59 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with durbin on the L dataset ***** +NumPy - default - first/validation: 697ms +NumPy - default - median: 1568ms +SUCCESS: durbin completed +Completed at: Thu Mar 26 10:17:18 AM PDT 2026 +====================================== + + +====================================== +Benchmark: fdtd_2d (20/53) +Started at: Thu Mar 26 10:17:18 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with fdtd_2d on the L dataset ***** +NumPy - default - first/validation: 771ms +NumPy - default - median: 726ms +SUCCESS: fdtd_2d completed +Completed at: Thu Mar 26 10:17:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: floyd_warshall (21/53) +Started at: Thu Mar 26 10:17:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with floyd_warshall on the L dataset ***** +NumPy - default - first/validation: 720ms +NumPy - default - median: 722ms +SUCCESS: floyd_warshall completed +Completed at: Thu Mar 26 10:17:38 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gemm (22/53) +Started at: Thu Mar 26 10:17:38 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gemm on the L dataset ***** +NumPy - default - first/validation: 593ms +NumPy - default - median: 544ms +SUCCESS: gemm completed +Completed at: Thu Mar 26 10:17:54 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gemver (23/53) +Started at: Thu Mar 26 10:17:54 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gemver on the L dataset ***** +NumPy - default - first/validation: 972ms +NumPy - default - median: 767ms +SUCCESS: gemver completed +Completed at: Thu Mar 26 10:18:10 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gesummv (24/53) +Started at: Thu Mar 26 10:18:10 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gesummv on the L dataset ***** +NumPy - default - first/validation: 1008ms +NumPy - default - median: 919ms +SUCCESS: gesummv completed +Completed at: Thu Mar 26 10:18:40 AM PDT 2026 +====================================== + + +====================================== +Benchmark: go_fast (25/53) +Started at: Thu Mar 26 10:18:40 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with go_fast on the L dataset ***** +NumPy - default - first/validation: 869ms +NumPy - default - median: 847ms +SUCCESS: go_fast completed +Completed at: Thu Mar 26 10:19:04 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gramschmidt (26/53) +Started at: Thu Mar 26 10:19:04 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gramschmidt on the L dataset ***** +NumPy - default - first/validation: 550ms +NumPy - default - median: 454ms +SUCCESS: gramschmidt completed +Completed at: Thu Mar 26 10:19:11 AM PDT 2026 +====================================== + + +====================================== +Benchmark: hdiff (27/53) +Started at: Thu Mar 26 10:19:11 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with hdiff on the L dataset ***** +NumPy - default - first/validation: 834ms +NumPy - default - median: 828ms +SUCCESS: hdiff completed +Completed at: Thu Mar 26 10:19:24 AM PDT 2026 +====================================== + + +====================================== +Benchmark: heat_3d (28/53) +Started at: Thu Mar 26 10:19:24 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with heat_3d on the L dataset ***** +NumPy - default - first/validation: 595ms +NumPy - default - median: 610ms +SUCCESS: heat_3d completed +Completed at: Thu Mar 26 10:19:32 AM PDT 2026 +====================================== + + +====================================== +Benchmark: jacobi_1d (29/53) +Started at: Thu Mar 26 10:19:32 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with jacobi_1d on the L dataset ***** +NumPy - default - first/validation: 458ms +NumPy - default - median: 594ms +SUCCESS: jacobi_1d completed +Completed at: Thu Mar 26 10:19:40 AM PDT 2026 +====================================== + + +====================================== +Benchmark: jacobi_2d (30/53) +Started at: Thu Mar 26 10:19:40 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with jacobi_2d on the L dataset ***** +NumPy - default - first/validation: 707ms +NumPy - default - median: 705ms +SUCCESS: jacobi_2d completed +Completed at: Thu Mar 26 10:19:50 AM PDT 2026 +====================================== + + +====================================== +Benchmark: k2mm (31/53) +Started at: Thu Mar 26 10:19:50 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with k2mm on the L dataset ***** +NumPy - default - first/validation: 783ms +NumPy - default - median: 523ms +SUCCESS: k2mm completed +Completed at: Thu Mar 26 10:20:06 AM PDT 2026 +====================================== + + +====================================== +Benchmark: k3mm (32/53) +Started at: Thu Mar 26 10:20:06 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with k3mm on the L dataset ***** +NumPy - default - first/validation: 457ms +NumPy - default - median: 320ms +SUCCESS: k3mm completed +Completed at: Thu Mar 26 10:20:19 AM PDT 2026 +====================================== + + +====================================== +Benchmark: lenet (33/53) +Started at: Thu Mar 26 10:20:19 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with lenet on the L dataset ***** +NumPy - default - first/validation: 623ms +NumPy - default - median: 565ms +SUCCESS: lenet completed +Completed at: Thu Mar 26 10:20:27 AM PDT 2026 +====================================== + + +====================================== +Benchmark: lu (34/53) +Started at: Thu Mar 26 10:20:27 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with lu on the L dataset ***** +NumPy - default - first/validation: 685ms +NumPy - default - median: 586ms +SUCCESS: lu completed +Completed at: Thu Mar 26 10:20:35 AM PDT 2026 +====================================== + + +====================================== +Benchmark: ludcmp (35/53) +Started at: Thu Mar 26 10:20:35 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with ludcmp on the L dataset ***** +NumPy - default - first/validation: 514ms +NumPy - default - median: 497ms +SUCCESS: ludcmp completed +Completed at: Thu Mar 26 10:20:42 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mandelbrot1 (36/53) +Started at: Thu Mar 26 10:20:42 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mandelbrot1 on the L dataset ***** +NumPy - default - first/validation: 631ms +NumPy - default - median: 617ms +SUCCESS: mandelbrot1 completed +Completed at: Thu Mar 26 10:20:51 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mandelbrot2 (37/53) +Started at: Thu Mar 26 10:20:51 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mandelbrot2 on the L dataset ***** +NumPy - default - first/validation: 252ms +NumPy - default - median: 226ms +SUCCESS: mandelbrot2 completed +Completed at: Thu Mar 26 10:20:54 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mlp (38/53) +Started at: Thu Mar 26 10:20:54 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mlp on the L dataset ***** +NumPy - default - first/validation: 192ms +NumPy - default - median: 79ms +SUCCESS: mlp completed +Completed at: Thu Mar 26 10:21:27 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mvt (39/53) +Started at: Thu Mar 26 10:21:27 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mvt on the L dataset ***** +NumPy - default - first/validation: 124ms +NumPy - default - median: 55ms +SUCCESS: mvt completed +Completed at: Thu Mar 26 10:21:50 AM PDT 2026 +====================================== + + +====================================== +Benchmark: nbody (40/53) +Started at: Thu Mar 26 10:21:50 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with nbody on the L dataset ***** +NumPy - default - first/validation: 195ms +NumPy - default - median: 195ms +SUCCESS: nbody completed +Completed at: Thu Mar 26 10:21:53 AM PDT 2026 +====================================== + + +====================================== +Benchmark: nussinov (41/53) +Started at: Thu Mar 26 10:21:53 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with nussinov on the L dataset ***** +NumPy - default - first/validation: 392ms +NumPy - default - median: 392ms +SUCCESS: nussinov completed +Completed at: Thu Mar 26 10:21:59 AM PDT 2026 +====================================== + + +====================================== +Benchmark: resnet (42/53) +Started at: Thu Mar 26 10:21:59 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with resnet on the L dataset ***** +NumPy - default - first/validation: 532ms +NumPy - default - median: 547ms +SUCCESS: resnet completed +Completed at: Thu Mar 26 10:22:06 AM PDT 2026 +====================================== + + +====================================== +Benchmark: scattering_self_energies (43/53) +Started at: Thu Mar 26 10:22:06 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with scattering_self_energies on the L dataset ***** +NumPy - default - first/validation: 480ms +NumPy - default - median: 420ms +SUCCESS: scattering_self_energies completed +Completed at: Thu Mar 26 10:22:12 AM PDT 2026 +====================================== + + +====================================== +Benchmark: seidel_2d (44/53) +Started at: Thu Mar 26 10:22:12 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with seidel_2d on the L dataset ***** +NumPy - default - first/validation: 534ms +NumPy - default - median: 539ms +SUCCESS: seidel_2d completed +Completed at: Thu Mar 26 10:22:20 AM PDT 2026 +====================================== + + +====================================== +Benchmark: softmax (45/53) +Started at: Thu Mar 26 10:22:20 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with softmax on the L dataset ***** +NumPy - default - first/validation: 974ms +NumPy - default - median: 943ms +SUCCESS: softmax completed +Completed at: Thu Mar 26 10:22:35 AM PDT 2026 +====================================== + + +====================================== +Benchmark: spmv (46/53) +Started at: Thu Mar 26 10:22:35 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with spmv on the L dataset ***** +Traceback (most recent call last): + File "/localdisk/work/antonvol/code/npbench/run_benchmark.py", line 57, in + test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) + ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run + bdata = self.bench.get_data(preset) + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data + exec(init_str, data) + ~~~~^^^^^^^^^^^^^^^^ + File "", line 1, in + File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize + from scipy.sparse import random +ModuleNotFoundError: No module named 'scipy' +ERROR: spmv failed with exit code 1 +Completed at: Thu Mar 26 10:22:36 AM PDT 2026 +====================================== + + +====================================== +Benchmark: stockham_fft (47/53) +Started at: Thu Mar 26 10:22:36 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with stockham_fft on the L dataset ***** +NumPy - default - first/validation: 999ms +NumPy - default - median: 937ms +SUCCESS: stockham_fft completed +Completed at: Thu Mar 26 10:22:49 AM PDT 2026 +====================================== + + +====================================== +Benchmark: symm (48/53) +Started at: Thu Mar 26 10:22:49 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with symm on the L dataset ***** +NumPy - default - first/validation: 455ms +NumPy - default - median: 450ms +SUCCESS: symm completed +Completed at: Thu Mar 26 10:22:55 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syr2k (49/53) +Started at: Thu Mar 26 10:22:55 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syr2k on the L dataset ***** +NumPy - default - first/validation: 483ms +NumPy - default - median: 482ms +SUCCESS: syr2k completed +Completed at: Thu Mar 26 10:23:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syrk (50/53) +Started at: Thu Mar 26 10:23:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syrk on the L dataset ***** +NumPy - default - first/validation: 435ms +NumPy - default - median: 439ms +SUCCESS: syrk completed +Completed at: Thu Mar 26 10:23:07 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trisolv (51/53) +Started at: Thu Mar 26 10:23:07 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trisolv on the L dataset ***** +NumPy - default - first/validation: 117ms +NumPy - default - median: 76ms +SUCCESS: trisolv completed +Completed at: Thu Mar 26 10:23:16 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trmm (52/53) +Started at: Thu Mar 26 10:23:16 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trmm on the L dataset ***** +NumPy - default - first/validation: 477ms +NumPy - default - median: 477ms +SUCCESS: trmm completed +Completed at: Thu Mar 26 10:23:23 AM PDT 2026 +====================================== + + +====================================== +Benchmark: vadv (53/53) +Started at: Thu Mar 26 10:23:23 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with vadv on the L dataset ***** +NumPy - default - first/validation: 818ms +NumPy - default - median: 810ms +SUCCESS: vadv completed +Completed at: Thu Mar 26 10:23:34 AM PDT 2026 +====================================== + diff --git a/mkl_umath_add_20260326_100014.txt b/mkl_umath_add_20260326_100014.txt new file mode 100644 index 00000000..c6a95630 --- /dev/null +++ b/mkl_umath_add_20260326_100014.txt @@ -0,0 +1,812 @@ +===================================== +Environment: mkl_umath_add (npbench_intel_numpy_imp) +Timestamp: 20260326_100014 +Total benchmarks: 53 +===================================== + + +====================================== +Benchmark: adi (1/53) +Started at: Thu Mar 26 10:34:39 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with adi on the L dataset ***** +NumPy - default - first/validation: 716ms +NumPy - default - median: 701ms +SUCCESS: adi completed +Completed at: Thu Mar 26 10:34:48 AM PDT 2026 +====================================== + + +====================================== +Benchmark: arc_distance (2/53) +Started at: Thu Mar 26 10:34:48 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with arc_distance on the L dataset ***** +NumPy - default - first/validation: 170ms +NumPy - default - median: 93ms +SUCCESS: arc_distance completed +Completed at: Thu Mar 26 10:34:52 AM PDT 2026 +====================================== + + +====================================== +Benchmark: atax (3/53) +Started at: Thu Mar 26 10:34:52 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with atax on the L dataset ***** +NumPy - default - first/validation: 94ms +NumPy - default - median: 102ms +SUCCESS: atax completed +Completed at: Thu Mar 26 10:35:15 AM PDT 2026 +====================================== + + +====================================== +Benchmark: azimint_hist (4/53) +Started at: Thu Mar 26 10:35:15 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with azimint_hist on the L dataset ***** +NumPy - default - first/validation: 818ms +NumPy - default - median: 774ms +SUCCESS: azimint_hist completed +Completed at: Thu Mar 26 10:35:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: bicg (5/53) +Started at: Thu Mar 26 10:35:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with bicg on the L dataset ***** +NumPy - default - first/validation: 94ms +NumPy - default - median: 99ms +SUCCESS: bicg completed +Completed at: Thu Mar 26 10:35:52 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cavity_flow (6/53) +Started at: Thu Mar 26 10:35:52 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cavity_flow on the L dataset ***** +NumPy - default - first/validation: 709ms +NumPy - default - median: 652ms +SUCCESS: cavity_flow completed +Completed at: Thu Mar 26 10:36:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: channel_flow (7/53) +Started at: Thu Mar 26 10:36:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with channel_flow on the L dataset ***** +NumPy - default - first/validation: 7061ms +NumPy - default - median: 7241ms +SUCCESS: channel_flow completed +Completed at: Thu Mar 26 10:37:35 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cholesky (8/53) +Started at: Thu Mar 26 10:37:35 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cholesky on the L dataset ***** +NumPy - default - first/validation: 585ms +NumPy - default - median: 546ms +SUCCESS: cholesky completed +Completed at: Thu Mar 26 10:37:43 AM PDT 2026 +====================================== + + +====================================== +Benchmark: cholesky2 (9/53) +Started at: Thu Mar 26 10:37:43 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with cholesky2 on the L dataset ***** +NumPy - default - first/validation: 597ms +NumPy - default - median: 603ms +SUCCESS: cholesky2 completed +Completed at: Thu Mar 26 10:37:54 AM PDT 2026 +====================================== + + +====================================== +Benchmark: compute (10/53) +Started at: Thu Mar 26 10:37:54 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with compute on the L dataset ***** +NumPy - default - first/validation: 1757ms +NumPy - default - median: 1732ms +SUCCESS: compute completed +Completed at: Thu Mar 26 10:38:34 AM PDT 2026 +====================================== + + +====================================== +Benchmark: contour_integral (11/53) +Started at: Thu Mar 26 10:38:34 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with contour_integral on the L dataset ***** +NumPy - default - first/validation: 694ms +NumPy - default - median: 690ms +SUCCESS: contour_integral completed +Completed at: Thu Mar 26 10:38:44 AM PDT 2026 +====================================== + + +====================================== +Benchmark: conv2d_bias (12/53) +Started at: Thu Mar 26 10:38:44 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with conv2d_bias on the L dataset ***** +NumPy - default - first/validation: 837ms +NumPy - default - median: 772ms +SUCCESS: conv2d_bias completed +Completed at: Thu Mar 26 10:38:55 AM PDT 2026 +====================================== + + +====================================== +Benchmark: correlation (13/53) +Started at: Thu Mar 26 10:38:55 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with correlation on the L dataset ***** +NumPy - default - first/validation: 476ms +NumPy - default - median: 471ms +SUCCESS: correlation completed +Completed at: Thu Mar 26 10:39:02 AM PDT 2026 +====================================== + + +====================================== +Benchmark: covariance (14/53) +Started at: Thu Mar 26 10:39:02 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with covariance on the L dataset ***** +NumPy - default - first/validation: 415ms +NumPy - default - median: 427ms +SUCCESS: covariance completed +Completed at: Thu Mar 26 10:39:09 AM PDT 2026 +====================================== + + +====================================== +Benchmark: covariance2 (15/53) +Started at: Thu Mar 26 10:39:09 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with covariance2 on the L dataset ***** +NumPy - default - first/validation: 163ms +NumPy - default - median: 130ms +SUCCESS: covariance2 completed +Completed at: Thu Mar 26 10:39:11 AM PDT 2026 +====================================== + + +====================================== +Benchmark: crc16 (16/53) +Started at: Thu Mar 26 10:39:11 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with crc16 on the L dataset ***** +NumPy - default - first/validation: 187ms +NumPy - default - median: 199ms +SUCCESS: crc16 completed +Completed at: Thu Mar 26 10:39:14 AM PDT 2026 +====================================== + + +====================================== +Benchmark: deriche (17/53) +Started at: Thu Mar 26 10:39:14 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with deriche on the L dataset ***** +NumPy - default - first/validation: 536ms +NumPy - default - median: 551ms +SUCCESS: deriche completed +Completed at: Thu Mar 26 10:39:23 AM PDT 2026 +====================================== + + +====================================== +Benchmark: doitgen (18/53) +Started at: Thu Mar 26 10:39:23 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with doitgen on the L dataset ***** +NumPy - default - first/validation: 421ms +NumPy - default - median: 402ms +SUCCESS: doitgen completed +Completed at: Thu Mar 26 10:39:30 AM PDT 2026 +====================================== + + +====================================== +Benchmark: durbin (19/53) +Started at: Thu Mar 26 10:39:30 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with durbin on the L dataset ***** +NumPy - default - first/validation: 696ms +NumPy - default - median: 872ms +SUCCESS: durbin completed +Completed at: Thu Mar 26 10:39:42 AM PDT 2026 +====================================== + + +====================================== +Benchmark: fdtd_2d (20/53) +Started at: Thu Mar 26 10:39:42 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with fdtd_2d on the L dataset ***** +NumPy - default - first/validation: 924ms +NumPy - default - median: 927ms +SUCCESS: fdtd_2d completed +Completed at: Thu Mar 26 10:39:55 AM PDT 2026 +====================================== + + +====================================== +Benchmark: floyd_warshall (21/53) +Started at: Thu Mar 26 10:39:55 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with floyd_warshall on the L dataset ***** +NumPy - default - first/validation: 899ms +NumPy - default - median: 894ms +SUCCESS: floyd_warshall completed +Completed at: Thu Mar 26 10:40:07 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gemm (22/53) +Started at: Thu Mar 26 10:40:07 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gemm on the L dataset ***** +NumPy - default - first/validation: 251ms +NumPy - default - median: 233ms +SUCCESS: gemm completed +Completed at: Thu Mar 26 10:40:18 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gemver (23/53) +Started at: Thu Mar 26 10:40:18 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gemver on the L dataset ***** +NumPy - default - first/validation: 418ms +NumPy - default - median: 426ms +SUCCESS: gemver completed +Completed at: Thu Mar 26 10:40:29 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gesummv (24/53) +Started at: Thu Mar 26 10:40:29 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gesummv on the L dataset ***** +NumPy - default - first/validation: 119ms +NumPy - default - median: 112ms +SUCCESS: gesummv completed +Completed at: Thu Mar 26 10:40:48 AM PDT 2026 +====================================== + + +====================================== +Benchmark: go_fast (25/53) +Started at: Thu Mar 26 10:40:48 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with go_fast on the L dataset ***** +NumPy - default - first/validation: 167ms +NumPy - default - median: 97ms +SUCCESS: go_fast completed +Completed at: Thu Mar 26 10:41:03 AM PDT 2026 +====================================== + + +====================================== +Benchmark: gramschmidt (26/53) +Started at: Thu Mar 26 10:41:03 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with gramschmidt on the L dataset ***** +NumPy - default - first/validation: 508ms +NumPy - default - median: 465ms +SUCCESS: gramschmidt completed +Completed at: Thu Mar 26 10:41:10 AM PDT 2026 +====================================== + + +====================================== +Benchmark: hdiff (27/53) +Started at: Thu Mar 26 10:41:10 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with hdiff on the L dataset ***** +NumPy - default - first/validation: 818ms +NumPy - default - median: 731ms +SUCCESS: hdiff completed +Completed at: Thu Mar 26 10:41:22 AM PDT 2026 +====================================== + + +====================================== +Benchmark: heat_3d (28/53) +Started at: Thu Mar 26 10:41:22 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with heat_3d on the L dataset ***** +NumPy - default - first/validation: 811ms +NumPy - default - median: 812ms +SUCCESS: heat_3d completed +Completed at: Thu Mar 26 10:41:34 AM PDT 2026 +====================================== + + +====================================== +Benchmark: jacobi_1d (29/53) +Started at: Thu Mar 26 10:41:34 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with jacobi_1d on the L dataset ***** +NumPy - default - first/validation: 559ms +NumPy - default - median: 556ms +SUCCESS: jacobi_1d completed +Completed at: Thu Mar 26 10:41:41 AM PDT 2026 +====================================== + + +====================================== +Benchmark: jacobi_2d (30/53) +Started at: Thu Mar 26 10:41:41 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with jacobi_2d on the L dataset ***** +NumPy - default - first/validation: 968ms +NumPy - default - median: 971ms +SUCCESS: jacobi_2d completed +Completed at: Thu Mar 26 10:41:54 AM PDT 2026 +====================================== + + +====================================== +Benchmark: k2mm (31/53) +Started at: Thu Mar 26 10:41:54 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with k2mm on the L dataset ***** +NumPy - default - first/validation: 306ms +NumPy - default - median: 300ms +SUCCESS: k2mm completed +Completed at: Thu Mar 26 10:42:09 AM PDT 2026 +====================================== + + +====================================== +Benchmark: k3mm (32/53) +Started at: Thu Mar 26 10:42:09 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with k3mm on the L dataset ***** +NumPy - default - first/validation: 299ms +NumPy - default - median: 301ms +SUCCESS: k3mm completed +Completed at: Thu Mar 26 10:42:21 AM PDT 2026 +====================================== + + +====================================== +Benchmark: lenet (33/53) +Started at: Thu Mar 26 10:42:21 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with lenet on the L dataset ***** +NumPy - default - first/validation: 574ms +NumPy - default - median: 568ms +SUCCESS: lenet completed +Completed at: Thu Mar 26 10:42:29 AM PDT 2026 +====================================== + + +====================================== +Benchmark: lu (34/53) +Started at: Thu Mar 26 10:42:29 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with lu on the L dataset ***** +NumPy - default - first/validation: 650ms +NumPy - default - median: 607ms +SUCCESS: lu completed +Completed at: Thu Mar 26 10:42:38 AM PDT 2026 +====================================== + + +====================================== +Benchmark: ludcmp (35/53) +Started at: Thu Mar 26 10:42:38 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with ludcmp on the L dataset ***** +NumPy - default - first/validation: 561ms +NumPy - default - median: 516ms +SUCCESS: ludcmp completed +Completed at: Thu Mar 26 10:42:45 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mandelbrot1 (36/53) +Started at: Thu Mar 26 10:42:45 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mandelbrot1 on the L dataset ***** +NumPy - default - first/validation: 892ms +NumPy - default - median: 818ms +SUCCESS: mandelbrot1 completed +Completed at: Thu Mar 26 10:42:56 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mandelbrot2 (37/53) +Started at: Thu Mar 26 10:42:56 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mandelbrot2 on the L dataset ***** +NumPy - default - first/validation: 420ms +NumPy - default - median: 334ms +SUCCESS: mandelbrot2 completed +Completed at: Thu Mar 26 10:43:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mlp (38/53) +Started at: Thu Mar 26 10:43:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mlp on the L dataset ***** +NumPy - default - first/validation: 202ms +NumPy - default - median: 135ms +SUCCESS: mlp completed +Completed at: Thu Mar 26 10:43:35 AM PDT 2026 +====================================== + + +====================================== +Benchmark: mvt (39/53) +Started at: Thu Mar 26 10:43:35 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with mvt on the L dataset ***** +NumPy - default - first/validation: 89ms +NumPy - default - median: 96ms +SUCCESS: mvt completed +Completed at: Thu Mar 26 10:43:58 AM PDT 2026 +====================================== + + +====================================== +Benchmark: nbody (40/53) +Started at: Thu Mar 26 10:43:58 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with nbody on the L dataset ***** +NumPy - default - first/validation: 254ms +NumPy - default - median: 191ms +SUCCESS: nbody completed +Completed at: Thu Mar 26 10:44:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: nussinov (41/53) +Started at: Thu Mar 26 10:44:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with nussinov on the L dataset ***** +NumPy - default - first/validation: 382ms +NumPy - default - median: 382ms +SUCCESS: nussinov completed +Completed at: Thu Mar 26 10:44:07 AM PDT 2026 +====================================== + + +====================================== +Benchmark: resnet (42/53) +Started at: Thu Mar 26 10:44:07 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with resnet on the L dataset ***** +NumPy - default - first/validation: 615ms +NumPy - default - median: 526ms +SUCCESS: resnet completed +Completed at: Thu Mar 26 10:44:14 AM PDT 2026 +====================================== + + +====================================== +Benchmark: scattering_self_energies (43/53) +Started at: Thu Mar 26 10:44:14 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with scattering_self_energies on the L dataset ***** +NumPy - default - first/validation: 460ms +NumPy - default - median: 400ms +SUCCESS: scattering_self_energies completed +Completed at: Thu Mar 26 10:44:20 AM PDT 2026 +====================================== + + +====================================== +Benchmark: seidel_2d (44/53) +Started at: Thu Mar 26 10:44:20 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with seidel_2d on the L dataset ***** +NumPy - default - first/validation: 549ms +NumPy - default - median: 552ms +SUCCESS: seidel_2d completed +Completed at: Thu Mar 26 10:44:27 AM PDT 2026 +====================================== + + +====================================== +Benchmark: softmax (45/53) +Started at: Thu Mar 26 10:44:27 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with softmax on the L dataset ***** +NumPy - default - first/validation: 647ms +NumPy - default - median: 607ms +SUCCESS: softmax completed +Completed at: Thu Mar 26 10:44:40 AM PDT 2026 +====================================== + + +====================================== +Benchmark: spmv (46/53) +Started at: Thu Mar 26 10:44:40 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with spmv on the L dataset ***** +Traceback (most recent call last): + File "/localdisk/work/antonvol/code/npbench/run_benchmark.py", line 57, in + test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) + ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run + bdata = self.bench.get_data(preset) + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data + exec(init_str, data) + ~~~~^^^^^^^^^^^^^^^^ + File "", line 1, in + File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize + from scipy.sparse import random +ModuleNotFoundError: No module named 'scipy' +ERROR: spmv failed with exit code 1 +Completed at: Thu Mar 26 10:44:40 AM PDT 2026 +====================================== + + +====================================== +Benchmark: stockham_fft (47/53) +Started at: Thu Mar 26 10:44:40 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with stockham_fft on the L dataset ***** +NumPy - default - first/validation: 784ms +NumPy - default - median: 784ms +SUCCESS: stockham_fft completed +Completed at: Thu Mar 26 10:44:51 AM PDT 2026 +====================================== + + +====================================== +Benchmark: symm (48/53) +Started at: Thu Mar 26 10:44:51 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with symm on the L dataset ***** +NumPy - default - first/validation: 477ms +NumPy - default - median: 471ms +SUCCESS: symm completed +Completed at: Thu Mar 26 10:44:58 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syr2k (49/53) +Started at: Thu Mar 26 10:44:58 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syr2k on the L dataset ***** +NumPy - default - first/validation: 502ms +NumPy - default - median: 502ms +SUCCESS: syr2k completed +Completed at: Thu Mar 26 10:45:05 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syrk (50/53) +Started at: Thu Mar 26 10:45:05 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syrk on the L dataset ***** +NumPy - default - first/validation: 444ms +NumPy - default - median: 445ms +SUCCESS: syrk completed +Completed at: Thu Mar 26 10:45:11 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trisolv (51/53) +Started at: Thu Mar 26 10:45:11 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trisolv on the L dataset ***** +NumPy - default - first/validation: 53ms +NumPy - default - median: 53ms +SUCCESS: trisolv completed +Completed at: Thu Mar 26 10:45:19 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trmm (52/53) +Started at: Thu Mar 26 10:45:19 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trmm on the L dataset ***** +NumPy - default - first/validation: 489ms +NumPy - default - median: 489ms +SUCCESS: trmm completed +Completed at: Thu Mar 26 10:45:26 AM PDT 2026 +====================================== + + +====================================== +Benchmark: vadv (53/53) +Started at: Thu Mar 26 10:45:26 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with vadv on the L dataset ***** +NumPy - default - first/validation: 946ms +NumPy - default - median: 867ms +SUCCESS: vadv completed +Completed at: Thu Mar 26 10:45:38 AM PDT 2026 +====================================== + diff --git a/npbench_full_comparison.png b/npbench_full_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..17dac9132caae022f09cb2ab7661d94ed9d68aa5 GIT binary patch literal 433054 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�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%0ADnR6+pZSPngz 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�g3ir!M(mVPTXlSqQccqFdbOk%lEulP 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­IF@a)Ab)bo$omEul?IX?`! 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 z%0D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

p0+OwP}nRM+Puo1 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 s#h+K=&od#s0>ZC + test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) + ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run + bdata = self.bench.get_data(preset) + File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data + exec(init_str, data) + ~~~~^^^^^^^^^^^^^^^^ + File "", line 1, in + File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize + from scipy.sparse import random +ModuleNotFoundError: No module named 'scipy' +ERROR: spmv failed with exit code 1 +Completed at: Thu Mar 26 10:11:28 AM PDT 2026 +====================================== + + +====================================== +Benchmark: stockham_fft (47/53) +Started at: Thu Mar 26 10:11:28 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with stockham_fft on the L dataset ***** +NumPy - default - first/validation: 962ms +NumPy - default - median: 972ms +SUCCESS: stockham_fft completed +Completed at: Thu Mar 26 10:11:42 AM PDT 2026 +====================================== + + +====================================== +Benchmark: symm (48/53) +Started at: Thu Mar 26 10:11:42 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with symm on the L dataset ***** +NumPy - default - first/validation: 453ms +NumPy - default - median: 444ms +SUCCESS: symm completed +Completed at: Thu Mar 26 10:11:48 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syr2k (49/53) +Started at: Thu Mar 26 10:11:48 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syr2k on the L dataset ***** +NumPy - default - first/validation: 478ms +NumPy - default - median: 475ms +SUCCESS: syr2k completed +Completed at: Thu Mar 26 10:11:55 AM PDT 2026 +====================================== + + +====================================== +Benchmark: syrk (50/53) +Started at: Thu Mar 26 10:11:55 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with syrk on the L dataset ***** +NumPy - default - first/validation: 439ms +NumPy - default - median: 447ms +SUCCESS: syrk completed +Completed at: Thu Mar 26 10:12:01 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trisolv (51/53) +Started at: Thu Mar 26 10:12:01 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trisolv on the L dataset ***** +NumPy - default - first/validation: 233ms +NumPy - default - median: 223ms +SUCCESS: trisolv completed +Completed at: Thu Mar 26 10:12:13 AM PDT 2026 +====================================== + + +====================================== +Benchmark: trmm (52/53) +Started at: Thu Mar 26 10:12:13 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with trmm on the L dataset ***** +NumPy - default - first/validation: 465ms +NumPy - default - median: 465ms +SUCCESS: trmm completed +Completed at: Thu Mar 26 10:12:19 AM PDT 2026 +====================================== + + +====================================== +Benchmark: vadv (53/53) +Started at: Thu Mar 26 10:12:19 AM PDT 2026 +====================================== +/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. + import pkg_resources +WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. +***** Testing NumPy with vadv on the L dataset ***** +NumPy - default - first/validation: 798ms +NumPy - default - median: 785ms +SUCCESS: vadv completed +Completed at: Thu Mar 26 10:12:30 AM PDT 2026 +====================================== + diff --git a/tmp/npbench_full_comparison.png b/tmp/npbench_full_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..5fcf16f61cb4ec7b910687c5b615e9f2dba1ecbf GIT binary patch literal 433009 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�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/vV+>&cr_dJeSUFQ;&4-e(%$FdT2SIS{Letou4ofC12UOvBSod54Cp4jAlCf@ z*V^$~4s6+Du=YC-zvN#Rre4EU63q&j&vpTW2>)8kr&&C%9|f}+8h7xF=^Gj^%er@F zf0jI?l%kc+C(ko7VPa|BAuS8bo848e^+)Z?P{}l%BKYvd@;)>Jx=vdz~$2p}Vi!IY3TOPFX5bVm#yL#P2>^N`T*wz?!rr0UOtK5Y$x4 zeRo6&LapPHFUQ?J3_0nL8Xxd(xuE_XVgnx*su6oMdmX4BYcK}AS1M;=PK$r16tkGX z0i1C!KOVc+M0XutAtd*HDj@ZZu&eooOZ*+cos<)W@U`RHgi27@tCuW6@kEDPzv zU-@3>ro%To40K2=!9O5h{A`$I`@3InHcl!XmqmC;?iHt7)c^ZP*SpWQA)t-yGAjBzHMw@j?@GvOF1B}}YHSy6n*mfJ&^+Ax+yX57< zx9hYLw=#Beg>}N=0?wC@dvP{n}2<*?j}biW@@xwJk#MZ=(Zm^&2sea9E~qiEIS{RNOxE*go(9>i+UB-_;h(P#41}W|ATiJKxK>X)^ zSoWy)Eco73e(_WT3bRQHXLWc+7+eVYqi!rAJI13;7eY~M{j_oadaEa3Vh6D+34`*i z{2hu6gN&6RTCGv>7}*K9*ANc8{OF+rU(i*9Zi@u9bHM^dP9AUJCm%T^kwC-6FqY<&!B z-VlSzi-8pDOoiJyN0ec;D9Q-7UWgE8o0XlIUD~8WEE(S+|8MH^z~f@h)^9eJffs1I zK|D|ntFCI^aPldJ=%D=srnP2wC>hT$yldB0*NKsvH{KGU#QA^@MQ#5Uh;|V>rCBI4 zebz&R7nQiM*@#mNH|B$D${3E71G5^crR3$2hUzMq#zg)8qAL{VMnep2^tR3b6FW?# zw5YSk_bJ~0z9<4da0;{_yB`0z-Of@RQ(k^a+HC-3@CWF~M%OQz9~7%Z>zT-XFQ#a6 znVXuyThnp_)+%WEYy%-fb+Q~|Bb$+&VUJAwejO{>mGKmbH$t0v@rVXm6JcH1&9j3( z^4+x&2{wEUG3gi<$5IV=YLY9&>6nUwe)bQBxR_$SDF9^JFbihu8s;OdYMP_?$&Yue zuX>KyMv?cdp>3Dv<<`9gm-_Bq`PmI1f5zGl<^<<(g3BrLOn~V@15MwyU#En;5lv0! z$k)LJ-DbmRuY8-bv^pT7@-Ws4B**D~1n6OiOPXco2@o8o#i@616eo7vBaGsW6WS|3dC(xw@(@EO;~TwWadBu=@yFvb_erI0k;t`~ zE>?^blof=H@vuWgcT*5qLm7}(iF!%6=L{6^5(jQH1Rb^*b<8;5D+}AcxQ_wp5o)KR z{yx#a`N2{XwMFO7Aa_%o$sX;!GsJ|Q6PC>BcYiY}F1=dnf(qJGl{yaOve;*s4z@jF zrRPrBE;}?Bzk?jBOOk)oJ~{0AWSTDDl}Vm{ZgK{fhlMG5&9?0hju4M2(Ki%$Gh}Dc zd%I2hVq9kTVnCH*v|u=Ldh==X+2BVoR0r~BeHfwtY`)p0!F%M<`2*}Tq#d>O`87o< zy!h|r2p!6b+!Ib2!A*Tk(>z5BW9@LsThBFUx%n3vOE`FvO04{*k9WMV#==#8k%-UP zxe3@r-li)z=Vein^VbeBO}mi;k=GvcZS=-{0A@fe2In~KV1+(@$I^{YZ)Yq{-aoGe z4w#hKJ>$Z2)zRG+*Ob@p%G>$Sf!rp4c@zbYb8g>|$<`PBzT+z?bEjY272@U?vF>51 zWH8c4FSc8ze*hT+)ipVU_jr5q2avhbq28bF1uPeN3uoK#B7|+-2O}7CK2OFtHxhv* zIQqXr)y?wN#dx`x8`aZLKIBUXD`P7-Djumn6wlGe*|9BNfLY5&!;)5>W^7u+Vq}E1 zK}Fqv5Ga;=CusttaIKhD61E+G<0l`FfZm68_-nRdOSN|pi~?fmPGy02xjQv=5YpjJ zwj;Fdav}aj&t!{s)-EL4)WN2^%M!y;j6@8KUrHPA4Ee0}e^zLh+CZJn!blsSG zEKj5zB0{3k*r>_0=6)KPjt?JD_yuoMPzjDGajgEAk#P9Gxpfo?4Kg6yB_X_>BAEiE z&FSx{A8AjGdA}QbcmOX&Dyvvhf4|c^(|24iHN??e*;L3GWVVN>Qr^nkVAN+q;-B+{ z=`=l4rydIgZJ}jp<=I6|lMnY`wY6(SkvJE{}^k5xV zLUm&K$L>z7z>ICA*q6^YsC-T&&pa56tqLG083hNROzh*ZTHJjPBsw8Ssj3rviXV#M zH=cVV%cOz38ar{CM7|tn%=R+S9FT(PO|fIz1k;R{RfCaZ-RC@NX77VLhIQ~IUyt{7 zjH?^{wjef@hM;hY0o;lor&4ollg+FJ<>b&v>ncb~N8Sb?#-`E=NSaDi_KdU1KL!$K z%gFFz0fRBRHQ~C=I8ncU!bf_(uhFFr@?BT40_=^ReXwqA#^+@FSaqQ>?!1HM<;CZW z=L2J@S@7QCELe7AuNTPv$LD}W_kxAT;499%Vj&mepQ6-91xQBx?bag14M1GxKY04I zYGhsV<#l386Xx5INs=VAnLypFBI=(uj|ns8lmaHrzCE|yM@%TKyZQ+q^)Jb7EME6- zY^W558OV$E{H}}B#$mL{CTvP)JHG)|*7QoP1Hrf>08;F|`mdH$KZe(!y9{&>@OEV* zS_PChEp!229LD`hLWcj_@3p_| zgI%XQ(>M6Bzaqk2Q;QSD+4v<_a4=!83!cwHLdZPlHb>NyKZO#0{SH}7LzCQsKTX$6 zhNrePR;^3N%g@H9c1IJXIz>h!@*Ku$&0BAQWfNpEZlj(E)HFuSJGDf)?9svf>`HLb z&s%~pSXsst`?0>TAV&Ng?G$O87CN{tX|f&DT1ViWctX!e6gMY%{TeAunXTzPjw2IpUyo(&iHv7b3zQ`~j~cQetPlWnW2LFR*RZwRVnDiB# z8z@sh_1w)fu^a@kj_NO1<%Dd@VB;2eZs&?viFNPeBTN*!@kEum7mHaNs zzWq`J{HOE4@fVUdw$Ohh=>&cMbn#H|&_g^ejrc>=nYrymBf>Qa4ASWU%`C~$@{c+4 za)|2fId-^V=Mv0$#aUjC0Am5P!nH`}Z$Dd&ZJ_Z%KAWyYbRt_9)-#mK#G$<02m82c zA|o$gNJ9}sUdhT8ZFPcjuML&Q%QsDd)UXGZ7Eo6js1jSkj`xAfRCJ0TS$_Bh=16)( zYvP1F*zewo0?9RPQxsr0=Z?dP>*xFSux$O5#v(;%MKxxHaq>#T#g+X(0hjXGO6qF2 zNE=XQqg~RW-&cUo4(Z-K&Sw3*ClN^{#(ge?ZdiyWL90+pD_dUguFydpz>)#7fqP33 zIBcfMPI9{-&vJzy=A+KF2TPWyB|XI~*|m>++B${(VhsJZF+7>S%PVwHo|DOo71S*| z{&+~b?O}Lmweh}~!k-aY>#}&Ls|)7Ue}!m@X{wWpwfb{M&9&z#&v}r1<_K%{+qckv zp;KR{?;t^0K0Veh2eRAvJFTk%LN=_{w9XX22=2 zHN+2dWG37-kTJH%xpv3@a^m-j-`+el{FQb6)H{>GMZ*ho07Qgbpv+hf&^evBb-Bf+ zUm}73jzyo8^A=*_S@EmhrY~${zJAVDB zCaI^=q2O^|GL8a8D=%8Ql<|@VMY(U9{_IRuu$8SA5eNEQ)%ZW`oBOK!uK@nj{C->9 zec)-s<+Fdau-UQDTl{gzqc@|tX8g=>(lI}e@o?E@=h?lI;o!OGk94ZZYpJ7`ama`5 z#vK1{CW#3Fj6yiyJ>Z<)m;WnQf-8U{u%+{#9HxK1&||(nykz+=()a%eYfJDOufsHH z*(Fm$c|?Idt8nLGlj;ct^;HJV-=J={QLe!YB_7>#))zUjLK_n>|6@IWryrqMUH|h{ zk2YFwEdO~6GK^+mj#(a=Ws%8hVL^y8sI#epg0Y3b4ERQ-EU$QqC9kAzwEZxJAAU+U7PGlEn}O0;eB<)d zn6X;E&cq|S{QlcR;z<>@cgl0FF?Qb=iffO)1*(}NkGfGDBBQfXSJkE!XKaCX@43)A zO(S(1(dmipN^dYTdKLM@8z1{-)X@zYOWJXPQUKb`SBX@-Sg=|o>igigT&g_Jjg}yy zD}7U9lbwo>imLwrfHG|D`Bdn+on5NAVm+lT6!`!i7TtUO1{XW#I!N~{9GXR~l9Wb2 zN6&vu%EX>1 z^=k42{%NWg;azBvD2&5I&(z~rLvG5-XEeE`h2l#%-9?0-1jh>W?cWZ9wOZn=V4ey{dGsjmfmO`|EO#rr6tCqDJO;n?P zA(yQ)+%*>{ofTvUNA*wM!+(Ex#8`^4fHnckLP*HjZu#uRL^ zNB&yv(lbGvT7fAs?;+}m#Q z7KwOK$ds)paiY7Ep$|jiI)()En8F8d>0fWQ{hX7!M21*{uo%Z{9st9@3SLKfUZ+ck zkG$CK-sFzlufS#00c7mt<699cwjmPN)Y(pzRRm9~jYyt#m;Rn~w5!L`4>}IyI*#S> z`!OWPiXw84ONnaT-oV2S_#qn_+hK-9yfR$Drttzb1LQ0NW1k!S*lYQyMINS=IYM*KXiQ>fhz!twF*t=pgpk_p6txwceE{!SJf6J*V)logz`2Y<93cnl_^)u8T4;3&dFl)S!+Dd#Gd>IaNb_hHhMpW`f_vnPGu*!?&k% zq;;?BLoUs?-0XiI!0`Ei&=qsxw{h9CowK&(nIl9sDWFcI@fex?O!wCTm6iBpnLG!B zKI4dY0KYfT(=NSg8fz*nmwpEdp$OXCJCGkD@4-WH4%@J);Q!Tpg*!$0cheD$-qEt; z@ST>z?7yR^o#cPZ7mDl)`mv>oh3=DmdZ8~gI(_2^V*VHhV|ejSe|c^22EN}m=}*Eg z^|%m8^<{Z8r;OAzVTRSvBJf-N%w%7x!6BEi(~i|AW>LJE3l$^9dV!20<+55v00)Q@ zq?Xpd<5hppbo*9ahS-8^$~We@z=EjUi3#dDR7nULepPrU6)(rDDk1>aO>Tu)sWIl@ z^JAB|s-Ml#*o!vDzCr2#!c9CyJTqjAI*~xk?4W6rSPmC{UWBt|1Tw2AZ=2!L$ zb)8J7Z;{8X6X6(SAMlN&{8&GZ14UUonWh}|*C-k~GAmbC>fPnHnyweuq60R(X520G z2-`#a0^AzLa?iAF;Z-#g2sw)?AZ~)HZu)oO=!ADK#Qk}Yc_b^iqRu0*kBLAlNHs3n zUdNEg+fDYuqHHP<>9}#KHm3xPq}uXG7Ki7bp=66@oW;A~E{h}xWnk?Y&y}Y)v|XK0 ztiOfdho?3E^rXOTR^@*1TN?XE8EVSIt1*OuDN+fkhHEy@Z$Qa-eZF5sG6!5_N$EK# zpJD_Dr~g)EZ?`&c?t!I#eV`9b=_j7?-%Wz!bgAv)uh}Lnv_uuih>0Kz&hmq zL(X^+638R14~(0dk;?m)&dp7NiZMy%KmS@`km9re#)TN@O6YY3*kFC0aBMs~=rOb$ z>)`h?z>Y_P^7gPS0cX>i9ScNfWM^~{)a}^lt|r1?>GA*{=h0_xn$-wIR#cH# z;T-YAKZ>rh<=(#9*|ki{qqSsc(3F8o=Z?FF+qBQn!<|nQCI|f%Yh2V4(E;RA`OXi4 zq;f_oX~-C)vll;psS9H#511S9GC|(SrIlE17H zTUw9-f-1(conh^bNKQ2JZQgeU9M~-SyXW~`)GP9%SUvMfAkq0?xG&Dt4;rYo=y7et z{XoSd%~SbZJ198$$AV1`SpG5);1sD6dbo@e0RYv0vkEijPqT(S9Yq!n-k${0y5j+E z&It!QP>NX>A|JyfN)QESZ;(8wges=v6c?z>u=0f+Vc-AhZk32+TR?~^lLZz{np!~M zMvwAMS|$>_7{# zy+<@$flri?C`u>xeES?3merUQz!LhKPs{yj#Bp**$Y?U0src|ITXtAy;kTrPm-UXS zfW`@Q$X&3V2rBUfuc^&O-d3_J{c#jzup8%fx~nmSSdx;9n`Kod!RIqFSUyW-3ETn{B$3uHg53e25{wLm{HCPt__%ETI}oiOsG1X z!RKMc@sRtR^bCvYeT|fEGiAsg6&mcGd$ zZIrgZSLg_Qj28G}-3ms|zLk6*_&OBtH-wmJbWhass@aYhY3m1RQo6qHykpN9mcaM( z$w#m(iJvtbcG-?pTvr(49J{L%fci1;T>$ztRKGUOcd z7WqN*lffFf4l0-pcHuumiBg~B*a{cDH5W~mh2j$>cZ*rYBz^vt8bf^97cF@f3oCr6}Q1^&iK|_{s#iq`F|i_ zi?~8JFbQ6AG&ERT1|K)UXF_a{v7B$ws>l$^z<>!3`!r=Mp*9+-?I`^c^vP+bpD)Ys z$KaD9Biba=>m#ywxs)YUd@`murGUNK{`64zn)?f@Tl81?&uz+ zpJ(;*$U2ekEAbxM7<8*B?nfxN<|a6>xp71lBanzO_NVF1gPxL78gH0boZt<3JPf7{ zhOIx557J?^f2cZjNrFNlUYTrFPOSR~2qY}JqXL74+m(peM(?RNNr66@HyTLM+0zL- zfeHTP=}0z=aQK}@*B)_q@vO}~C$WzdP{TtiyyzZmyFG`))vJPpp(I5o^vchj>vDqI zp^Sop>>HUXid!VEZufZuB9$3?^nkSk@GW_tx^EpieA%J!FsJO0dR?6D*aRS2WOloE!y(gq+OS7lj56Gb zoZO#Jgm0tsYGGfu3+UULy$CTu)xPWnQZ5-d_Z@Sk%(aQEzQH>vykk{r&f-~W{fY)9LsHPl$1 zz3`g%{f7G4JFgu6MII_{i%}GEhAm70PUw@w=7@5q{&uoIlt`DXtx>8)%pd*kqscth z9@%V%zIn52{^>xao@?xBsK43#3-Aq5uHjG@CK8+!f^2{~J+=)7(v8pEVGGAH@VpSX zP95+F(4zLs}=O@b{FWHMlwAAL0YiUI4`V=yoZ{N$2zZm zsXUHRm(b{f?o-UC3D6Z%{V;#%pEGFOmE>rw7Z{9nA6Nu46P`-NUOC$UD}4FNSgJ4) z&~~iW{@6H1BEpL@E%;GGEUD&6f;$?}OYKy;7oHs{gQ~rCnbX9@mK)r-IT+1^u>bNx zqP#j^l?-M;1;rrZ9V~|aujQ}{*XY0HTfV~aluU88HASBULDyF(rQ^T81+u?OFz=YO@5ng3=@4C<0PRJfkPv(& zDsUL9>hx`S9A5vk*a?1+dLYbJGz5oll5@a@A`gS7m^WUhY4?6+4l0mi{f!g8dJQ=G zooDp|H(J)>=UB|TR-AT_Cm9Vb_)Z754q5iN)vWF%;GSEycRl$iF_F4r3&2<`U!B_) zT)d@sb?+?dPI)!ixSs$6uCO zN0+nRzg<(pHT-|)Sx- z868ywo^ZO71dlez?MSI7A&p97iSqD#NaL2d196+){ex`m9yo3bh9n+jW+%E2ae;*) z6bfRmjh01fJiAk#uUisifRT4*G!<4PqH-MHlWTxy=PI)(LVsJ?&o4KLKSU8L$uKpi z-H&!kfv(NfB!x|Cf*2KvUw>&B%V`j1XZ>TxwBa^bq4Jf4x?8!7d8ua_*id0z~V^{UrRgDRsK=Jgp`XARd(M{jwhw5 zL|gd6(N&NfQabi^5Gg0;9CJRi zs3s&iBWey(c{E`xCx!}74BnKendN%Uzx$3!;)k)ZEB~e>1?sHAJr+L>=!C26;s)Dr@=Y(;GAY#$JwPVSBdvSBnleo+UAm^T%eJr zfStA@A$Z0E+;p<8dLFAD2!V3xQ84HtYjXJB;9cDT2SXs_KXYLrq|PEdnv@NTk6{q4 z^8th!7p8nkc?pYnuV6-Q>^{1Big;)boakNXCTb`^N*?L{7TWY=6s)f>3>uM=6 zH|wG?w{oXJYL}FpQ@zz&m}smbp@I%7Q;n;;&_qkN@p~B1#MyK!biSjF}|m%cOfoy6grX zwWsJDn`!t=L068DJWZyKn9U&b6n9ve*bgK3QAI{LixMSpb1n@T!YjK|DuRuVqmf7| zI=w6+cD4)hOzxe4eQ?JWNG(Z02NU<2a_%ep;!^0~Oz20kn{prg9 zP!#%fv?hfY?`(38TL(Fd9Ye)g-N=#{)+t&f$XiWU(O2mRLF0lTBQQbtU_bM1h<85R z2Vq#wtlEp8wqKw`7q>9C=j7&Y%2)E|5{?7lEJ{UCLKwxw>HB2)ZV$GjIO+%+W?eTz zXA+N#|M_xAY>M@sVfZ~h>gR7wDKVu|egI(0#o1GAz?p8p`PUx==u%yzi8%xVbiey> zhsPtWXcNa}iTOoro)C$;%e%Mx7%gcb6~>+3B`BtiAB)G!22WJF{U!x-R|$&)AhR3d zdGYpPCsGI9k%dYm1CAl1aGbVbMNvPILq%mj$QEap!8;FVYQ z@BV@7xw>!?a_G-MZ>Fw)PANY`j55pm#3gm5NWJwEFzEg>O82~9;Isd`eS^bd_t8)l zXsJnD-PM~#%ROyQ)q$9Q`cy>oNzxx-%qL^!FvksyW+WK3G?gFbnGgleQN2$l@_5(o zCv(0B(&#>I-ndlerfU3)s*c=It$a{vSx(t~+{4pZ)PHF73z`NKTX#gk@yWp1HqmrY3y;w5x)Wp9rOGwpTcN=ME%8?d66*Wbd!2Dy_J>#Z5 zDRA=|`}LRu4}y>BRQaTB_s@%pts|fsgH0$@0hbBZoprnenp5~O-62D>LDvr+?_a3C zYgSsHeu8?}rawCr^Z`Yv0e`+wu*n@K=$@z6ZoH9eJ+m(PZTYDXqT9j?r*a~rF{AiG5`2Q6)*$DYSts5hf|+k0 z%KqT~*X=6$AM)gXILULws!V2vETq)QSU{3)H@czHrTl;VK64Qv;zcYn^ZcqyI zDI$wgyVryzlwmYhB0JU32NVVOwGFHC4oZg^pN(D+c%#+O6umyX;WO!~n^&~SBzn;G z@NCS#-)kJFUGK{*e=cL}y8rt9od*OBsiL;wefA5*cHGrOI6B;yx`8uyfvGlFG4}-r z4T42{U3lc7+{z)~p{ikC44P1Pi+eZ30}`mZQ|qxqJ?Gzc&>?(e$9awkT?{dxd|K_B z^F!2O(c=RdwDsuuPgrdC{+4%>eFT)+BAj>UUT3$09Wd7y1HE)|%p!xW%@kcq@$2{7 zUH1B8NS=_DRrkifexjbi|9SI|;sFg~k3;UwHn3W8UK*Fr7BQRtgpk%+?;)X-h_h(5+^ixmL06^%xX{)NPr-|+{)uUA+TFQ3Af+Y) z8<(&7Zohyb@DUaNmqF#!`$A7$Dd!U0|3HU3xN%a6oJ}?15@HMc4j*!F?Zew))=j&1 zl2LoRa1`t|Rp>8bgfPWK6z@Y|o=IHwvyjQp3d06OQDUc5h)TX;m(_9ij4pA9OmWkq z3KILTjyEc7*)IjP^gUG%sr+s>-!hzih6H;Au{tevu@0i2)A8kAM58D)Ou30zQ*Lle zBoBfBoE|<)a{TdqY)`sa$XR%v6bcy)rSmc4;2imFKRmnHLnhOZ6=8BeNY(mk!@OE@ zk#ij3Kk#b^J&YOj>8$i(b|blE+qCh1vKr@2Gt^HR)%=!@bL+p}1wuJUuENgQgNp&K zs%-igK(!nbfa`rKM1aB4ao=?9L4Pn+xR=Z7mtL*UxJkNK(7{wxs(oR6UXDgZEhzGG zo-~cS8?b*LvLdN)7bJQZwzez7*#luF$Cs9h8x5#ge;#84NN6#X1F3OU99K3&r) z`f%A#K?rPa`h{oALKzJAdgxJ0q@gR+1vSCm!`NY3(}?YFW%|=BV*_9hh8{>eiqjxN z|EXQnsc}{-G)!;JcI-Ykd-wHR!avVNvkbU{*IGC12evWPaP`V_ zef@b~g)lhbcu>SNiP&Rq7!Ae2-efM^r>CX#(l!u$OcNIg)cl>YojAM$#V z{k?sO=R2}W&y6OEce4)Rv1e#4r>mhOAe_~DEXx-nmLLM(K|iM1TM@LeU#cH>GpFKQH6YS zssOir#8!Pg$-cRzs>8ao)ueJs?2XESRMuJWdS{*e`29u0m1vt6r2)5K=Dq#fxpwV3 zgof;p<69a2w3Z^4WDA_sSd??t- z_R6=Co2w|i3WI|gr6GUDb+Po#6C4lyv6MgEG2Sy+n)rkaGA{%@1c}b13aeFd<>T-M zKU9~vgT?ecJ_bq>XYB=bDl<|FB8I7i;Wo7%mnUw)>YUhucu7NlP!ZN^4c;5F5>Qk1BEDkexy}#dVEP0GPy}FS zu*f94tr7_uFh1aBmdAO58n=vk>G{$D6jCF(EJPXbZ6vv=euud_)^&|iC69Q`PrI!6 zlO%+lV1Ri^n2^pq5I8vo1S z=jB&0{j+*M<}yL?VUO)QOD&VJ;Pb?SF6ZxXr2IB~msB_a^|<~8coW>g6bJW_OPK&F z-44}XIViy>2(Tthx(T@$t|SGJh*QIKb@Axj0!j6XBLYC;z5U{N$oD7T~?`vU4V-Xqh|BL zFTB_(%&BO7vk`6S9vNc_TTF}V82}7bf~)L2%a4cH)rf4~1_0eahZ}L>w{ubYVbK+6 z4bnyd9RxLOCELDkZ~^eX;7qO!8pK^6NxKurYh4rq8AG}MhEw@A*JBNQ5;#SBG4!R@ z8laY#Y=akQGHeu{`fZNng;#u=ds@D;idPFHYsa`#zh|sgfd-}b#IQ3kOCU;q3>q(L znOOX7Um9>X^3NFqt=-1Kgq#*B^Vz>?Y-ZA-$!KrbrH&90Ag<;N-00FI6yLEL4k0FB z+x8b&nY1gm_#KImu3<{G5KeJ%JQOnY*JohLx&aKox2IKWb`QZt;VVn%3ev$f{`oJ* zg8#nYmi!Li>&3DV<2_jY)Nim)8P?mNK>78vNc5b{26;S89a|WbRiv@&%K%XCCTq)i zmD=U444urCwEs{0^O~FMPp?g$plD(KDDOAk$)6qsFBj40ES-Vk5L2!WkafOF8YNpZ zAicjc#0G|082`N0iF>KD0r~+~8MD^i(KUI^g@W}g9 z`(r^dMR~?VA_Mdnd_NmV|~Xh~z#5eb_shVpQJpGu-{#gOo- zqkW}s9{ysUr3#0Qsx?GNTjR^S8aRSRrQw4!OVpEh38D+Q4hEYlr4eQDL9c(HKf-tQ zXw?UD&AQ6!L&>8d}8V4B&Y5?I0P1dj7H12AaEL+#$)+Xx9%O9fxSw@PcS3czmMH)3semgy73^emke%k9jqS2Z^jQ=i zrP}7%n{zDzIprILM`&Fuz@7NC{Kvm0FcaZ+?X^Q#9ZE-8su-_|jCO1owGUTcTC5g( z2Tqf@qdE&_+W*r81lvhs2RJ>FQA(dbW#a2Cy;Cg{_0=FRtubc}2uc<*f$=tpM5bwJQ6PGnc?zsV8HFmQbS0kPBPcFbn#EJSO4pJnjBb9~~>MI4z*c znfl6rYLrYFzSUh_0>RcCm?0pT8Fj_Pu}^_JM>8=rS=+`h37hS#b7V4U7$8~Su5r}D zxaDiQ?m1P|PpPg$T^Cl_ky+Q|aSN})UL`PdMv&Ap(>vaa6XF-Q*!@p0M-@BM4OSH$ zqFpuvQ6j`wofxlwRQdt`Q#kNbaSHA-(b>A?`o(J#HfmD|(jxCg*iY1y+w;fO3NGnA zyd4*BpUZ9fTw$7gJOi#iJQS{#VVvG;DLDMUcsvtgr-Ng@Mb|n)=;QprZ?kZ`zx2!f zK2?i?CSBfKB5#K1iQOqt0)6ZeFY_`7HywKvWJ)FrFLw(TVYEF6WM`+%AGd1$pjYA@ z_fmag$8P^4s|mg7exSFLA0his?!ZtuBg3|+&Q&Q>G>{2{6F-a@F8Mn z`Y5)&CLl|W!`3)m*Z}4pF_E7d%VJsRrS@*Z7<}E~7jkmrbILPBV0Gg-$ad!s0+Pvv z|9Gu9N0==x`9(i}+@{6J3mgIIcsQ-ZZ8dD@Qj! zgnh$#$SV3~&IriBHrhT2f${$@Kw5dYEVWLQwNVa~ef;335iQ((8;+5*oU609Hnlt_ zQCRG;EHwey@inon?(|FR%yJdtqV?Q^V$#0uQs74Tf#w2Jf(Ol7QqH#x2TDkiux@wqdY=;1RtDYu6#UJP%3sfB2Q%PBPmG= zDzImU38D$a33^~^cDOTIX(1^~@xWijed`|>{wYw%v_(#Te@2bKgFV|7SOV+Ib9k)q zy&JNutG9vDzTtbr$x8S>h)+|2TRJ-y?*IWpJ&GVoaSQG7zlmXa>aeVmf@gpcrp8Ou zV>z~iEAg#|ZNw;-DD4z2K)9!`_ghiF_%k3V{ZL0P9KgKMGc)QW0<>01d-e8={=^}f8g^uh)2LSeZV4({n#hf%i2a$&)4SCmi?hMob<~=QrorsTb6(HZHTtb>< z%;kISD)5ZR#4JKMi!cR00LQ%gy^k1Ek_lTcn&Tazj8C@%x@oen$Wz|HzT0Q5+$vqD zbz&J4zhn@Za%h4kDZ*r{3XTCj{4`85+`Es;N)f~U0)c_o?y&v}{KN^Hu6W!>>w@Gs z3ZN}7Kl}-TA8XHr%kEmEvyk)!kzLnv+t+!-l>U zwvxks>qdanP1^pagx=y1X-R*jzXAkO_Q>mvZn}s4SNm-_*@{Q|9Q?+t@QLBjuy-f) ziAl4y$3@fD8fmseSs5+Z%wZ-B(%(h37!(G?ACIkqSNKm#j@`>iz6dd-QMNAx>pv5)_7eP7^DvVK=*M30zZ zjQ z{8#*e->M_C!%(M8hezz+P=9*2UG}k{Y87djn`F25Sri~fm_FeA$KvN>sjG&eNWsZ< zO9cN8x=c@~WY`76ln@EWq@!_K2|a`qJ_{yRmDMOriDsWFN5#i&-LlxO!(E_%`9q0D zG(_a0m75eH8LD;_WufA*bqI&E0UFXPW?IK?U|=2BL#K7IDo+tuyZ|9_Kk3MJYz}K? zkCuY$`DyAjLHCJ$uzVr4tij*usQ1GM>>jCd?yfh~!2ZJjl4|e=;_0F9ANp-%z17`mkQH3CvVFy%5(N5VL~ku1jX zlJ6V%gW_Y4Luh9DE$JxDf7blUhh726?t)c*`99y!i5?=oP;cR0>)p-%_W>=#gUq|JW2TC}0!>P)tDr5klc& z!LlLSHd!8}X|Lie<3__2_OnA_b4GW5!#T?;8!S6SqDQNoz0V{8(=l32jgaK8v%{O; zKa2VcaH*ZCz2TBV8u;T|6=6h}!%4?BaE|HsQnT)}yj|xs?5#BGR%}_$a+iJ?)~PDh ziUu?8-p$0vA5VV2?xn3hHyeQM-zhnDK{ULi)ZdNR`U5494QuhT@Gqxm8s%FJY1Se( zy^%hz*M0*f8a5Mbo`_}{qSfzhH}7I7PziN{CY%1+!|da1mf%sYdS?P&9gQaGu~==V z?2}eReFuw(19G!j^@fzR9OX8RrOqdR@da?b5yijk!@OQ z*3%yFWYugPZJHIt3HMF8)rs;Nt}oh&^R-&z3(ljp21vAZ`6&p#5&r(cE6TeIm46pU z(2~A+f3zxX7`;y1Gxu?aVJ;0hA9`1o;y&MYbj?awk*?A4)~GUd`L_2GfLpxnv;CW9 zF@c9T8pB%7h}apDYX1}5ReyH<^egze%Nx>n-ed5=oSUV=8p7vqxc^;^7ip+fTeM0u zRf^c*nSC3)?%Rn%T#HC=0LmdO*XbQ3!W^O`@V4PC>Wi-DOysy$M&xY~KPAHP9zP&1 z`}EbzFFTo#?5SR2kUnL&G(&%4B5wo{72jhVELpmOH;r?XI443X%7Xq=v>J#u~1${4T*AU zAi{Hc_#o(`@rjS6>(YMHatuciU;f2O2mP({SW*8|=YL@TZ9h0oHQYTD_1b2?I7wML zQ&dr@jPCAs5IZ_zCz(%0u(8~ssr(pILv$eexuM*3GpA^RosQP;#wzxJQUn>pHx2>CWduA}c=Jm(Q$$}`>)YGIUu&3LlA~zk4gq)JGQ&bM5c1US= zxf=vQ2ztNi>Czt#fW68>1E~19m z#@9YzCfN%AKR zW2#lc3nO+DmYt9WfJ&WSneF1Zy6>ZF&n?!Lz{J zJ6t80>?g`;b>Nxe zRyy-Op%Nr=*G?!3#JVZ5Ga=@2AcU-~c@qv`x{f+qF6}sK{4G%bz2d+0`*|#(Xe%T@ zGb5d^a?x2&c)_`&3*=YAr?5^f6*L7MBi--Ch$i_ZT=BEzW2rY^h>N{g|Kx#)Agb6o z(3>bw=9JYU%o&f>#S}KC`z{Gj((&i*0@B^+2Vq8C?5rf)uijS zXo{C=-EkDW`O2LuUzv4pCH&j<<20jW3v~;u<`=EU+53evIva{ozp_`noot)%H|N(q zPO#mG{%M)OXhi)btJ-dxut#|DJ9t%pM)ZR_BElTXIrkV#1@eRsv-Bt!o6gRcC;1VX z_;VB4R0H6I9QRcbeZD#a2_VT>M%S2d=pq}f?opsN0=zBC;F|I+SF&oJOSm@u$SN^z z4bn<*SSn6mkGT5+sQTX1xFAS0ET&XH=oFd-Fvh$)slrjzHj5LQvU6-XC1{2(H zTavuGf20&j;DlJY8xR;46hg|DadMEEzrg3mZZr zeT-R#wjB}lh_a`4q=BvAG$mb+|_g(Ct3c%5FXpNH_gV7UH1s=wl7Iuj(2hAY9 z#9l0ewMe>5NOTeEaD122TXr4`h;r!5YH@rKqBqyHJisd&3=;PuyKJ$4YZC3aoFQcBG>EU{Yp!^#37vFbHySA-TJqeg%XwRz@ zs{_8!D2RaeIRH)+8oVq5qqYAQajlQh`9R`$f{@(ME{~P*vNxT(TQuzI?jTb7E#NKC z#qs$4#j_`rjX|iVoTpF-MI`ufq5Z|m7JIYyxxice{)(XECm~~DC3FO|oPbIfzL@Wk z|8yo4$htmF_;vWmXr$nc-J(kMA#sSLCuuF!jpXYRv40IK@jGg}TCGe}&)jC;Hkypg zCE&0hhC0OUQuir(kRE^HGgg9@&tFluVB7vD&B*4kY=sG3gD^UK6il+$&#iV)xSz`5 z6!xL0-#Zb#fHj0zYVg@AooJwQYP4JXalTX|wt{Gh0C=UQvKXeqM8*m9J?k`IV85Hj zae%TBN?j~*3Tq2Aga>W|7oeXOSMq*ogyL_?_d0B(6W~*zKE)Jc^&;U5h>9rY+h_n& zE6peiymK>^xtM$lt2rb}+II zGX*`<*E{9XlCmr-D$Gc(yh45W@vqjK}p2%=W~G=EICRm*b(55W`ZbWW&&s zI-YWbUtxf0Y`Bp^>{0ym0UCcGp%q(_z`#eB8PNB7I=AajYCeza;))d$Q7@ z>22kzoea|PRQpLpIZVy!miG*XoxZ7$Zg;YTB<^bTy)h=Mun?t!K z#xG^!1dbRRO8k>!|E=4Od7{&&T%r1Df8-tIWc%zLaFq_@kA9RV&*3_<+3F|{0ZrUQ zC-gE%3djA2)wcl}h8#a&A}I8hGo7TrJ%~hPM`%&|-V~T~-+0PNX$gT28}U0rE0P@F z5#M7RI9miWD1TOWscSj6xOt5%!o6f&=*8sK6Hz>iqAUR+7uRT)HZvmgVLNd2Ep?23 z$0hS=MM z*oQ2iJxUj*fKByX?HVkk6>slR7T;z||1`B2eeN2D7Qa*C+>m<)3`cUF-+I6l!3pTw z=E5TQ9T2G~0#I~a7e1kJBRHV6gd1KGEvvoyD^bU9tVI7wsN=@)G_(tYyV=L3P_oBl zxK-NsZ1<$8cNH^AT4>rGyl8+I&7j2v51k56mq#SrujKHy-@3JXzlnbduF0Zn9f>dE z#k}HX zDa=k%B$fQEWLuBB!Ik3b7*$6%iah)>Cvh4VX@7*FNaYHZHauM|n>Zfy9iignH^xGW z%DY901^o%QhN12WNVa*0bqDI|=ptl+^U3S+Kal^T*?T|cmCubt8(#uxv=E za%;)G>Lk8=d*6Qxja!b2meg%n8QQFaU}O?Eic$`Id_dsy0o1SO>VkDK<_>h;dG=IC z>~LmxamT6hE>OXOhal&)hkDNnm5mJf5W)PuL-tHm?p^mORS>k|B_YC?nh5yv&GE2=#v?&v^QB&2yH)R7 z)`0CnB$)Bo z{@+6kPU{5RgXwI%P!#i5_Y%bp7mSSmS5$wbC{P%aSQ6Jh_AgGsL6U2HLEddR&| zuQIb%*&x^reETtX((|sU2*)$;4E_2(Trf9~$YXt~j(gJV7SF&ont+VlBwOb5L--Ar zP!J!b91u+dX;YSe)ihGhf`p3iwD#>cBdvq1E*P0u2kLDYJLj@&!ar|^a6{NEM``8YJ+KLa)+d4gANDxiSm2GJ!g_Zrvd{s?dUja0^}{UCjIi?t ztoU1ljlxD8c+9vi)+v2lM(s(2Q37oht1J0!P^<}ltt@)L6K}p zjzhH%qmKPb=%cpc0e+Abt-Z%>;CwDIL1*6syd8g!zCRm=ghql(f+>+&=SJrSvI-$d zBxC!w3mfTmZ&Zy#@IrlpAPJxVZ8QGv5d|vdqeZrC_hdI6A$e^cOeEu4C9m%S?mgzixAY69KIW|qRru%LP$03oj;G}0my#Niu!ZWP!` z3k!BZYnL`R>%%~UnAI7MAZfekHY^)c)l# zMXHv0C`wXvrCcN~6qpc2s`}w3c>2p~9stgg-4SPSm6HFPxg$9mW%qk^ktLeZShO&H zMOclY?+6=n;OAy6Z*^~TNJn@VP8F^X9TU$(!fTM3nzUAF333u7m#_WH(z(?lahRRf z6Z!n?Xhx$I-Cnlvo*0aNq4(X%*JM1Dhw?poT_<2nzT6Te*|&*6-3}3>_|)9gs4w_F zh-0$ZvPuOBg9W_{mt+_E1tZgngGCP)Tn-m#W@6 zx(GdN16bgPXvz0QP#zdxhxF};=t~&48>0jsDtV~fJjBA|M|~c^X&@IzH|fiEyP??k zT?A~0)PK38Q<*zpqM?O0OWz@f4OZk^8F1e=8A%^V$O}W|xGDxb*g*0Y(ixx=t@dNr zeFQg+K}v*u-00=K*eDC#(&`;2J1<7NY7DsqobuYesP~cy%Qcs(;{RZM? z%h6^wCH1w$NK-KfkBMn4@k@+!p}53ck6HD&^Vy3qgpDgjZjr-*!osswDMcGFqmLk_ zlW-uDOMs}d`KT}Td=HrM^EY??@I(-G#tdLj;T)06*bV_{c;1TS+a`%tGt-gFpax~0 z9sE6nl%fA1gs_Bfa{yVL;9q_S+%{*Q;kkSpyL~1FV%SEDW!QpBh}0}*GA*59=;D6o za1@yCIMrw|iaX#F`H(MyyHovRq<4@Ey2tzAQ(4;w6_3&rh;7-s*e#oA{`%+rVNi}f zp!RqW$K~iPwf|AXc&b)Iz-fTdU0heEqrXTX(jT2p8c%)9pA946#y> z{m5|>zpF-mTMEjDUx6?!5K?3C`3m$HHaFmpu>NC$dV;;6gx%Z0b=ujYNBLJ;f2{by zTk!eqeR5Fqj{odx3gM+bt+Y;TvuQ@Wmc3B+mCUJ4{aJh^xnC{vORv0f zERU+uhRa3EPevyu8CcrjqBiM1$BdOA^S#$vlx?=;^f<k2z46d3m@){xY}$dHhJZ`r1A|EJTqs6wV~OJf>tVDC@aPOVJH?wr=}P2L zTdvu;+>ML?noB`8uE7Hm`LM|BH$qAYwlx@q-ki|DjyXT+|5mL)h_PR1&orf5(`T5{~? z0_Bs<7B_*Q98}E&n~MHs?2Zzi&A;(CBC9kbKs$&DbplybaxBXVF6b7J=_ z7)~qN6!T=>eh3mOKarc-Yc6rOrjaH@adad2yYd`joBw)Rb$SBAxh$&m?(o9H>w(>D z0kY&zW(hVMK^dr-Yg_<`n57lIP6@p49uTMGFTC5h4n!xG$!zg3b35rQurv`$P z>({?E|8)+QkzkYB_OdoC`4JdE`J^r}i81ECGme7jl3dQqtD70IYmQ;mqV_I<^3Lq& zncN9?G>qn1B7D1_&C8zGxNv*FD@oYm&#`ol9(|m{O#TY11*}gmLuW3=wi*lc2lXvf z^(USe;5}r%Ux(~6%H*E@LHr~+-y-Nk(RLEz1rSaLl{{1-bRir~um1IbgQcAw%CUUT zV8zTXPcptqPbhKlbJuA|luW3%(-u~5bO$=(awNhVEtmmUqXt`1J25}Di#v)yFr50d z6J;)7b&(!u=9B$}SOzef_aHP`DjFk+{>|CLux=-6W`eKorakD8!7z2_@M@U8E0 zB2U-_MxI#AuzZ*tKKYoXlt~s8fM<)MYi|T3FPACW(y5q^ybGC}ZDa~HT;y0J90C+- zIV|K6dv`}^ZR!na8fnVtP}0L^-l3vH<-cQgqV@`A`6*n?*gy}+^c{@H;x4;@v6M<{ zfEYxX@6`#9^q69S!K(DvK!&AUp)ilmbi)@K(Y4kC%paqro5F{vSJ^Of7_VaA-?nBk ze|ml0qb#N4Q^g(&QBE9ZvdKe>t%Yh6t#)SRQ#x`mvI#AiB@(a1gHue&f0`I(|H;?J zIJb*(aEA$n5oV9W1EGp)Im!a zHJ^OPeF+D>Qg`UO53K61>O|8MJHi)k_Z7<1U0QUc^cJ(&u^?yOC?(E1^UnU>>*A&vbWpHJz> zG<63WQr1DM%uU(c96o!opfeukNnpzg7XT4`+H>xd=6r5+UCIdf&PQF%-qzP^$S#G* z8FXDiQDM|%NtlT5Lb!+=oV{g5mpB%3dU3qavs_PBSE?wIrK#y&t7!<0lDQNDvI@4{ zwwE)N6bJ~NepP3z91C&iT0@#Z>dEO~mRRkRh*joaDJftsS2t!8eHsjo?f2?wdfhD3 z#2WTZ0JcW^=#RXJ_9@s9%^5*AG79_-Y)(hf0z%L+O5uS3lF*uGhK%q8{$Q z4-^Bv7f3_`q{2c@yYs8e6^6yyYHr=WS+e;A5u8YAbT(%$bZQ?=q@P^*d}+DYxSUv*d3kcInjnC8Eq;DYp&qleWnKg>)WW6h+rE*<5$L3 zAOxfDVkAY#I8{lV(*IsTTdwr|_nZ;7cK3hzqpbU+X{puI7w5m+Gj6{;HF{%tWJo08 zhAIbQFb(5=^B#g_vh8I!aBhV8ay#G;Qg@;q{Oe!MypU?L0Gq$qfcM$!73Pq&OQ$6T zu%#f#SdX=MAQ<_V(;X->hJkISco!*OM zatZovv`atlA5i!&)wUM>z$Xo ziquFW0H<_8+y9=@*i`O}dS%YC#~Ol)G5LH^%PG0!88HY2&KHml^!p=x-eJAj>H`*x zWu%}U^cYd=c==#D(IP0C3!HLAqSYgEc%Q2nCouXTkLTSR|A+#0IjI;wdC?omSTe#V z7V*{`tIAGU4HP1jhs-0GcuNcH@rL5wvYgiaFKmly&@me ze(bR-%iBk_sHu#?Owm@~CK1FmCaKyS4ISYZY;aeEru*v|`1W`L4?#Os;un@g(Tq;5 z_|>-{1NX}(vrpRi_+!A|)6ZEsBGpdwcQI+^XZYbVt>*&YU#Toc09+8^gox3Bv*Kgz z9d9L0R5iH*iDOiipqZZ{X|W9-{jfxc1eI-%gLjAo%WIf(6y^^h?F9(4}+O`dZ{Ge&DFVUju-@s${jK+Cn;`p zfw^fphu{s^^1|PpdG(ZM-B}t%@=;!SiP-dq0JRC;z@z2o(LX!A+uOuEQ-9BcRiug6 zW?p2Cf3Q%P5WPOH&vr1YLA5c*;mEC50RIWD54$LI5re8b* z9A803Psjk8i>;pjE6Arr}E3ZXJg6` zF}9KN+fp-ic*w=Gtfi>!I`kc|8GROSopc|q2K7>~PaAoTTerJ7v}mMR-W(QXzAy7@ z12cs)rr+nuYTR2LcfU3t@qT03AAtRWGmg5*a8i0}@1g@?Mu3(^8fFg9cI@@ciz+2` z@}#Bod8i|`^m5XfO%(a{hFU$o26lC=A+-mklx*91*=NV+i-Bz}hn*B6 z(MaC!pi-=j*abS2ExK$I#|gZcD`L)W;@4sv%flZm5EVZ!3#cfKAVWOP5?h%3MXcOy z*GGswPzC*_^V)Pa!FIP%`1DEhJU=IssnAQPo_tbg7AnZan5WX$F^hAX^k*`RangIUFQbax1^J20pVA7^v2(WK%bOtyEX1`S4fw?es zgtl~|QwWcIdC)6$L78}Qm#o(#g&+TD2^vd*e2XT2<9NsL#)qf(e3Hu)b45PU7lUW- z&^n#e4tLem5lUCMhI1~n(SyRNZ?&(QQskHpVIeBZaZfa&GIQE`j9(mw@z4(QY)(*} z-WShZh2QQi-g3o}7!quDcOE}47Lu5f9ASnw?!0nSplG2&#hGr?3P;5H`APd6Ye@R~v=PP)K zY*dLP4rHF7+ZK4H3pu_L#!6&Hx&D9g>1tE0B%?Yg``rtX$`O@iv+5Cs;2 zld*>1n*_Wq<8DLx4>!=_GP|JuS>V>VgkSq&WR95$2limQ4eHLK>r&ji`U0&`EqbG{UwA z@*xAuKBR0_II#*8`^m$O2WSP7CdEomvjr4f3wrbQ)WI1UznsF;d>}`EdtXV9Bo5G% z-R^tyX*pL~e9ICsHUWP_*uPHX37D%7tmmGGjo$l3AUKbZNEwPm5s5#u?w}-)uq+Xl z=kF&d%DC*ba)oF2+-Mg=6HByt>dG_@J>Yt4RShU-4}4PTZJ40MTM%GmFChX@U?1r@ z=TDfDzJlPDdX>bLw!5pgAGgLweDWqe6D9OV$j1XI{lfDO>b)8z-XbuIS$FTc+(U(r z%2+)U0{yT?iVSYj$mB?r=!jbSax_7QJJb*>ME*MSN^K(bJZbSI;jc}u620VSLpk(2 z@0;FE%)1*5Kl7DgtJDP!i{-JN@I%8FP9^_(JOFL@1DU1l+hmD#)G>FNr#_G_oe5+} zv?{CN5ZQVy%BRO-E;tftU>NbVCH3-?33kFSzeu0p!^iZ_V=8PysPgBdR@VyxsYi!- zu9%8$0A#R&Cbs_ilY}XIam%t-UG-@cz|<9e?rFPqm=&d&+WRL}=Qwu1wBl zFPYOC$`#wUv6mIsv3DdaU)yA%iZ@-bpL#PX7xy>+ZG2+ZF>sOAxD*d5?tP)PeI{oa zUmfRA=6o33Scg@g{2qfn&XvKm85DswMx+&2l_cswQ3?6Y)FwrWUQ>CUb9WrbADSt# zJbMfRWrn=?K~qIP6EvS*zQx~&HAJ!cCGaREM?L)wC^WxNl~P9VT^N#w{EdpEh@Sio z6efW}l;dkXTjv?5E$1!hF*PMAwp((!DsipVWnP^No7A?gf| zxYr_~Bnh-UI4&BI%8x4&bv4BvcgCFje)abYIDG4p7K{1Vwg2Vm-qDEhSP)#+flC34NXI4 zxf3*DEl0!OfJQMtX4Hpc+}dI4cL=i2KO>>*An2AtvQc~EFZjJ)mS7;R*7b7JFVPKJ z9V~j)Oh{)1dNb#DM@5cG`?5s-*FOZNJU}3&iOuf>pJ10@W|dtWY#pkkfzl2l>E^NY zdO(?0vmRgb$secEE*3&SBt+GKj_sdk+x-8d>aD|~?4mYa0V#>0lN32Bs2LPQjh)M03bkrXNEMh1|Ev*-Q3@0{!WtCxy1&$IVh_xj!U^0ES1 zIji63aqZ>dJ4bYZ<#97O)`v=evVUI3Iuo?vIp!?f*Q9_-F3@Q%rCUohLRQsJk1;e! zM?Z7ad^8S4gBq$7%-Hq26>-7)kQ*!4!frVPpK{x^k+B*qfAhO-OzoE-SBsr8nUjtq zNM^TJ$xqahBXS+y{&(rz+yW*XhXcO9Dj?5+Bg-9z+f2kKTy(s(T6pICg?!R_{`=on zS-oMV7;C2)S=`)oP5A$~%*n)D%{}@I^6WeIF)C4iqR2#?g@ExgM~t&pJ)*BH_YjX% zJtHC8WSN5O{zEXOZ6CCf0n@?sDuE}TT}fo(qFZwK-UguZOS*uOe;6B@3DtJkhT}I% zdaAsaN-weU!8hb#{3KB$uKu=HgQr%#YJxXveL`sc}g#3URPUhHQezH?2*vn7{p4L@V~F(#1W7>ABo_!y0XRVyX;*t zH^1&7T(zMR>7+U={qM{A@q@3qQFaNfQ0?QXl9NlfpA35N;Z6AmXJCRkIGD+jC1*6n z*trteN_R{ww#I$sASl-F*Ees`^M!a_-Tnq){Gp1#!@&!r$<#D?F6GaJqf>}+}JT#!+dtho$v0`h{{@TPYVU+IqC_$d4`cr_+ zSIKD%+#@K&>fs2;k)zOA7LkLa@&paEbn+R9C3bb8VfL8^9x^SSZqOrxkcvZMgo3bopguiLyOZh0%m3Rfrl)C_CK?tx}?g*#AdplZPlGyqRv2_`W*FE&$& z*#bDKH|3S6*tKtESEtw4aBJoAFUsp~cGd*vy zMAe~Kohv?#KlH+9bx0V*P&IAL43KUxB%bm4u<;Zasb=}49}-E4kZMUlaO*5<7OoFi z++;?wWawmVLKI4w`a$n4!rU(Bv+}sv7!0q52(j6Pr=#UR1EZS*-3O4$$!7G9H5wk& z6W*?RNG#CVfXF1)Zs)XZ_`(aX(BMYrS9%;*MY-JgHV#lzoD@;PHC(zEg!VCRy5yr!u%%!}ob@KTTN)BOfpYVtZB%@s;l3y~&t* z@EaHsM0zOnkLdUlv#AM~$3(fp4ocbIg$?$2&2yhpX5Y>N=^ig`&)%Hg09XH4^p#fh z>>5|tqkP=e9dV4$#(dG>S@K7&1drs(FU!*Z!M+PvoPZ8^?SSd?%_#)*a}Y;6Uq^Dc zGOfz4CwO=gXhkyg2He!JEyYO`9rke=hFkzs5`w*%3ceg zO`Hl?&3|#jo*ef~F?gKwy`{e?H9!375}^DBInn)cuOtXspZugkK%b4iOEpeM2IQILx&zlk{wcxbmk3_`dw&Xri?2}{ybfi_wm;v!z zhJW9E<=E{%?heD>SX*x>e_?*%EaVbl!=Ac#4#2}VZAaiym&_qkev7Up1A^0Y^|$r+ zEklRb-G>Dokv7zigrkrHmHTKVrF?3a8dpE-*1`$p#?hSEi-ZaDEeGEfRZuwCb?VB+ z`e*$Up!QuvBb4>IG7e;udL(<-So?M+s;wr#VCo)X zf}Cg9O=Il^?8&~`-QiIRj9C*3^c%^S*SMw%f_Hvld{6rB)DHBdNoqgrDRtgXaq9wf zYxY8qbBTtCmfEjI_O4)+ymxqc4JsNkist0>ULj&KG)W`c5+K(p!++`omqv zCV4fOgc!x==9)2c$>Is#3YqjZVKy-n7T;l&Uq01`1^cS6oVH6OA(Ti;I9ygls zjMR*T1Osc1Hswpx{dm|tqmM)S=#{+UlL{#fCp{*W$O(9mN*zZauXhY$5jf2X5_T}~80ES@hSQPiGqy&8k3w*tXNAQ)pMJlr-@;R%N5yZ%xjNw0q3QxB z&e0`n&Y_D#2OXjoaj6{Lum&I`K}Z7f!cNzFS?HmU3N9puWJ~S0o7b9Fx!ouni9sBn zrL96{qqsL;SFv~;nJdviG&<~G{jb1Bdu)q0(FE{r+kjs;Fus9T7e`;$vGAzodsQl~ zl<-}(OMU0B=cQ&vwmrh{?s4?$G$hg@KP0yz3?z+IuERa zW!(h_)gErnDOhL!?J~P%UEC=NJWCWnWRZ0X15%D&=q>1r`$OKq_^_3o3OqppDw}dA z+_FOhgb0^WV&l=fD&dqTTHDkMm~Egv((dH%?(;*sV1_9y#aJ8=Y;$E@ssR4^5~(W? zXYqh#!eoN$iQ1j}e({2>hTDi2`NSVy?BG!lAB*LYy|(oKCHWi&QLP7qMl7UQQ4eeQ z*TNcT+BK(wran*8y1V36W=2=hom{yTdx4-b+?e@GCH58*e3Sd<(FX~Qu{w7UbbZyA z7atT=&nGpmm45tn$a(z1dJInL+6Tkx6Sq|CJ5QD?Xm!QM2fDy#H3v;eSLr6-;z z%UQwC7`PUiF91bXZb1MP`~m_mBu0~crh;G?%J(`SU>YC8U)}bjj9gR((beF=pL(@} z``ihpSgOd(xD~>Vh)5z)(MV_9Z`OF@kl&bI2`SQ#79OAfJODGw|Lv!SIA z*yUXHsf;^TrQ_P!hTY!n0X5QLYD0S2{=TFOhQ8lTeFa_qS2~B@`FHWj-oM`-<+bMF zU##YvDh4}aQ2W}7eL@s>%$Lgizj8Sl%>bPKLts=YPeVzzFp`YKD~&f9pyAwX^t~jK zzJ`ry0`4+p{Z!>VvW|wCrwZ*nOt_E>nD@#C252e1 zzHA4w?Hh<}!;lq;!Uy~6Xa(rKwodW(xT?=TAO6~nZp?!+d{mP7=UQgZUL>2aN42LC zwtcym8V>uzhC8(Bof=J~0yz5ObDp_Zttt-)x3Q4ep)8o1&6u_Y7a9PT5Y$rRbR2x?`YC~R8w*8@x1gthA(Eb8`^0l zBzaeV{C>mqhlLRi5MO5-9i}&ZnqC(8pg{F+UInov`5V%PMi^0_B)17 zWHmU&x%Nu4R03%mv3TtTbO=yI^jV|E7v`Ehhlz@P^yU_{xYY;DkJRS^HGD z$m(`+s$d{azx_vYy_iSZk(}58m2N@1sOzCdM?0pjHwJ(j!vH?zfjpLbOR}Djg;+y9 z1*uRa$n|oQc&ZNL&Pa1A_GrNb06Ua?&9)~Gbxbo@8+W0ZcW?OkN9bbC zTVetcJInp3mDwYDFz#fex;p^2p8lHEQ!tOJUlLuk*pQsK<`mcRQBH%9MDKM|78C{~ zo}OLw!F*bLQQ3p=>!CCuLyXr-2Xr|olTS1hyM5(u^xwTDhQJUg{6muTnI`dTiL&}t zemdj_<*g#t&v7rialY$?xDW@Lr+#pfS-bk>^rQ4yNSQoNCl()i#CBsR?D8V{OYifOY>lgqfa0r?Q|=a*u`lzIPkQNbJg>Ham94XM{D_mtL>f8z@dWt)#)^g%4~xk_7TUp$3mubv$5ue-Gw?=4t9%Xc{4y^-X(&rjKBFAV^Fqpb41NOd2;NPqH2*vg2HisMtob`dpo@;@;4Fd`*I&~MY!;xW+lm3@B0&gIz~7%I_QG*wHxDcMqtAau zwGaoo1aR&ugxag?D*$6|K+0!yiq2uRr~I`PApRr_+si-V#zD6poVJ{Vf^yXm zlO*j`edx?crQ^a<ay^v3==Za{{gqY*w%#8k-f z0m*j}fO*_y!aZ7SVSvfi2PLASnguB-4Yx=xOfDQ1K*+_qGPk`F4P|KoS4(f&eS6aM z20<4cpV;~YyKw;~jc8rVSncxWb@4qs{GVXKNb9|x_!jS+5am36uEzCWbFLq%&1SjV z+p>8~MY%$GKJUZ&JMPJ;!4Jiy*Way+2d4Gr$}#@{I)0PmfM9dzP}2*>;)kVH9OaBh zIUq?wBH5`Ru*{ddVuFJqLN0EH!1miiZaAiWHNS-}&^4K&p$gnP-$KAG^w4DNb$^crD+yJ3+~UJyY*z% z&#kd&U5uj-f_HqekRuaJP^~GntSvYqiX9Gfy*&s3YO44XVOplF`xBLp@91(d#6~x#iK~agy~pS8`KKOfT#AV4D==YHky4 z?A!uVr#!)`&c2{G>ty^Fzz86tagk<*+VYq zj4?|5#slU>2==;{Xwgtly(xc91`-q5JXxG1oK$8$RlBD2Dtv>jB$}mRPiAZnRRZ(4#_0tkGbaWIFJ$ zCaJ*S6o&ZoeZO-}8aJN!gI{NpzUA#3Rppp%Vk&$4`YzFNS(OqN- za6y}doc*4A{`1z7ok*vtGcmZuh#xPmgfN~^ER=m-6h+BJ7=0$G++B$Qu80lmN##_v|2%$}TYI9>z*02W~c{9%azd`JU zaxHnovlXIEVzcFi;f6kSFxK`hu2V&;Pw7-q9IRgeIf-hnw@js zrHzt;M-k%8;xbgmco!Axn)mvnGvgn9@Lfa1eyZmYelpLaPb(~0e`lu@v&E}s>0miw zrTT+48I~l{>@0mHX7S1NxkAUWSR2){{Z{H-HGXb#7cs=qjNK{8yV59 zL}QnsZE0!fsl9LU>YI83s2cSUxV6f%uPrFZt?LfLpt{J(ERn>=u2fNvc><~q~ToY1C~hp!4Du(?|pAk#~Qk^J6o|mtDEHj zxWzKa#i0Cs(E;K$q$Dw}ltu{<6Q2O3CNFFnk}=Q8*E)u$grOK3qCYYXcAw@V;B@>P zM0~bifh6r?TlBQF^bbc0?`o@#^e-M-?C{~mZg{%^Jx76P+bc|AU`G(^pa#!QRO2G9 z2ivofwk%+pA2@nd8{!Z}MYVYbie;mq+BFc^6Gj#(w@ZEa1I!)7I(wdi!L6=SZ;MH` z_Y`hxyzvR&Ag!G#c9|p?=LM&2^B{+0o4U4?gUjE$y~F()UXe-Z7O)hoi2rV#04lQr zhd2!QIk((k-Fd2D5|R=qV3z{0Q(@AsVGlgfBqng6Q`K_|vdBF=ktl0~oH7N6)oN!o z4ZL7r!EGBlkhz+gXd4dzwaf36#a#f{AS07to3KLhA!@6yz>Vs(do|I1ImV-QUoYiY zG_c0<(kjvT&%|G=QYDTf+9rP7NQViccx)rhU-HX)KxsJ1@ad2{;>h9`*!kn?)(n_b z8GhTkMkU6JXdwO*U7ZwO<#?4Y%<56Jkhd3u(XAA8pLK%*Wbk;-4uNd0vPOx5+s77Y zNtFM=fZ7l4HzLfafP2B`I5Q+N{Bg1mm=&iesa9w(~h<0vRMNCVPAysFE{ z+ zf&Yx&8&GGfQ%1F@e~s8LntHHB0F5JSynQgGWlmK(W z%yle)24o`Urq^yA=s62pfwf3K8GXc07mR|BCtn=g74zuZ=x5kg@%Vyz)#43AvShMA z-qtMGTVKunMZG!TzB?Hlh-tV9DXhh{*Y8dvlmA2)JeSvh0c6`%~%6lQgeM4njO{PyRRHAtdDhleIjGOTl9 z=_W}2k@O7HWDQzdpZ?6sFsT}@ToYE#D-PsN?BnoHNQ;4nC?_s7@uE@}2Q8G5#jK{q zJ-%`^5+LQ&?Vnlq>(Y^cBs>v5hm*s|m5l%qggr$hDV~p%sanoSOz&=a!`?T==g-0lpe0r z#Z;P>jaj7#L^JvEK5PNS-Mcue9Knr?M5zUqsb^njKJD{C2~oR%dM^F2aCe9{Ta=7R zYmm(K7Dg;NsbwUV-fA)c3|Gij4f1>>r)t0++g}CICd;5ES|#0u5=EaMZ7BJ?+xfDnlaD%n1c`{vTNyC4+*bO#DI{qws{bud`kC3Skj)D_XCQ*? zAIK`H}RHfCzU2^_ZMlq-!wNe?Ez>Um8TqHxmvUVL6#&9l>q{G zJmhb)zMga5pYA@Je5j)+M~dcOLbd_mpr1j;rkT9dHU)pGZ7D_(@KW}*30ev+1a@q>!@AjUWCa|6)M%~iPq_a=}mH9kl5UMvf%4wpO9 z^956ZF4!9fI$aF-k@trPmjqYA>ZY)3n}|kb^8iIb%+bF%gnup zgJC{oLLW<<63eEFi`t6X>{4ZUf2jWQu=cinT16iJAub-T_BNYCLHZm*!OY^Xt(fs` z?vm%^L_lQ{{d~`CxxGIkOmATll*F88xo$Iu>}Sr(>g^uDxBKdano{4zY$-wV7$od( zG#vqeJAs=>&<~=pzou33B9Gx-vxF5bQT*{1hV16VN=V40$g04IgG=jLRKFe?^)yKB zj}0)GY#xJ*^NekZ(Pk)Hq?@Im9+-3nTnoE%Cg&y_YHBpT+Y`BH@xE0#By{K_&N!&i z<(mU*{wLYZ5RC_oK0T?B`Cge1Dz8&3#U0Jx>T-f!PB?7tL5>KduVP~Dd@Es&Je5L$ z!w%I_Kquv~_t&pe2LOELr;4wo&Dn&ou+vF5W(vynUh4NNH^7&C8aQv&q~~+6LYn(% z^mDJOxYB&}OF8B*;+AD18M_iP8wB3TUhEtwAzCf$0M4wJjB`YSA!IPm_7s?}h;06< zpi%uhML;PFZpFYcBV!$GxO9U`c;?WH_sq}1%E)9KO7Q$lF`OWRQB;8H>)j2@8JmhA8YLY2mZY5 z{P+NzVR!ztm+XSkPD_#6AAnNjCtNBg#vR8T`-UVdaw)cU5-~rGjR)7>Ng!e6#^u?r z-uHVvilq!WP%~VPl-t`9&nEDimX~n9mDPUqLD`Lz%MfP>ZDxNO2Vx)sqXM#_Ar)Tu z3#B(^#nqPXiBUzpu>q5oI21iK7N(*C#ba*=NkLC{ad$&B(HSn5IHB1&mE*PAaQZ#z zx%g|ue{8|r{kc%%e3Z_993KLJ*lnZe@3Qfe&>OE3V`$a6L;kU_!8g(Jn^oFEk{PCA z(gNJGz&Xxn*EY{LeR|IxWEY}&Z0V~ZaK$=JD&n8oNmL44Z_|F4xO~gKeVm&MHBaZj zby;e;OR)DxUSHG)SR{^}E#?o4+iXJ7G6ofqB@c!0@KWl@_VH-1ue{M7^99R{{6ep; z81hv@BB)JSn5&NvoZnezVD&ht@{5z_vroNzicTp4*pvI?QC8U^{m4EqwF@c=!Q(vH zNJlNZNZq%=xR2rbD!$#r0bb{@CHLDSzx}01)Pj3tK0Oi8Q0rL+4vJ^LOf(6G4%SEN zK_WbVa4fs!4ytR zL#(rRHwdw6iHAA#$WY1oh$mh=L;?me*{PCY+zewP|3bhlI8!!4?GAOOa@F)9;xej5 z-#sd6@MB$#_H!}C)of$BYBG4h?bQy2UOCLicOgdQPUpZ$<2C^LjdeDlS$j!ej*gVh z17DfW^r3P{jplpHq`*WvV3-o3RLhpQdX3*-U`g`MdLBm_?i$zYP#v4FwIoypv< zHW2O6kC4S%#6L!;%kH-9KiW>XcngFDjf)P3PqX$c9miZWB1?rA0V@%^9A4!BN?_Qv zwXua_F>0WSPd<%q$;3WbN-Jf&Ya?1D!n&`Er2cCgemYXfd0F%oC?ELpWO~@aLt~!ckxx&b0&?8AKeyXt-(yKI zp>v%3E7|J+{n}&f0Zy9R);q`cVnvD(jlN5@Ub;o)iS z{nN`YB#8*n@q0w)6V?|S#tEw7AdW^-1U&XU_zz|T+P@k@EpK^9i;9~9520iKs0>Jc zhxSDtr_Pe9+5TzwPn>Y?P-swbSKcwTI}G8OT@~t(i)x6GQy)xPm9L>qgg$TCLw!+- z-t7)}g_c|VUMo#rdRZhYs(6HCZ5^Nm2G8E;wCEy~U`>Modq+}qCQYyiGMuA8?Wk0U zuJj|iqr6kr2SB`TQxc;i1aseE6{o;9yY_C~+u-sWx$GHqm$(UXg(B;mQeb}wvjixhMyRU$w}MS z!IhBy*2U{5y9QU3t-o7wy#!hE%@gN6owW}aBZZfekuo0|_dzuKLzZ*kt^VyE_|eAl z+DW~mWY_YEF^h8QG9c(NsThl>cw59uUgRp%1R=t&zsNak{Zr&~g}STDGbj6lF43?$ zu{gvgvETjAHg6v=h`L(gsQj|sM|^R^t-XHK(eU!YoUdC7h=hQnnHS8sC>+BAfgnm> z@%uO7ybF`xf0T*h>rR7(WK)x1PxzZQy#mHi`k=P49}igY_{~G*7y4d8J!Rs$E5Uk0 zS^&LUS^hf$!Gg_VmYUY@ZycN(mU3L4FYzm_Px(_6`(@8Q2&i6=!|e~QoCR01vbFRf znF!XTkAlu6xpUQMOL=#2>sS4oHjn?mEJSWUUlb6NJz=29Iwm_GL6FfXh7S#~ME>*d zdVo`4ULKUz#UVdtM3EePrs0j}_=eG7))CN6So=8y&@O9G3vWn0QgJuf%d`_vN4zI= zuu8pVX`v;wVxR|7LAZ62#l5zj*o43qcLga+4I9c#=F)so*1&?FOz647w*Ys!HuZ})UIEFnp7tWmF=M(5LzL_(fk}F=jog&CDTu-_O0A< zUK?Yv)BV`a@faOq$42ubZA7_fvZ4?~)2-X?)}C&OTXQ_Ar@w8*EA92%wPheHK?Vz^ z@*n!)_}mUpLwqdu>);+n|&8Z1wF*^c;b1GBZSFjfPh3eW<4!%Za($EC~AtuA?)}W0m)v7}F!Oy?;2M`2aAn!8W zf%eM8Rm(4|3Nfo>C&}F!{=Mm51xCFX<&wyHHLisgTamS+&a?&4x@ucbpZna?91y)nAPOv6!`WVBX>+*ZF)O?|-fk3%GK6=Ek`12`-PMs$twr$4<1ybd;FJ zg<}V|4644CJ^_tOpmR|Kk7&pq&~2m^F*L>zPozMjCepnR_Zct6$;nFd9BIZYzv9^a zz%L?(fpKTtvkjBks6CPDX9&-n z;i`8yav^6cfGm<0h;C#6gzYK@CaK}~myPXjJ%{IQM8Y%!1|9`8vj?hSsP`F zjc;=o&uPNS%HU8u7~u+OtI76wIJ2jo!kXzj4c&!+_<12;!V57y|FBGR|$Kf zv2b$%4ao10P|*0ij9-wd1D;+2&^;(=XYHSO*t;SWG``I+Js*MGpUr{6eNujC7K{w< z8DW-gf z+J}!Z@t7g^rkS?k_r~R~*0ExZQyTk|HnQA{zHK#rHXsWpr;K=|M|@Ja-vEQQK}USh z*`ZP3P<;PdcL;`cM4T4afQTl^lCt$*PK64?g-T$v3f^Va>G}Hhs_BXlrnkegi5Gm; z^vGb&uwk~0Id)0W9*HZU&OdAxi59c`@(XJd`GjG*`}~+bX91-+4>HaDzq|EEO%hUe zfk?QQp@VWCFp;PmgFViTC%6H&FT^9y+F2JH24ZX>Rb-xd7|)-whI8&x1qVwQdP%vk{L?<%B=jVRY^Q=svGnv1Q6pN!9>3eS7oAl5m#e$4NHH^*unEjy0z zfxS=*6F#|rXyV4oiS9jDAy8{DI1U=8sM^gdp3so*46$%{WyGWeT2;Q5wpZ)oQ|W;5 z{Lv&>s^CNpS^NIb-eU7}z^iJzR)BZCb4mI5glDhdbBqh`BhfwKk+`P}#4{f*nXD$!Ugzs}cKB}=mcY#+@yCmve-m;; z52MT|F3Ho&bq?}M`cM`Vz>}Sx>!V&puL8m=3?aC0c2KfTjH1a(Kr8nZ!!+nF3aN#g z3U&N9iEpTj(+o4E21cN)!Ne$a8eDt|z>CW;gbo2aR!>jEC7M-vWIypKyPtws=Cp+F ze^b7uD1H+CPq)Byi5?^*ZNaW#ZWbF9-(Mp%P=R|Ixc>#Ph4Yz&nBHKa<>P}CBz>Vm z95D&;goTfeYnoBsHQOgE5;O4jCjeLFs@DjOU~Kk=kcqZ<_G!{>lX^W@euQMuLpR0b zQx&;s#t8mybQ)!rl;5kOwf>|xT=W%mg0G}4;{=3Dcy(aymxr|@6V_mugyKpP${4&8 z7WZa<19$-(&F*Jr=lT(N=h0No0w;IoaOyee33C@h;mdp9?PB26}bu{GWB8BA= z*S_^)No68RIA@pXP?^PifK<{7JTj{jgxKlPZwbO;?D|#3O;JT8hmT6H><8v@&NIA+ zP8{7_4f6+H?*|hEYqXT3vRe2k%uo34jx&w35131#vzbp!GN$fN>m6GnIynoO2Ua0q z2uW+-;nnFm!(fSvF-XP*Z{4o3Pwr-T7D;$3+opqs*@yV{l7nsPL+-I+StqW) z38voP%+!BP8vyLeiGGFMiP1hpC+m;7E)ew#Y~8a>AYzJ3Z+i&DPz*PayXr`&{T%2{ z*Gk7EwB4JKG+J+Ak;v%&rD~w{OQQ(nqyJKSu_vhBX5*|C&i<_*zSIq8`m%txL3{5* z!ygc_x>gBzdC`#sXIKPBQX6sjr;)rUNOYwsa6;)qOIL^IsjkNJ)&bbGXF*c?MR)!v z`6PAnw>_f0x5h^wkn=x|BNV4vI5`iAMD`dzcN?0Qu$Rmf%=S4OAFY9(c(%SuzZ#=( z30z|3Q$9;9&gXQZ`lYyV^6-H#66C0* zqHq?}$Rn1c%ey;`+&NECmrNq$4L!kP;ZM^vMClh(q%9@QXMz4v4|_e42FR>Plu_UZ zz{!k)mzxgu12z)m2xW7b_*N|ybt-l7_`uM{|HY8p>f8PIr}8S7Re~c9LFZCeVi;%~ zF}V+p0Dnmj?4ZOW6OxVymjNZUi`RmiazT^>cLL4;c&Uf_P45v`pa^ynBsYWI5}Px~ zx{aHXL1bR9#6}$k`5*}*@#A~q77Sjc^H0IdHKZdjUGAD@4f#<6H~rR`BFqaSr)`$3#W%Z}?=U(*zl`8(|Cu41Ef4+gXcWpo4G)VUY4Vt>+6Zo*4936q6gz6@i^TXSns=;iUcipQ*=R3nD%UC{SVv zMr-#iDrCQ0hyiIn6}Q16!90Oo<(m{q@iMF+JM7?=eiX8kC@1v{z;KTI+_qXC?x#~A zhr#Ct4pT`+hwk|3`1FJC511cthjV&1Ny3*mQM8U#Tn`MdHT>~bD0CaprowaB+6AuK z13&oag}CL)cb-AD*wY0-y1Tf8vRMad0)GH#jn{Hq$@30f%81TCV8@O}&~s`pm!or9 zCk+BAk^H;z)W4p-S1To?xS1Ye4`woDoE(^#N(Ec6pICQgY6eNP*O0HB1yV~eBUh*}UtoGNE!D@BhQTC5qw5$&w@=u9$#jaz3}_t=1wd<$zU? zxK^N?n2MH{Qw!CtUk1wlIL~;RwWbIlAAysJ-VNUi@8}U_G#UQka+Y<0)FtB&LdSk4 zW~OJ*KKlXZyxY;oA(>7K7hY_`FMn7p6wst&PNTEQ<&vzVuuQGgAD+}dmNYX?E(TG8 z*ZEwQD(L{?X1SR(P89mo@_S32Yjg^R^>YfKULE^;T#8ITRsHh5EFh7s2(%8yE0kdG z@xb&bfJoD)Au4UbfV3YBqg>#WJSNSxW{{H5{QP`)m#R|`Huz5gHQ#aC(bjqVN%w32O&~qO@U9p+ zZ()hHI7wg?JE1`Bd)*8YL6QTAie~|pjZv>MzWp^Og4hk;g16YY79QLJc#+=$^ML5q zsa1KanAr09gN#dZ1;`E_CD=PDdwwm;DDa`8c#2b=7b<3glJJ+bH&t-}4B5v=%}d>4Z$7!dVs>zh^#U!}^Har^ z3vnht)O@5!^zl)jCHPETqpXO>@f5x;<;v$9V*Yi0wnPO&ArD0x4@hGJYWWL8#1A8E zPC=ybpC~r6agQ-!6UcloZnK`-OGgHKe=rSuykas^%6;+Bn_(?uy`>KwQ~E$BKLEKp zc3L6=K|4aa58 zfFRg?TOzV!ojOWI;9&YbaX8}Jq#M#w2{(yv18FIr`Gf+)_BrdwzC)j8o*2L3im9rK=wkCNkwUl?syoRUvMJ zMXiyt`f*>8;iI1ykCHk9392zIZFDfQP2JShAS^h-%3-{FTxh8Viqpg2huD!t)~0NW zmeeq|e;mH02Y!m>N9{9HcK;)q*!*uiF?s2(ve-Z7xnm7OJ2>AR5=uZPdpo{lW^Psb zSC`7$SqLD2A~2?5@}qhi3Y;nm-=&CS_>%M0;QQBIE?Ys;fh2EH>21OY?Re5BAv&{Q z*-~Tadm~R z0FVdaR0gLB+4SW@%uSdYW%WKUB~WNzdN~V5B%=&3fV{=e?N3T_tLsg!mb#-EE>p$q zDhaO5AYtcN(iFupdDGYe<7@40jOocNw8c61oshtM4U;l{N%(YwA;}7a)U0o&Fm4d` zAdr5zw9P;Vgaov6Y5G^C>3cAS7yM9_alaACFu>|PDvnvq1r+2%nPbKaVkmxG3_L`$ z(|}1l2a-pshs*G6(mlgp>|u-vEi)fk2IHCzRSRzC7L%_IzQ}A~JVtY`bmUOkAHqxv zg6NXXPGmWU$i`W{a|d`=^s2J<y(NHY( znofiHvxc!4mRJ#2Tg=Ci3S#F9&~}FYY`V7p0hcd}?tM`Y3EeO(6wHIVpa zqZrsZO|(6F3|`>keh8LQpvHVM!cgKan$gyq=HG1v&+@XMmOEcL%YSXslHXy8^G|68A4 z0&kV$l%V>mdV^v+CSiS<8Ei4=4j20yk{uNB4S$yhZOBoGlZJSQ4gkn2j?uLv8f*N| z!)X!sWK%;4;h%gNH7gfD99Y9`ubyIN5g(8qtzQEYZ5HF-2ii44a+&1~KQ|MzG|OgD z<%36Gs09>qudF;6G>(+7WjnoQLIO6>u&KuPmqV6Ah+F^#hP+bnK*Cf47hvjtu24k) z4dVNj&L0layLAJqp>2Od#F}H1UzCf${vCD$EF>$)e7@fA=Mo2sXWRm;{;juow1gBa zK!iSClGp)QF(RHF{p#QnHyqby$t^j$Wtsi1NQOIG(+GkLjFwB^Faxz%b5R)GiNR02 z+n}bNf2YefaZB-2TTe@j1j&VbU~+1J(tv6I-#x^ovb`68lAIP(Q20$+_id)xqU7c#MNX8DR71PvLj25IL-^ zGwMFYbAZa8r|y0rzyH@7v}7_^v(A&i;&2J4;gS`L&OGI_Hp{|7Xf8)N-J<3=#i@&| zj5lS1Mz#fDQ2pM=uBa3?woo^k=)v{+hhBl>Qanka$1UB7pup{7eLYLM8+fP+*A>;5 zn!aSaO6;sjQr$sL&}~zk&f<#VuF5K2XGoyMX5@JzX0>+JxG7#7T?pWVTe6}{XAMdJ zVr0YThiU+0qtnz^K~bD^L3Hsjm416}UIIQ|quR?BEbb_X72s&p*v2 zZqRQt;mP7J(UE0=`>qG^2U8Tzj&L6S>jh@jjN1dRldMFepAAMo+3!*-3%cgR)w3<{ zlPEOfg24G}d8lG4=$sz+U~rQLE~AY=QE^L9^ySxwu7Y}b)&4i zlPH9vg3V_Dn)6Hi5bg)OmQi~oXt}*VS#1aJNC$I~alj>OKf>>*rD!}#Ty-da*Dg_e zWb8w2+tdNm3jRue;!W@*uXbnok=XjUKE>gtz{UF<@A=OU^bDJz`4LU{=bZP-X+ch7 zl*xCWTtbhk>Bx;NE0pp*lf899nVPL9@J1;GEqCwuL_t07 z_Ino^9}b}(rk}@7|D(jaO3&L7o!3;Kd+Qm%qa~I=EKR-y1FL>GJlRWf3M!g7MB;V+ z>x}yEyy-50wPO{Ci0!U7>Y34k$Poow5oDmUVn&%8xfstz=}E__-sL^m`;y5t2E6E% z>}YILNtjI`U#<3Kq*rXWhNT-?;b?$dH>Si3WTyl~Hsi}hcC&}WEb}0NLb|p#7m9&1n|srkh|>usEh&Stc+G* zhsduLN$x;v36;dJ%u1~$0n1o_cn!J-IwI*%T~UoHm#^TIFOS>17Kj8GhRDSkm_%vS z3jYWOKZkR4uF(KD&DGeT?=Ly{tm>wG!}S7NU~QqyzPX~lV79#-4c6BjAF&re3~6!s zt@c3R>M5|k9@|TLYwRohW+l|MP=9b8TSsxgT~t&D zmaj-wUm?@-gJfXz8pN>QGP42pyeXu$k<9dqJwWX!UEchVExhlMZ#om~z;Gz`DKW&q zaR{)&e+;_MvEV(DS)bbkj>Bg--vJ~0_vywx@n6aK*nzL-ZpnK%{9f3-<*py*`PPTr zJ4~&Fp`Vy&PaS^eh)AR$5r3Jmb^P+8xIG|o((es5Da0DdJ5GJ6X4L@u9Q z_(F0V_s$Z_Auy*6LcnrTGt3J*4W5eHmxk2PNU#KXu5}I`J%iidoQMIHmCSOf+2IDm z55iWO_lCI1e1Zhn77|vq_Un;SoJf#AZlf=0tuVgDM!x^l?O+c{U%q&zKtpf~gqsz@ z^fr=hb40$)D!?iV@9nW|wvC4b-TCmBJIUU|DNqIH?Pvzj>3T#Rk(mh&YV5m=+Ck_eGi~u#E6LhKdFS^`yRt$qNf@sb1{)x zsfyxB0O)>rzPs}@b6F)%%5tH=7vCgMuz#1~P)$gL1!T|RoQ&W827?CC-H?X*Q)ybE zDqZeDb9P9~+IO^AS&C^>;3tCKcBzfGtRm1=l#5{>v7TE%+%t0 z)TCbUs^tu5BxBzj{|Gwo_xHKcR7h9nbvNUZ=Y|`D-|@wDObsku+3m~C#lDQR4xV&6 zrmnB1ELX+V0xuopGtt2!junih!8C*`VqW^s-gJr{s z?~@~@Xu1BxJ-bV9j8j1PCrsQqUS73NBM6SYsp{i1;p+&Wud_}@4iP#_EYU~-&R?nv zE*h6#Jz8xXx_;;Y!^uipHaOF2SJ^gu+E{)~{`JuB_a_FE9tj7*^*XOX#3)G25()#z ziKII7{p^;VQ|059{ zoe6R_qvw12{KBAo5=a*r4LlgHba}JaEk2*#7@616`>Usv(KKLHo<2`kI01^eGZ$0> z#}$oY{F}1&L&oRc4xt$nOnfjsH&4BO}@Mi5GNNQJXtJ zZ{vx&7o`bTUw^-{3%*!ep9G>ztUQys#% zVA=}|(EhG8ap_vHq-AgF#|)K^NlbpzuDv%#g2AV&cmd0HWW**3;NZmGLO-;pGvy@wagwfqg`bly0g( zP^Qf(S6!z{i!Mc3$l1d(X4kDpM}h=F&`q)S@mFj{xe1{CaU}D&3g0704|))zF7&P@ zdXFCBmplxu0V97tEY9#6J=<Hx%!=KR=v^mz_>m@}bxZ z=+Y(LzBfzb8bm7mpsMVzb@e5a25jy2JS>@YHfM3^7sLz{1@9N_P#^HndVEQbeSa#O z_jf*fMp}0!6>+}ZIwtn+xcmi|=E!S(sXag{vf!_e{q)t2Dg=&b_8m!S0^K^p5>or0 z$iKt@PpwJeQ5CKosZ}bJPP<^p5R^rormKnj-kZFA{uSmQ{}&kR1s+cVVmhEDnA*MX zA03G1M4}|2G6yIiM|paGx^^Cn9sVCsYJbk4xdj7;ufLFAS6hnI>KC<%4}5_=>~78s zN-%3$kuyIIYh>DSW7Hd5T1qG6E_3Mk{rPxm#m6ka8mP4a3Av8&gednCoG^r`nCJ-| ze4lY(JE~m~D)RSRdpY&A-b+-&6OVf~1Q_cqtgm=;Ve5CdO(E$CRVH^;(vvvnDVvph zlsJlSMjp1?HiFOWQ@aZf zUlk(>r+%cF7)Q)MRD6-BbmMUs-;?zlfcidB5!_*@ASa)3G@|YT}FKNIp+Y?F^MSYU* z{fF@o8hrIF>WPIMz2ju)lYVf9$?&T9EJvh$%51-1YkxOuva|pe3HtrEwkasqX zdpP{TXy`j@d4-2RvWAKJo%M5iZO|MT!h+DbyZWv_Ecv%wFNkbE>#Wzum8ru*FZb6{gA#(eHB#tDy;^9-E=Ml%`YKg_y1%1sv2itJ21@+|>KNfuHX7|f_KR+cfWc6J9iQ$vRTdYQHM9%fh z&DE4CDB#q4t+-oX3iX@*Gs%02ar)$*B*B2RUx>-Ab?~!iZ|tF4D{2Y!$cq7C+amC%aSJ(UxvK}^X79zA16YwhH#x7y~lv}sM2?1UVv@e48=haJd_d}@*uS& z0$(3&Nz$=M^w~*Izc<7yRkIU`;u37CrgXJf-z$HYT5^(}XZVRrgjwpxP**qy#Z%~c zAHS?ODJpiw;5P!r1sAGBBblCHMkU^!#{3Zt7bUL^0N1#8R-s4%cO>?gSGGcrIwDx~ z5~|r68KSu!0C=*mfvlPR@AN6@BVk*`TPsAOPGOShbCxaUqnc)1V!;Lak4@P$m4BzY zVO)B6)8)-C!pehsoRF6W)INER{%3#fud_k5w|fD{Bm%eFV#PVowanKzGU&j+x(DkC zUVf+hQUXO!kne8@D^wS$wMIgb96AW!a+}Z)SXMd0NLV*p8<`#KKW1@|RnOiHei&6~ zU&rMj1R6eEyI?+(xRh!ea31hP$Tx8{Fj?fLq$5XuG;FY;9w0+P|UQi@r_B<5x4snN;4)JxH zdPV>eYNH_S*xt?<5UK&pBJ+{S-{8*jFS&HlCH$?o0;e=lc4br)^s7U}3kn1EZ;o9$CRpKL-I zsgHdWPP1*!wpEu<_7!I;1Kw_USFOy4H*tj2b|{@Y(_=RLJC>-2vhNn+$V^VYFL@sLe6fcB9&1>f~cTA~@F~<+!4W3n_Igs}AEp^eU z0f$Q(21;U^{f_54tL)Hi?Os{~^*#S>?yvrD3FK(0$Y1}(Nv%RpKEww%!n}g$S)Go) z#YcALFhG=;&@g|Rz_J$e<~mzPX)0c9J|noce;l#QgoWRT@_~kETUeqKidaLN`cbTO zPLgK&XvmI3p4LD@9+^_&9m!i?@?(1$u052=6E{pQgdC8qmt`czHI|YI+X~BU9C!i14_{6XHZaQN!YaJFCRDOE^ z>EUemj4lB$${Bstbzk~PTYunQGbj^D+m(ae?dMVqGJ5^plu_(-IX4YO!ZHx=yA~@; zrfjElr*0IR;~W~&pcB=wu155?O-SJ^5iXwB&0jNcS^=yVY^G0zY}RB*R)@4T)OzWF zqfmec`)!v1(OyiB_$z3kaE%ZpFy~RB6KewOyj(Iob1?-%dqJ2;KnCDh-~wnrb{c#S zv&j@M1+CK5R08u=QC_`4oB2p*i@TtOTFnD=q+b{;Y1(QC_Eli^=&K+92Mwpl@^rx! z{MUvFhs2U~j^aJ`<`_np_wEg#A8S()SG-l?t1I|126U<1t7%7nAWh^ebUyg854=j^ zDOq;|VB`T={#Qr-8fE|N${H$Y_rWga;BggYn(gRBP`@8y%0)5*1rO1>N6VO+0}P}G zPyVIk=}UwHQG)AY@;IFp|MQY4trKvlfL;4VJNUM&?XN4ILlFO8uV~w$MC@0!a*+w} zONjywccjc_K>Zxh2maLn+pxB}avuJ;-82IFD|p8yGzr(|K#?uA)h|`xsKSPM;5rl4 znxeiv_txZ+&bWE4<4x2B2nMDI2!AWEN@rr7_pwJv&ZXix*<*o4>#2JI%OGgyFa&-i z-_t3Y1bD0I21ol7QciM`y4(&{>H{K-u6u#QA_l}7UK~pxSCe_PIXdasJb8wQoe@yx z?0dUi%rvVQ35j#je4;@LkBUd~iKcn61&TmdeDehGQ}i`JzXv7M1f1?-rr=A_E_4(3 zu+^>B_HtYdRMRJd0?|KY(o^c5^UzS7ac^(7V#lmLoI96KqCBhb4lvgp9=|2T66TT^ zgEBM>4VLa;tLCNY{nI(rdk7?w2fI)!PYahUB!w^0}ygiPcI+SuB(NJSb)iG7oz>Fn>cncWgdvr z%*pzSF)^SQaDPhaoThe$n1TzEkjBrC`YQC`Lu?|Xrp znTM)g#JgFrt|@P2HG>|;Z|zMl7h%4XpM!=$9M8E7H?I_c&32~m6F)h7b6K)e0fKhD+2 z@3<0-S|%as@0YMn+W@8a^I-^LwIEl#F&{t!E~XS3D2}2E+HNSQZp@BR$pOM(fg)n7vKq)yW%srr<|KlB#3?$)fn*3 z?sXni6H!|(u~1un4;ns8pETX+%M>ICCtN0uD*p=isRseLC?KbB+hdJhrfn4G_2zB+&K}cTi+t z?wCGpU~}elLgJQal1JBdxu{w{zd=y}Daz(R-KZAo*)SCzdoNHvrF;yw}W1Lwv zR`8cAf5$HbWx0N?B*jh`!HtC&s0zjW-Ti>y2){V@e))^O5xS|ENZ+i^tHI+>FwOFGW9~IQ*J`Q z9l*7j4uo6Uzm845UOWe>M8?>YICrT`POy?(+6rne>=hvlatQtv&WKFliTdeGUzI2u z-J8bU&d!x;4;Dvs2k$VjPt=(^AdURs;^mSwibEXSsku?-bx}6_&Qd#)v&8ane;~UD zmjF8eRoNL*R0QT4?t6PJ4!epERv!egm#Z>#ufItjaN#M_TX8(*u-H_<&dn&c_KjyawRb{><4@blK zNQ5+ZlN2uA{UKgbjXDBmsgy=zfU&qTR9O}me)EQt!FDF=GHB`JId0(miL1>eeWxAN z#CJzzQNCI4=U5Q%snBH-$!E zwpEd=5$K&;2r0lXQz?_eyaGrIUh{gr!?!MqLmY5DDKIv2r1RE7J?`eeI4jeO&N=~+ zC1Fvv+B1G!d0rsm>}7(wy0cXHWPj!_{bO*U_lk;@ zki?_BQh7MHnrU`Eg)$U!XL$qF+K@6c7YV_D%6) z6^n$PoB#!{^fCDtXrKj<OqNG9cl1kQ|Cbn~Pggwp0-v;95v?Ssj4 zdlg2wko3!MFSZ&+V5pdmNSn=mJWCR4aY|_YX7d_qj7R$?DBqWO`@-uK3$|IRuD8|Y z5Lp;3GVAIlXL0O;7>n-BFyfZ?G?a^W3jWuY=7I4ugU^^B9#K!=_6h3b8>$?Bl((F; zQnB_gAv9AUQ>tWZUt_^t*G#IKWT!tU01G?$4R-U+3~=4x3U{81*N4=j!fV<`L$u9a zO@Q0}1@WaBF_U6tA7dxgAcDRPT*bM>Xl(qL%VV+)i2LDYSw6PwlnrN>WV+0s3OT{i zt@xPu9550N*4z9vKrh#(4|v!LGx(qHtlOOku+)pLnm}>?)v>Pjkh+2_WU}(r5_Gy@ zfK?*4jd@wwiG2DpVn^|-s1_1CDKo`>&ehAfXsYi)c0i7H1jrB4PU>9lF;L3W+z zIKhBwuCHv)_np9RF>#B^92rCApOs0B-R0b_dyLp=?tRhnv^K!TOaCcAK zKa(Wmfl}VCz8o#Nuv#Zzy7}0c^xprJeD`KL=P;s|_8c4`mOHF#?_9c2R<}%~7oWmR zl)uT_1&C@1dOzFxjcw`pRUjhD%U2pf+9AgJgL3rhypb$FUV=5^oqTTnquFB!>vZj! zQih0_qS@zk!V`2Cq=9D@*PRUMF52%j0KunYsC;i0a3+>PJ>adq`ae~6`nisX=JRYa+BG_$su#LzU;P+! zkgHtxZcS&7mrzec$4C;C#opgqrkC@ixLSFgUC(G1;|bs<90!gIRGp+wmys7_ zIMLh_7y$DuR$kVyx=B(w>3?;R*rW|6tR}h(J%+1Ga6mr5a|t18Svg6U^!2jXd*-65 zMM5SUQ1pO*JnE$HeB6AW5Oo1{YOgys0T{4V9;-zk{%wL_a#?QNJ%`mPh;cgj-ctZW z=&ALah|X!0awrNQ9xlPy5l{0Bh1X#*SjpH#VAYs0RttCV-dy>qvg4oAzwkJWK_9Z{i1J z$?-l1nyqel8t&A!+imU{Tf5X;+w%@C^iYIZk{j#C9Bo}&uv>h7NDgDt4vn6Z>uJuE z_C?0YQ>A=+8=LkANcO3_G@c)XjChFm?s*YrJ~VqACA9XqPSUGy$RsFyGhgzcFt41K z-+U{7r2_8rZ8XvZd*TQZ+tx+iw&!B35ChWYpHAj8Py3pqqL(l9v9(Q;qv`??TPVcgq(*GN5!nmKF}U1 z1Wx<^*vugVuCMrVW(9HE*i!aFuCryDJ$snS-Hy+}P7o)`nv(z=Z;TWjzE?>y*t$TeRmc^}4zly)O3x_Vqh@e+pNN2TdL>qL4wdH-CnG`%+cA!iicqSE z%T^0OG-{~%VXSdjB-8}NLmv@@ktR{(hh1X{c&HI9eH<_<+xR(v(DWA4O)aT<%rXs> zb&EYI{-dtS-z51YHH4_l-4cAr?M@p3mq+tOEJV#K~X23Fju^Rn&XR3rid8< z|2M#?n3v@aG6#@F&I@d0V!vpJuYA5SZy;hcZ08$hSyOzMrEf7yN_8CSg$>l!;wu6O zPB`p|Lv-)&7w9IN;xE!kK3aDc!p^n=MLsInS`o}5K?9A&(;8Ol3xeTvJZ1Qy0 z8QW9+rGOOp<;WIX4OC{uZ-CE5)w<%dbJoNy%-a%76NrOEy@8m9%k=NcnM3Yyq&vyn zK5y>GrrQ$-|43g=`viF&KW>#;_>*e!mye>MrrX(fOIiMY>}11_9FEVXt}M3FUpQ6Ng>A`j|WwOuC`S(#-`n z;KS^EmX}6#xxy=WNc6qHlXmA0=H90~Q4vw?*nHG1PaPjz6ug*TE;74kab$Y13}e4n z>-FSbzPgHGF@~Hff89f9K?L2b_{AufD+7c+L4uT!(pJ>3MX+5%C=UwHb=5_mgf}xV zySkT5g#{k`cGGvdXC@kkY&q>sHUS<)o7Vsj*~aClCnyQXF(kPeD;2ZQy5H4-`?L;z z3S^iacVrzfz6Qf#-@EQXk+^aNLBC-kpxEW-x@1?@mE*rJb`rmJk~{8JHTo z+h!Tvw0=o4PCalFJ>sKx z<43=zBj$*3W%InbQ1cas@(a`-H`jifH=EiN)i)N%@Yp4IC;govnGZEVt2UAOS-r~+?vtGzZDL;q^{`IrZQT>5V`KV|mWKUDFAtxx+8-C!u|jq~N8EPFtb2avEAynlO&gmFC&2ZS zhPl&+80WJ_f5*k1f#j+nXg}tTQDpS}zQ1MD*g7B37=kL*ueONgaiDW%DGxZjzNjGh z(sC=5a`fhZ(WGmqe1*FF(IAuaS}|i9r0_Y{{sQ@~CjfL9eO;G6C-L%sT`Xc~?eJ|; zu2l`3Rn!0=_Z8cHp?}Z! zqeK%wPdj3D=j?~?j5Sf((|?|ab4N|edOxQ9R(#!nQuO8g!8+&->oLH+65idZoo;`z zu_921Hy0#XFPJIFbK*-+3KRU*kLwNgrfJ612VZh+4lmEPq-G>v?10rF$7GNY1AwCt zub-SCK4kiOc@3D?g3IP_syC$-y;JkGv5A@WLPX-)2k1E0^8ddmtk{Dm#$b96N8cun zcuJ-9IpiA^W!K3f?fugGFzJ>@5!bc$=O-;t@u&fOwud)K`BhrKC7HPoAf(rW(A7P+ ztXJdtG6r5gkS4kD5u?<>878;*sa!hN7%PTe%o(LskOI@b-?z6t>0$z$(egF1@XUVN z{eD?;p%i-=FKMQE=wtuQzpY&HA5kHActz0h&0-#O!vK1txhA|r&n;ZlA)STQ(@G`lr>tt0M2_$9lpI|y4@%DC52JS?#* zey%vQQLF>yeOm7~+5PjIat56uA?4Et^Jz9++IYd}wp_6yRLY)Zci26=uz~UbY+m<4 zGgR3z^chpfNM|H2B+|C@;q-d%Px+}Ci#XyKeDEM}$sG^a{E7kj~ zauRdm#Oq+V|Cq`s4&+FOFU*XUs>tJ4_12BubnM8)Fe3AOLph-SswRLf*{QoS=5~wX z>@{>Y1>Q5H+s9-y_)jZH`o*kCl8y>0nW_KgaV&;!f;A?*=6<3c%Z*oz?n7Gkdz!HA z#rKYdgAn4uW|MZ#st!egvt@Nph7G;Uyw${3Wn^7fDy36ruf!BZK*iVi`jMb)eY&lPAn&iPGtwL=&=dE{KxXugEE(pzh z>-G|B?M+ObYA(;>{nVFecHsvFB6=EZ_+9S{%zqwSXTbCJocKGuZ(^~Ltxw0y-{QG+ z`VR39lZbf!*p>3h#lyZ&fLt6k!x{}2V;R|js0;xCd#80B3CwYaep;M!OY^(snjO)VR@SVsvnoJtW`++{k8?t`>L0u@ z^jdRM4kopWsdlOOzcYe%eYSm;$@R)0k0{zc-%6w5!;3@r-4{i^E?QTs!k3X-vYLHW zg)Op{qo6&ien(+tCx=nim1*QF3uAOlc}$QvVS1|i(T{6K%c(qgr=0f%OD64mui=_^vH zpo7po)d}zEYIJJiz)R>@q&)P(4*|K}@$N#E)%9>=;xmGA@)P$gdOVq-Ix9gzaS&Nf z+x!R2%!YP7-%!xog%70_LUPQ~)CEJBMZ+p1JtpVptR(kR*6o&+Uv%orS8{n>%<6wv zWekNIHowSiC&N?2kVXrhv-goWPr7xLQ@>!5MZ~jrZ9&=;f z-GYyxi!%$%b~KDXlMqV15+i9>M^~37*iE}Txjld2?A!UDAGRajEq$)@OgUz;)rglW z+1-n}3`i9e!t>&olPm`psR%F!RG`DZc10?52e}fR;&?WAw-p$u{HdItpwT9`#-(V_ z*1xkvWUvB^6xeV6pk331F%b+=f;>*o3cMq_hn{lYo^$_BD|xY^A>y1<5L4a#xI&Sl zI({oKKU9+G6i4Aoy7)bT;GCS4Z{wBpnMnEP{rj~YvJaP@e+Esu$tZjJHHYcOKCi%~ z(>O&2WjKqNZCm*GQWZh7J?mAh$jcFfz-Y~RX$q@G;69W+&jPPTa3N6r@4kOL$B6mc ziyRuJAKC1M#|Dy_AZV{P%ftWeK^@1HF^B-&OcSX!{7kzwUmZdJ=ot$=>+Kh86LHO- z#Wb$plFN^}yvEFUKlnt+bOvnZdo%Tgh6i48+)h{0^vr$S3i}WX8wJSCjNl+HCSi9q z;6yDR-!5qCeSN#2jP8@_d-aH9$Une-o5Lk{G-Loo4Ll&HetRlr`!3KMMljiv3+$2& z%9_7m470HBw{yzO>UwJNUF~Ts+sKG<4t4S`)oj0w_E z7pU>;nPDo`j~OZae`jOu+xc%9|$vvsaVK?})v0nJ>aG2fqH&gwW0 zoBaLRl!OsYD~M>jsMi+o13L0Y9Rt9mU?svNc(6)V1KXd5a49IylGQ!3x2jXU2&`%e zoIePpEjvK4<_!RQ1Pp67`AAD^;gNa#bNtE2KtAgUb{zk1(@F8=V`o0x)B5$}lo@vr zx&S})I$682TZH) zeD-4xbX}KD7dxSsmhSO-(Q5ma-49H9seKBSW=L?GHT>aqctuoH_U0N9leLwsVD$v}MQaEN+Swg&10;l{v8XU&=wI&Jvm zJZ#$u!K)b=Ob%g%?=$b@9D%0T=%aw25Tu*~xp^!=!OfKr^zGQ`N;SzM?-5ef%gtOt zCoezd;GMIH>HE8>tC>TR;sL2YY?m@TXo!B>O!fes`r)YkbAUS@xS@p~Z{-1KE+4O~ z5uj!m9WxN@%MZ_W)o7JI|B1AwS-X>A><{d7f*VKajEg{>Lzn04v?+S6vv8825kmLuxjfv^n+^l!+fYq=BA@P674C480Jhm zup4Z552_PCu`i*UHH_ep-NHv8R!2@IpP=LB7#58iCh;-_EM>K<>pI+M`gOVgQH}Vz z;PY1v{XthUXSHHSjBmAHf}%IBb6@Z%>a~E;BN$0qVeXF{4;#@I?fcbiq~%3e2k=p>JEYZcpJT0YNKWa%5p%SZX(Y1GhZ0){ z2C5^UZwcI6$Ps<3Q2IlQ{FS9o2Xm;okY+Eb=qPZ3dg~r>b!puJ{W6C%eQ5C*e#RL$ z+6%miw?`sk`xpW2{Jz!nY|yOaMr`|X##2+Q2mA+z*S4;=23&4#>qvrLsQhw$=eE0apr6a&uk*@?oBkH-ksAO6 zw0c`D#7r*y2@fsYho8mW~*kg!~-0U#{axO4gZgTPm+7%=_1AI3i+P5gOFxgw*@EyL>s0~`+ zn34uYj(Fcf+N5^UmA0LP!9~l$(fMFY_K1d;rd6JvW907a(+=xV6Mx@Rde)TVo2hG9!QuUnYnCTXuWUxhGsj<$wwd-tG=0g1#33}YrxbFX@-_GdTu%duqnPk$q1E@wr z!jidSK9J|xQ@Jf(^5s7H0L317(Qr%fGPOkD^wP-7Xr3&^y0c1F7T*o@qlz*Ndw0v~ z(FiE|N#l|dMK=jq`3iN!m2r8g<$KRdQ${c1mE-hYZ5YSQPzAp3+v?()Ur*7KM3o6`(ln9EP1H)s>AmLrT%Qazw+t~6{DsQDW?c9C(vhv7Z z3~==cV8!E@kFd`EvLku(1~mStS$*I?3q^_5QpALnE9b-B*WYhS!~f(%wQ_HEkBB_{ zBqz1_Bns7&Tfh z{Ho%H38~f$Af<8M(A0kUgeY(L1gPg2@JC`L?^_D@VvcU-1!+|b$lF%<vba>Ni@AwD|qcegc zUGpCWH`C>B<$TsriwZh(CGb7pX;-<3wyz7~JD7#X5w3G6- zcsJq2_a+prD2z@o0c39&UF+nRq$K*jl?7} zf(8)n-kT0|%Wo#Yixy%O2-g-e!`|Aa^#th%b?D*cI=sKJ1-+Kn88#MGFTK-QlZk)F zGgH66anpc8;R3)rMRvsuQ~VBfY)j0HKIz`^?Goik5ePg=oeXT^AQ&A8qb>;pcf`+y zsh<&>ik#U(vKkM3Liy`V_usc=SvAVK7nsOXyI1ILavbGZa~fNcCz*VO~+j7`gwpH%?gFXk^;Fr7Dox8=<(P|{f} z5DsF6WYhA~+PI7|wXbam9+nYJkxs=Ia7vThUZU{|h30nCA;$k5+}YWP;MsZ(wF|TW z6ryn0pobGNo5L2EXkc52xu0bCtZP1T^kIOUGqH4-Iz>u|j7UhSpc}KWxpu-1;q|9C zwLL3?aw5_9*@=W_7)VM%iKNV+#Rxf3G(h+Tj>Y(&&naYVgWQ`%*3S;1Ng1qmQcg#Yr1+|IO@(MJ^_Kf(V9<4dlaqR{#wF1#qHV4dAMgjv=MuMBNNAbe)-+)20*x`JF zh6DfTmx1mAa^*y;q(zmEzH|XTP9`g8XULx0rUQbT#dct14WIs%&U*FETIpO;%@Eii zr`}z*E9fuNSYC|km4G>OB_$d;Wj}bAy;#sEo{n?SqZ4b<#BB8?tJSA&HiENabcmb1 z=x=58%%{sYCda?1Z$B(4b*7a`Br*uByNsU0K`HOr348vk@OKSvpfYr7k^4+Fd+O9L zO(^s)&A+Gm#2?^d1uXBU)6DHnlmJ|3o_sMC zJO;Gcxyej2@7|vX8xWG4pwIcI-j*N@8{&SB;1|eL(%|))h3(QfF6kF8wAo0j>c3 z&F%uJX%6_M0o_nKmX>#~n;-s)V{pMDQJ+2KLCY9?^*xL1ZKMy=;7|T{Tj;TO0y4Ku z0uBPszt1-29Dtq+egr46pPD@std%ZF88^F=`o;Kt$8x+1Pl^lmjyK{c*~%=>5RfAz z*~A=gL_J#Sz0N^k`e=v$@9<2x$*ecG z+<3sJZJA~Y@Ly6={F9DOp2Q!^Tiog%Be9S1H$+1E8qCtr1 zJ~?7)UwGN4e|5H)y7wVCa`9Y#!^*nXANiZ+9n@ldOPzt?T)2&~@8cokaw!P#=TY5T zi_wa$OBhROjLELu#q*gT2QUjd5XzXkx%Daidi`VD&HvbH;EdTHbkm2=gAG_xO6G@N ziH8cYouo^uyR+6WXbu9+5MEr1z!vxVe5HNKuB1PF4Yu?YsOkr+z6+ctJNh{a?@VG^ z7NILL&-K2cccx9v4g`dzgG!7BQ}D@zO+tD9k?j~>JG#km&&RJstcSRdsZTyCaizj` zdjB^_8!~2RCA)4a(Af_OUcCX_iglqyvm-*7#Zy+?Qar;^9se!kWNt;8ytS^(H zBPc%xLx&^7=Xi*adIs6XOj!H7iBHB~8|#2e`SaRkA^1?kHgEd%tzE;Q#6F#WH+u|d z`E>O_i~qO<;t>NOht_8J3n`rzmE`?D|31VZjR!=iM{|vxb5Jc$)}#!+ZNolL#x_1r zsY3Xbz5b`XHM7)OCGXAOmkVGc&bO~PksqFHDvQ^yt2w!WQ1@xxXicVAeN_O1{egyy zpLu$Jb-r$q?PPfoc!wfqYgp7`|f7_H{yfat@ds`PO z1Ip>2*>);ek=plALV7Ta$+&lm{C{o$^8dR5lGBwZ$aiU@VsYEn9`F>&#nG05HlL}t z=XTEu?s!sZjp=kgyzIrwY+t)or-b^XtWDr2EJWk4iIcyh6MRFmYg$*KM{tP&SpTUu zVK}?LjI{P6bA*0iYarI9)Og8wKtWu3WFPn>|%^Xnn<|B`vu5Hxf@cG0lZ zGjpf-rYtS;Ck{iREC^a;v_o2{Xlqw+MxJB1c9PKFRwdKJ^)boN=Qw$mp7FN-)RF>_ z6PF?*zj2~kOkWIIl#IGA_4S%{h#FJa2`$w?imvK&{-$U-<}Pb=k>PzcKie)rg3ufZ z{SX1ct%Nf$Q*}T3w+D_|WGXeS)v!VY>h=Df%`ctTzs4PbIobswpfGq?6jeWwhOr0Y ztwu*$(UGl&qeY#n?;f}{tC$YL(s&a~AvL8HF*1j7NZO3eydt98mrFavrG}%waP zQx}_W(^R{6-SdF){8nNl(0Rdr_sJ!%g8M53> zmto0FwyqV}1X4$QX+C_%!=8d1+MpiP0#qr3uv>O* zRHydWTTk;z!}M2t`+sTDh8Bn zl`O2yF}QYfR|_uihTmiH9|wGktyPf5p2Ky~gS2?z!y=2KA8M!^EV3cZBWTj__!5k5 z#E7JA6A&~Q%d>h5{H{u#++KNna?v53UTR<;$ATpGpxC!wYe%fSd>lr3K*Bef6dDw<>|*tr^IRXwU)BC$VhQWTnp^)X25szx>rv)Mo_f3 zF;3T-7#gS-GNzS(muVP1BDc+$I_Z0x+DB&H;KXC!-adL>yIS=1Hx2u$RBU9$k7?^P zo?P-9ymh0%qpG|Gth}G$aZ<#CSvS&7l&$J4&N_Y_4`Ix_+!}N zTzq)&z}Ty;BeeEVi*#S=nblBoxi0lE{lQyyk?Z+FCfXp(0=95gXMO;fu5W@m4KOyu zaGJcGWi7|W`o1u>2hOYW9)JgL^_>tRFcdi5n5l0ok6c58mI>{w`%7U>R~K89UVavs z&J(Sz0LmSx@9E&m@_FdUb)H3h#9ihl_U9X|5BF%j&S{i(aM@!qd|j??{$9ky)1B_U)KB2eac#v&2@=G#ieEoqYQOni6JS#{^x z0{aJK_hZVzFv*@l=sbU10|Lz_F*eZeMJV)tGr7e?axB&<7KxoiPkqp@m{NJD!y{$h zC2U)B{9arAS~fXU+>3q9K}DP94mXbE3%6OtaXEmP%&AqZo!48aZcYhWUx2Iu-C>!S z1w|z04nxj64K`j-4T9)2&sJ~NR8)4j`7pL3sxYW7oQf7x1De?0SdWu~r!fgI#>FwE zma;vkB~5yPjyC(^g8N|Eff-V1^=(i!+ zGYO@r0xMae6j2AzL6Fki05{~5B&vc6(jU?vJy=E$mnxS6`^5;sBFvHJ^1H#w_T*M?9onqR`s_vX6e7CV3VpAC0Igxap2v7A`bj4=P+F32w(9E5UT{K zQ}bFWlzMldXS27P&L6-h6Q}j!1*H=!RX)#Izl~lD$VvfK@f0UWpf3qAN941-KKd2j zo5o|uEp0dgB@uWIsdtq!@a6xu*mYQEgQ#8dDm=8nzMX*A*U$7;0d4LLWr21{p@89qj<2E=4rxzzoFa zu*ap~x^4Gb0v?d@qpQ$?2NDV>&bhu6a)%9Iu1q!yt$%pPce155^t(2~HkOHRg0=4= zx$8Tw|I0q2;(yNEp_D-@V^G?BBnWX7Ao^|i813l_mK_{;=^gK9*B|Y0#B2;fqIMe_ zu=!l_-BhJK+p3w1=AOHRqH>hmTBLyoUqCe=6QhDX-JZEiwwLdigiT+%*veZs-+F)c zpX12=bNk)G9?mB5_mZBhUSa09=2->M(2;ll<`cnmCsH%>P`P;=<^jbUI7 zLJPpcsDV&5d;exJRNi%C&E(2!kmmh_`=t=Z`W?MHcs!if?f`R+iu>!8n|$ORyjHqq zcZM6ol;J$JKrf>_8U@~Yp!i`cPn|pxJLQeQ4=)NDJjW_y0?4YOpb}7e?H-dV0V9Vh zj_=|xy~tM>$9I-rrtq{T1zcg4e9E3)Xdyf4bNo3mB*_i}gvDq4i2wi8<};!ql)>l$ zoyX+yrb+}gA2y<4?xjPmg*Z|?vw#ss-FJufEBJ;B_%{60GmRy1q}uc~rhex~=O(vn z^E&72GZpV`!KLG93@`otHf&4BS>*_x7Yx8ybiBgWn*P{O=itK{N3%8KuY~GBruC-ITknb_+<-@5%&I5yEA=1p z-SPmQ?-E6bui)&NMNmM~@Es|o1a)2GBm>JSYx!8-9R_Ii0z3FW!U8+f>gV~2cuBTU z=Bju3S$=iO=xexm%DENFOG>su=S3_ZZ)?Hh_SY-1!Zc4*U_JPGg~Uo^Ai}O|`zI49 z__uv*EQ%~h)KSOKsiFDdRmPK7%va;4fimIfo?51-VfA(}g{`=$vIhScUKVG4mS5n1 zF2te^1-nB^1qF+c(44}i@hXJCIXW*bOdQRreOIuOX_fgCnVE85Dv=lh?1fj(P@K5? zu!N33>eOa)M8k>Kdc`1KJQDQYIn=cS>1k4s1Hl-Aw?M!L*9RqVsY(OM#*_C zl}9nwKZ0(Aq&*_w+zz&84f)}`4m>RG1H6M4yMK2i3GcaSDoSgiao9-O#@#_MBG12) zfabvV^%FkH2#<0R;ML8uiGjt51|9u>Tzyqolu^63G)RXqgtUMPNQX3%3JQWqcY{bv zBOy67N_Q(EB_Yi)bO}--4MTSgx!3sZ|J&E~AL#)HF!R1^JS3iECN{GoG)i&u5;Satjb$rxM)`KDCHF#X2 z_3PD%L3|#mD$<6Uz!8j(o(YY@s&lZsap?)*O)YF_GYr`9{-$52{)%y&6q$${;zWe< z;_0SxQDwZ!D_%$WMh#;~D3Fhrh+Vi9wg{L=pDf8>GJ?E^Qc-v&TIeqb_gC>4;O3~r zR=@^&H&-xz?OT@k0;`DsJcRDh-^DgnygCvLf0*1{qIS0TfxvrJEfkl<+OG)J_E6l~ z%@OEpVAj_VeeMW?6;q5GOA*v2A_rd}{?2#DGk*&Q98g=4Eww^EI5Tlhmu>K69sQ)y zpaM!Q+}5_p!&!*rF@X_awW!bVFx-P#f0O4S3@Zu@mAUxJW%^89`3!dD(@Ey-4i<0H zw&8;Ji8RH^?SCGa#{7~Xl~52F`j&kp6t)M702wK;NqN zdc7;gVQQ0+=-|{hGXjw70A6#2R`2&S)JqCLUqZUjUBmzS_hqm8V7h4aLxqQb&MXM% z9p}vaq;-kp1xtXQHO~no{h8~MHWruhzY=&`sG9a=a~0`%PYT4jjIA@E#0)AJuYD6M z5mmU>7;w+F%g=ibZ^nX!@!lG_X*%nrJN4>NpG>nyc-iPuTM%`)rewyVQe=Kg>9T_H zz~I#P$l*^=vt9!$^y}h}w+2Cr&0Bk~=9q7VD@=dTRf4;-aPn98-*2g(UEcm?diMPM zed(&~oB(y^F_-`+v_T|U)ePp^XTCQ(Ad5v1|73Ijy_tYYQo&*y;$I}fq&o=RZenjv z2ewr~{UwN5KEbUU=vYiuOBl!U54aH^VA0qB~)=z~4&m z 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 Date: Tue, 14 Apr 2026 15:19:04 +0200 Subject: [PATCH 5/7] Remove debug files --- conda-recipe/meta.yaml | 2 +- intel_numpy_20260326_100014.txt | 812 ------------------------------ mkl_backend_20260326_100014.txt | 812 ------------------------------ mkl_umath_add_20260326_100014.txt | 812 ------------------------------ npbench_full_comparison.png | Bin 433054 -> 0 bytes stock_numpy_20260326_100014.txt | 812 ------------------------------ tmp/npbench_full_comparison.png | Bin 433009 -> 0 bytes 7 files changed, 1 insertion(+), 3249 deletions(-) delete mode 100644 intel_numpy_20260326_100014.txt delete mode 100644 mkl_backend_20260326_100014.txt delete mode 100644 mkl_umath_add_20260326_100014.txt delete mode 100644 npbench_full_comparison.png delete mode 100644 stock_numpy_20260326_100014.txt delete mode 100644 tmp/npbench_full_comparison.png diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 5ec1f81a..4ee562a4 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -20,7 +20,7 @@ requirements: - {{ compiler('c') }} - {{ compiler('cxx') }} - {{ stdlib('c') }} - - {{ compiler('dpcpp') }} >=2024.2 # [not osx] + - {{ compiler('dpcpp') }} >=2024.2 # [not osx] host: - setuptools >=77 - cmake diff --git a/intel_numpy_20260326_100014.txt b/intel_numpy_20260326_100014.txt deleted file mode 100644 index 756b13cd..00000000 --- a/intel_numpy_20260326_100014.txt +++ /dev/null @@ -1,812 +0,0 @@ -===================================== -Environment: intel_numpy (npbench_intel_numpy) -Timestamp: 20260326_100014 -Total benchmarks: 53 -===================================== - - -====================================== -Benchmark: adi (1/53) -Started at: Thu Mar 26 10:23:35 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with adi on the L dataset ***** -NumPy - default - first/validation: 727ms -NumPy - default - median: 728ms -SUCCESS: adi completed -Completed at: Thu Mar 26 10:23:45 AM PDT 2026 -====================================== - - -====================================== -Benchmark: arc_distance (2/53) -Started at: Thu Mar 26 10:23:45 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with arc_distance on the L dataset ***** -NumPy - default - first/validation: 165ms -NumPy - default - median: 97ms -SUCCESS: arc_distance completed -Completed at: Thu Mar 26 10:23:48 AM PDT 2026 -====================================== - - -====================================== -Benchmark: atax (3/53) -Started at: Thu Mar 26 10:23:48 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with atax on the L dataset ***** -NumPy - default - first/validation: 95ms -NumPy - default - median: 100ms -SUCCESS: atax completed -Completed at: Thu Mar 26 10:24:12 AM PDT 2026 -====================================== - - -====================================== -Benchmark: azimint_hist (4/53) -Started at: Thu Mar 26 10:24:12 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with azimint_hist on the L dataset ***** -NumPy - default - first/validation: 768ms -NumPy - default - median: 768ms -SUCCESS: azimint_hist completed -Completed at: Thu Mar 26 10:24:25 AM PDT 2026 -====================================== - - -====================================== -Benchmark: bicg (5/53) -Started at: Thu Mar 26 10:24:25 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with bicg on the L dataset ***** -NumPy - default - first/validation: 98ms -NumPy - default - median: 105ms -SUCCESS: bicg completed -Completed at: Thu Mar 26 10:24:49 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cavity_flow (6/53) -Started at: Thu Mar 26 10:24:49 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cavity_flow on the L dataset ***** -NumPy - default - first/validation: 688ms -NumPy - default - median: 628ms -SUCCESS: cavity_flow completed -Completed at: Thu Mar 26 10:24:57 AM PDT 2026 -====================================== - - -====================================== -Benchmark: channel_flow (7/53) -Started at: Thu Mar 26 10:24:57 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with channel_flow on the L dataset ***** -NumPy - default - first/validation: 6748ms -NumPy - default - median: 6883ms -SUCCESS: channel_flow completed -Completed at: Thu Mar 26 10:26:27 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cholesky (8/53) -Started at: Thu Mar 26 10:26:27 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cholesky on the L dataset ***** -NumPy - default - first/validation: 502ms -NumPy - default - median: 458ms -SUCCESS: cholesky completed -Completed at: Thu Mar 26 10:26:34 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cholesky2 (9/53) -Started at: Thu Mar 26 10:26:34 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cholesky2 on the L dataset ***** -NumPy - default - first/validation: 603ms -NumPy - default - median: 642ms -SUCCESS: cholesky2 completed -Completed at: Thu Mar 26 10:26:45 AM PDT 2026 -====================================== - - -====================================== -Benchmark: compute (10/53) -Started at: Thu Mar 26 10:26:45 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with compute on the L dataset ***** -NumPy - default - first/validation: 1767ms -NumPy - default - median: 1745ms -SUCCESS: compute completed -Completed at: Thu Mar 26 10:27:26 AM PDT 2026 -====================================== - - -====================================== -Benchmark: contour_integral (11/53) -Started at: Thu Mar 26 10:27:26 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with contour_integral on the L dataset ***** -NumPy - default - first/validation: 712ms -NumPy - default - median: 703ms -SUCCESS: contour_integral completed -Completed at: Thu Mar 26 10:27:36 AM PDT 2026 -====================================== - - -====================================== -Benchmark: conv2d_bias (12/53) -Started at: Thu Mar 26 10:27:36 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with conv2d_bias on the L dataset ***** -NumPy - default - first/validation: 833ms -NumPy - default - median: 758ms -SUCCESS: conv2d_bias completed -Completed at: Thu Mar 26 10:27:46 AM PDT 2026 -====================================== - - -====================================== -Benchmark: correlation (13/53) -Started at: Thu Mar 26 10:27:46 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with correlation on the L dataset ***** -NumPy - default - first/validation: 551ms -NumPy - default - median: 512ms -SUCCESS: correlation completed -Completed at: Thu Mar 26 10:27:54 AM PDT 2026 -====================================== - - -====================================== -Benchmark: covariance (14/53) -Started at: Thu Mar 26 10:27:54 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with covariance on the L dataset ***** -NumPy - default - first/validation: 422ms -NumPy - default - median: 492ms -SUCCESS: covariance completed -Completed at: Thu Mar 26 10:28:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: covariance2 (15/53) -Started at: Thu Mar 26 10:28:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with covariance2 on the L dataset ***** -NumPy - default - first/validation: 139ms -NumPy - default - median: 131ms -SUCCESS: covariance2 completed -Completed at: Thu Mar 26 10:28:04 AM PDT 2026 -====================================== - - -====================================== -Benchmark: crc16 (16/53) -Started at: Thu Mar 26 10:28:04 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with crc16 on the L dataset ***** -NumPy - default - first/validation: 188ms -NumPy - default - median: 198ms -SUCCESS: crc16 completed -Completed at: Thu Mar 26 10:28:07 AM PDT 2026 -====================================== - - -====================================== -Benchmark: deriche (17/53) -Started at: Thu Mar 26 10:28:07 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with deriche on the L dataset ***** -NumPy - default - first/validation: 531ms -NumPy - default - median: 543ms -SUCCESS: deriche completed -Completed at: Thu Mar 26 10:28:15 AM PDT 2026 -====================================== - - -====================================== -Benchmark: doitgen (18/53) -Started at: Thu Mar 26 10:28:15 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with doitgen on the L dataset ***** -NumPy - default - first/validation: 415ms -NumPy - default - median: 419ms -SUCCESS: doitgen completed -Completed at: Thu Mar 26 10:28:23 AM PDT 2026 -====================================== - - -====================================== -Benchmark: durbin (19/53) -Started at: Thu Mar 26 10:28:23 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with durbin on the L dataset ***** -NumPy - default - first/validation: 767ms -NumPy - default - median: 1025ms -SUCCESS: durbin completed -Completed at: Thu Mar 26 10:28:36 AM PDT 2026 -====================================== - - -====================================== -Benchmark: fdtd_2d (20/53) -Started at: Thu Mar 26 10:28:36 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with fdtd_2d on the L dataset ***** -NumPy - default - first/validation: 943ms -NumPy - default - median: 948ms -SUCCESS: fdtd_2d completed -Completed at: Thu Mar 26 10:28:49 AM PDT 2026 -====================================== - - -====================================== -Benchmark: floyd_warshall (21/53) -Started at: Thu Mar 26 10:28:49 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with floyd_warshall on the L dataset ***** -NumPy - default - first/validation: 910ms -NumPy - default - median: 924ms -SUCCESS: floyd_warshall completed -Completed at: Thu Mar 26 10:29:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gemm (22/53) -Started at: Thu Mar 26 10:29:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gemm on the L dataset ***** -NumPy - default - first/validation: 247ms -NumPy - default - median: 240ms -SUCCESS: gemm completed -Completed at: Thu Mar 26 10:29:13 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gemver (23/53) -Started at: Thu Mar 26 10:29:13 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gemver on the L dataset ***** -NumPy - default - first/validation: 432ms -NumPy - default - median: 444ms -SUCCESS: gemver completed -Completed at: Thu Mar 26 10:29:24 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gesummv (24/53) -Started at: Thu Mar 26 10:29:24 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gesummv on the L dataset ***** -NumPy - default - first/validation: 119ms -NumPy - default - median: 117ms -SUCCESS: gesummv completed -Completed at: Thu Mar 26 10:29:43 AM PDT 2026 -====================================== - - -====================================== -Benchmark: go_fast (25/53) -Started at: Thu Mar 26 10:29:43 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with go_fast on the L dataset ***** -NumPy - default - first/validation: 169ms -NumPy - default - median: 96ms -SUCCESS: go_fast completed -Completed at: Thu Mar 26 10:29:58 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gramschmidt (26/53) -Started at: Thu Mar 26 10:29:58 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gramschmidt on the L dataset ***** -NumPy - default - first/validation: 505ms -NumPy - default - median: 467ms -SUCCESS: gramschmidt completed -Completed at: Thu Mar 26 10:30:04 AM PDT 2026 -====================================== - - -====================================== -Benchmark: hdiff (27/53) -Started at: Thu Mar 26 10:30:04 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with hdiff on the L dataset ***** -NumPy - default - first/validation: 836ms -NumPy - default - median: 724ms -SUCCESS: hdiff completed -Completed at: Thu Mar 26 10:30:17 AM PDT 2026 -====================================== - - -====================================== -Benchmark: heat_3d (28/53) -Started at: Thu Mar 26 10:30:17 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with heat_3d on the L dataset ***** -NumPy - default - first/validation: 796ms -NumPy - default - median: 794ms -SUCCESS: heat_3d completed -Completed at: Thu Mar 26 10:30:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: jacobi_1d (29/53) -Started at: Thu Mar 26 10:30:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with jacobi_1d on the L dataset ***** -NumPy - default - first/validation: 754ms -NumPy - default - median: 710ms -SUCCESS: jacobi_1d completed -Completed at: Thu Mar 26 10:30:38 AM PDT 2026 -====================================== - - -====================================== -Benchmark: jacobi_2d (30/53) -Started at: Thu Mar 26 10:30:38 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with jacobi_2d on the L dataset ***** -NumPy - default - first/validation: 966ms -NumPy - default - median: 960ms -SUCCESS: jacobi_2d completed -Completed at: Thu Mar 26 10:30:51 AM PDT 2026 -====================================== - - -====================================== -Benchmark: k2mm (31/53) -Started at: Thu Mar 26 10:30:51 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with k2mm on the L dataset ***** -NumPy - default - first/validation: 379ms -NumPy - default - median: 332ms -SUCCESS: k2mm completed -Completed at: Thu Mar 26 10:31:05 AM PDT 2026 -====================================== - - -====================================== -Benchmark: k3mm (32/53) -Started at: Thu Mar 26 10:31:05 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with k3mm on the L dataset ***** -NumPy - default - first/validation: 321ms -NumPy - default - median: 319ms -SUCCESS: k3mm completed -Completed at: Thu Mar 26 10:31:20 AM PDT 2026 -====================================== - - -====================================== -Benchmark: lenet (33/53) -Started at: Thu Mar 26 10:31:20 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with lenet on the L dataset ***** -NumPy - default - first/validation: 599ms -NumPy - default - median: 569ms -SUCCESS: lenet completed -Completed at: Thu Mar 26 10:31:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: lu (34/53) -Started at: Thu Mar 26 10:31:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with lu on the L dataset ***** -NumPy - default - first/validation: 658ms -NumPy - default - median: 613ms -SUCCESS: lu completed -Completed at: Thu Mar 26 10:31:37 AM PDT 2026 -====================================== - - -====================================== -Benchmark: ludcmp (35/53) -Started at: Thu Mar 26 10:31:37 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with ludcmp on the L dataset ***** -NumPy - default - first/validation: 562ms -NumPy - default - median: 519ms -SUCCESS: ludcmp completed -Completed at: Thu Mar 26 10:31:44 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mandelbrot1 (36/53) -Started at: Thu Mar 26 10:31:44 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mandelbrot1 on the L dataset ***** -NumPy - default - first/validation: 910ms -NumPy - default - median: 830ms -SUCCESS: mandelbrot1 completed -Completed at: Thu Mar 26 10:31:56 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mandelbrot2 (37/53) -Started at: Thu Mar 26 10:31:56 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mandelbrot2 on the L dataset ***** -NumPy - default - first/validation: 428ms -NumPy - default - median: 331ms -SUCCESS: mandelbrot2 completed -Completed at: Thu Mar 26 10:32:00 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mlp (38/53) -Started at: Thu Mar 26 10:32:00 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mlp on the L dataset ***** -NumPy - default - first/validation: 199ms -NumPy - default - median: 131ms -SUCCESS: mlp completed -Completed at: Thu Mar 26 10:32:34 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mvt (39/53) -Started at: Thu Mar 26 10:32:34 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mvt on the L dataset ***** -NumPy - default - first/validation: 91ms -NumPy - default - median: 96ms -SUCCESS: mvt completed -Completed at: Thu Mar 26 10:32:57 AM PDT 2026 -====================================== - - -====================================== -Benchmark: nbody (40/53) -Started at: Thu Mar 26 10:32:57 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with nbody on the L dataset ***** -NumPy - default - first/validation: 246ms -NumPy - default - median: 188ms -SUCCESS: nbody completed -Completed at: Thu Mar 26 10:33:00 AM PDT 2026 -====================================== - - -====================================== -Benchmark: nussinov (41/53) -Started at: Thu Mar 26 10:33:00 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with nussinov on the L dataset ***** -NumPy - default - first/validation: 381ms -NumPy - default - median: 381ms -SUCCESS: nussinov completed -Completed at: Thu Mar 26 10:33:06 AM PDT 2026 -====================================== - - -====================================== -Benchmark: resnet (42/53) -Started at: Thu Mar 26 10:33:06 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with resnet on the L dataset ***** -NumPy - default - first/validation: 701ms -NumPy - default - median: 625ms -SUCCESS: resnet completed -Completed at: Thu Mar 26 10:33:14 AM PDT 2026 -====================================== - - -====================================== -Benchmark: scattering_self_energies (43/53) -Started at: Thu Mar 26 10:33:14 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with scattering_self_energies on the L dataset ***** -NumPy - default - first/validation: 464ms -NumPy - default - median: 406ms -SUCCESS: scattering_self_energies completed -Completed at: Thu Mar 26 10:33:20 AM PDT 2026 -====================================== - - -====================================== -Benchmark: seidel_2d (44/53) -Started at: Thu Mar 26 10:33:20 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with seidel_2d on the L dataset ***** -NumPy - default - first/validation: 553ms -NumPy - default - median: 555ms -SUCCESS: seidel_2d completed -Completed at: Thu Mar 26 10:33:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: softmax (45/53) -Started at: Thu Mar 26 10:33:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with softmax on the L dataset ***** -NumPy - default - first/validation: 644ms -NumPy - default - median: 589ms -SUCCESS: softmax completed -Completed at: Thu Mar 26 10:33:39 AM PDT 2026 -====================================== - - -====================================== -Benchmark: spmv (46/53) -Started at: Thu Mar 26 10:33:39 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with spmv on the L dataset ***** -Traceback (most recent call last): - File "/localdisk/work/antonvol/code/npbench/run_benchmark.py", line 57, in - test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) - ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run - bdata = self.bench.get_data(preset) - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data - exec(init_str, data) - ~~~~^^^^^^^^^^^^^^^^ - File "", line 1, in - File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize - from scipy.sparse import random -ModuleNotFoundError: No module named 'scipy' -ERROR: spmv failed with exit code 1 -Completed at: Thu Mar 26 10:33:40 AM PDT 2026 -====================================== - - -====================================== -Benchmark: stockham_fft (47/53) -Started at: Thu Mar 26 10:33:40 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with stockham_fft on the L dataset ***** -NumPy - default - first/validation: 787ms -NumPy - default - median: 778ms -SUCCESS: stockham_fft completed -Completed at: Thu Mar 26 10:33:51 AM PDT 2026 -====================================== - - -====================================== -Benchmark: symm (48/53) -Started at: Thu Mar 26 10:33:51 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with symm on the L dataset ***** -NumPy - default - first/validation: 480ms -NumPy - default - median: 473ms -SUCCESS: symm completed -Completed at: Thu Mar 26 10:33:57 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syr2k (49/53) -Started at: Thu Mar 26 10:33:57 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syr2k on the L dataset ***** -NumPy - default - first/validation: 511ms -NumPy - default - median: 515ms -SUCCESS: syr2k completed -Completed at: Thu Mar 26 10:34:05 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syrk (50/53) -Started at: Thu Mar 26 10:34:05 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syrk on the L dataset ***** -NumPy - default - first/validation: 480ms -NumPy - default - median: 471ms -SUCCESS: syrk completed -Completed at: Thu Mar 26 10:34:11 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trisolv (51/53) -Started at: Thu Mar 26 10:34:11 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trisolv on the L dataset ***** -NumPy - default - first/validation: 51ms -NumPy - default - median: 50ms -SUCCESS: trisolv completed -Completed at: Thu Mar 26 10:34:19 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trmm (52/53) -Started at: Thu Mar 26 10:34:19 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trmm on the L dataset ***** -NumPy - default - first/validation: 496ms -NumPy - default - median: 497ms -SUCCESS: trmm completed -Completed at: Thu Mar 26 10:34:26 AM PDT 2026 -====================================== - - -====================================== -Benchmark: vadv (53/53) -Started at: Thu Mar 26 10:34:26 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with vadv on the L dataset ***** -NumPy - default - first/validation: 836ms -NumPy - default - median: 824ms -SUCCESS: vadv completed -Completed at: Thu Mar 26 10:34:38 AM PDT 2026 -====================================== - diff --git a/mkl_backend_20260326_100014.txt b/mkl_backend_20260326_100014.txt deleted file mode 100644 index f28e033c..00000000 --- a/mkl_backend_20260326_100014.txt +++ /dev/null @@ -1,812 +0,0 @@ -===================================== -Environment: mkl_backend (npbench_mkl_numpy) -Timestamp: 20260326_100014 -Total benchmarks: 53 -===================================== - - -====================================== -Benchmark: adi (1/53) -Started at: Thu Mar 26 10:12:31 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with adi on the L dataset ***** -NumPy - default - first/validation: 694ms -NumPy - default - median: 689ms -SUCCESS: adi completed -Completed at: Thu Mar 26 10:12:40 AM PDT 2026 -====================================== - - -====================================== -Benchmark: arc_distance (2/53) -Started at: Thu Mar 26 10:12:40 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with arc_distance on the L dataset ***** -NumPy - default - first/validation: 482ms -NumPy - default - median: 484ms -SUCCESS: arc_distance completed -Completed at: Thu Mar 26 10:12:48 AM PDT 2026 -====================================== - - -====================================== -Benchmark: atax (3/53) -Started at: Thu Mar 26 10:12:48 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with atax on the L dataset ***** -NumPy - default - first/validation: 127ms -NumPy - default - median: 58ms -SUCCESS: atax completed -Completed at: Thu Mar 26 10:13:13 AM PDT 2026 -====================================== - - -====================================== -Benchmark: azimint_hist (4/53) -Started at: Thu Mar 26 10:13:13 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with azimint_hist on the L dataset ***** -NumPy - default - first/validation: 648ms -NumPy - default - median: 649ms -SUCCESS: azimint_hist completed -Completed at: Thu Mar 26 10:13:24 AM PDT 2026 -====================================== - - -====================================== -Benchmark: bicg (5/53) -Started at: Thu Mar 26 10:13:24 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with bicg on the L dataset ***** -NumPy - default - first/validation: 154ms -NumPy - default - median: 59ms -SUCCESS: bicg completed -Completed at: Thu Mar 26 10:13:49 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cavity_flow (6/53) -Started at: Thu Mar 26 10:13:49 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cavity_flow on the L dataset ***** -NumPy - default - first/validation: 468ms -NumPy - default - median: 468ms -SUCCESS: cavity_flow completed -Completed at: Thu Mar 26 10:13:55 AM PDT 2026 -====================================== - - -====================================== -Benchmark: channel_flow (7/53) -Started at: Thu Mar 26 10:13:55 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with channel_flow on the L dataset ***** -NumPy - default - first/validation: 4995ms -NumPy - default - median: 5031ms -SUCCESS: channel_flow completed -Completed at: Thu Mar 26 10:15:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cholesky (8/53) -Started at: Thu Mar 26 10:15:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cholesky on the L dataset ***** -NumPy - default - first/validation: 439ms -NumPy - default - median: 441ms -SUCCESS: cholesky completed -Completed at: Thu Mar 26 10:15:07 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cholesky2 (9/53) -Started at: Thu Mar 26 10:15:07 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cholesky2 on the L dataset ***** -NumPy - default - first/validation: 701ms -NumPy - default - median: 697ms -SUCCESS: cholesky2 completed -Completed at: Thu Mar 26 10:15:20 AM PDT 2026 -====================================== - - -====================================== -Benchmark: compute (10/53) -Started at: Thu Mar 26 10:15:20 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with compute on the L dataset ***** -NumPy - default - first/validation: 1715ms -NumPy - default - median: 1711ms -SUCCESS: compute completed -Completed at: Thu Mar 26 10:15:59 AM PDT 2026 -====================================== - - -====================================== -Benchmark: contour_integral (11/53) -Started at: Thu Mar 26 10:15:59 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with contour_integral on the L dataset ***** -NumPy - default - first/validation: 1011ms -NumPy - default - median: 648ms -SUCCESS: contour_integral completed -Completed at: Thu Mar 26 10:16:09 AM PDT 2026 -====================================== - - -====================================== -Benchmark: conv2d_bias (12/53) -Started at: Thu Mar 26 10:16:09 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with conv2d_bias on the L dataset ***** -NumPy - default - first/validation: 769ms -NumPy - default - median: 747ms -SUCCESS: conv2d_bias completed -Completed at: Thu Mar 26 10:16:19 AM PDT 2026 -====================================== - - -====================================== -Benchmark: correlation (13/53) -Started at: Thu Mar 26 10:16:19 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with correlation on the L dataset ***** -NumPy - default - first/validation: 1173ms -NumPy - default - median: 551ms -SUCCESS: correlation completed -Completed at: Thu Mar 26 10:16:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: covariance (14/53) -Started at: Thu Mar 26 10:16:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with covariance on the L dataset ***** -NumPy - default - first/validation: 995ms -NumPy - default - median: 431ms -SUCCESS: covariance completed -Completed at: Thu Mar 26 10:16:36 AM PDT 2026 -====================================== - - -====================================== -Benchmark: covariance2 (15/53) -Started at: Thu Mar 26 10:16:36 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with covariance2 on the L dataset ***** -NumPy - default - first/validation: 202ms -NumPy - default - median: 135ms -SUCCESS: covariance2 completed -Completed at: Thu Mar 26 10:16:38 AM PDT 2026 -====================================== - - -====================================== -Benchmark: crc16 (16/53) -Started at: Thu Mar 26 10:16:38 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with crc16 on the L dataset ***** -NumPy - default - first/validation: 186ms -NumPy - default - median: 189ms -SUCCESS: crc16 completed -Completed at: Thu Mar 26 10:16:41 AM PDT 2026 -====================================== - - -====================================== -Benchmark: deriche (17/53) -Started at: Thu Mar 26 10:16:41 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with deriche on the L dataset ***** -NumPy - default - first/validation: 598ms -NumPy - default - median: 626ms -SUCCESS: deriche completed -Completed at: Thu Mar 26 10:16:51 AM PDT 2026 -====================================== - - -====================================== -Benchmark: doitgen (18/53) -Started at: Thu Mar 26 10:16:51 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with doitgen on the L dataset ***** -NumPy - default - first/validation: 1412ms -NumPy - default - median: 418ms -SUCCESS: doitgen completed -Completed at: Thu Mar 26 10:16:59 AM PDT 2026 -====================================== - - -====================================== -Benchmark: durbin (19/53) -Started at: Thu Mar 26 10:16:59 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with durbin on the L dataset ***** -NumPy - default - first/validation: 697ms -NumPy - default - median: 1568ms -SUCCESS: durbin completed -Completed at: Thu Mar 26 10:17:18 AM PDT 2026 -====================================== - - -====================================== -Benchmark: fdtd_2d (20/53) -Started at: Thu Mar 26 10:17:18 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with fdtd_2d on the L dataset ***** -NumPy - default - first/validation: 771ms -NumPy - default - median: 726ms -SUCCESS: fdtd_2d completed -Completed at: Thu Mar 26 10:17:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: floyd_warshall (21/53) -Started at: Thu Mar 26 10:17:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with floyd_warshall on the L dataset ***** -NumPy - default - first/validation: 720ms -NumPy - default - median: 722ms -SUCCESS: floyd_warshall completed -Completed at: Thu Mar 26 10:17:38 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gemm (22/53) -Started at: Thu Mar 26 10:17:38 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gemm on the L dataset ***** -NumPy - default - first/validation: 593ms -NumPy - default - median: 544ms -SUCCESS: gemm completed -Completed at: Thu Mar 26 10:17:54 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gemver (23/53) -Started at: Thu Mar 26 10:17:54 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gemver on the L dataset ***** -NumPy - default - first/validation: 972ms -NumPy - default - median: 767ms -SUCCESS: gemver completed -Completed at: Thu Mar 26 10:18:10 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gesummv (24/53) -Started at: Thu Mar 26 10:18:10 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gesummv on the L dataset ***** -NumPy - default - first/validation: 1008ms -NumPy - default - median: 919ms -SUCCESS: gesummv completed -Completed at: Thu Mar 26 10:18:40 AM PDT 2026 -====================================== - - -====================================== -Benchmark: go_fast (25/53) -Started at: Thu Mar 26 10:18:40 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with go_fast on the L dataset ***** -NumPy - default - first/validation: 869ms -NumPy - default - median: 847ms -SUCCESS: go_fast completed -Completed at: Thu Mar 26 10:19:04 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gramschmidt (26/53) -Started at: Thu Mar 26 10:19:04 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gramschmidt on the L dataset ***** -NumPy - default - first/validation: 550ms -NumPy - default - median: 454ms -SUCCESS: gramschmidt completed -Completed at: Thu Mar 26 10:19:11 AM PDT 2026 -====================================== - - -====================================== -Benchmark: hdiff (27/53) -Started at: Thu Mar 26 10:19:11 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with hdiff on the L dataset ***** -NumPy - default - first/validation: 834ms -NumPy - default - median: 828ms -SUCCESS: hdiff completed -Completed at: Thu Mar 26 10:19:24 AM PDT 2026 -====================================== - - -====================================== -Benchmark: heat_3d (28/53) -Started at: Thu Mar 26 10:19:24 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with heat_3d on the L dataset ***** -NumPy - default - first/validation: 595ms -NumPy - default - median: 610ms -SUCCESS: heat_3d completed -Completed at: Thu Mar 26 10:19:32 AM PDT 2026 -====================================== - - -====================================== -Benchmark: jacobi_1d (29/53) -Started at: Thu Mar 26 10:19:32 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with jacobi_1d on the L dataset ***** -NumPy - default - first/validation: 458ms -NumPy - default - median: 594ms -SUCCESS: jacobi_1d completed -Completed at: Thu Mar 26 10:19:40 AM PDT 2026 -====================================== - - -====================================== -Benchmark: jacobi_2d (30/53) -Started at: Thu Mar 26 10:19:40 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with jacobi_2d on the L dataset ***** -NumPy - default - first/validation: 707ms -NumPy - default - median: 705ms -SUCCESS: jacobi_2d completed -Completed at: Thu Mar 26 10:19:50 AM PDT 2026 -====================================== - - -====================================== -Benchmark: k2mm (31/53) -Started at: Thu Mar 26 10:19:50 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with k2mm on the L dataset ***** -NumPy - default - first/validation: 783ms -NumPy - default - median: 523ms -SUCCESS: k2mm completed -Completed at: Thu Mar 26 10:20:06 AM PDT 2026 -====================================== - - -====================================== -Benchmark: k3mm (32/53) -Started at: Thu Mar 26 10:20:06 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with k3mm on the L dataset ***** -NumPy - default - first/validation: 457ms -NumPy - default - median: 320ms -SUCCESS: k3mm completed -Completed at: Thu Mar 26 10:20:19 AM PDT 2026 -====================================== - - -====================================== -Benchmark: lenet (33/53) -Started at: Thu Mar 26 10:20:19 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with lenet on the L dataset ***** -NumPy - default - first/validation: 623ms -NumPy - default - median: 565ms -SUCCESS: lenet completed -Completed at: Thu Mar 26 10:20:27 AM PDT 2026 -====================================== - - -====================================== -Benchmark: lu (34/53) -Started at: Thu Mar 26 10:20:27 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with lu on the L dataset ***** -NumPy - default - first/validation: 685ms -NumPy - default - median: 586ms -SUCCESS: lu completed -Completed at: Thu Mar 26 10:20:35 AM PDT 2026 -====================================== - - -====================================== -Benchmark: ludcmp (35/53) -Started at: Thu Mar 26 10:20:35 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with ludcmp on the L dataset ***** -NumPy - default - first/validation: 514ms -NumPy - default - median: 497ms -SUCCESS: ludcmp completed -Completed at: Thu Mar 26 10:20:42 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mandelbrot1 (36/53) -Started at: Thu Mar 26 10:20:42 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mandelbrot1 on the L dataset ***** -NumPy - default - first/validation: 631ms -NumPy - default - median: 617ms -SUCCESS: mandelbrot1 completed -Completed at: Thu Mar 26 10:20:51 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mandelbrot2 (37/53) -Started at: Thu Mar 26 10:20:51 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mandelbrot2 on the L dataset ***** -NumPy - default - first/validation: 252ms -NumPy - default - median: 226ms -SUCCESS: mandelbrot2 completed -Completed at: Thu Mar 26 10:20:54 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mlp (38/53) -Started at: Thu Mar 26 10:20:54 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mlp on the L dataset ***** -NumPy - default - first/validation: 192ms -NumPy - default - median: 79ms -SUCCESS: mlp completed -Completed at: Thu Mar 26 10:21:27 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mvt (39/53) -Started at: Thu Mar 26 10:21:27 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mvt on the L dataset ***** -NumPy - default - first/validation: 124ms -NumPy - default - median: 55ms -SUCCESS: mvt completed -Completed at: Thu Mar 26 10:21:50 AM PDT 2026 -====================================== - - -====================================== -Benchmark: nbody (40/53) -Started at: Thu Mar 26 10:21:50 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with nbody on the L dataset ***** -NumPy - default - first/validation: 195ms -NumPy - default - median: 195ms -SUCCESS: nbody completed -Completed at: Thu Mar 26 10:21:53 AM PDT 2026 -====================================== - - -====================================== -Benchmark: nussinov (41/53) -Started at: Thu Mar 26 10:21:53 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with nussinov on the L dataset ***** -NumPy - default - first/validation: 392ms -NumPy - default - median: 392ms -SUCCESS: nussinov completed -Completed at: Thu Mar 26 10:21:59 AM PDT 2026 -====================================== - - -====================================== -Benchmark: resnet (42/53) -Started at: Thu Mar 26 10:21:59 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with resnet on the L dataset ***** -NumPy - default - first/validation: 532ms -NumPy - default - median: 547ms -SUCCESS: resnet completed -Completed at: Thu Mar 26 10:22:06 AM PDT 2026 -====================================== - - -====================================== -Benchmark: scattering_self_energies (43/53) -Started at: Thu Mar 26 10:22:06 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with scattering_self_energies on the L dataset ***** -NumPy - default - first/validation: 480ms -NumPy - default - median: 420ms -SUCCESS: scattering_self_energies completed -Completed at: Thu Mar 26 10:22:12 AM PDT 2026 -====================================== - - -====================================== -Benchmark: seidel_2d (44/53) -Started at: Thu Mar 26 10:22:12 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with seidel_2d on the L dataset ***** -NumPy - default - first/validation: 534ms -NumPy - default - median: 539ms -SUCCESS: seidel_2d completed -Completed at: Thu Mar 26 10:22:20 AM PDT 2026 -====================================== - - -====================================== -Benchmark: softmax (45/53) -Started at: Thu Mar 26 10:22:20 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with softmax on the L dataset ***** -NumPy - default - first/validation: 974ms -NumPy - default - median: 943ms -SUCCESS: softmax completed -Completed at: Thu Mar 26 10:22:35 AM PDT 2026 -====================================== - - -====================================== -Benchmark: spmv (46/53) -Started at: Thu Mar 26 10:22:35 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with spmv on the L dataset ***** -Traceback (most recent call last): - File "/localdisk/work/antonvol/code/npbench/run_benchmark.py", line 57, in - test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) - ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run - bdata = self.bench.get_data(preset) - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data - exec(init_str, data) - ~~~~^^^^^^^^^^^^^^^^ - File "", line 1, in - File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize - from scipy.sparse import random -ModuleNotFoundError: No module named 'scipy' -ERROR: spmv failed with exit code 1 -Completed at: Thu Mar 26 10:22:36 AM PDT 2026 -====================================== - - -====================================== -Benchmark: stockham_fft (47/53) -Started at: Thu Mar 26 10:22:36 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with stockham_fft on the L dataset ***** -NumPy - default - first/validation: 999ms -NumPy - default - median: 937ms -SUCCESS: stockham_fft completed -Completed at: Thu Mar 26 10:22:49 AM PDT 2026 -====================================== - - -====================================== -Benchmark: symm (48/53) -Started at: Thu Mar 26 10:22:49 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with symm on the L dataset ***** -NumPy - default - first/validation: 455ms -NumPy - default - median: 450ms -SUCCESS: symm completed -Completed at: Thu Mar 26 10:22:55 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syr2k (49/53) -Started at: Thu Mar 26 10:22:55 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syr2k on the L dataset ***** -NumPy - default - first/validation: 483ms -NumPy - default - median: 482ms -SUCCESS: syr2k completed -Completed at: Thu Mar 26 10:23:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syrk (50/53) -Started at: Thu Mar 26 10:23:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syrk on the L dataset ***** -NumPy - default - first/validation: 435ms -NumPy - default - median: 439ms -SUCCESS: syrk completed -Completed at: Thu Mar 26 10:23:07 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trisolv (51/53) -Started at: Thu Mar 26 10:23:07 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trisolv on the L dataset ***** -NumPy - default - first/validation: 117ms -NumPy - default - median: 76ms -SUCCESS: trisolv completed -Completed at: Thu Mar 26 10:23:16 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trmm (52/53) -Started at: Thu Mar 26 10:23:16 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trmm on the L dataset ***** -NumPy - default - first/validation: 477ms -NumPy - default - median: 477ms -SUCCESS: trmm completed -Completed at: Thu Mar 26 10:23:23 AM PDT 2026 -====================================== - - -====================================== -Benchmark: vadv (53/53) -Started at: Thu Mar 26 10:23:23 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with vadv on the L dataset ***** -NumPy - default - first/validation: 818ms -NumPy - default - median: 810ms -SUCCESS: vadv completed -Completed at: Thu Mar 26 10:23:34 AM PDT 2026 -====================================== - diff --git a/mkl_umath_add_20260326_100014.txt b/mkl_umath_add_20260326_100014.txt deleted file mode 100644 index c6a95630..00000000 --- a/mkl_umath_add_20260326_100014.txt +++ /dev/null @@ -1,812 +0,0 @@ -===================================== -Environment: mkl_umath_add (npbench_intel_numpy_imp) -Timestamp: 20260326_100014 -Total benchmarks: 53 -===================================== - - -====================================== -Benchmark: adi (1/53) -Started at: Thu Mar 26 10:34:39 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with adi on the L dataset ***** -NumPy - default - first/validation: 716ms -NumPy - default - median: 701ms -SUCCESS: adi completed -Completed at: Thu Mar 26 10:34:48 AM PDT 2026 -====================================== - - -====================================== -Benchmark: arc_distance (2/53) -Started at: Thu Mar 26 10:34:48 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with arc_distance on the L dataset ***** -NumPy - default - first/validation: 170ms -NumPy - default - median: 93ms -SUCCESS: arc_distance completed -Completed at: Thu Mar 26 10:34:52 AM PDT 2026 -====================================== - - -====================================== -Benchmark: atax (3/53) -Started at: Thu Mar 26 10:34:52 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with atax on the L dataset ***** -NumPy - default - first/validation: 94ms -NumPy - default - median: 102ms -SUCCESS: atax completed -Completed at: Thu Mar 26 10:35:15 AM PDT 2026 -====================================== - - -====================================== -Benchmark: azimint_hist (4/53) -Started at: Thu Mar 26 10:35:15 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with azimint_hist on the L dataset ***** -NumPy - default - first/validation: 818ms -NumPy - default - median: 774ms -SUCCESS: azimint_hist completed -Completed at: Thu Mar 26 10:35:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: bicg (5/53) -Started at: Thu Mar 26 10:35:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with bicg on the L dataset ***** -NumPy - default - first/validation: 94ms -NumPy - default - median: 99ms -SUCCESS: bicg completed -Completed at: Thu Mar 26 10:35:52 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cavity_flow (6/53) -Started at: Thu Mar 26 10:35:52 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cavity_flow on the L dataset ***** -NumPy - default - first/validation: 709ms -NumPy - default - median: 652ms -SUCCESS: cavity_flow completed -Completed at: Thu Mar 26 10:36:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: channel_flow (7/53) -Started at: Thu Mar 26 10:36:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with channel_flow on the L dataset ***** -NumPy - default - first/validation: 7061ms -NumPy - default - median: 7241ms -SUCCESS: channel_flow completed -Completed at: Thu Mar 26 10:37:35 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cholesky (8/53) -Started at: Thu Mar 26 10:37:35 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cholesky on the L dataset ***** -NumPy - default - first/validation: 585ms -NumPy - default - median: 546ms -SUCCESS: cholesky completed -Completed at: Thu Mar 26 10:37:43 AM PDT 2026 -====================================== - - -====================================== -Benchmark: cholesky2 (9/53) -Started at: Thu Mar 26 10:37:43 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with cholesky2 on the L dataset ***** -NumPy - default - first/validation: 597ms -NumPy - default - median: 603ms -SUCCESS: cholesky2 completed -Completed at: Thu Mar 26 10:37:54 AM PDT 2026 -====================================== - - -====================================== -Benchmark: compute (10/53) -Started at: Thu Mar 26 10:37:54 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with compute on the L dataset ***** -NumPy - default - first/validation: 1757ms -NumPy - default - median: 1732ms -SUCCESS: compute completed -Completed at: Thu Mar 26 10:38:34 AM PDT 2026 -====================================== - - -====================================== -Benchmark: contour_integral (11/53) -Started at: Thu Mar 26 10:38:34 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with contour_integral on the L dataset ***** -NumPy - default - first/validation: 694ms -NumPy - default - median: 690ms -SUCCESS: contour_integral completed -Completed at: Thu Mar 26 10:38:44 AM PDT 2026 -====================================== - - -====================================== -Benchmark: conv2d_bias (12/53) -Started at: Thu Mar 26 10:38:44 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with conv2d_bias on the L dataset ***** -NumPy - default - first/validation: 837ms -NumPy - default - median: 772ms -SUCCESS: conv2d_bias completed -Completed at: Thu Mar 26 10:38:55 AM PDT 2026 -====================================== - - -====================================== -Benchmark: correlation (13/53) -Started at: Thu Mar 26 10:38:55 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with correlation on the L dataset ***** -NumPy - default - first/validation: 476ms -NumPy - default - median: 471ms -SUCCESS: correlation completed -Completed at: Thu Mar 26 10:39:02 AM PDT 2026 -====================================== - - -====================================== -Benchmark: covariance (14/53) -Started at: Thu Mar 26 10:39:02 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with covariance on the L dataset ***** -NumPy - default - first/validation: 415ms -NumPy - default - median: 427ms -SUCCESS: covariance completed -Completed at: Thu Mar 26 10:39:09 AM PDT 2026 -====================================== - - -====================================== -Benchmark: covariance2 (15/53) -Started at: Thu Mar 26 10:39:09 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with covariance2 on the L dataset ***** -NumPy - default - first/validation: 163ms -NumPy - default - median: 130ms -SUCCESS: covariance2 completed -Completed at: Thu Mar 26 10:39:11 AM PDT 2026 -====================================== - - -====================================== -Benchmark: crc16 (16/53) -Started at: Thu Mar 26 10:39:11 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with crc16 on the L dataset ***** -NumPy - default - first/validation: 187ms -NumPy - default - median: 199ms -SUCCESS: crc16 completed -Completed at: Thu Mar 26 10:39:14 AM PDT 2026 -====================================== - - -====================================== -Benchmark: deriche (17/53) -Started at: Thu Mar 26 10:39:14 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with deriche on the L dataset ***** -NumPy - default - first/validation: 536ms -NumPy - default - median: 551ms -SUCCESS: deriche completed -Completed at: Thu Mar 26 10:39:23 AM PDT 2026 -====================================== - - -====================================== -Benchmark: doitgen (18/53) -Started at: Thu Mar 26 10:39:23 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with doitgen on the L dataset ***** -NumPy - default - first/validation: 421ms -NumPy - default - median: 402ms -SUCCESS: doitgen completed -Completed at: Thu Mar 26 10:39:30 AM PDT 2026 -====================================== - - -====================================== -Benchmark: durbin (19/53) -Started at: Thu Mar 26 10:39:30 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with durbin on the L dataset ***** -NumPy - default - first/validation: 696ms -NumPy - default - median: 872ms -SUCCESS: durbin completed -Completed at: Thu Mar 26 10:39:42 AM PDT 2026 -====================================== - - -====================================== -Benchmark: fdtd_2d (20/53) -Started at: Thu Mar 26 10:39:42 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with fdtd_2d on the L dataset ***** -NumPy - default - first/validation: 924ms -NumPy - default - median: 927ms -SUCCESS: fdtd_2d completed -Completed at: Thu Mar 26 10:39:55 AM PDT 2026 -====================================== - - -====================================== -Benchmark: floyd_warshall (21/53) -Started at: Thu Mar 26 10:39:55 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with floyd_warshall on the L dataset ***** -NumPy - default - first/validation: 899ms -NumPy - default - median: 894ms -SUCCESS: floyd_warshall completed -Completed at: Thu Mar 26 10:40:07 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gemm (22/53) -Started at: Thu Mar 26 10:40:07 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gemm on the L dataset ***** -NumPy - default - first/validation: 251ms -NumPy - default - median: 233ms -SUCCESS: gemm completed -Completed at: Thu Mar 26 10:40:18 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gemver (23/53) -Started at: Thu Mar 26 10:40:18 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gemver on the L dataset ***** -NumPy - default - first/validation: 418ms -NumPy - default - median: 426ms -SUCCESS: gemver completed -Completed at: Thu Mar 26 10:40:29 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gesummv (24/53) -Started at: Thu Mar 26 10:40:29 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gesummv on the L dataset ***** -NumPy - default - first/validation: 119ms -NumPy - default - median: 112ms -SUCCESS: gesummv completed -Completed at: Thu Mar 26 10:40:48 AM PDT 2026 -====================================== - - -====================================== -Benchmark: go_fast (25/53) -Started at: Thu Mar 26 10:40:48 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with go_fast on the L dataset ***** -NumPy - default - first/validation: 167ms -NumPy - default - median: 97ms -SUCCESS: go_fast completed -Completed at: Thu Mar 26 10:41:03 AM PDT 2026 -====================================== - - -====================================== -Benchmark: gramschmidt (26/53) -Started at: Thu Mar 26 10:41:03 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with gramschmidt on the L dataset ***** -NumPy - default - first/validation: 508ms -NumPy - default - median: 465ms -SUCCESS: gramschmidt completed -Completed at: Thu Mar 26 10:41:10 AM PDT 2026 -====================================== - - -====================================== -Benchmark: hdiff (27/53) -Started at: Thu Mar 26 10:41:10 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with hdiff on the L dataset ***** -NumPy - default - first/validation: 818ms -NumPy - default - median: 731ms -SUCCESS: hdiff completed -Completed at: Thu Mar 26 10:41:22 AM PDT 2026 -====================================== - - -====================================== -Benchmark: heat_3d (28/53) -Started at: Thu Mar 26 10:41:22 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with heat_3d on the L dataset ***** -NumPy - default - first/validation: 811ms -NumPy - default - median: 812ms -SUCCESS: heat_3d completed -Completed at: Thu Mar 26 10:41:34 AM PDT 2026 -====================================== - - -====================================== -Benchmark: jacobi_1d (29/53) -Started at: Thu Mar 26 10:41:34 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with jacobi_1d on the L dataset ***** -NumPy - default - first/validation: 559ms -NumPy - default - median: 556ms -SUCCESS: jacobi_1d completed -Completed at: Thu Mar 26 10:41:41 AM PDT 2026 -====================================== - - -====================================== -Benchmark: jacobi_2d (30/53) -Started at: Thu Mar 26 10:41:41 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with jacobi_2d on the L dataset ***** -NumPy - default - first/validation: 968ms -NumPy - default - median: 971ms -SUCCESS: jacobi_2d completed -Completed at: Thu Mar 26 10:41:54 AM PDT 2026 -====================================== - - -====================================== -Benchmark: k2mm (31/53) -Started at: Thu Mar 26 10:41:54 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with k2mm on the L dataset ***** -NumPy - default - first/validation: 306ms -NumPy - default - median: 300ms -SUCCESS: k2mm completed -Completed at: Thu Mar 26 10:42:09 AM PDT 2026 -====================================== - - -====================================== -Benchmark: k3mm (32/53) -Started at: Thu Mar 26 10:42:09 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with k3mm on the L dataset ***** -NumPy - default - first/validation: 299ms -NumPy - default - median: 301ms -SUCCESS: k3mm completed -Completed at: Thu Mar 26 10:42:21 AM PDT 2026 -====================================== - - -====================================== -Benchmark: lenet (33/53) -Started at: Thu Mar 26 10:42:21 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with lenet on the L dataset ***** -NumPy - default - first/validation: 574ms -NumPy - default - median: 568ms -SUCCESS: lenet completed -Completed at: Thu Mar 26 10:42:29 AM PDT 2026 -====================================== - - -====================================== -Benchmark: lu (34/53) -Started at: Thu Mar 26 10:42:29 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with lu on the L dataset ***** -NumPy - default - first/validation: 650ms -NumPy - default - median: 607ms -SUCCESS: lu completed -Completed at: Thu Mar 26 10:42:38 AM PDT 2026 -====================================== - - -====================================== -Benchmark: ludcmp (35/53) -Started at: Thu Mar 26 10:42:38 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with ludcmp on the L dataset ***** -NumPy - default - first/validation: 561ms -NumPy - default - median: 516ms -SUCCESS: ludcmp completed -Completed at: Thu Mar 26 10:42:45 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mandelbrot1 (36/53) -Started at: Thu Mar 26 10:42:45 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mandelbrot1 on the L dataset ***** -NumPy - default - first/validation: 892ms -NumPy - default - median: 818ms -SUCCESS: mandelbrot1 completed -Completed at: Thu Mar 26 10:42:56 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mandelbrot2 (37/53) -Started at: Thu Mar 26 10:42:56 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mandelbrot2 on the L dataset ***** -NumPy - default - first/validation: 420ms -NumPy - default - median: 334ms -SUCCESS: mandelbrot2 completed -Completed at: Thu Mar 26 10:43:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mlp (38/53) -Started at: Thu Mar 26 10:43:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mlp on the L dataset ***** -NumPy - default - first/validation: 202ms -NumPy - default - median: 135ms -SUCCESS: mlp completed -Completed at: Thu Mar 26 10:43:35 AM PDT 2026 -====================================== - - -====================================== -Benchmark: mvt (39/53) -Started at: Thu Mar 26 10:43:35 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with mvt on the L dataset ***** -NumPy - default - first/validation: 89ms -NumPy - default - median: 96ms -SUCCESS: mvt completed -Completed at: Thu Mar 26 10:43:58 AM PDT 2026 -====================================== - - -====================================== -Benchmark: nbody (40/53) -Started at: Thu Mar 26 10:43:58 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with nbody on the L dataset ***** -NumPy - default - first/validation: 254ms -NumPy - default - median: 191ms -SUCCESS: nbody completed -Completed at: Thu Mar 26 10:44:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: nussinov (41/53) -Started at: Thu Mar 26 10:44:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with nussinov on the L dataset ***** -NumPy - default - first/validation: 382ms -NumPy - default - median: 382ms -SUCCESS: nussinov completed -Completed at: Thu Mar 26 10:44:07 AM PDT 2026 -====================================== - - -====================================== -Benchmark: resnet (42/53) -Started at: Thu Mar 26 10:44:07 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with resnet on the L dataset ***** -NumPy - default - first/validation: 615ms -NumPy - default - median: 526ms -SUCCESS: resnet completed -Completed at: Thu Mar 26 10:44:14 AM PDT 2026 -====================================== - - -====================================== -Benchmark: scattering_self_energies (43/53) -Started at: Thu Mar 26 10:44:14 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with scattering_self_energies on the L dataset ***** -NumPy - default - first/validation: 460ms -NumPy - default - median: 400ms -SUCCESS: scattering_self_energies completed -Completed at: Thu Mar 26 10:44:20 AM PDT 2026 -====================================== - - -====================================== -Benchmark: seidel_2d (44/53) -Started at: Thu Mar 26 10:44:20 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with seidel_2d on the L dataset ***** -NumPy - default - first/validation: 549ms -NumPy - default - median: 552ms -SUCCESS: seidel_2d completed -Completed at: Thu Mar 26 10:44:27 AM PDT 2026 -====================================== - - -====================================== -Benchmark: softmax (45/53) -Started at: Thu Mar 26 10:44:27 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with softmax on the L dataset ***** -NumPy - default - first/validation: 647ms -NumPy - default - median: 607ms -SUCCESS: softmax completed -Completed at: Thu Mar 26 10:44:40 AM PDT 2026 -====================================== - - -====================================== -Benchmark: spmv (46/53) -Started at: Thu Mar 26 10:44:40 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with spmv on the L dataset ***** -Traceback (most recent call last): - File "/localdisk/work/antonvol/code/npbench/run_benchmark.py", line 57, in - test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) - ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run - bdata = self.bench.get_data(preset) - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data - exec(init_str, data) - ~~~~^^^^^^^^^^^^^^^^ - File "", line 1, in - File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize - from scipy.sparse import random -ModuleNotFoundError: No module named 'scipy' -ERROR: spmv failed with exit code 1 -Completed at: Thu Mar 26 10:44:40 AM PDT 2026 -====================================== - - -====================================== -Benchmark: stockham_fft (47/53) -Started at: Thu Mar 26 10:44:40 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with stockham_fft on the L dataset ***** -NumPy - default - first/validation: 784ms -NumPy - default - median: 784ms -SUCCESS: stockham_fft completed -Completed at: Thu Mar 26 10:44:51 AM PDT 2026 -====================================== - - -====================================== -Benchmark: symm (48/53) -Started at: Thu Mar 26 10:44:51 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with symm on the L dataset ***** -NumPy - default - first/validation: 477ms -NumPy - default - median: 471ms -SUCCESS: symm completed -Completed at: Thu Mar 26 10:44:58 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syr2k (49/53) -Started at: Thu Mar 26 10:44:58 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syr2k on the L dataset ***** -NumPy - default - first/validation: 502ms -NumPy - default - median: 502ms -SUCCESS: syr2k completed -Completed at: Thu Mar 26 10:45:05 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syrk (50/53) -Started at: Thu Mar 26 10:45:05 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syrk on the L dataset ***** -NumPy - default - first/validation: 444ms -NumPy - default - median: 445ms -SUCCESS: syrk completed -Completed at: Thu Mar 26 10:45:11 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trisolv (51/53) -Started at: Thu Mar 26 10:45:11 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trisolv on the L dataset ***** -NumPy - default - first/validation: 53ms -NumPy - default - median: 53ms -SUCCESS: trisolv completed -Completed at: Thu Mar 26 10:45:19 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trmm (52/53) -Started at: Thu Mar 26 10:45:19 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trmm on the L dataset ***** -NumPy - default - first/validation: 489ms -NumPy - default - median: 489ms -SUCCESS: trmm completed -Completed at: Thu Mar 26 10:45:26 AM PDT 2026 -====================================== - - -====================================== -Benchmark: vadv (53/53) -Started at: Thu Mar 26 10:45:26 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with vadv on the L dataset ***** -NumPy - default - first/validation: 946ms -NumPy - default - median: 867ms -SUCCESS: vadv completed -Completed at: Thu Mar 26 10:45:38 AM PDT 2026 -====================================== - diff --git a/npbench_full_comparison.png b/npbench_full_comparison.png deleted file mode 100644 index 17dac9132caae022f09cb2ab7661d94ed9d68aa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 433054 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�zf%pBze&ny%nj|+sYl-5dAW@fSJ6Xi5|5QG$gbJNr_Zb z7j)c2&$5Le(-<|<(Dhy*du;i`03UP;K}j6*J4NGo$qg1eqZ{aPWve?x=gpU0vLKD( zwE>Q9kM$OFakyy%Bq-JR#MZ#1>W_!G}37!2Edu-C$R#G9wJnQS^!9XkWUM-ee&;>c$Rwkk4JAren#~h zVoSHCN_~$CCeSC2at!Ww*&j%yp5{Y%jRIz8nZvh~4yyJhIA(In7Nwd7;b(Llhw*YM zq0~_9>7oHc4?XFQC}{s@7B=Bk$oiHb(s37Mq+t6P(Ln4BlA@#oW8vDj1Aft*=0l$F z{iQ&VuK16F&5)GJ;O?4c2;!qhHv`|DgS&K_X=fmSR-|&7vjsrSV?qNh3qoD;V@G1c zh`>=G5a!m?O#SCvP~Ph=GVSX~vSsXAVfyPW3BHFWq>dVRQm+Z*_}s3rKDnl<1bF<6 zw~=Io=^a+U#u;WkIbOSdNI)jAqJ~IMY(7L?LM9wl;#@KWP>`j1Hx@a{z%RWv_Ti&- zKpaZbco;tF6%?HD>i=gUc!qwDyP8_-t>!z}Sj`=8kv+O>sFsWslPHsm7}pLIdCK)6 zG|%O}#McesL%lF(7Z`*g8RD(}1fo>4=x#GWHO9EB2mSCaq5wT*JIgop<{4sds&#@M zb^S*b?@~^AgnIaUQhOMbS4iJUZUh?Xbv){7vljT9U#b_FA022)W&c(bjZOc|mia~l z=xnwlngz>`p!5LF>Dj8sATzz^ZA^kAzfN1xhJs|B{0;#ZtE>sx` za4uKWgKyo}j?*v%u+3^Q&Ax9F_lTu0e+<0MSVcDQ6666EA@f5}jOhH&>DE-u^F5cV z-~0P~jzBZ~ZXoM2>K!718m^iy{u9P7rH6kL)AOMqezrr^^zcz8LNgoY3}--rlIxHY zG*8%v%VqDUL4`Yj(Mn@xAq({LXV*&*(e^T09{)-dzeY(Vs2&KSpfci zeb@-{V2==HqHtw3^>@i|#^xlBL?Kxlv7WQ*rx6+jyFly4$xZkOvJD?k0LsMCN*?87b{3+uA-y?|J}tr+)4N@`-gFGF#x3 zgr5lZ4_ZgK*m=|c+0>wYKie>+_&ijXZSA(FRtvm+#z||ihcfnY5lQ<{VjFEn=tnDk z>@x0g!hwRf%!nR|P*NELImRz_+c1mK4tXy1C3k8;`{?-=snglRfKm|*R9kXad=KOJ zg`#!Q7Ns+*M!Nr27n}mAKSt5HUW4kxi6TqQ4h(}Z6Zdu?r|MwmD3*zG8t4%s{7<&Q z;ANlbt#Dq?v{G#T$4q zNu6k}ufkirM?Ybx%EpEM)i_`;dA1+$p7oSk>!BuNx30X%nH3CftJ8teB>srG^rWCn z-d`boH-Q=w_gRAKwk_-o4d?1M7AD!I9wbe_*J>wEqcbR{fM5J|2S&{@s2WwJ_MeqbJ;+JNn_)EosKt@5 zhf9kFwE4>|ltxTBPww{*AB4eZ%1LoF<7V=yiANfEqccHltjgg&YU-;6(BB@QIpH%E z^4fDi)+?S~GW5J%>qcZ#1~*RdR68|Hc_{x~lC*8jp(>dbMQjIiD-+x5xCQd{5a3?b zRA(AVNhufUqU`VjI?7!E`I)!WSTx&X0?qxq8E>{MTT_gt8C#%T59%b0Rf}-7zZ=H$ zRpm)+1L{wMc6l@So?$tK8KqUl&iY)q9REZ}{+E-K$!PxEo9rAF--qR0ltA3>Bet8* zt4l@GCBgq(oq(&;WR6l1%&P}7PR-}zc&PwxIk6MD88rSFjTG~72>1dMB}3I|PvH+a zAS6-aEsbSS5}hB?a{;aYz_wQ%?k|~qe??bf$wDu@c-D%EY+89@)o7ssfO;0 z4csI=Lvc)uu#;wlAC8VoWn5yIn49nC6ub+86h!*g*${6f zqe2qjO*{)^peAh_5voupsI;|+-%8uoG)W0Pvm^-V?0jeulTQc857Di5(ngP?nYff$ z%&{c`uA?eJS>W{s`mxXGVJ@e%YNP36KWSp2E=}fHKbasMTZa+%_|{6!4R;Wi&n!@K zFChV)KsV@D1zw5&rAlDJ48i=7Z;df)hK98P84kn6!}OQzr06nG`JNrB*gf2H6Y3z8 zpw@2^7ZW+(lMB=NPV z<)Cobzl65yQ>T)23Q}u6CgfDb+^ivg z3gxh2juQ>XQh;AckQrb`JExI-KN}_(Y}gjyvJ*hJXp@w7H*Z`w^mo=^vZ^q|UxOGF zldF8qz$McO1An%#9$`bFola%>i3ihop6s*FP7r+WiCFcS5)ySXGz)N?WXN~5hU2X! zqzpW=MGM!o2rQl4M`Ahw!W^+*dXY}D+Z3@Rq2mg4`Ap9N#Eh&zibSD!T-;M2p(Fxo zomqHM!Fin^TF0G88na2A4mQkEyNu(U7{M!n|JT1&KmF040OPc{f~cn;($|_@@O{s> zz@aIFDVSO(aM;tJFcc(nEG_{aAG(_X!Y%&?rsFpLxO+0h3BoAVIb`fqYQGTaK~Lj6 zolxD<1@JtUSF;cgPXGdqXBNs}KqeI~`>j)Aq}%{RY#~xG5f}my%H*JO4AeL8=)a(WJ4pf-r?O7M)3vsG8BpHN;f?r%r*4EnoeJi^GovXViuKB~tRHR*0Q;o0`LN{fJ%(|qS;38B^ctlG5ZSEHzzQ)!^biOc^S*p5n(bgvaEr2x4B?RhcJ@&va1DjM zgN~?|o(;m>prn-~E||^$n5;ri%TOu1*clJ8*pKtiF_^tE+6L#wN#@!x^iZ_&L#V=0 zXr_4$WR$e-2e5%n|2T_-i^+Yezo6DiyrfQ9+1Z_8%|+_D)i2#l9aJxAczGXPGxg+d z0RRXIdal6;cG2>rT#G={M~j`2yAv9`j&P2pC|Gz>(2k+Klyw$95>B9$UU6v&Ls#T3 zlI!|c(9>Ilyx#{qIW!QCOevn2rDPZcwNjSCy&N8qk_s@Z>c`M;BsM_{ZkloW$z&X$@-pS)exQt<$;ja$LN5J)JSG;)mGOgNFX1D z@L94xh~CTfza9-~3WaHF1|91kjA*LUVqV`^pZ;!cr;)W3;^_#ehAcQX>7d7A!6QTk2&!<5he*Q&diK>VmkpV0)&D9? zFek5j%IDdDCddF+L%EtQWqMbkaKD8tZHZr%y4iV~VT2=*H5(}04V*Lradgq$NQa`o zIV(%SXzGA?oYqn$5}a~|k!AZft4a_4B*D=BdoG_@pa0_ll&Vhwa-|Va3-E2KqH(Ka zG@}BKD8ZO6lTAv-*Mt10J}r%Xmw!|gGI_)!aGJg%vk`@;C8!yWJ1}_OIDXmK9lXV; z6F(tq(v=T6KAvfEG&_NqZ4M{bo`5!V%o*6ku9g+O%^G;En6J+$=0cR^e*B}fR|El= zv}7!b$08Sk0UrLw{bSwI6x2w4f>_h<1IQUDdCA?4`ZrjJaiG8#c4}+G2qu4eDHA-# z>4uXo8eZo9uN@demKxFq&_iIvgG37PFlnV8w1g_hW+-Jl`7p3Y;@*UM2}-C?HS3&Saq0$>>vd0KlJ0N(k?Yi-<^2qL z?u+erI&Z#BS=JYQ$jGHy76jdkDz^J597MrotN?r?P>E4Yp`KX!CCXZs6dpp6eb0Md&v%w)zBA@M-sAn_eSgQdjyZZ5p5^no@9Vy<^E%J- zy3l+Vr8kiT@RxG;8`Y%-L6>gj9BuR!bE^yTfPslD6vNk18ey&dz((wue0 zlveCed4MibFv$4M8lw$_fm=2Om$9HAO2@`jTJlMT>skdUwk*k~dAg zyuA~*m<+Rak%x?#;)>Zqxm&HHIp)q(FGm4?3s|;4=Rz(ABOU<=L>_={M-E%KrHRid zcd$yge}Og6bVNi^-djWMrHRReGOzoc;)KrD(GOSsdlm>}p-{YUP$|h-{UQ z$Uh8bC%jbcw1NOr@Jt+7fF^M|3%J}l4bx}keuBX335#&3snd2A7wU2xE&Ez}OO?}g2 zSfW1j&Mq{#Jf~aTbWX$kXEs>8J5CWgcuk+I#OCkH0L`N1Xa-2L%c!6-X3e^Kvj>@+ z&;H1}ON5_zbe)`Hqq?PN@e1zrC!YbxS{xnJ(}@HlgL|weczpK{oJTil*;T08PBQ{V zTFCW?ec&@#8aHbe8@wempu6r1KI?-xvX4#-(qut}@OiXzuhZeTNLPe`W`&|*!0$0& zD6?YAip47`w^Ey2dMzbZrGQTL`jhr;6qfK%e(|xS1*V%>vD)y6DMgJQG~zFRNljvB zqR0ue&xvA{o--k<8y(3@Gjmm6yy3n!j!_ z(FY$z`mzFf;IJ=F=yqaav9Gqy3Z(`mbtJC#yr0JHahj(x6$sgzsUGPs)5o>1r>a=s z6bfjtcWWQO61|5!Px3QrjiFQGNo!rqIeT8B-ys#d86v&A&+@L?6;eU?7$zC1!EUEx zmp7cadOW*xksW`f!8d)go3|wFy7aGpv&vbNC9pqKm^LjEs7*#0gXqwjl50g7xG^^} z#bhB4ae4Kb(8V9(v*&M)BQFdcH*cHSPtQ*Jt`tlv&+|Gf1cbIEP>h7TMmSYH(^)06-x6K_; zy0CIPi`s>dGpGb4*V~gdAuK{t9k*FJb1a#pzSryS#OS3CnzM1%oS~&O0AWPfZe@!XE97a8@fP;!kD!^m8(cX)r$m{%b zrjG6*SJlS0UeHqeWMjvHyL77sgCQs(>s1~DD0pqvg=zC$1iy0j^+5tTUeb@9*JQrv zm!sA)D@WILTwnNIEYMHMFA1K8XSkMM5zcjuV?exZ``P0Z`(|xnUsRrgwjs;h)&Z9x z0Tbt=jW`cRTc)jZ={i&U<7@TZ0ShP-tpD+Kix8afOi|hjC*4)8SD53-X_v5ZZ?fS= z9jnG%x57l5hO}H{PhWzCZCwXeRd!RjU-tBd-}cY0TJK(cQI6n`X{U2MI1$;Agae8X z`x&b$AKnRewclHG8UKuQB*P=_a)y&b!%1c|7o;1tixV3(b=oMAh9nF z-kL4$_OL%?=N)~QI3^`2E5E zUsgqoF0z|ZCmK+JqH56Tt29{0_fTF`uK6ZK{rzM8{@`Xd)nMS)^#{uifZ+TR)^2;c z-%a+reQDd9Zs4q{pT9x6fB&^V9vmchmul1=Dk_I-xH~6&F_xdd|Cp_|B(GP1RLJWA$Au8V(`h5HI|9LFtjK0u1SRSc)z0`^3{-scPD@m%xhixwi zQj1yD{2R#mzkmHz+MbbHMHTX9H3vHxjb7yaw||Fe79f4|uOlLa*@+u!kB(bevE zO9zkmec!r$_Pph15AWY()cO5}6|3f39JpsH5XWtJXVqR|;W*x^`Qkes8t`E3QuylQ zSFYaCVEOS}>1L@BCzB4RlDg;fi?h^5&vb}-v;>MC@juaA6d3&~I&Q>ur{&QY%wqR}EA(ZT#`C zzwpP`PpkREFG!r#vO>Q*?qI%Wl-7njbt~DyCoksX9jIw~GSNM{iD1?K(1%~$R|Cdrk2x0o$P%R>pC0UcyncdJ zvFyZTKZ7M|8X6jgx_WwgZm!?6RPuz@DJi5+6#cJl_!A8B=g&`HZF2j!&{@9z|D>l- zW+kfEi^9S}0l9BYj{kaP&epQ;KcM~oho~NVkBZ*em214#Zs0b%1#wKC_Zk%u27zg( z`afyjHCmy~)*y|w$5w{pI5``wloU0~v2MRiS9A>CdB;Ah^$CUh((60hUEZLHWC)Pn z1Ku9|M4OHImX-h4w;*4z)_4g^dBoA0jEsyTPw#vQV2m1%4qrEYVC-o`TpIFaZ6KO( zz|kyLLdsI0g*42$$}TP={nuyv=Id}fw0}1(82}|J2lPypvggZwux&1KM$bxi=KA+6 z%in(U!+(AFa5|R5!W!E8{X1WsRP9Ul3j3c3cY{1>wG!%Mjz3nbq?L>!SxzV!@=P3pV=uq93c1vR&*{p*|j=4<5|D9p}E@v-(;B0k(d0|GLs*!SKwx^oP1?+S@DZmv5L zl=v0B0pW=T0e%^Ws{O1~1WZ}1p?N!4;Id$?J1CM5cjRq*3qP8ryn)B|Ri@F(@D zBDjH1y3=L8pdoCgcjw)>&{zrd{^(}cg~BVEOM-)aJJEMqkBLBc(7lZl;zNLfr^-q= zXL}8T`nf_@Ru)VY4zwR!)uOe0vM1sN z7KxVZ{w^SLADSQvQ3|dS`6Zw!I<@FK%@H##QF!fSZ=Uun@0>f@_U}4 zZdDnjS=mp+lLF3k=T}IKkY-#e2=?d)qdT#HOaj2Eaduy_!Q}Bcns>QyiMoENzEW+^ zO)+PpBb(QuSGKtQ9H!;n&ui(c(l5EdHUMp#J6ddmAW?7-BW8}b?mR7N)6#oy!0~OM z#%*D=cCtI16hiZcL(b3SvsNUP6`Aa)wSGMVdMQt3qG{PGeoo1?YuBofs++&uv3n>T zj5ra-d_k>ywiBGpEOx(OE>mSSs-XqnP5tQ#F5Vl6R~kSCy^`<6n+Lul2WW(@pr=aR zR|@9BX4X@CjKv~Ly=}J7nA)|Rx$sj#eo1(zP_VtzCyComy$|jBu+2&QYEdtu+QDrn z`DC<;STRlOLq5qtkrjQfl?k6|;bjiytTpTN_jEmimhDS#qJ<2iu|3zWj{G$)3C5y# zZA}B@TC{A=5V`T#xF<{F!CU9fo!cGAoYzyZ5snSC6j~*(PdUeHP($psQ&CWc=HHO8 z)Cz#PrsfzifK@qS#;`38`aouR)2^8M%`+|viCER9^!9j1BBpJ?y1cc9H<)Id#rCC4 zuv|i<5Sc_{Wz75aPoxlHa{=G)N>DtAGg)XE%A$iwFu$mr>ltE^-aKmwnPxy|%9jQO4 zVZB$IXT$;H`VK~;>*?snE~2}D=a>Ax_9_o3(WHyP17iE|EWb+{v9po*0hPnJjZ);g zvjZL>rB9o2+U{_4?5_%1wdZCwZuLT_@r$MOJ(qon_(DfBI3N2ObQJnyQ$XAoj0~6} z-(pr_sXoJdg8JiZHBCPAF~l8oBYP8`$sX!<5YOy@7lsG}aqfw{$0oK-8?Z%o53S1_ z+Vc~a^vT4&o0u6%6!0kAVt+fL@0FX#z4(G|_O&%mU!MJ7jpK5=?f^Lk5hLFwS+dbp zwA4sVI$RPOmJ{1Bq_Z&k))dJFeitsOCn1_iLH#xto*RO~9jZK&UdbsRyWS)nAbP0S zY~&>Aib7wY!@dOMD2A5Dw^O(N8Vn*_urc^@Kq0@23@EbB3Wu);arybL9Eb0S>hXC% z8q$i|xvvdCS@R;*3PHAPcH;`7zX%{?nMESrQ%)0KiHV8=^VjNe+Nq*f+K4fATAz>S zrzV5qa45P4V$xD$J5S52!Re5H#=ctUH57>R$C-yU!x1jAjR+))=RI65FXyEW|9U8< z6(0Eo2QLi^u#vw%%5;Bu9cc@qqlu5pgu#uu)A@2}v{z4(+@OWEDtpQ(x}`a&hC~^V zIECFVWRC-1@Sq;AK_M|E%1v;=^wq9(g5J1@yk5#xX>8{si?SFF7II26b&g2C!7|nxx>%R6UXXc=gi*Ngcy(P7&LY+CJ#DS45j zcbAT>UZoVIbDM{?QLqCv7`N&UaD`lOOQO0lO60DPmUuwAw4m0baPPFpODomyqo&LY z{@NQxN!eYTF~(L^kl3sTy-I{Z><|ifBFUMcEg7P;_V0fG?EGDv`#$S!{xU};ZL{mxrG3^|b|!?@6QyDCW^;tOc8r$xDGCYWruOa|$KoG%tbMXjWznB@y1 zODRZB{D!(4lc!IQ&#c5%w{dF|(tje&w-qBy%9gdDo%}OVHz{C~CH3oja$W&#!5EHb zjr(?}0Fnz8y5ON!ry-O(q{qAb0|i<>gNdN6kW&nGTPK#N^PXp`st-38`TM+U9v$kr zE0hA#&mDYX|8C@W3y2gudaXFRO=>NoQs-&`0f9IHtw*cr_*n=dbuDx-!f+G_cBh5c{5lWLA`Mex}swv}3LNSWiz7Tv#e1kFPp7c@vLD+A-76 z5+k;I+6yeeYq7=-ImFCmY4#Ly*&HffiZb-#56aP;9iF6Au)X68NcQ_+g69uWWJ4Ax z6$u%UCW8)v8N2mv8N+&JueuHn4XOrq4}pH-fu#^qofn5X#jMj-*BYXS9pL_nGKg2J zdAlBA#ud@RxBzH?E4GyS$oh#65D_{+0xRH<7uAi>%_+-Gd;&@_`3DEdLz5#>RayC( z{o^x3-P0=qk^FM>$!){kH-ci<|G^D0(|x3w_3wt_!!X~I$G>~6W0y;~dTh{xZ|OAO ztVnvu{IHv%ef|8BbM45eIf@3+E|C?Jdv616wJ2j8gBQAxbgQKVVp|;2EAbZ%+hWJN z`-bv|uYB9=u;BY6&JZ*FPH1N!Z| zW&v;aSU{ z!g1Y=rq8zBfet5+Tu2i;;3pBKyqFoGiMixq-_z`)-2(O**uE)uwu~vKA!p1X$@-dl z=&Lkuza_^?BiJp8JA8X3{_^q53Y`I&(C3baZq*7?$zHFA+423uu&86NBL|^p`jM z?U!wj#ub96oYiWBL%3Z4WTO7v#5xiR9YQ{O7g+&M*103VP!{6!p+j1C05%}G(2Om` z@LYFtk)&D}QNRs385K!}4cX49GF>&)xeYRK4BB(T?!#P%W`VkqKW;(?(s&P;l7((A zmRs0!m7U)ZEaEPNim=$Z02EGqf)0U+3Y7LUF7rvMytNa3X+<#vrQzXN9b4pl%Y5^kl4nn6ayAg z{z@ZnyC4wB?Pe4f)^0>uk6JGH-m_y;d-m`h0r#?exBSh?bg#U8szWuWOLPnPO9-S$Cb)f0r0UqPu zO+^Q?6aB`1&t-4ryjB@UBb#}7CuCEl6gSX_r8H%NN-JR?t6~|cNZ4N^8|Y1l$GD>% zJQI{!5d{}9JK-q8Z2qIa`f5`U<^&n8~>iTOj(i@B}Zm$r!Pm zMY+%c0f>N$-KoI6>E3WG`DPB(pFbzQ+Mjez{>U7bv*JlO(gqQ>%Bld%dr(nN*%!uP z?=ZQAEMq&O#7mL?`t?7)(LRsfb>c3zq*|2IBJ~tjbTFB-LTc3?KlERZ!eOKBz1qte1ewd z&7WV{`}2Rjoj<-2Qq53z^84fKzkBo+C)VG6|M%~S$AsMfPujexucoa(IwCrDU}}cC zrNcjcKIIb(=8F0K8UE(MzrLvApH#;G{S3;D|9gtxuFC&e*J6{PEmh|T|0Z$;-d0GL zHEqRD^&VDH{T}TFfANyvKK9@ItIR$<;-2b(I?<@@dpr)*iC9>bOMuJkjxLevp^Fs#A(sOZM-egB# z@1Or{`V1E6S)0dDx(LHCWO_*{rSgOlCYE%d>b-+TSrZ zn&`pzhdv?n}Dk+TIdS6Y%bn;xFT&UH_Ma-&pJtfjqTt_@Q zGSTz$U8d(vgp?wirbMjq0NUK*5C6N9&32`^AkFI-Cye5sY^bIdkrR%IZlSMWBeHjA zB)_VfnG-$v{+M&}R6C)p z0aWd|nDXY++JFCEEOGh?{RZmi4uVZCX^5uU@#c|A*`?Y9 z@H3TVxey4EcGD(rQnVMXo{#BEiY- z08QWE3mCFvNE?l`(L!U9m5GHyFXKcqhlSfOiL{Pj7%r zh`mqIQMR@-@CM9j$Z-*EM@`QLLecKf%ag0-%dvD*(Nb*9X7MD3aMGyzSGL#nM;jJc(>&9b&k-O%G-Bbop#L`ROr8d6F*=%N>2e3U zAeEm3!!r}9uN8~n8=2;@orb0?#ANkh+GZXYXv{}7>Av=_O}w(sScL*`2WMyZIirZn zkU?8S-htd%T%c>(KyIZUlK$za#dSWghY@SNho#aU{SFu8<%bF|KvKgpu%U+A&P#%? z2GWeO10Na;3gJs|1w}_xf*2Tp=- z&>b;9Y4GD8D z`C$6`32M(LN6_ycdNryCaep}pb(ZORTQ)siWo2cv*Q@ahS~f z=P0`Av!{O9cPt^t6|znc%@Rf7Q{9Y{)(?J3qPEBVQOF3T$q>!7ao0It^%>e7Sg9O0 z(uFPy@_J%Z!R%!*X_b(UWMit-YyjSFv}_Zs0GpT|IAV|0vVhNtoi5#Vzpb9l#IyEP5B%n+)-1XrE^n&+S*{e5^lqqCv0r zrkl(drq1_cPYNKAWcMuz!N^gdT=#5swH|f>)ZzdHdVs@G=V0kQxh|ZVf-Q0LFADPB zeo1X;dY35fgQi-XfT0QhryVl=I16KsS z4he!&IYMq-U|%5D{1G7Gngm6*B<<@5K9TDmsa;iRE;XZa2ms~{)s0AWN*~ti5GcqY zVX@G>0ZYz>-1cUu3)!H>os0U^5GzI~;T`&P?6{vN?`I&F$|Yn?>?eCW5~Ak9j4f~t z%|dm8>F4ZPD$&G*56P z%DI?V0$5WHPM?4^vzBhm$d<^d;+d2TC?mGiUl5!LWR`=sHN+pK2+-sjj$)mIhyd1D zY3gkn63~IaLEsT#fVPoXWQi1_jto^q7$z@o=0NJkRq+7~peqP_GU(CX)EtP^ALAqE zkBUpv^sz5B8QcLWC$HJrdnz|4V9bvS`IQ;L$z8Gn1LpS#A{q;0z@ezwHAn^o^kCG!+aBZ>pN)~|j+gL_ zW52k<`c@dH_@eeS8uX)ULq7ab-MBfG;q_$YN}Xzz`@5ad!9FAyt(90{vCg_7TZ|=L z3|dbe=QwdBXA#vv?wA8^iog;OTrh7QvlHqxQd4g;ox>6Ng=p+LpjB^hgz%S-!z;o| z6+Iw7+lXYk<7C8AmJ}#ucNKl&Lj|HHMXT-7xsQ#IhmyBfKaG)jp$h25_T2=)4@>2a zXId3g-~Z5vJ?W-D)}|hJ`1KvJra{U+Kw@6za0DKF{!i;*xSNB^sopwP52BVeZdxw5 zA)@V9hxcUp*|NTlj-)xWiPc}xz16V{Y`U?^b_4mbj8N-phEDPJeJ23d5{-+k^D#vG znhXT*9jaP!hT91xHGOY$o%{U|@g9ho5hg(%wUou)&p`X+{_QgMI6#bSmd$tI%fsFl z20YfkQS3xV?Y?AxOf(rz6^us)vJ<9ZHXTNATX3fB#bhSZGbSL+rnJ81JMYbZ z80wistCtt+R zys>E@(D&$zo(Q9upNQ^injSH2MljCl&>*FW-kj?6h$!PWZ`{`$Xs6leJOSpp9r?{& z9I$b?D?6ZX=TD4<245Q9=u64WSwQ3AGKwjbczgnOyBEoqRI1XKtu!>~Bi`| zp|vlbnTI%ye~m-xlZ*4`rrtWQkako@CW+Ul=DfkfVPMF<6(J%A~QlIubSU=9CHXwNsn%64Xb<7=o#l1N?zmIRo zmE9pmJxb%cy{vt#RF;m{mwIZkS<^WM3tS&fS+vB(j!ClW>-lZ*!-Y;)vx9HPwM(mF z+o-ccAx&i?3=11k<~pOt6_qrG!-OH`t{U5tZ$~+ddjwf|e8fQz0N1G2)N2A{=2_iI zjvwM2J=7MYy#8*CSw)2Ezb%ID$S7m8-N<-ssypaFz_ba9jT$CDTQ{J*bOU{a*)sw8 zIO@yE`2rfVu~&6C?aKEWqyF#|<~EYc-7mc;*wIpK)jj$Kvh|B3$T4|aL8Y+}6A*XS?>s1rc zaft(}G9q`Q2b@})>f<=>*IGx%%*;<5qjn(Hs&S<*I90+2UtH^bw?BwNAId-x25hWz zskt8`-yb$8oq-R?K5PMZ*Nt7b_Z>-oM}OV>h8PQGNM+#MRX0 z-QwqE-b9sOPd^%zC)DgwyRD9Ui8vWwkn`OoThq+Jz9ebX4^GZ$73_Mopy&2h>z}Dd zLO6$tgVae`Ocaq_Dd{n6RB(AZ?1{v1UmES8Uao-1>nnGvy?!ylI$Cz?DMRZH0s-CD z>1zqrP}@K=#fY@P=(mGSR}N?>q6{JwSsnuST40XhDVPo3H^|8u>x*@A0}dK>JQ!I= zf>`az3YKzo=w&D-BtF3r+y#Kn_@WRZzbN@qRrIR_j!YSi<%UxR3=6ct&ek?6^U_hF zC`Dlw1T-)tuaX-F*uC@Z>WF_@c3ket7|o<*PpU!w#8#7NR>2o3jYKJ+IvCa1D4Mrd zb?iFd$&e?>ZhIsU);M@~+R0_z2X@3{ZAK|fPMd`R^%{^X`1ch<2^M8zBMVNKR=FzG zP|jnTsWuF=_C0}8;?%_A$B)`(BKP|krhRC5|%bE_}YFHkIN>gCYB`qBUuF|-9vy7e~3n_cwTph3UbljoX zb6HJ;0^4CdFV6!XxXWc&&kG5$R?%3z_A?)C*zTMGTI8Mn68mv6(2+B0*R0|@$x-S- zRV~a%1ym@fl|~-HNCIo6K98t6I4SfZAAUS28v|q1fOg*HB}A$gPsGpPyZs)iVL=o! z{T4&~f(J-GK3ZXiN`kE6wserv#VbI7@=yV3-hR@8jw3D9@<)WVkTuqtOa$vL;1!OE zc^e)iAN`PJws83b>us7&Oc`#r&n4ygRPsBAyjJD8?Lq8IZ?DfTKUn!Puwq{F(NGE zS?2NFcKq6rYSE?R{ssTi=Rh;vjh zLz4_fjNmC62dF-eoY=xm<(~HA_kt6d>@f5LTS7a=F_3W%`2uGkQTFd#IKgFCu9zN? z@k2xrH3?KZ(3dBN+gd5AkkzPYk?ixCvcCgXRHo~Vi8jWJe+K@c2L zw*Ti<%U=NRDVfqy4Bj@)w?qwldCBoB$k><+@sJP50*&jAc-kvgmsC)Nh|KV%)GCVG zX^-GxNh25z!`Ftm6f@Kn``54v#q7>M^B54MHOQNJD7pP(ZlOeA(jb7QWK#y0I0kmk zJW9BG;kzojQ|?V45u*tSI<*vJ@ja#X^0_jHiUS65UX;E6%zZEIM4@Do<&286Yn%UvY?{U8oR(S*E_zvHo%LQk698!#?vMwaO?w7hpMV$a7hz=-RY11ns~Uu5Q0(v-OlHXeFIUsZ=p^~?gj@zx zwcgv}941bfxUwBIjjEGN zJ&#jvkFl0>ne#i&#~yllQ?k>ZvZV$tNn26HZQVS!{16ph(%_*y_l*u)gttIeJF9*v@1--VHZIJ09= zC&YRaJV>V{;M<4y3s1lx`10IGT|+w2Ps#wYsMiptkP=3u-SbN}S|ic5r)aZt_-Zzh zqJsR=S{%K8Za}hruz(9OEw47EbO-_s?MaFd?$LBm0-A zEm2}yT?Y!dxYZGAsbV!o*`bQpoHy@<*5xz{@a%*ESKSaXmS>V(W-Cti9YFi#@Vks5 zj^qv4r;q9gtD!;w3A&>NoF?ONLT|e~bIG0fXe_B2qk%XTPJP}pY=M=|aWo@mzIHZX zvL(b>uU?g!L`QWOj)Qy8m~;?8Dom*m=oWIFC-O5YzR#CoN)ix`LO(Ro#N1O$wQij* znRW5B01Hd|xoE5Ui0a`}N1mRpsQimE`H!WW$ZwRm;$BSUX4=GRZ)}h!+(F?G8SOV^ z>-+&whQqgvty*4^!?WCr8gQVY8AmIf^L4o_7%QhAX_aYq_^4gy+)b9HfF0jpYx6&@ zLpHSo;NG1y?n#+)H*Dj}dE^d{QEx)Xu8syjO~h4GUQBeI@Dwz55BVUXz7XTKwF9W@ zrD_G}{o*hhr>4Y^Hm?JLM7>4{6sWtPDzUejSH$^LQhoWyNBf&cs*xdAYr;HLqXcSpAyLIgB_ZcQ4zLmVEK7 z#M-fZnW}*+X#;iPo5fzF2C|QjkH=TLXM`{9vyIU2buB#c=IT=3`oi|ymVE2qUde7e z{knN-V^eL9y^Y)ITjr@FUZ-R5yw+|=#zjWrFZ%yDw+ws>0~d}dvD z?Th;0t0%3RQm?n{c(U03KM%g%Pm=m->F#u^@ooH}!k9UZvi3=z=;4#ajI8mmrgeh@ zr!gH;C7N%tU;7R6&~CrbicT?2Ka;G`6%R-OxN1I6QTlZMCy|<{BF6&rgtP(EJ)=k> zJYXevGP;_&Dn+P!5^H!CM1WN4t(Ez4i^?%!1)&R}-*5Ll5hvfae_Ls8goF2jULD`z zK830M`+LWSo;dK``t5>xm~YF8nUnumWN72{+7mWJGCvGJ#JS|4(7;#&=u^6e(#R_v z1R#THkti7E5=KCnuFLz$>(^&EDtN-lrle2iPKU#~wtcU7T8^8<1T3nL9u+dzWlIV$ zU%Y*!V}nJGhgT=VuCb?Sy`*BXOfYZNm9+7?7m2mjHXTFKsXM%1{N$e^(sy|0iD&)#x4~)XbWF=bNAtmfIZqb*l+>F^dwfae z$PCt5IU1d7`=;AIx8d}KLjpl@DLYQ)HVl-t;paQ&1U)~M+raTbGOAuF==rKq$L_ip zoxGXBcrfzdN+#W?P9^4z>{Qw=P50M!Wxd<451drAmyAo~WxnjPc$;8cH4RHcyPqD` zyV-nj8h>OpI`SB0;f_7|f^*!pj6mBp?m;C^g83Tx}7UM0(4<8 z-}Rj1xIe3HE3JRxDE3-kiJf*Tprh%4UF<_HWy}6L$l5b_CdN z;Qu;4Zk)Kpey?m>%l`31$Jo&Ez9mTwdHDm~X)xnzTCBOAed~ z(pg#1tkvfH)jj)({CM4YKd0u8oX}KBS)z~1Nt9qJEpE@A6naAaQX=K)&>$#{vWeQ z?NtTH^H0}+zQ3trPKwSCKY=h8nSoXbHDdKX9A|d@Py~oFux0$F*$9>3awinf;CTO< zeiRe6X$*Tnc4cwwZ&APBg*}M)lZl!IAn`8wr7*GfH|7`U zzjKLQIY)9;rqeiW_xq!OxHkY3e^h;n`1xu>lntXj;G60|8549-jHJCcfiAD-f}1{* zri^-8oxgtqa}RPAT8W-OI?~dF0wTtXnU)@Ot09s&wI%$!sTqSg^8{6kv;)f@cP4O3 zh34t$V4_asXLAw{0p#2*Y1)ViM#y&L;7>FaJa0cxt>v#1&8xH${^g_3z*T-j$T7gC zLah^+ViaSSj-uB35r8@snki;P(3109UK7h?AnPfph#D~7ra()UdI9AR%FITnnr?vN zut2K{Gbd7j9w%(^nM)(EDL%JqTqV_h%j~AMYTk*K7E8pA&FqN^Jg9^=5OL7o#)C`7 zkXj7w$1&DnHWRXjIJscT(oB%xh@JEXbx>JI6ArpuaHZyg^tCj3K31uB z01G3GB|INCwoQ|cDW3SF9r)Z7Ydn!+3A;6M)xR0B{-0wmMS`)p;8!m~>f|39PvYXp zF`S_4rUr&P8-9i%SG-LWT;);|4Xd{(AX|u9ie$rk|t4P_(+HwQ_nWvtbBKUt&shzC{oEvNo2e^z7vc6bY6WJ9E;(jQq*5ju0sYZD z(Beva!XQGVhP&FZ^(la?jhW+PM^5Px?>4ZWsEZ`neK0n`ZBUj0cX&29#)@05UFbw4 zjgZ*2zTfOigzdYV*hCZmVqqfI{urp0kYx*^mBLm(b)O3i8ZTf?jj>6^sth20F8YAn zOb0Dju-Ys39|D4unBFN zwRlgdA|5;0&SU_G471gc)?re-LC5m}X?a(5Iu1W09C>SOZ>d^>+S?j;8uzpSjxhqj z&}kNL?-?2NI?HVK$Zc`Mo@hC?QQ=2zMd+q-;lsm8-B%79UDcS>=9|4YFviC%62D6d zy{`27F(%|pM;c#w6_Jq1JA*8ELcvBLZ=p-dM_}~W1$;RB=B_R8J>W0!5sb?R28G*u zMlirR2ULOpy@|8};Txu#f!$NSQ7*g{1`2G{bkZUejbjCK2G*nkYH^c4lmF*DkEOv= zJ2qm|nLadU>%Ix39Vp2Xng&j1y6F{Lw(46`V&|u#wQNM>apHaXNPOk~(uY|t`O~L% z0OOGcmDBXv+P9w9YKaG?(t!X^wb5%}kG&^XO{$i=Vrd9Imo+95-y&*_C~GaRg-n4=b2t9?1{eJ`hcbr3+> zRmvNftWFsxuVr7_`jPzHH+Tm^p1l_3@*EKXt}?8=N?V-C+Nr2Ne`7Dkj1ouwFm_C+ z$Ds=zRePN)8BL^nJ-)7zi>jE6YMx2$SQ|&EtJm6MVn^4fS2Xy{6BmX4)7XY? zfKqcQ*+nZ)p(OZTETxJV0;Bn1OfJjUtHjzGSg}&95@EkYJd)}3v=y|*0@w*77rydY z6T~9%olvOpkZF?Xfo>vLP!7$cy}hu!&V6QJ>G))t(o|W-b!pMy;Dvxzh;6rRfcGHbd=$AQ|j>9`b#xZ!Z$5 zoFg!a>a`O&0;;9m=wO~~adk6bJB9N;UPl}6guEv^AR6I{6`FSfvxAwPb!3L|ZC|OF zK*6(dM%Etg|DB~`73(4wL>Z8uYwIeq+`8u*nG)?JNRoC^ID#%L{o{s5z z4oAwLd+aj25i3aac7yYskfu_Ck=0r-Tt=Zqlyy-iEM$y`iT%RbnglGPh*V1F-RI^X z;*lK3I<5?#F1PEHi2K2fm~!kVHZT3rvc{$aW;^9WwKE}C;5C+AYw9L1#=02L&TOJ+ zW3I<^k%WyS`I6TH^vMCnhz!v%_$Fz~h-bMVR}#4-(x9tTLi1%iJ=@Eu5yj=f{hlU- zI&c(Bpt0KYndDGxp0nR@hxDR$_Mi!9*&}kVnB%oB#Z&k}qiyw(eaT3EsaZkG(K(Hb zm#|=jiOrg%KQEhxw8Q1Zd?jni*xM4v`55n45~Yykh$!uJ|HErPj!p)J$hHrbCh+{fC~9mi~AEy`hwUc%R&*fHkgKe`Ab;5~L8J@}?@066GoWBcVfpO(y z)PIKPj``cfkLMq9Li1!zoF&TUMoiqfN^PMS_Eh9Bv84wX4PU`A%7emgpJ7cCr(&}` zfCeVP4#!FWYvTkNSjh20%J-BvjNut@PNb$_a@Wckdj*&r1)yfv5%YS%v3kFADk{ffb z+R`|fvIM7F3B_h!eS`3lkaYs`t{ky@$!T>cEWtBd@D@m71Az|SUiN3;hQ;R~kbmf? zok3v^Pp}ty;s+}hK^W*?6N?6v%#o`j=o#*XUzj!Z=14rTcaGe`L7ZF{sod zn%PwO31lkD>vn~F7jgmpsXWX;O|14e#Th`oZOwM#-XGHpJb3G#<8=&@jqSQljwz)- zzrVAol6!qWDob~GlpJ=e8C||e>eyk$+vUV0bGD{R{@M@ToCYbT73ks+5xeh8UgjfOfUhLV=)Xy7t=iE9RsIWY<#GjS$T* zT@1-}E|`G}iMwf12btPz$Oo0x4ht|gAgba!^c$fwIBcW){9@y8z%-kF1}*xW}Be*@}) zHQ9ui707+GkMS&NrCmUh9JAyxP$Ve~`*%}E5tVjHYAlU0s+tHaGm|9;A&H-oe)Rx? zra$u4b!sPb9)Dw?c{^6FUhb?p&~3i*%2}GkgT(<`aVm=6CWELsDA9i?RqiCc9>o^h zU}_k)l>_z&NEYNW3!uKsejiW+iKcCYHNvz!0OodWs!)s8I!U!iuFPym2z*p=hXeV= zVh)bzO!niyyL5tMtZnMAZ@G4{+~)r1d$?ET`%eIjVV}7d#3UtA2AcJ7Q4+QJtb9 z-w`Am>}CVlG}ekW(U!7gXhV`jY#9Fi6RfARZOl;J-P2=!&uaU;S=x$OXE3d8xd#E9}S<43*4 zI)GKY1MW2@WDa6}tTr+KSJttnK_L}tRB3b(x=0s?C`3frQToourNjtb8inG2mQ{US zdU{}zv8r9?tkHGPU!{v}{yvIz-#mr=^X3$K9q2Y(?z_uS;ZAOnz+Q{Jy%)n)2@B`y z3D3D3uJPSM@rBz2G$t)x7P5NUipR5xoC15k))rly)bX^acGAY+sPu!KZ$~~kkTH&J z|8BIp4;1eA?qp?on!9U@5ltLt4x00ADe|978s?vnr_5-nyBUQLm^2Uf)dNtRs7ef2 zJj7+|(jV{BU;Jr<)7Me?pt|P9+{H(BKlfJn!CMw5If0kcH@E|p(v8#yThu0~5n^Tu zvjCkDOS6gAX@s5uSMHRvd(`&tpGQ%FY#ja5;9s3H%kj(klOR;AD;!%BoszP?<%!&z zUf%|Ae_T*Z8yAp*NYS9s8S|7Q*bXJx%Wa8JC-jeFcaXvx8+&&nN{|ZRgtEGd69dA^ z_!hMw&RxN6^o^WgNwN%)#_gpVindW4^zP;{sjF0y;XlD7fPiY~_EHYWbbJB)VP2+o z4t6yfDa4uFuwn}dj6{WpW--%EH4}tDHa*NF-!K+lROs#y-S? z4;bcomOw?I#Tt-3Z>oL;&S~2=0QXxSvR#XbyD4VssY-ru7BBOT5_1%#QHyjj3N22O z@p$LCE}BbP97Ts%SjuSt!zeZy`*cXQkdJ1NO7@*@k4|oYj62_c!t1Gk>#6NZh_dP6 zQDB%Nb})@K3c%dNI1t^#i;sin0+#)f_$>2aaKiffhfwS{Qc(NPmN@+>Zl~H1^3SoU z14odCo2DGMCriu7QOF&$eM2C&Y8`r14OBS&nS(ZDdjZG>N#Y%lw+3n}YIH^l4Mkb5 z9+Vn#rP+Rx9to$?LuIRoE=B_E_RpdyyFWtHmpJ}ug2dv>Qbf5ocSgTlmUTr}pV=v~ z1IOe<00z90-B@_c^j~$>YPxLmN5JTas*qq^MwII_ou}(vz@}SGUW(dRiSqv%vdP`{ zkhWPD3Fna$dz@Mg`S0R3He`;EWEx?iks8RxtpX=kRCg@23@MQMG=L0A4Tbw3o=55v zN%dtunqJpb70;!jXYe60>#~Bpd;`STuHVgEzih0QyTF!{h)q$~K4H`H5$ByYcol~^ z)uy=kq0fr*OA2h?StZvUH?1#q?2FXT!LM`TqG(1su>D+zBa>Kucfq!yh!c=EK{sxh z)79?v5-j^Ena#$myMRjr#aQdnxQls)SY%zOba$XiieOyN#5nT?tTtClkS3csk;l;H zr>I$#I5y=H53#*^jKw)n@~?^6*KTTlDC z_TjGNQ6d40H`819IuNH_^}lxeF^11Dkw5ZUWpF=2UUI~p{6qV}#}M(aaT3(QrGt$`hZb_=drCB5aE@jC)3`N;aKU%$o0|d0;<#6bMBB!r4_&(4 zy*rn%FLfHVwvhAe8KF~v49nn-AljF2?^Eu_!>Ud5yKYoQA(iEk;vU_dgtEq-68BRMF2AS@JkaEZ{)5_}88lxp^BsSC! z6`wFfzGnKOo2<1ep{_6o^x`3Q#-2cmw)?-XOT<1EpY0E+%CwJbtYQM7bY#J`kv?L5u3U=c%M+|kPtxpv6lW5HwJv;Zk@zkrl zMmo^b5ebicpbBIZ0V$VV>!QP=g{0Y9Ch4Rj#m(cA9eg%R!pv!cQ|pDtIZynNcAF7p zfbx=vh`a4EwBR+~u-isOIgO7uH`5qX^Lgy~T9;owgQBDn)Z-Hz+ySE-SQiqTjT5cc zy~$Q}Z#cM<*T_w?VcQ}DDFt-AJ2*t@a6qkxW3*0*4M_@5qOaMAs@a8FQzS;_%EN)f zOEwwP9ZG-_`CeM11a&?!<${v)7b4;JpoZ>84OEbh9DFh$&Gw2i;cc9=rOQ4SG;f&C za-hBJNqvv1M5Xs)_XtmGsac;mRgH1aBQ3xm{QEx<>bYk2yL7)lYZig`*>!&D=&~de zwEtft-{{TBHOGGN2~e^N&-VQ5zJok{=O-}v>Lw^pM5csPlm&t7O( zvOLP56`f7anvD}BU$f_2be|xmi~>*6NWZir0#!n=lXwRMg8wm{I(pM z=u(7lLyAkX;9j56iROo%jc1R(%eAa&O)^NBCpw7MRz{GiIa2@VVk7ehspdL)TK_8nUYXfEnj+q2oVx7Pwnk477IHf z!$4p1BEwUpf@b27)j{Ean8tG)oFsS!$9^f({T(AA42bToi0TrsMoi-bZt_p(Z$$vR z#}~Eat{{vJK=^B-?3P*g1x~-wE8;$HHU%<)J$Re zWnMvA3+j_1%`~e;Jx+G8MI~rr&L>!$x~Lo=w&x^F@b1oDRn>S_^Bs$XEjm$}Pr@En znAJZS(~2bx9;I<)x7+~a-5vT?lRkf#>yCDu$SkZ0nCN=mfveWp=vp%C?My84m+#slhI=_Yar=5`L<^m~Y*Nz}dP-fFdTK-)PSb^IHI_iu_H+&=$ zX>JZFh5GjtyWl9#gX(rRtXd8aFM2RNUqep0AH7;pyWdDlsv;YI`78`nL>ZJVNcT4cr1z24NI2 zNIvb7)-K7Y!_|D`1pZgh73M$^NODmXzYDUlzMr0>J``abtoJff=F0!NYI7-Sy0t7_FJP3kFkZb@HBsYSR%^4E{lEg>`mE4G6 zAP6l%B}Ww+L<9r`B;V(4Kfhb&{4=}1Q|HuQ_tYJ!8XSaX_ugy0>kUtUuxQB)Oo4wk z9YT4V4yNxc8ho=esThB2WP{OqCJo9vF$|*(jZ#sMnnr4BB$`i41dz^2PJI|%XrX~m z1~Imf88gXIENH>(E~|8Bq;9^xb`#2GYxsm;0e%HDuReUa_30n%w{UI*a-Uuf7M_$`Cw+28&-x=mAq?LTsl-E!RE zZ;&Jj(A&c7(_TY)Cs zbgmtxB|Qjwf%IOC5Ub640Q0^`s`k`1oNbhQrM`~I(dlRobW-;$@%d%c5RJQniNBkK z@kcF*X_45$s_E3iZY$V0;r`zE`u(^a%dCk073C6qafrjv3BOAfa&OD&qc<_QPG2t7@7M%AT@rpi%YhfbNr^w1H;p zS~LxeEb?e5PFTP)ID1CVLEXB6q};)YqX*4~c4?^p{QjhW)DGxn*L5z2iMdr|Hop-P0I{ekGn z0#HHP=u_!j#wi*7vR6k+r?VN~>cXqYbV0-wTZt|8?xkH7PXHftAwQkhPwBU{6 z!4tR%HL71UMUE9|&PYh1L6y(xu@4;3&LBUteRfhP8^5LjaO^r$E@giy>kr2XXhvKU z{Nv^?+iNgiQA6MO>l2lqFP6BdUh7Kh=Pr9YvEdD2J-3zl%r|w!EL_JvyTKk2BR6~v z{6+4l1j>F_4nMuI;RAd=at`{RT+NWZD43vLcz(aYIRWDbfw|CHX)3t(LD@wX2boV8S%@K!EL*I=xBC=rGjsq@UW* z$4jsOj4@yS;`H9L^Dey+GkO9JYFQ)$@v?sGbx1pArH{A0D~edb+98@rA~gVRNrk*L^BrBBf!78l|!WQq16M86tP&k!PhnAiMSq__X*79^B!Zq>da$|q>~x!0RY9t4e8 zvnzQ1^3`QNlpd)c2H^jGmTT^pCYQ(Wj*oq#P*X&z*^sqwKYz9u6h!xjNJI<^^0g1U3Q?HCi!p-nP8cP7Jv zEXKSA`847*ahSI3eea$+iHZmc(?+;ER6uQpd}=L00ADy@+^f5w!w*AXEys$#|@@KMpD$&FH_F~T9L>#dmK zzMQ$~NjY-b-)OvHVYO}K`CTS8?c08STH>g&cI)U3Zs zW_z&6Sd`lRr1k#XXy8b~uFt#iORl%pjvWuPD=G`5ME70nBuNZPVRZHuQ@0R@;wF1d zWErF%t5qeqOaC{lFh~E%+{3ub2ZnE@Gs8SyQN9F$lXD#qsX~cJhGbA6{5-1umFLf& z{{R5rIRfEfkzF0}(>lzg3A>s}wR7=RCu(M6r9@w!mxKpx?4>mFS^dFWdEBO4(bYIc zBl@wbwwQ#YLZeQ%Ev9t`J^^1abENR09fYh@GZ4nCLudVKk`X3#0ZsYKSRz_IH}uZe zbyP&`dZ6rxDHgBgAHP`mdBDlbB0~ zOiK+KIa}=Q0Y%>L)z{rR2hu3jp*vdNAeFIeAPc_NEmBqWtrqq zgPK@8QD16#1)w384uJtg_0St9ip>SWL8$w@>cnjAA_;k^33q~*<<#90xEM$JS_~Q2 zc{#7~m?@bfnjg3(QNMMu&;#V>gvB<=0ddQH;g?>hQM^3pj9go$km=%OaPikGi1DI% zQ_itn_QWYAJqXLOfA&%8b_YI+l$>R{N$A5*Qy!z;9E-!W7`$46fDRo)5eTbcnK--d znsU{(1xg>VGgLN4Mck!q*5mo}p-NfG4+z4`vLsNC4tK)3{^bp+MUoet?5?I9zJKDn zXTfL6D9P=DQjk?7ORJKRRC4#DbRE$trs_aOj1|TKH*Y6fa!nr^N=P*xY zh=&=}uOO^)Ob%6wDg(smIc*hdrh>8m*Vy=SoT4)bTR@gmOLn;C=1VhNx5jYXZ9O(> zEosy?cUhf^KkF(rL1EUnxj51t7Iit2d4Nt$N0H^*jwb$8blKwey2=75*9rD_lJw}3FE4acG8qqn~g6>0_|()Go7 zL$c#m&xWEBh3!V|`@0oOZOstuJ%ChO6d^wP58?`uQ?9v(kHrx9UFV5(j2^&BvOt8?}d!8!ix7$-JM5wrfW7jvCa@DG# z`A6Bwe^$RG475;H8b;q{zjqxZY!HyH;jfmrfV7wew98~_aT31zHS|+FX8U~3FF2UZ z?nF^GOR$)E_MV~V|NFA@?W>jw6e&(hmW46VS9?UOEjZ%dOsuaUOh#&(j?_B8h z%&~5SAE6bL0TrS-m=t;d2$%)?c(G&=N_JRV!r+1`( zLSbR;R3S=eF2lm~UY{3X+MGUn7Btmqi_9%keA-UuH!AaO6&3)W6IUdYaGr@el@NPDpS}Sa|t;v}1 z^Ky}lWp2OG-VIL0Kpm~l_&hhn)bnsd%7pb$;9F@$(?gRKoG}y4LbbfA6UEzkY`B1mQHNn-c~wq$IZ)2oPU3jaFi#Q$ak;(Hv%Z*NDfV>`cS^TQvrGUm*TJ1ap5q0u_30z$& zKYAsJ27f?Hq;wBjQ-I#Lpt;1;+Nbsfp(M~ooq=Zc;$4s#yBYAy+&K`(Q^V4;Pp||? zLLWdKQe1&i-mVJNdv9+w68;>|`|9a!4^$`p5^yp8(cU*rZxEh&?S!64DU$J9tBXaW zF*4f?6@t^4 z=lhd7D29pCAUt*!0#*0kM`rij2)L^#z>+6=_&9(TILmmwWAr*g-lr%oYNh#ioyhs4ox6T|`RDQTo;zCVGy^38okt2_u%H%%pNKbEW#!cHz%ifXqG}YelAMpAO9|{R zqe+ND_4kpaMij|-M7SVBasIoDpp)$Te|6SMxEhT91Rex zub#s24IoLf=(U*s{9iPHP1u7B$h^qw`t>>!ae;>mbg+z6YM3wqb(k(&JR38%Wbo_* z?MHtsv-|0&n4+z%Ex(@gu8*oW+38IJ#XUE=))uJQ4ZsCiqas9-j*_rHNE9y_hQ`VLEa1=FMu_i`<0; za$*2JTqG{eV^^c8QG$+i>H!SWn%^;OAB#VZaUPyp0?j{6$I_v!I(xx_1-`xWm$Hz6 zHI5Z1jcYBdV9goh79&uKXoM1rcb;1&^K*O9gK#9#)^Y-VXxf`G>cLz`DH84KZ zKA19PN}cmIhKtaHpW8z(#piRI3d1~8>CD8tClKe?Gy#ROnn36{|Lo0h_e6c^O)Qvu z4Y|7~06rn}GgU z-Ft;{OwwN`?mWq+LcDz<-~;D?cHTlY?bj$jIY(9sIvZr!mjUg(yY@}R#MUACf#M*utBFpOM1+HP@9e`cFr-G)YmApj=OC{l2#79fFp&*qCi+l% z`~ByS>LFS%364u;kiHg;s$qGM{3^(r{N|pI7D>mTeHuoWH6LxmSwa7P7=QJb(nF^N zAC41!4f`IFc{qpGt-}-G22jdpf)gN24q~k8LG)ayn}9Ca;mB1tq}u?{fNwSmOAla0 zHam);)yfkgL}x1{?;&^7$}`5|*#QIy6uKMEN3iR>y2i1JJI6a=C^1ggP#vIiBlLjK z=+Y(06M{vpfRH%r%m|VwyM#utcB+eGa5OqL0PQ~@7!`R+wV_-ke?`w8qG9n^g1~2q zju~smX;L|UOBIwcV2cK?Y6iVZLqh)=ZIK%Q3d(As5b2FYhg%l?mpK`rrA?=yO?(A& zo+;{msO;dU3GUxs=C<+LlsD z15kv?z;g2!R3=-*Ok%BpkwFFs8RUvp z_upsUU(m;*?kp;Zm`|8-bsr&h?hQU@Z3_?db=SO;)?_o3X;_{ba>qDD%BVwmUMTLn z9-}EudVn(4Ahel2Sr-H)YC_yWy6`dxea}MGL-J(%W&xH#0$o5-c#ClskCHKq1@B6^ zr%+whW6r?GtxXn$={O{Q|HTb*vXMw)C-c$z6I6Z2l3aypC~1?d^j37 z6R0H-y`RLfBik|BRC{kkEYOGm^ILY%W8Me!6z4i5LZ?t$TebowVsb#)1uUkqL|av> z+v<=<#Q|?g{Y;F{hRd0Y=kE(#FL983S%_&geGrtzFl5ySz}WJyU%*5Z9+0otL(ojQ zra2qWUAAJpkd(y}*OCzDSrQAL2%w@<+_YY!yQQ&Gi!4lQ0dvUflV>RO1O#@-{35<< z9zl^}a-dePjoMP0T{nsL|9Il_yq;~ys5Hm=2!#utZ+xl%u@WuH3eV8!S*)zxQP`S-sNtQWgh>{R( zmvbcSB;A4&uCOiojV2d38f2*xN!UW)W)djUw8Ejst}n$v2OCI*;KAycVyBpv$2B@- zg<&#E5?K01Q8J0f0WK}-jxbO9PD^jueGKK$bdeCqsglB_gsYvU0sptK?SW15&!4>RWuLL%-Jf&fL2N(!u_c zQ=#k|(bgZgw|H;WR_!zK&6EIV{fpsg+?*UPnC{=1y+;AL}mt4IyI zWnQIFRFJbaJpkVOaCi{jdDdWN!|WtEbH(+q`tx_Hi;mXIvloge*(d580p&rv4E_NIQYPz?+ZIcU`CwFr7@G zf=Q2e3ufweV=jt|it0wtxH6~Xw`H)e$$#A9WA4m9C|FR61|r6?#HDLJ+K zHv~o@oihUyzK5p&DON>_HDs2@;KK3S@pcd^%j0U)F2j6`c&|NWNJ&{a+EJr^_KCQP z1(AUYh{P=eGhZTQN48^S#cBDI zWvCZA|XV{8eIDB^Ll{y;^X znWrX1IJ%(6HFrY8L0p4 zTGjzN5!sHcC{4>B1@?jAYk=X&BItR?bn;<0&ue-E09|L7K@f#UJH05X?*MXJS)uhG zrHoYE)4X5ZkQ6zAHkRq0189vF8+;X$gf-9zi^-uCt5PvUoDj&0z9iV}9B8l%#piVq zr5*x8tJNWHa46YBpCpf)0_{@&gDl)n1}Az<4ps0f18~`zL8)7?K2j+_W5i>dftj2| zN!9fr;CyZ@-}`(-RuZ&Ipll7NGpv#Wfz3^r89`-Ar&TJa9a}5&%G`}Bxj=J#gKCG?ER zN&2~1K=Y_CvS?|4zMdWQ53`0()1Sywo*3X2=%CUQz(&0UM<%eKPo1(FLDw(0f&`(n z*mx*Z5qT%J9DYnoNdW#E+7baM{KGKM5~>U$_I{wV8SdISq7>-d&N)X+d;(D)5|1Dp zJ#@9h`RHnk8m>p@KyiVE&-UxTObP;DNyi>PdJ*;0I#325^Q2kPBch%_q!isD05}$2 zf?LeEODh0m0*&ciEwX5GDTdlMkd7IowvF^E=TkRP)^CD*A~8#L8bPYaSd1Vzk-a3g z2&Z*HhzDOpdtj+>#Mj0fpOwDb00mIrDSRm*ClLota!^@aAYY~L(1T4pP=)a6|Fw9y z8S#+ofU-XLeVUIxOOX^(qx7&*V0*<1bOoAMkmO_zH5H46tQZeRK{6jF8!w)0_Yrh9 z8Y7lcgM>6CxMLQol#{+;8<IhOb7mMzQ&N#JQ3#X5C|Cbj_I{#d_K8ujQ z;a5%y@7ny%R+EoIk8$9sgB* z`)C|L*8Wa@$^d`zrQF-|Q#dI6=OVtZtE2ziiGOXdf9}MONb}E~_~%aixC1{v|Fb6k zxf4I`z>m-Wtcic_#E(1hIXbOl-qB#TCJU1TM)Sx2XAYJL+0@qQJSl^754w9gKt9f2A|*EsLT zb^PULg*Bt}ZvqWK5;|=p*9ofUjwfm1;o+}cEh>{%z{^|MI;Cw(CAh6+t{?!C^YMy2 z*`~N<}7p(MEzMHry zx5IPrn%e}ra_Q_Q6ukFbxIbRxFF!vVI0$q(sW9k6O7S%YOQhCAnl?p0WqXWPvocjG zJnYsoU>v|3kYRrHt-*b;;WLx)1k}=+m)i88)V|#6+UiV|aT12+`@jdZKYnfUxKoR* zv%NRmu*;fXTa8(EnImyE${ZPIlLF0hHa(#Bc+Ba4H}Vl`$P8SC`xaRBNPUx@b~3=i zWAv_Q$dyOUmF$aJYq;_<(c#J*4cvOTWsZCn!*Uy5lN+?2bTp5qo0yn5KFd1SyTRLk zW_V?(-N8$mtB%O{mcZVG^I6Uv)+AOPt;`pDh4rqT)Hop>P-9WRa-Eya?l!j~u@T7H zeS71RIt5r3j+>acc=ULc=qHw8t$wW{&EON7G%&Fj1Oz04p8u(q`>@upIiPZI6EUpO z;kkr0xBBt8*>ch}z$8snsYC39oSYnNiy|vfxu&eCdz(@1W zVOEm>#wx%_Y+CiR^5!aFS4e z*P`nfb@R+alfPWcKfY)xGyH1I{C7!sA=@I&T^T6YdGuzmrb2X{dpEs>T7$*Y4!T@m zZ2lBpbVu;E@;ORJkia)@&I=UYUGeWdF^iV8#u44m`hV*c`T zfyyu+&);i@dLIm(r`A$8c-ABU5VsIh6_T@Gv?h%REnVo!#Dy?Wity^qx_f7yShzlu zG^dIQc0(f8yealg277V*V4V4IvtP@nKKC{sxr|AnK|mmP>$T;7`96Mp@ro?JcETqx z+J1cZUw#hbCk%KmdU-jUz#Bl}OvFqZYw|bZ9uoom5juGxYbF2kg@1hU){~LqX~h19 z>~aQznSN^@aUY4#OKM69-ztB6=U;w4Dm6Wc=tWsjA87hKN8aTKxsOE04xtJ3@}|0> z;cQJ!P3Ry)OevF`)p?3FSkUI)j?8bodA^M!zzA(*lz2X>E#@P=$3Ni>lz_1(zG zr4`YwDFL9tCqd7{2rh>-cC@VZWqw@`&52Q!7|rMnB;yovQgZ3=uZgtl2fKJ5f=}5k zu5pB;N^^&2H;2QiMOd(WwuH|H(0@lR1rfU&He8oP<1!>AQB2ueDnTAquz|Af)y#hz&YF0vzCzgSbYIUQMqSB@2%qK=^=Kx+%}v zywL~Etsnp6P5FE!5QrXyUA)ECzpK}#KsEO7&hbuCLT;>e6gnv6O#gBG5#b@V09{tWfus& z4ES?{uV)F8yRhzlbpIoJOEWKyWPBNmtYaLs$D`Z=PcABPafP;%Mj~LZGciz74D7%o z)wNCoeJJd(J1#MSmC5*GPp7F(k17RC&)~rBg`U|X#7Xj<7(@hoCDHVB)>ZqOwBz6#>8{K?>fdSDj5H>4}tZ9 z{jI{sE2^Xxk5`T^Q!#{KO9l;@WL-(X2uNCuR%vqIl?qzJ{BkNk`%I=`O+PStm!3a= z9vU8=GuAK<)^UBF&7_qBRrZpKd_dDx0Smw;AJ?@4%WyhQy}$v``Obqtyt<;2F+5RV4w$}T-zL(5e`H&m ziMi{9eL&Js4ovWAh#lKqXjq4sFSe2ycX~^Bq<8}^aXcyDd}ii_#<>nRV}3OOzGBe- z2eO$Z7ajHh(f0_rywK3l(r~xl?$)&2dgfFvuJ$PxTa)nSwGjTe4AF8)k___l^3toa zUg%l&>FIvP1+oWK=wQ(UH$gIrMv1(?0!fJ(BWYJapw#eZAB4{jura%UXuNcpv5aT7 zh3DXKCSf+XVkehxdPmS=VN7RDPt4`$O}>#5wZWgyqL`H=hmkA!{Inmxnz(QeGab;> zRoC@hJ3`m40o{U?jPE^8HA>co4K*ne%JEeWe)f=Cx0dlIZdsZa9pgaU()!C2zxAAP zr&cgW2Fr~RDho(csw5z^^deVSJBo-tPbIl{X#oV}!etHIvI`@W9iJp`V z8}~A=FWZgr&D?6Hh(LY16Rliy3dZi^ciXgtlTyHDa5~}bc?F;vxW*8$mrQv{xcM%i zjRfF?Ao!mq%n7B!nqT$NH3?sBA=A^lY^Z%%+lAfzf5fvHZ-_vJ%KA7e=OU0mE^Ro} zTD_LcDzEQnQ0vAGu-J8sLo6Czco0gFLxT?0iL#|3MFeOROwBS~$b=ttEla$g2 zOEKfz_N*C;P439`D!anngpAb973fi;&QC>)^O>VjsnyRu`O>u)zm=DyY6&L?ELyVU zf_q=0yOKTsOAJT?D`g*|Bq~Yeg`NYla6~5I={v|+o5@j|;ZMcJcPwmTGDtcH6Ncr> z4mrYco}T8nZugY*JjMfv%KUCk z_YcoyKGOuAdh=5)`M(2zQYt^p=dw)wjT`V8iyNLT2RxHMpSyU=Kxu(ZPguy!^Du2$ zc?n8@pPPyo`R-boW_**Zgv#GC-rb`PVqQP|%-ig%yl~kO9^4tV-`dB`NC9~*aYd29DFibG%Ffc?12%Hy zJdx{9g<)mQV0?w$+}g}1j$^tZGtEYSRi$*|veD~P;T^z>6#XyO^>3WTdO3FmtL|kf zID1AgW+$U2u}if5Nf`wAJP~T`V}vqo9|TPvfu)er_R0TD0dteQ6s4)BLhbz0r2Su5 zuJ1XD(j@FSb=85qS8LKxkUv5c&4e7&bi(;3pgy2uhRPWpcC*><;E1ISnU$4&6&K*p zP78%RvC3NYK;eq5sX(Dk-dl-{+B8~98SHIp!`vVPXlEXcl@#9K2t5Z{Y;^_Lzvey+DzY|O3?xHho?(r{aq zc%A_$g8H8~1VPT0oaGh<#=@l`38Yk>kT`tmVyca<{a!}{rMAmM-!4CrY=Mq8P1r~z zv@^8^sAWo{$nl9NzsuxQlnj|v+XMtEwyeMRjtgydj09F+-`I0 zir#OPgXBK~qLN}G*wTd8`w2N>vl*o?t_Pxf?Kwc@-?{_)WWjtGC3fSnEmI$^4l*Z(~7;< zh!SBU1?3O05LzA)nN*_dz_gb1??G%jv_J79!s9^5gMaXz4HcZ z4vLWb7txUKX8M8JYFNs`&_Njj3Wj(^0MxN{JSeoII&`v_pr5m_qFJt5YcTMFib zZV{h1g=VH5X;**lBBC$`k2l5%8OHA4-u0yXJ!ktky=Ygf+z#ZDS<)S^RvEz`jOM7O z+k3m3g@%nBUs*o@oN+wSc|LW~Rw7(0u`7fV$(#&~#+h{dK|(dk$$iod7et55qdyIk zT9b!qSj;+(A2AE0A+h&q)?>6P)3GLJ@Y-+>8}*+ehngXQ(!8$ zPpVL6MuWGWl^NWnb4|c`BROfU#5Hi`fn877WMzHz_EpjtFGN((ULP^nT9KuUnXi2x zLT?08bna@dg5j(wIJ#bu5rr7BoTl#wI3T=fC#NF8xtIj83~XlQ5{H&o7yW+s5wt53I7z)HI)yhiFV z*X8T$t;AF%#JZFMJ1$NF;@&sL9c%&n0xh&vBYvHJr3ynSpHKaIo|rZ)e=rc(>Jp;X z01Wz4nkA9cTx>Hm5HbKc_zg!a>j{|l-)hT(6!X9zo&;`zWubObxi2!)psFV4+DZYzYxgu-UWYC@T zh%W&`xVx}hRCagtU*2VYJittU9o#R=1%5UAL;Tt#pF-rmaf)o zgd)L4LuZ7?M@SOriOPZILp_O7xLT07X#R***4fak=qShbwSMD5Pq&1&BoTF;x<30R zx^r{9$}G(@!(ID9-P-wN;osdT-q-zno^qwEfN!ydmuDskA`tUr67|Q7(2WW#sRjkx zPeKdFHYrH(`unalahR;4?;L<_y9soE&&=?(;2KLjXuP1Ee8_C6UP7c|L*e)<;>(uh zTj^cvuN*tJY0x%0H1sTr>@Amf!%mS}85KSOL0{ia$<{wOByLq6w^($^5}~Ry=IwUv zj~ntmozojCIRgWAt@=%)%M1A)ia0=XjKL94x=S_+pN7EhpJG^y2fJm}I-9AE#%#d&D;m4RTu7Ox~g(gzzyzd@y`Z7+SCPTbvH5!!G`}PJ5H~n-zIDxi+hI`cx_YHa&rbz{Yn`{0`J@(p zWKXfEoNh2xEIiizMa$#WVV6vVUoY=`(i^7J+i`Dyf}}~XRqBf%3hoP-(EXkRWEqFx$y1r5t$!m-v&)o zQCJGgz5M0(rExQe4oLSgvO;r%yEs7KjSslQ^@kknRM5^KRP zEsvp(cr~MMLqRj^i6gq>j6GJJCRX1gtigDxoo5Ezi?{sOkAs}%2MH-i<^RM8UTgkn zZI$EK(@=F4D~`>VK@hLKrX+rj2GT@hA3Jqvs9S5ux&gCU5KbT+4++tLB!r6Hivo@m zg=>!MVvA*!=?96qZf6Wc5)Y2=ZwXq+vj#^RX}R2j9ZX~_G7=;9bbFWTjpcKp&{!DS zHglDVo@~f{Cd*<0fjt%3nBr<$z8Ey!OI6G1WhMP9;Pv3{0k4MOyhjjWcOtG|QM12Q z@?w&7U+7VSRj3Ws1N%PYTW1M2)q2CY25>!YikG(BIP2Q8&9yrkmxyu4he&?DKL{Q1_!aYt4_iu`Yl4T)ngN z?E4bA;*V~k;eSYJa`P8V)_ncwmTg0RosR@+;hrq4#=6$G|GD&6^*UyegSl zvyg0;ltRH{(H}= zZdJTko3$NQdAv!yN%yFH)q@=RDBj}ne#rgc4fnJLosGi9Yc~jM32S*|$ZilWF8@=w zYe)y1^>LvAV`n{MOpAgW^Vq@CaJlUrNayR#3WFYZwU7#|*efOxsDYAUv zzAc~2n?sk^&gFEJgZ~-Uodn~)y7(ICelHRev-~QJVO@=dyFZ*4r|q`*Dvig$$%|TH z6ko@u*mC(rJaHK5$s0PC7#xo3P9kRxFnV>WC~G0&_Ul^kVOKdeKX7d}A2*v+(yhBH za~+ZQ#n^FXpo0C3k|S(4bNx@rq);O8H{ad{4PH;QM)@#qwmYB;+<5ZF+v2ebXpEFS z4VbM-gJvltH;AuZz%YGRB4Gk7=6F!2A~#PaiqAdo8KrMkORaw5MjBQ@jC`XDoYSno zd;{WZjkB`Kq~a7{cD8t^za`0d!WN#$A`zcF6h66KYD9@zurJo}UmJ3t zUtKcKhV4b&byx-8Q*0m?trfN((oE<7efh0tcH~tK_@|ZqWAqH1^N?!Hlxx5i zvs3n6c|W-d#@5t;Nt8|_;U_heLscrhH(>5{B1^>X8%%&a1J(1$^0Sn(>ot7)ExG8| zFCkBiER0lRo;`!Cw@sv8V)Qek18^gv6M!teX*Bu79ku?2p#C}$y;(~}o3#LWX5R;M zinC6>k0CQe4TWr~lKgw4AY;DzAXs zAm_V4B^B%zA>redJ4+a6`wAT|HHwr!FOZ~(BVhxJn!zq6GA;>bVQbGO{3cwCsB(fQ z(!IPM%F%AF159L#NB65$`RRa)`Al;O$TsF_O^sOaKqqz~WpAXawWc+Fvg$>6UoBb_ zlvx^QrXFzUjUuVi)i>9W0vkpSuOW1=4SbtJq+i;3;WZ8yN$3m}*y~VRR4;yS5iC30 zPNS+ihqEo@U-Z@QA#B{gLzsKqb>{~UOt0FW&J8O0qxSDk{I~;l>aVoLEUv1V#^C%r zf+rMP;Z5~yu(IzYG!o5sKJ7qTW;(4LdjZ=?N91r{K5GT7%9mS3niC7rp2;E!dr~sX zBAo4~0rGtSJ|VK&?%MKtOblZc_j34!I}7LGxdkG-pF+j0mRQDUJW71}M%xd}{(Uf1 zDT`XXmm@=dBvMsOCKAy zOhyM&SvzK^FJ%qglAuwRrny;r@=e=7C%E@%7!UQk%$+ky^c& zUcHd&GxYKD%0Rc8EHA03Hr{ylFaX}vP9uJF!hLjCmeC5BoHi945_P>+ntjO|QjP zYE5#eoOCRU?_&zV`2|)7S*x}IV3>tzSJT>s(~|U2uR%#}{gW)?mA<7&*!=CI|K{qx ze^~(|M>>W`m(Lb(x=lJdI#SB)+rM-D9%Ok4O?!~izU@g??#;Dppng~#*}**DovAg^ z@+JB#wV`(}ohQ#(Uh73q1?V#C&YlwYfs)T{ot9({RP~{Rc_tY54C4rk9)jzW3c@l| z8MRe%?76h^2*GUs+}G0%ht18YDU%rA;H~Wdx!ryVFAE3a`d35?$5m=iGdQHy*(RA! z;7lV7JStqO|Mo?OIMsmyWtv5f0)uJ6v6J_8{c^Hkbm*~%t4>|{{oEhRFKYhr*mS*s ztuv;tb@|sm@0-Oy)+~{HyR*%t7eScbrp!gPc1*~T@HNhdT z*ge)#5C`Smz%9(&heMB_a^WbGMQEU@3HqWk)zWfo8R-70_gB>n78@EmT7cr46zcD+k@~&>3t)nF#*M=fDp*EDUtA5l4YCCydgH5hp7Es!}R-wRxPw~MEAB0F@6eE z>Pn22j$iXEp`(fya-!1)d(T%?;(^}*p&_Gd8~IiqY*@nhE(MZZ-nC=2H3v;d)owr& zo|{j)-cM5wa$-$L&Mhx5Cv2W)>k|l;RLJaOe6?E@!^P83?B}K)e!Y2GJi7{1nJL2p zl%jNEgL5sJ*L{_Qjbl$cH)B9wd{^b1H4YXe=W1zn7!I)8XOoR}c_niPt6)2DQ<2(g zT6ql}W?$N&d!Gj zNa&jnPGkJ(kEf4u0Owu2WZH&nK1+4p)JyFKp@=HT6)EgOD05a+^7-|{;5_!?s*jl7 zR20&t>i%fxZ{0k=xVQuYL&AsobfZY#U-K9nMz_jv(i;+9+AQv4-addJm{`Q`rh_as zIq2Ia5)i9W-Egg=$ED5wU-n_UDvOaL3IT7b0bIjev1#R^rPxwNND+i>n4Cedg?+~B ztI%v<+*a{L;|vCo49yG)U~Q8_H+lQbKGFtKkqSafkp`N{P?g-pJb9+v^3s4Or&ds3g3S7e)T|h4xe&yfgL}aWZmi zbTiw-GW*CfD`15^cfP-ub1M11rH9aJaT-gHPvsL|IU~ed0X1!dXLA1b)1uRkUsrnJ zsU%o!J}aT}TmL=Rzr6zbhu_y|&PfU&SE~=G01mDAovp!&3|n6Rrh8_IV)>%D&a!+r zDVlIQd}C&-2pC`@JbKGuPrm!?d0Q_n^-c_lI*wu}9ipa1;zo?Qra&^NN`H*jLn`BN z5pTP_$7NU&vZOYhHk@0RQ>;nFWR8q;V3`(3^pb8W={f>UJpoF{|1bKM|WF${RwUw_SGYIC( zuK3rRh2inkM%I~RrF;ar`I`Znz(ICrDhctBj}>SIccP=k$LW$MU9HiaKJDTc%%^;^ z`a9M$#FYRyvW_(At%)_&t7{5b6fS*9fD}DkYEBUFEybORZCexqa?c!e#N7F+j zST$%idj4}hU^I0OnP*4^ZdG~ZesP}*fSxBdNi#;GqgKjS3tob8DL_Pk;3C_lG^B9F)5&O_AzGY zp~C73-#NEv512fAX*pVp`8kL0DjF$H0X)N%AKGKBCa62mVKjo|;Z+XTFY4_ZXXZCh zvIEFLa@jh4`m}_GOi+H}^tj4z%+cajQ|PCsTx5TbvujU1Nag!3xiz zeH5SPGbbqpHtPFNc#p)0pA;#1hJcXV+b^+!@p^Anj1=!~DzT0*QY>XnO5r_ajFJ7a zlNf*OXqV<>&B*BJ=%k>NOQ(?-`g11p7?5s+!tfSV-P%3X)H_P%)_3$s93d-J-%HHN z-pBRFIEZ@}fesB>&p9{WLZ)mt#%0ADnR6+pZSPngz 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�g3ir!M(mVPTXlSqQccqFdbOk%lEulP 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­IF@a)Ab)bo$omEul?IX?`! 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 z%0D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

p0+OwP}nRM+Puo1 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 s#h+K=&od#s0>ZC - test.run(args["preset"], args["validate"], args["repeat"], args["timeout"]) - ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/test.py", line 63, in run - bdata = self.bench.get_data(preset) - File "/localdisk/work/antonvol/code/npbench/npbench/infrastructure/benchmark.py", line 62, in get_data - exec(init_str, data) - ~~~~^^^^^^^^^^^^^^^^ - File "", line 1, in - File "/localdisk/work/antonvol/code/npbench/npbench/benchmarks/spmv/spmv.py", line 12, in initialize - from scipy.sparse import random -ModuleNotFoundError: No module named 'scipy' -ERROR: spmv failed with exit code 1 -Completed at: Thu Mar 26 10:11:28 AM PDT 2026 -====================================== - - -====================================== -Benchmark: stockham_fft (47/53) -Started at: Thu Mar 26 10:11:28 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with stockham_fft on the L dataset ***** -NumPy - default - first/validation: 962ms -NumPy - default - median: 972ms -SUCCESS: stockham_fft completed -Completed at: Thu Mar 26 10:11:42 AM PDT 2026 -====================================== - - -====================================== -Benchmark: symm (48/53) -Started at: Thu Mar 26 10:11:42 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with symm on the L dataset ***** -NumPy - default - first/validation: 453ms -NumPy - default - median: 444ms -SUCCESS: symm completed -Completed at: Thu Mar 26 10:11:48 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syr2k (49/53) -Started at: Thu Mar 26 10:11:48 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syr2k on the L dataset ***** -NumPy - default - first/validation: 478ms -NumPy - default - median: 475ms -SUCCESS: syr2k completed -Completed at: Thu Mar 26 10:11:55 AM PDT 2026 -====================================== - - -====================================== -Benchmark: syrk (50/53) -Started at: Thu Mar 26 10:11:55 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with syrk on the L dataset ***** -NumPy - default - first/validation: 439ms -NumPy - default - median: 447ms -SUCCESS: syrk completed -Completed at: Thu Mar 26 10:12:01 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trisolv (51/53) -Started at: Thu Mar 26 10:12:01 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trisolv on the L dataset ***** -NumPy - default - first/validation: 233ms -NumPy - default - median: 223ms -SUCCESS: trisolv completed -Completed at: Thu Mar 26 10:12:13 AM PDT 2026 -====================================== - - -====================================== -Benchmark: trmm (52/53) -Started at: Thu Mar 26 10:12:13 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with trmm on the L dataset ***** -NumPy - default - first/validation: 465ms -NumPy - default - median: 465ms -SUCCESS: trmm completed -Completed at: Thu Mar 26 10:12:19 AM PDT 2026 -====================================== - - -====================================== -Benchmark: vadv (53/53) -Started at: Thu Mar 26 10:12:19 AM PDT 2026 -====================================== -/localdisk/work/antonvol/code/npbench/npbench/infrastructure/framework.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81. - import pkg_resources -WARNING: JAX is not installed. Please install JAX to run benchmarks with the JAX framework. -***** Testing NumPy with vadv on the L dataset ***** -NumPy - default - first/validation: 798ms -NumPy - default - median: 785ms -SUCCESS: vadv completed -Completed at: Thu Mar 26 10:12:30 AM PDT 2026 -====================================== - diff --git a/tmp/npbench_full_comparison.png b/tmp/npbench_full_comparison.png deleted file mode 100644 index 5fcf16f61cb4ec7b910687c5b615e9f2dba1ecbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 433009 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�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/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 z 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 Date: Tue, 14 Apr 2026 15:22:17 +0200 Subject: [PATCH 6/7] Revert logic to match Intel compiler in CMakeLists.txt --- CMakeLists.txt | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ccd8fae..7083502a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,17 +83,11 @@ elseif(UNIX) "${WARNING_FLAGS}" "${SDL_FLAGS}" ) - if(CMAKE_C_COMPILER_ID MATCHES "Intel") - string(CONCAT PRECISION_FLAGS - "-fprotect-parens " - "-fimf-precision=high " - "-fno-fast-math " - ) - else() - string(CONCAT PRECISION_FLAGS - "-fno-fast-math " - ) - endif() + string(CONCAT PRECISION_FLAGS + "-fprotect-parens " + "-fimf-precision=high " + "-fno-fast-math " + ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 ${CFLAGS} ${PRECISION_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${CFLAGS} -fno-fast-math -O0 -g1 -DDEBUG" @@ -118,13 +112,10 @@ set_target_properties(${_trgt} PROPERTIES target_include_directories(${_trgt} PUBLIC mkl_umath/src/ mkl_umath/src/npyv/ ${Python_NumPy_INCLUDE_DIRS} ${Python_INCLUDE_DIRS}) target_link_libraries(${_trgt} PUBLIC MKL::MKL ${Python_LIBRARIES}) target_link_options(${_trgt} PUBLIC ${_linker_options}) -# Compiler-specific vectorization flags -if(CMAKE_C_COMPILER_ID MATCHES "Intel") - target_compile_options(${_trgt} PUBLIC -fveclib=SVML) - target_compile_options(${_trgt} PUBLIC -fvectorize) - if(OPTIMIZATION_REPORT) - target_compile_options(${_trgt} PRIVATE -qopt-report=3) - endif() +target_compile_options(${_trgt} PUBLIC -fveclib=SVML) +target_compile_options(${_trgt} PUBLIC -fvectorize) +if(OPTIMIZATION_REPORT) + target_compile_options(${_trgt} PRIVATE -qopt-report=3) endif() # Enable AVX2 for npyv SIMD acceleration # -mvzeroupper: Prefer VEX encoding even for scalar ops From 7038e563ac022cc64b033fe3c5fd59bb10f531d8 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 14 Apr 2026 15:35:02 +0200 Subject: [PATCH 7/7] Remove rebase leftover --- mkl_umath/src/mkl_umath_loops.c.src | 1 - 1 file changed, 1 deletion(-) diff --git a/mkl_umath/src/mkl_umath_loops.c.src b/mkl_umath/src/mkl_umath_loops.c.src index 4e9e5302..c68e183a 100644 --- a/mkl_umath/src/mkl_umath_loops.c.src +++ b/mkl_umath/src/mkl_umath_loops.c.src @@ -640,7 +640,6 @@ mkl_umath_@TYPE@_subtract(char **args, const npy_intp *dimensions, const npy_int } } } - } else if (IS_BINARY_REDUCE) { BINARY_REDUCE_LOOP(@type@) { io1 -= *(@type@ *)ip2;